panel_ex.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. 面板扩展
  3. 功能: prettier 格式化插件
  4. */
  5. 'use strict';
  6. const tools = require('../../tools/tools');
  7. const path = require("path");
  8. const prsPath = Editor.Project && Editor.Project.path ? Editor.Project.path : Editor.remote.projectPath;
  9. const OLD_PRETTIER_CONFIG_FILE = path.join(__dirname,'prettier.config.js')
  10. const PRETTIER_CONFIG_FILE = path.join(prsPath,'local','prettier.config.js');
  11. module.exports = {
  12. /** @type import('../../panel/vs-panel/vs-panel-base') */
  13. parent : null,
  14. // 面板初始化
  15. onLoad(parent) {
  16. // index.js 对象
  17. this.parent = parent;
  18. // 复制配置文件
  19. if (!tools.isFileExit(PRETTIER_CONFIG_FILE)) {
  20. tools.copyFile(OLD_PRETTIER_CONFIG_FILE, PRETTIER_CONFIG_FILE);
  21. }
  22. // 读取配置
  23. this.cfg = require(PRETTIER_CONFIG_FILE);
  24. this.cfg.endOfLine = this.cfg.endOfLine || 'lf';
  25. // monaco 菜单
  26. this.parent.vs_editor.addAction({
  27. id: 'prettier-format', // 菜单项 id
  28. label: 'Format form Prettier ', // 菜单项名称
  29. // keybindings: [this.monaco.KeyMod.CtrlCmd | this.monaco.KeyCode.KEY_J], // 绑定快捷键
  30. // A precondition for this action.
  31. run: this.handel.bind(this),
  32. })
  33. },
  34. // 设置选项
  35. setOptions(cfg,isInit)
  36. {
  37. if(cfg.enabledFormatFromPrettier == null) return;
  38. if(cfg.enabledFormatFromPrettier){
  39. if(!isInit){
  40. return Editor.log(tools.translateZhAndEn ("使用prettier插件 重启creator后生效",
  41. 'Restart Creator using the PretTier plugin.'));
  42. }
  43. this.initEvent()
  44. }else{
  45. if(!isInit){
  46. return Editor.log(tools.translateZhAndEn ("禁用prettier插件 重启creator后生效",
  47. 'The Prettier plug-in is uninstalled and takes effect after restarting Creator'));
  48. }
  49. }
  50. },
  51. initEvent()
  52. {
  53. if(!Symbol.asyncIterator){
  54. // 旧版js解析器不支持该库
  55. return;
  56. }
  57. const prettier = require('prettier');
  58. const diff = require('diff');
  59. // 代码格式化
  60. let _this = this;
  61. // Editor.monaco.languages.registerDocumentRangeFormattingEditProvider("typescript", {
  62. // provideDocumentRangeFormattingEdits(model , range , options , token){
  63. // // const editor = _this.parent.vs_editor;
  64. // _this.cfg.filepath = model.dbUrl;
  65. // delete _this.cfg.cursorOffset;
  66. // _this.cfg.rangeStart = model.getOffsetAt(range.getStartPosition())
  67. // _this.cfg.rangeEnd = model.getOffsetAt(range.getEndPosition())
  68. // // 格式化
  69. // let code = model.getValue();
  70. // try {
  71. // let formatText = prettier.format(code,_this.cfg);
  72. // // model.setValue(formatText);
  73. // let edits = _this.getDiffTexts(diff.diffChars(code,formatText),model);
  74. // return edits;
  75. // } catch (error) {
  76. // console.warn(error);
  77. // return []
  78. // }
  79. // }
  80. // })
  81. Editor.monaco.languages.registerDocumentFormattingEditProvider("typescript", {
  82. provideDocumentFormattingEdits(model , options , token){
  83. _this.cfg.filepath = model.fsPath;
  84. let select = _this.parent.vs_editor.getSelection()
  85. let cursorOffset = !select || !select.isEmpty() ? -1 : model.getOffsetAt(select.getPosition());
  86. _this.cfg.cursorOffset = cursorOffset
  87. delete _this.cfg.rangeStart;
  88. delete _this.cfg.rangeStart;
  89. // 设置换行格式
  90. let currEOL = model.getEOL() == '\n' ? 'lf' : 'crlf';
  91. if(currEOL != _this.cfg.endOfLine && _this.cfg.endOfLine != 'auto' && _this.cfg.endOfLine != 'cr'){
  92. model.pushEOL(_this.cfg.endOfLine == 'lf' ? 0 : 1)
  93. }
  94. // 格式化
  95. let code = model.getValue() ; // endOfLine 换行格式 即\n(或LF换行)和\r\n(或回车+CRLF换行)
  96. try {
  97. let formatInfo = prettier.formatWithCursor(code,_this.cfg);
  98. if(formatInfo.formatted == code){
  99. return [];
  100. }if(formatInfo.cursorOffset != -1){
  101. model.setValue(formatInfo.formatted);
  102. _this.parent.vs_editor.setPosition(model.getPositionAt(formatInfo.cursorOffset));
  103. return [];
  104. }else if(code < 50000){ // 保证性能情况下才使用这种格式化, 解决格式化后光标错位问题
  105. let edits = _this.getDiffTexts(diff.diffChars(code,formatInfo.formatted),model);
  106. return edits;
  107. }else{
  108. model.setValue(formatInfo.formatted);
  109. return [];
  110. }
  111. } catch (error) {
  112. console.warn(error);
  113. return []
  114. }
  115. }
  116. })
  117. },
  118. // 对比差异再插入,解决格式化后光标错位问题
  119. getDiffTexts(diffList,model){
  120. let edits = []
  121. let offset = 0;
  122. for (let i = 0; i < diffList.length; i++) {
  123. const item = diffList[i];
  124. if(item.added){
  125. let pos = model.getPositionAt(offset);
  126. let select = new Editor.monaco.Selection(pos.lineNumber,pos.column,pos.lineNumber,pos.column);
  127. edits.push({
  128. range:select,
  129. text:item.value,
  130. forceMoveMarkers:false,
  131. })
  132. }else if(item.removed){
  133. let s_pos = model.getPositionAt(offset);
  134. offset += item.count;
  135. let e_pos = model.getPositionAt(offset);
  136. let select = new Editor.monaco.Selection(s_pos.lineNumber,s_pos.column,e_pos.lineNumber,e_pos.column);
  137. edits.push({
  138. range:select,
  139. text:'',
  140. forceMoveMarkers:false,
  141. })
  142. }else{
  143. offset += item.count;
  144. }
  145. }
  146. return edits;
  147. },
  148. handel() {
  149. },
  150. /************* 事件 *************/
  151. messages: {
  152. 'openPrettierConfig'(){
  153. this.parent.openOutSideFile(PRETTIER_CONFIG_FILE,true);
  154. }
  155. },
  156. };