{"version":3,"file":"format.cjs","sources":["../../../app/extensions/format.ts"],"sourcesContent":["import { EditorSelection, Facet } from \"@codemirror/state\"\nimport type { EditorView } from \"@codemirror/view\"\nimport { formatWithCursor } from \"prettier\"\nimport babelPlugin from \"prettier/plugins/babel\"\nimport estreePlugin from \"prettier/plugins/estree\"\nimport htmlPlugin from \"prettier/plugins/html\"\n\nexport const formatCallbackFacet = Facet.define<\n  (formattedCode: string) => void,\n  (formattedCode: string) => void\n>({\n  combine: (callbacks) => callbacks[0] ?? (() => {}),\n})\n\n/**\n * 格式化 TypeScript/JavaScript 代码（用于 code-editor）\n */\nexport function formatDocument(view: EditorView) {\n  const onFormat = view.state.facet(formatCallbackFacet)\n  const code = view.state.doc.toString()\n\n  async function format() {\n    try {\n      const plugins = [babelPlugin, estreePlugin]\n\n      const result = await formatWithCursor(code, {\n        cursorOffset: view.state.selection.main.anchor,\n        parser: \"babel\",\n        plugins,\n      })\n\n      view.dispatch({\n        changes: {\n          from: 0,\n          to: view.state.doc.length,\n          insert: result.formatted,\n        },\n        selection: EditorSelection.single(result.cursorOffset),\n      })\n\n      onFormat(result.formatted)\n    } catch (error) {\n      console.error(\"Format error:\", error)\n    }\n  }\n\n  void format()\n  return true\n}\n\n/**\n * 格式化 HTML 代码（用于 js-editor）\n * HTML 格式化会同时格式化 script 标签内的 JavaScript\n */\nexport function formatHtmlDocument(view: EditorView) {\n  const onFormat = view.state.facet(formatCallbackFacet)\n  const code = view.state.doc.toString()\n\n  async function format() {\n    try {\n      // HTML 格式化需要 html 插件和 babel/estree 插件（用于格式化 script 标签内的 JS）\n      const plugins = [htmlPlugin, babelPlugin, estreePlugin]\n\n      const result = await formatWithCursor(code, {\n        cursorOffset: view.state.selection.main.anchor,\n        parser: \"html\",\n        plugins,\n      })\n\n      view.dispatch({\n        changes: {\n          from: 0,\n          to: view.state.doc.length,\n          insert: result.formatted,\n        },\n        selection: EditorSelection.single(result.cursorOffset),\n      })\n\n      onFormat(result.formatted)\n    } catch (error) {\n      console.error(\"Format error:\", error)\n    }\n  }\n\n  void format()\n  return true\n}\n\nexport function createFormatExtension(onFormat: (formattedCode: string) => void) {\n  return [formatCallbackFacet.of(onFormat)]\n}\n"],"names":["Facet","babelPlugin","estreePlugin","formatWithCursor","EditorSelection","htmlPlugin"],"mappings":";;;;;;;AAOO,MAAM,sBAAsBA,MAAAA,MAAM,OAGvC;AAAA,EACA,SAAS,CAAC,cAAc,UAAU,CAAC,MAAM,MAAM;AAAA,EAAC;AAClD,CAAC;AAKM,SAAS,eAAe,MAAkB;AAC/C,QAAM,WAAW,KAAK,MAAM,MAAM,mBAAmB;AACrD,QAAM,OAAO,KAAK,MAAM,IAAI,SAAA;AAE5B,iBAAe,SAAS;AACtB,QAAI;AACF,YAAM,UAAU,CAACC,MAAAA,SAAaC,cAAY;AAE1C,YAAM,SAAS,MAAMC,WAAAA,iBAAiB,MAAM;AAAA,QAC1C,cAAc,KAAK,MAAM,UAAU,KAAK;AAAA,QACxC,QAAQ;AAAA,QACR;AAAA,MAAA,CACD;AAED,WAAK,SAAS;AAAA,QACZ,SAAS;AAAA,UACP,MAAM;AAAA,UACN,IAAI,KAAK,MAAM,IAAI;AAAA,UACnB,QAAQ,OAAO;AAAA,QAAA;AAAA,QAEjB,WAAWC,MAAAA,gBAAgB,OAAO,OAAO,YAAY;AAAA,MAAA,CACtD;AAED,eAAS,OAAO,SAAS;AAAA,IAC3B,SAAS,OAAO;AACd,cAAQ,MAAM,iBAAiB,KAAK;AAAA,IACtC;AAAA,EACF;AAEA,OAAK,OAAA;AACL,SAAO;AACT;AAMO,SAAS,mBAAmB,MAAkB;AACnD,QAAM,WAAW,KAAK,MAAM,MAAM,mBAAmB;AACrD,QAAM,OAAO,KAAK,MAAM,IAAI,SAAA;AAE5B,iBAAe,SAAS;AACtB,QAAI;AAEF,YAAM,UAAU,CAACC,cAAYJ,MAAAA,SAAaC,OAAAA,OAAY;AAEtD,YAAM,SAAS,MAAMC,WAAAA,iBAAiB,MAAM;AAAA,QAC1C,cAAc,KAAK,MAAM,UAAU,KAAK;AAAA,QACxC,QAAQ;AAAA,QACR;AAAA,MAAA,CACD;AAED,WAAK,SAAS;AAAA,QACZ,SAAS;AAAA,UACP,MAAM;AAAA,UACN,IAAI,KAAK,MAAM,IAAI;AAAA,UACnB,QAAQ,OAAO;AAAA,QAAA;AAAA,QAEjB,WAAWC,MAAAA,gBAAgB,OAAO,OAAO,YAAY;AAAA,MAAA,CACtD;AAED,eAAS,OAAO,SAAS;AAAA,IAC3B,SAAS,OAAO;AACd,cAAQ,MAAM,iBAAiB,KAAK;AAAA,IACtC;AAAA,EACF;AAEA,OAAK,OAAA;AACL,SAAO;AACT;AAEO,SAAS,sBAAsB,UAA2C;AAC/E,SAAO,CAAC,oBAAoB,GAAG,QAAQ,CAAC;AAC1C;;;;;"}