vue-tsx.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.tsCodegen = void 0;
  4. const computeds_1 = require("computeds");
  5. const script_1 = require("../generators/script");
  6. const template_1 = require("../generators/template");
  7. const scriptRanges_1 = require("../parsers/scriptRanges");
  8. const scriptSetupRanges_1 = require("../parsers/scriptSetupRanges");
  9. const language_core_1 = require("@volar/language-core");
  10. const muggle = require("muggle-string");
  11. const templateFormatReg = /^\.template_format\.ts$/;
  12. const templateStyleCssReg = /^\.template_style\.css$/;
  13. exports.tsCodegen = new WeakMap();
  14. const plugin = (ctx) => {
  15. return {
  16. version: 1,
  17. requiredCompilerOptions: [
  18. 'noPropertyAccessFromIndexSignature',
  19. 'exactOptionalPropertyTypes',
  20. ],
  21. getEmbeddedFileNames(fileName, sfc) {
  22. const tsx = useTsx(fileName, sfc);
  23. const fileNames = [];
  24. if (['js', 'ts', 'jsx', 'tsx'].includes(tsx.lang())) {
  25. fileNames.push(fileName + '.' + tsx.lang());
  26. }
  27. if (sfc.template) {
  28. fileNames.push(fileName + '.template_format.ts');
  29. fileNames.push(fileName + '.template_style.css');
  30. }
  31. return fileNames;
  32. },
  33. resolveEmbeddedFile(fileName, sfc, embeddedFile) {
  34. const _tsx = useTsx(fileName, sfc);
  35. const suffix = embeddedFile.fileName.replace(fileName, '');
  36. if (suffix === '.' + _tsx.lang()) {
  37. embeddedFile.kind = language_core_1.FileKind.TypeScriptHostFile;
  38. embeddedFile.capabilities = {
  39. ...language_core_1.FileCapabilities.full,
  40. foldingRange: false,
  41. documentFormatting: false,
  42. documentSymbol: false,
  43. };
  44. const tsx = _tsx.generatedScript();
  45. if (tsx) {
  46. const [content, contentStacks] = ctx.codegenStack ? muggle.track([...tsx.codes], [...tsx.codeStacks]) : [[...tsx.codes], [...tsx.codeStacks]];
  47. embeddedFile.content = content;
  48. embeddedFile.contentStacks = contentStacks;
  49. embeddedFile.mirrorBehaviorMappings = [...tsx.mirrorBehaviorMappings];
  50. }
  51. }
  52. else if (suffix.match(templateFormatReg)) {
  53. embeddedFile.parentFileName = fileName + '.template.' + sfc.template?.lang;
  54. embeddedFile.kind = language_core_1.FileKind.TextFile;
  55. embeddedFile.capabilities = {
  56. ...language_core_1.FileCapabilities.full,
  57. diagnostic: false,
  58. foldingRange: false,
  59. codeAction: false,
  60. inlayHint: false,
  61. };
  62. const template = _tsx.generatedTemplate();
  63. if (template) {
  64. const [content, contentStacks] = ctx.codegenStack
  65. ? muggle.track([...template.formatCodes], [...template.formatCodeStacks])
  66. : [[...template.formatCodes], [...template.formatCodeStacks]];
  67. embeddedFile.content = content;
  68. embeddedFile.contentStacks = contentStacks;
  69. }
  70. for (const style of sfc.styles) {
  71. embeddedFile.content.push('\n\n');
  72. for (const cssVar of style.cssVars) {
  73. embeddedFile.content.push('(');
  74. embeddedFile.content.push([
  75. cssVar.text,
  76. style.name,
  77. cssVar.offset,
  78. {},
  79. ]);
  80. embeddedFile.content.push(');\n');
  81. }
  82. }
  83. }
  84. else if (suffix.match(templateStyleCssReg)) {
  85. embeddedFile.parentFileName = fileName + '.template.' + sfc.template?.lang;
  86. const template = _tsx.generatedTemplate();
  87. if (template) {
  88. const [content, contentStacks] = ctx.codegenStack
  89. ? muggle.track([...template.cssCodes], [...template.cssCodeStacks])
  90. : [[...template.cssCodes], [...template.cssCodeStacks]];
  91. embeddedFile.content = content;
  92. embeddedFile.contentStacks = contentStacks;
  93. }
  94. // for color pickers support
  95. embeddedFile.capabilities.documentSymbol = true;
  96. }
  97. },
  98. };
  99. function useTsx(fileName, sfc) {
  100. if (!exports.tsCodegen.has(sfc)) {
  101. exports.tsCodegen.set(sfc, createTsx(fileName, sfc, ctx));
  102. }
  103. return exports.tsCodegen.get(sfc);
  104. }
  105. };
  106. exports.default = plugin;
  107. function createTsx(fileName, _sfc, { vueCompilerOptions, compilerOptions, codegenStack, modules }) {
  108. const ts = modules.typescript;
  109. const lang = (0, computeds_1.computed)(() => {
  110. return !_sfc.script && !_sfc.scriptSetup ? 'ts'
  111. : _sfc.scriptSetup && _sfc.scriptSetup.lang !== 'js' ? _sfc.scriptSetup.lang
  112. : _sfc.script && _sfc.script.lang !== 'js' ? _sfc.script.lang
  113. : 'js';
  114. });
  115. const scriptRanges = (0, computeds_1.computed)(() => _sfc.script
  116. ? (0, scriptRanges_1.parseScriptRanges)(ts, _sfc.script.ast, !!_sfc.scriptSetup, false)
  117. : undefined);
  118. const scriptSetupRanges = (0, computeds_1.computed)(() => _sfc.scriptSetup
  119. ? (0, scriptSetupRanges_1.parseScriptSetupRanges)(ts, _sfc.scriptSetup.ast, vueCompilerOptions)
  120. : undefined);
  121. const shouldGenerateScopedClasses = (0, computeds_1.computed)(() => {
  122. const option = vueCompilerOptions.experimentalResolveStyleCssClasses;
  123. return _sfc.styles.some(s => {
  124. return option === 'always' || (option === 'scoped' && s.scoped);
  125. });
  126. });
  127. const stylesScopedClasses = (0, computeds_1.computedSet)(() => {
  128. const classes = new Set();
  129. if (!shouldGenerateScopedClasses()) {
  130. return classes;
  131. }
  132. for (const style of _sfc.styles) {
  133. const option = vueCompilerOptions.experimentalResolveStyleCssClasses;
  134. if (option === 'always' || (option === 'scoped' && style.scoped)) {
  135. for (const className of style.classNames) {
  136. classes.add(className.text.substring(1));
  137. }
  138. }
  139. }
  140. return classes;
  141. });
  142. const generatedTemplate = (0, computeds_1.computed)(() => {
  143. if (!_sfc.template)
  144. return;
  145. return (0, template_1.generate)(ts, compilerOptions, vueCompilerOptions, _sfc.template, shouldGenerateScopedClasses(), stylesScopedClasses(), hasScriptSetupSlots(), slotsAssignName(), propsAssignName(), codegenStack);
  146. });
  147. const hasScriptSetupSlots = (0, computeds_1.computed)(() => !!scriptSetupRanges()?.slots.define);
  148. const slotsAssignName = (0, computeds_1.computed)(() => scriptSetupRanges()?.slots.name);
  149. const propsAssignName = (0, computeds_1.computed)(() => scriptSetupRanges()?.props.name);
  150. const generatedScript = (0, computeds_1.computed)(() => (0, script_1.generate)(ts, fileName, _sfc.script, _sfc.scriptSetup, _sfc.styles, lang(), scriptRanges(), scriptSetupRanges(), generatedTemplate(), compilerOptions, vueCompilerOptions, codegenStack));
  151. return {
  152. scriptRanges,
  153. scriptSetupRanges,
  154. lang,
  155. generatedScript,
  156. generatedTemplate,
  157. };
  158. }
  159. //# sourceMappingURL=vue-tsx.js.map