版博士V2.0程序
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 

660 satır
22 KiB

  1. import { createUnplugin } from 'unplugin';
  2. import { normalize, parse } from 'pathe';
  3. import createDebug from 'debug';
  4. import fg from 'fast-glob';
  5. import { isString, isArray, isBoolean, isObject, isNumber, isEmptyObject, assign, generateCodeFrame } from '@intlify/shared';
  6. import { createFilter } from '@rollup/pluginutils';
  7. import { checkInstallPackage, checkVueI18nBridgeInstallPackage, getVueI18nVersion, generateJSON, generateYAML, generateJavaScript } from '@intlify/bundle-utils';
  8. import { parse as parse$1 } from '@vue/compiler-sfc';
  9. import JSON5 from 'json5';
  10. import yaml from 'js-yaml';
  11. import { promises } from 'fs';
  12. import pc from 'picocolors';
  13. function parseVueRequest(id) {
  14. const [filename, rawQuery] = id.split(`?`, 2);
  15. const params = new URLSearchParams(rawQuery);
  16. const ret = {};
  17. const langPart = Object.keys(Object.fromEntries(params)).find(
  18. (key) => /lang\./i.test(key)
  19. );
  20. ret.vue = params.has("vue");
  21. ret.global = params.has("global");
  22. ret.src = params.has("src");
  23. ret.raw = params.has("raw");
  24. if (params.has("type")) {
  25. ret.type = params.get("type");
  26. }
  27. if (params.has("blockType")) {
  28. ret.blockType = params.get("blockType");
  29. }
  30. if (params.has("index")) {
  31. ret.index = Number(params.get("index"));
  32. }
  33. if (params.has("locale")) {
  34. ret.locale = params.get("locale");
  35. }
  36. if (langPart) {
  37. const [, lang] = langPart.split(".");
  38. ret.lang = lang;
  39. } else if (params.has("lang")) {
  40. ret.lang = params.get("lang");
  41. }
  42. if (params.has("issuerPath")) {
  43. ret.issuerPath = params.get("issuerPath");
  44. }
  45. return {
  46. filename,
  47. query: ret
  48. };
  49. }
  50. function createBridgeCodeGenerator(source, query) {
  51. return () => {
  52. const data = convert(source, query.lang);
  53. let value = JSON.parse(data);
  54. if (isString(query.locale)) {
  55. value = Object.assign({}, { [query.locale]: value });
  56. }
  57. return JSON.stringify(value).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029").replace(/\\/g, "\\\\").replace(/\u0027/g, "\\u0027");
  58. };
  59. }
  60. function convert(source, lang) {
  61. switch (lang) {
  62. case "yaml":
  63. case "yml":
  64. const data = yaml.load(source);
  65. return JSON.stringify(data, void 0, " ");
  66. case "json5":
  67. return JSON.stringify(JSON5.parse(source));
  68. default:
  69. return source;
  70. }
  71. }
  72. function warn(...args) {
  73. console.warn(pc.yellow(pc.bold(`[unplugin-vue-i18n] `)), ...args);
  74. }
  75. function error(...args) {
  76. console.error(pc.red(pc.bold(`[unplugin-vue-i18n] `)), ...args);
  77. }
  78. async function getRaw(path) {
  79. return promises.readFile(path, { encoding: "utf-8" });
  80. }
  81. function raiseError(message) {
  82. throw new Error(`[unplugin-vue-i18n] ${message}`);
  83. }
  84. const INTLIFY_BUNDLE_IMPORT_ID = "@intlify/unplugin-vue-i18n/messages";
  85. const INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID = "@intlify/vite-plugin-vue-i18n/messages";
  86. const VIRTUAL_PREFIX = "\0";
  87. const debug = createDebug("unplugin-vue-i18n");
  88. const installedPkg = checkInstallPackage("@intlify/unplugin-vue-i18n", debug);
  89. const installedVueI18nBridge = checkVueI18nBridgeInstallPackage(debug);
  90. const vueI18nVersion = getVueI18nVersion(debug);
  91. const unplugin = createUnplugin((options = {}, meta) => {
  92. debug("plugin options:", options, meta.framework);
  93. if (!["vite", "webpack"].includes(meta.framework)) {
  94. raiseError(`This plugin is supported 'vite' and 'webpack' only`);
  95. }
  96. let include = options.include;
  97. let exclude = null;
  98. if (include) {
  99. if (isArray(include)) {
  100. include = include.map((item) => normalize(item));
  101. } else if (isString(include)) {
  102. include = normalize(include);
  103. }
  104. } else {
  105. exclude = "**/**";
  106. }
  107. const filter = createFilter(include, exclude);
  108. const forceStringify = !!options.forceStringify;
  109. const defaultSFCLang = isString(options.defaultSFCLang) ? options.defaultSFCLang : "json";
  110. const globalSFCScope = !!options.globalSFCScope;
  111. const useClassComponent = !!options.useClassComponent;
  112. const bridge = !!options.bridge;
  113. debug("bridge", bridge);
  114. const runtimeOnly = isBoolean(options.runtimeOnly) ? options.runtimeOnly : true;
  115. debug("runtimeOnly", runtimeOnly);
  116. const compositionOnly = installedPkg === "vue-i18n" ? isBoolean(options.compositionOnly) ? options.compositionOnly : true : true;
  117. debug("compositionOnly", compositionOnly);
  118. const fullInstall = installedPkg === "vue-i18n" ? isBoolean(options.fullInstall) ? options.fullInstall : true : false;
  119. debug("fullInstall", fullInstall);
  120. const useVueI18nImportName = options.useVueI18nImportName;
  121. if (useVueI18nImportName != null) {
  122. warn(`'useVueI18nImportName' option is experimental`);
  123. }
  124. debug("useVueI18nImportName", useVueI18nImportName);
  125. const getVueI18nAliasName = () => vueI18nVersion === "9" || vueI18nVersion === "8" ? "vue-i18n" : vueI18nVersion === "unknown" && installedPkg === "petite-vue-i18n" && isBoolean(useVueI18nImportName) && useVueI18nImportName ? "vue-i18n" : installedPkg;
  126. const getVueI18nBridgeAliasPath = () => `vue-i18n-bridge/dist/vue-i18n-bridge.runtime.esm-bundler.js`;
  127. const getVueI18nAliasPath = (aliasName) => vueI18nVersion === "8" ? `${aliasName}/dist/${aliasName}.esm.js` : `${aliasName}/dist/${installedPkg}.runtime.esm-bundler.js`;
  128. const esm = isBoolean(options.esm) ? options.esm : true;
  129. debug("esm", esm);
  130. const allowDynamic = !!options.allowDynamic;
  131. debug("allowDynamic", allowDynamic);
  132. const strictMessage = isBoolean(options.strictMessage) ? options.strictMessage : true;
  133. debug("strictMessage", strictMessage);
  134. const escapeHtml = !!options.escapeHtml;
  135. debug("escapeHtml", escapeHtml);
  136. let isProduction = false;
  137. let sourceMap = false;
  138. const vueI18nAliasName = getVueI18nAliasName();
  139. return {
  140. name: "unplugin-vue-i18n",
  141. enforce: meta.framework === "vite" ? "pre" : "post",
  142. vite: {
  143. config(config, { command }) {
  144. config.resolve = normalizeConfigResolveAlias(
  145. config.resolve,
  146. meta.framework
  147. );
  148. if (command === "build" && runtimeOnly) {
  149. debug(`vue-i18n alias name: ${vueI18nAliasName}`);
  150. if (isArray(config.resolve.alias)) {
  151. config.resolve.alias.push({
  152. find: vueI18nAliasName,
  153. replacement: getVueI18nAliasPath(vueI18nAliasName)
  154. });
  155. if (installedVueI18nBridge) {
  156. config.resolve.alias.push({
  157. find: "vue-i18n-bridge",
  158. replacement: getVueI18nBridgeAliasPath()
  159. });
  160. }
  161. } else if (isObject(config.resolve.alias)) {
  162. config.resolve.alias[vueI18nAliasName] = getVueI18nAliasPath(vueI18nAliasName);
  163. if (installedVueI18nBridge) {
  164. config.resolve.alias["vue-i18n-bridge"] = getVueI18nBridgeAliasPath();
  165. }
  166. }
  167. debug(
  168. `set ${vueI18nAliasName} runtime only: ${getVueI18nAliasPath(
  169. vueI18nAliasName
  170. )}`
  171. );
  172. if (installedVueI18nBridge) {
  173. debug(
  174. `set vue-i18n-bridge runtime only: ${getVueI18nBridgeAliasPath()}`
  175. );
  176. }
  177. } else if (command === "serve" && installedPkg === "petite-vue-i18n" && useVueI18nImportName) {
  178. config.resolve = normalizeConfigResolveAlias(
  179. config.resolve,
  180. meta.framework
  181. );
  182. if (isArray(config.resolve.alias)) {
  183. config.resolve.alias.push({
  184. find: vueI18nAliasName,
  185. replacement: `petite-vue-i18n/dist/petite-vue-i18n.esm-bundler.js`
  186. });
  187. } else {
  188. config.resolve.alias[vueI18nAliasName] = `petite-vue-i18n/dist/petite-vue-i18n.esm-bundler.js`;
  189. }
  190. debug(`petite-vue-i18n alias name: ${vueI18nAliasName}`);
  191. }
  192. config.define = config.define || {};
  193. config.define["__VUE_I18N_LEGACY_API__"] = !compositionOnly;
  194. debug(
  195. `set __VUE_I18N_LEGACY_API__ is '${config.define["__VUE_I18N_LEGACY_API__"]}'`
  196. );
  197. config.define["__VUE_I18N_FULL_INSTALL__"] = fullInstall;
  198. debug(
  199. `set __VUE_I18N_FULL_INSTALL__ is '${config.define["__VUE_I18N_FULL_INSTALL__"]}'`
  200. );
  201. config.define["__VUE_I18N_PROD_DEVTOOLS__"] = false;
  202. },
  203. configResolved(config) {
  204. isProduction = config.isProduction;
  205. sourceMap = config.command === "build" ? !!config.build.sourcemap : false;
  206. debug(
  207. `configResolved: isProduction = ${isProduction}, sourceMap = ${sourceMap}`
  208. );
  209. const jsonPlugin = config.plugins.find((p) => p.name === "vite:json");
  210. if (jsonPlugin) {
  211. const orgTransform = jsonPlugin.transform;
  212. jsonPlugin.transform = async function(code, id) {
  213. if (!/\.json$/.test(id) || filter(id)) {
  214. return;
  215. }
  216. const { query } = parseVueRequest(id);
  217. if (query.vue) {
  218. return;
  219. }
  220. debug("org json plugin");
  221. return orgTransform.apply(this, [code, id]);
  222. };
  223. }
  224. const esbuildPlugin = config.plugins.find(
  225. (p) => p.name === "vite:esbuild"
  226. );
  227. if (esbuildPlugin) {
  228. const orgTransform = esbuildPlugin.transform;
  229. esbuildPlugin.transform = async function(code, id) {
  230. const result = await orgTransform.apply(this, [
  231. code,
  232. id
  233. ]);
  234. if (result == null) {
  235. return result;
  236. }
  237. const { filename, query } = parseVueRequest(id);
  238. if (!query.vue && filter(id) && /\.[c|m]?ts$/.test(id)) {
  239. const [_code, inSourceMap] = isString(result) ? [result, void 0] : [result.code, result.map];
  240. let langInfo = defaultSFCLang;
  241. langInfo = parse(filename).ext;
  242. const generate = getGenerator(langInfo);
  243. const parseOptions = getOptions(
  244. filename,
  245. isProduction,
  246. query,
  247. sourceMap,
  248. {
  249. inSourceMap,
  250. isGlobal: globalSFCScope,
  251. useClassComponent,
  252. allowDynamic,
  253. strictMessage,
  254. escapeHtml,
  255. bridge,
  256. exportESM: esm,
  257. forceStringify
  258. }
  259. );
  260. debug("parseOptions", parseOptions);
  261. const { code: generatedCode, map } = generate(
  262. _code,
  263. parseOptions,
  264. bridge ? createBridgeCodeGenerator(_code, query) : void 0
  265. );
  266. debug("generated code", generatedCode);
  267. debug("sourcemap", map, sourceMap);
  268. if (_code === generatedCode)
  269. return;
  270. return {
  271. code: generatedCode,
  272. map: sourceMap ? map : { mappings: "" }
  273. };
  274. } else {
  275. return result;
  276. }
  277. };
  278. }
  279. },
  280. async handleHotUpdate({ file, server }) {
  281. if (/\.(json5?|ya?ml)$/.test(file)) {
  282. const module = server.moduleGraph.getModuleById(
  283. asVirtualId(INTLIFY_BUNDLE_IMPORT_ID, meta.framework)
  284. );
  285. if (module) {
  286. server.moduleGraph.invalidateModule(module);
  287. return [module];
  288. }
  289. }
  290. }
  291. },
  292. webpack(compiler) {
  293. isProduction = compiler.options.mode !== "development";
  294. sourceMap = !!compiler.options.devtool;
  295. debug(`webpack: isProduction = ${isProduction}, sourceMap = ${sourceMap}`);
  296. compiler.options.resolve = normalizeConfigResolveAlias(
  297. compiler.options.resolve,
  298. meta.framework
  299. );
  300. if (isProduction && runtimeOnly) {
  301. compiler.options.resolve.alias[vueI18nAliasName] = getVueI18nAliasPath(vueI18nAliasName);
  302. if (installedVueI18nBridge) {
  303. compiler.options.resolve.alias["vue-i18n-bridge"] = getVueI18nBridgeAliasPath();
  304. }
  305. debug(
  306. `set ${vueI18nAliasName} runtime only: ${getVueI18nAliasPath(
  307. vueI18nAliasName
  308. )}`
  309. );
  310. if (installedVueI18nBridge) {
  311. debug(
  312. `set vue-i18n-bridge runtime only: ${getVueI18nBridgeAliasPath()}`
  313. );
  314. }
  315. } else if (!isProduction && installedPkg === "petite-vue-i18n" && useVueI18nImportName) {
  316. compiler.options.resolve.alias[vueI18nAliasName] = `petite-vue-i18n/dist/petite-vue-i18n.esm-bundler.js`;
  317. debug(`petite-vue-i18n alias name: ${vueI18nAliasName}`);
  318. }
  319. loadWebpack().then((webpack) => {
  320. if (webpack) {
  321. compiler.options.plugins.push(
  322. new webpack.DefinePlugin({
  323. __VUE_I18N_LEGACY_API__: JSON.stringify(compositionOnly),
  324. __VUE_I18N_FULL_INSTALL__: JSON.stringify(fullInstall),
  325. __INTLIFY_PROD_DEVTOOLS__: "false"
  326. })
  327. );
  328. debug(`set __VUE_I18N_LEGACY_API__ is '${compositionOnly}'`);
  329. debug(`set __VUE_I18N_FULL_INSTALL__ is '${fullInstall}'`);
  330. } else {
  331. debug("ignore vue-i18n feature flags with webpack.DefinePlugin");
  332. }
  333. });
  334. if (compiler.options.module) {
  335. compiler.options.module.rules.push({
  336. test: /\.(json5?|ya?ml)$/,
  337. type: "javascript/auto",
  338. include(resource) {
  339. return filter(resource);
  340. }
  341. });
  342. }
  343. },
  344. resolveId(id, importer) {
  345. debug("resolveId", id, importer);
  346. if (id === INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID) {
  347. warn(
  348. `deprected '${INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID}', you should switch to '${INTLIFY_BUNDLE_IMPORT_ID}'`
  349. );
  350. return asVirtualId(id, meta.framework);
  351. }
  352. if (id === INTLIFY_BUNDLE_IMPORT_ID) {
  353. return asVirtualId(id, meta.framework);
  354. }
  355. },
  356. async load(id) {
  357. debug("load", id);
  358. const { query } = parseVueRequest(id);
  359. if ([INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID, INTLIFY_BUNDLE_IMPORT_ID].includes(
  360. getVirtualId(id, meta.framework)
  361. ) && include) {
  362. let resourcePaths = [];
  363. const includePaths = isArray(include) ? include : [include];
  364. for (const inc of includePaths) {
  365. resourcePaths = [...resourcePaths, ...await fg(inc)];
  366. }
  367. resourcePaths = resourcePaths.filter(
  368. (el, pos) => resourcePaths.indexOf(el) === pos
  369. );
  370. const code = await generateBundleResources(
  371. resourcePaths,
  372. query,
  373. isProduction,
  374. {
  375. forceStringify,
  376. bridge,
  377. strictMessage,
  378. escapeHtml,
  379. exportESM: esm,
  380. useClassComponent
  381. }
  382. );
  383. return {
  384. code,
  385. map: { mappings: "" }
  386. };
  387. }
  388. },
  389. transformInclude(id) {
  390. debug("transformInclude", id);
  391. if (meta.framework === "vite") {
  392. return true;
  393. } else {
  394. const { filename } = parseVueRequest(id);
  395. return filename.endsWith("vue") || filename.endsWith(INTLIFY_BUNDLE_IMPORT_ID) || filename.endsWith(INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID) || /\.(json5?|ya?ml)$/.test(filename) && filter(filename);
  396. }
  397. },
  398. async transform(code, id) {
  399. const { filename, query } = parseVueRequest(id);
  400. debug("transform", id, JSON.stringify(query), filename);
  401. let langInfo = defaultSFCLang;
  402. let inSourceMap;
  403. if (!query.vue) {
  404. if (/\.(json5?|ya?ml|[c|m]?js)$/.test(id) && filter(id)) {
  405. langInfo = parse(filename).ext;
  406. const generate = getGenerator(langInfo);
  407. const parseOptions = getOptions(
  408. filename,
  409. isProduction,
  410. query,
  411. sourceMap,
  412. {
  413. inSourceMap,
  414. isGlobal: globalSFCScope,
  415. useClassComponent,
  416. allowDynamic,
  417. strictMessage,
  418. escapeHtml,
  419. bridge,
  420. exportESM: esm,
  421. forceStringify
  422. }
  423. );
  424. debug("parseOptions", parseOptions);
  425. const { code: generatedCode, map } = generate(
  426. code,
  427. parseOptions,
  428. bridge ? createBridgeCodeGenerator(code, query) : void 0
  429. );
  430. debug("generated code", generatedCode);
  431. debug("sourcemap", map, sourceMap);
  432. if (code === generatedCode)
  433. return;
  434. return {
  435. code: generatedCode,
  436. map: sourceMap ? map : { mappings: "" }
  437. };
  438. }
  439. } else {
  440. if (isCustomBlock(query)) {
  441. if (isString(query.lang)) {
  442. langInfo = query.src ? query.lang === "i18n" ? "json" : query.lang : query.lang;
  443. } else if (defaultSFCLang) {
  444. langInfo = defaultSFCLang;
  445. }
  446. debug("langInfo", langInfo);
  447. const generate = /\.?json5?/.test(langInfo) ? generateJSON : generateYAML;
  448. const parseOptions = getOptions(
  449. filename,
  450. isProduction,
  451. query,
  452. sourceMap,
  453. {
  454. inSourceMap,
  455. isGlobal: globalSFCScope,
  456. useClassComponent,
  457. bridge,
  458. strictMessage,
  459. escapeHtml,
  460. exportESM: esm,
  461. forceStringify
  462. }
  463. );
  464. debug("parseOptions", parseOptions);
  465. const source = await getCode(
  466. code,
  467. filename,
  468. sourceMap,
  469. query,
  470. meta.framework
  471. );
  472. const { code: generatedCode, map } = generate(
  473. source,
  474. parseOptions,
  475. bridge ? createBridgeCodeGenerator(source, query) : void 0
  476. );
  477. debug("generated code", generatedCode);
  478. debug("sourcemap", map, sourceMap);
  479. if (code === generatedCode)
  480. return;
  481. return {
  482. code: generatedCode,
  483. map: sourceMap ? map : { mappings: "" }
  484. };
  485. }
  486. }
  487. }
  488. };
  489. });
  490. function getGenerator(ext, defaultGen = generateJSON) {
  491. return /\.?json5?$/.test(ext) ? generateJSON : /\.ya?ml$/.test(ext) ? generateYAML : /\.([c|m]?js|[c|m]?ts)$/.test(ext) ? generateJavaScript : defaultGen;
  492. }
  493. function normalizeConfigResolveAlias(resolve, framework) {
  494. if (resolve && resolve.alias) {
  495. return resolve;
  496. }
  497. if (!resolve) {
  498. if (framework === "vite") {
  499. return { alias: [] };
  500. } else if (framework === "webpack") {
  501. return { alias: {} };
  502. }
  503. } else if (!resolve.alias) {
  504. if (framework === "vite") {
  505. resolve.alias = [];
  506. return resolve;
  507. } else if (framework === "webpack") {
  508. resolve.alias = {};
  509. return resolve;
  510. }
  511. }
  512. }
  513. async function loadWebpack() {
  514. let webpack = null;
  515. try {
  516. webpack = await import('webpack').then((m) => m.default || m);
  517. } catch (e) {
  518. warn(`webpack not found, please install webpack.`);
  519. }
  520. return webpack;
  521. }
  522. async function generateBundleResources(resources, query, isProduction, {
  523. forceStringify = false,
  524. isGlobal = false,
  525. bridge = false,
  526. exportESM = true,
  527. strictMessage = true,
  528. escapeHtml = false,
  529. useClassComponent = false
  530. }) {
  531. const codes = [];
  532. for (const res of resources) {
  533. debug(`${res} bundle loading ...`);
  534. if (/\.(json5?|ya?ml)$/.test(res)) {
  535. const { ext, name } = parse(res);
  536. const source = await getRaw(res);
  537. const generate = /json5?/.test(ext) ? generateJSON : generateYAML;
  538. const parseOptions = getOptions(res, isProduction, {}, false, {
  539. isGlobal,
  540. useClassComponent,
  541. bridge,
  542. exportESM,
  543. strictMessage,
  544. escapeHtml,
  545. forceStringify
  546. });
  547. parseOptions.type = "bare";
  548. const { code } = generate(
  549. source,
  550. parseOptions,
  551. bridge ? createBridgeCodeGenerator(source, query) : void 0
  552. );
  553. debug("generated code", code);
  554. codes.push(`${JSON.stringify(name)}: ${code}`);
  555. }
  556. }
  557. return `export default {
  558. ${codes.join(`,
  559. `)}
  560. }`;
  561. }
  562. async function getCode(source, filename, sourceMap, query, framework = "vite") {
  563. const { index, issuerPath } = query;
  564. if (!isNumber(index)) {
  565. raiseError(`unexpected index: ${index}`);
  566. }
  567. if (framework === "webpack") {
  568. if (issuerPath) {
  569. debug(`getCode (webpack) ${index} via issuerPath`, issuerPath);
  570. return await getRaw(filename);
  571. } else {
  572. const result = parse$1(await getRaw(filename), {
  573. sourceMap,
  574. filename
  575. });
  576. const block = result.descriptor.customBlocks[index];
  577. if (block) {
  578. const code = block.src ? await getRaw(block.src) : block.content;
  579. debug(`getCode (webpack) ${index} from SFC`, code);
  580. return code;
  581. } else {
  582. return source;
  583. }
  584. }
  585. } else {
  586. return source;
  587. }
  588. }
  589. function isCustomBlock(query) {
  590. return !isEmptyObject(query) && "vue" in query && (query["type"] === "custom" || query["type"] === "i18n" || query["blockType"] === "i18n");
  591. }
  592. function getOptions(filename, isProduction, query, sourceMap, {
  593. inSourceMap = void 0,
  594. forceStringify = false,
  595. isGlobal = false,
  596. bridge = false,
  597. exportESM = true,
  598. useClassComponent = false,
  599. allowDynamic = false,
  600. strictMessage = true,
  601. escapeHtml = false
  602. }) {
  603. const mode = isProduction ? "production" : "development";
  604. const baseOptions = {
  605. filename,
  606. sourceMap,
  607. inSourceMap,
  608. forceStringify,
  609. useClassComponent,
  610. allowDynamic,
  611. strictMessage,
  612. escapeHtml,
  613. bridge,
  614. exportESM,
  615. env: mode,
  616. onWarn: (msg) => {
  617. warn(`${filename} ${msg}`);
  618. },
  619. onError: (msg, extra) => {
  620. const codeFrame = generateCodeFrame(
  621. extra?.source || extra?.location?.source || "",
  622. extra?.location?.start.column,
  623. extra?.location?.end.column
  624. );
  625. const errMssage = `${msg} (error code: ${extra?.code}) in ${filename}
  626. target message: ${extra?.source}
  627. target message path: ${extra?.path}
  628. ${codeFrame}
  629. `;
  630. error(errMssage);
  631. throw new Error(errMssage);
  632. }
  633. };
  634. if (isCustomBlock(query)) {
  635. return assign(baseOptions, {
  636. type: "sfc",
  637. locale: isString(query.locale) ? query.locale : "",
  638. isGlobal: isGlobal || !!query.global
  639. });
  640. } else {
  641. return assign(baseOptions, {
  642. type: "plain",
  643. isGlobal: false
  644. });
  645. }
  646. }
  647. function getVirtualId(id, framework = "vite") {
  648. return framework === "vite" ? id.startsWith(VIRTUAL_PREFIX) ? id.slice(VIRTUAL_PREFIX.length) : "" : id;
  649. }
  650. function asVirtualId(id, framework = "vite") {
  651. return framework === "vite" ? VIRTUAL_PREFIX + id : id;
  652. }
  653. export { unplugin as default, unplugin };