@qualcomm-ui/mdx-vite 1.1.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/cli.js +322 -230
  2. package/dist/cli.js.map +4 -4
  3. package/dist/docs-plugin/docs-plugin.d.ts.map +1 -1
  4. package/dist/docs-plugin/generate-page-map.d.ts +2 -0
  5. package/dist/docs-plugin/generate-page-map.d.ts.map +1 -0
  6. package/dist/docs-plugin/internal/search-indexer.d.ts +2 -2
  7. package/dist/docs-plugin/internal/search-indexer.d.ts.map +1 -1
  8. package/dist/docs-plugin/internal/services/markdown/markdown-file-reader.d.ts +1 -0
  9. package/dist/docs-plugin/internal/services/markdown/markdown-file-reader.d.ts.map +1 -1
  10. package/dist/docs-plugin/internal/services/markdown/markdown.types.d.ts +17 -1
  11. package/dist/docs-plugin/internal/services/markdown/markdown.types.d.ts.map +1 -1
  12. package/dist/docs-plugin/internal/services/nav-builder/nav-builder.d.ts.map +1 -1
  13. package/dist/docs-plugin/internal/services/nav-builder/page-map.d.ts.map +1 -1
  14. package/dist/docs-plugin/mdx-plugins.d.ts +2 -0
  15. package/dist/docs-plugin/mdx-plugins.d.ts.map +1 -1
  16. package/dist/docs-plugin/remark/remark-code-tabs.d.ts +16 -0
  17. package/dist/docs-plugin/remark/remark-code-tabs.d.ts.map +1 -1
  18. package/dist/docs-plugin/shiki/index.d.ts +3 -0
  19. package/dist/docs-plugin/shiki/index.d.ts.map +1 -0
  20. package/dist/docs-plugin/shiki/shiki-transformer-code-attribute.d.ts +20 -0
  21. package/dist/docs-plugin/shiki/shiki-transformer-code-attribute.d.ts.map +1 -0
  22. package/dist/docs-plugin/shiki/shiki-transformer-preview-block.d.ts +7 -0
  23. package/dist/docs-plugin/shiki/shiki-transformer-preview-block.d.ts.map +1 -0
  24. package/dist/docs-plugin/shiki/utils.d.ts +2 -0
  25. package/dist/docs-plugin/shiki/utils.d.ts.map +1 -0
  26. package/dist/index.js +204 -671
  27. package/dist/index.js.map +4 -4
  28. package/dist/open-web-ui-knowledge/generate-knowledge.d.ts.map +1 -1
  29. package/dist/react-demo-plugin/demo-plugin-utils.d.ts +0 -21
  30. package/dist/react-demo-plugin/demo-plugin-utils.d.ts.map +1 -1
  31. package/dist/react-demo-plugin/react-demo-plugin.d.ts +5 -1
  32. package/dist/react-demo-plugin/react-demo-plugin.d.ts.map +1 -1
  33. package/dist/react-demo-plugin/virtual.d.ts +0 -12
  34. package/dist/tsbuildinfo +1 -1
  35. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1486,12 +1486,15 @@ var MarkdownFileReader = class {
1486
1486
  reset() {
1487
1487
  this.cachedFileCount = 0;
1488
1488
  }
1489
- checkCache(filepath, fileContents) {
1489
+ readCache(filePath) {
1490
+ return this.mdxCache[filePath] || null;
1491
+ }
1492
+ checkCache(filePath, fileContents) {
1490
1493
  if (!this.enabled) {
1491
1494
  return;
1492
1495
  }
1493
1496
  const fileMd5 = this.hash(fileContents);
1494
- const cached = this.mdxCache[filepath];
1497
+ const cached = this.mdxCache[filePath];
1495
1498
  if (cached?.md5 !== fileMd5) {
1496
1499
  return;
1497
1500
  }
@@ -2012,9 +2015,9 @@ function getRouteMeta(pathSegments, metaJson) {
2012
2015
  }
2013
2016
 
2014
2017
  // src/docs-plugin/internal/services/nav-builder/nav-builder.ts
2015
- import { capitalCase } from "change-case";
2016
2018
  import { sortBy } from "lodash-es";
2017
2019
  import { v4 as uuidv4 } from "uuid";
2020
+ import { capitalCase } from "@qualcomm-ui/utils/change-case";
2018
2021
  var NavBuilder = class {
2019
2022
  initialRoutes = [];
2020
2023
  flatNavItems = [];
@@ -2299,8 +2302,8 @@ var NavBuilder = class {
2299
2302
  };
2300
2303
 
2301
2304
  // src/docs-plugin/internal/services/nav-builder/page-map.ts
2302
- import { capitalCase as capitalCase2 } from "change-case";
2303
2305
  import { join as join2 } from "node:path";
2306
+ import { capitalCase as capitalCase2 } from "@qualcomm-ui/utils/change-case";
2304
2307
  function getPathnameFromPathSegments(segments) {
2305
2308
  return `/${segments.join("/")}`;
2306
2309
  }
@@ -2570,11 +2573,25 @@ var SearchIndexer = class {
2570
2573
  * Parses an MDX file to extract the site data for the nav items, doc props,
2571
2574
  * breadcrumbs, and search index.
2572
2575
  */
2573
- compileMdxFile(filepath) {
2574
- const { cached, fileContents, frontmatter } = this.fileCache.readFile(filepath);
2576
+ compileMdxFile(filePath) {
2577
+ const { cached, fileContents, frontmatter } = this.fileCache.readFile(filePath);
2578
+ const metadata = {
2579
+ changed: {},
2580
+ filePath
2581
+ };
2582
+ if (!cached) {
2583
+ const previousData = this.fileCache.readCache(filePath);
2584
+ if (previousData) {
2585
+ const cachedFm = JSON.stringify(previousData.frontmatter);
2586
+ const currentFm = JSON.stringify(frontmatter);
2587
+ if (cachedFm !== currentFm) {
2588
+ metadata.changed.frontmatter = true;
2589
+ }
2590
+ }
2591
+ }
2575
2592
  this.docPropsIndexer.reset();
2576
2593
  this.markdownIndexer.reset();
2577
- const defaultSection = this.getPageEntry(filepath, frontmatter);
2594
+ const defaultSection = this.getPageEntry(filePath, frontmatter);
2578
2595
  if (!defaultSection.categories.length && defaultSection.title) {
2579
2596
  defaultSection.categories = [defaultSection.title];
2580
2597
  }
@@ -2589,9 +2606,9 @@ var SearchIndexer = class {
2589
2606
  console.debug(
2590
2607
  `${chalk3.yellowBright.bold(
2591
2608
  "Failed to parse mdx page content."
2592
- )} ${chalk3.blueBright.bold(filepath)}`
2609
+ )} ${chalk3.blueBright.bold(filePath)}`
2593
2610
  );
2594
- return [defaultSection];
2611
+ return { metadata, pageSections: [defaultSection] };
2595
2612
  }
2596
2613
  const { sections, toc } = indexedPage;
2597
2614
  if (toc.length) {
@@ -2606,17 +2623,17 @@ var SearchIndexer = class {
2606
2623
  if (docPropSections.length) {
2607
2624
  this._pageDocProps[defaultSection.pathname] = docProps;
2608
2625
  }
2609
- this.fileCache.updateCache(filepath, fileContents, {
2626
+ this.fileCache.updateCache(filePath, fileContents, {
2610
2627
  frontmatter,
2611
2628
  page: indexedPage,
2612
2629
  pageDocProps: docProps,
2613
2630
  pageDocPropSections: docPropSections
2614
2631
  });
2615
2632
  if (frontmatter.hideFromSearch) {
2616
- return [defaultSection];
2633
+ return { metadata, pageSections: [defaultSection] };
2617
2634
  }
2618
2635
  if (!sections.length && !docPropSections.length) {
2619
- return [defaultSection];
2636
+ return { metadata, pageSections: [defaultSection] };
2620
2637
  }
2621
2638
  const sectionReturn = [
2622
2639
  ...this.formatSections(sections, defaultSection, false)
@@ -2626,7 +2643,7 @@ var SearchIndexer = class {
2626
2643
  ...this.formatSections(docPropSections, defaultSection, true)
2627
2644
  );
2628
2645
  }
2629
- return sectionReturn;
2646
+ return { metadata, pageSections: sectionReturn };
2630
2647
  }
2631
2648
  formatSections(sections, { toc: _toc, ...defaultSection }, isDocProp) {
2632
2649
  return sections.map((section, index) => {
@@ -2671,7 +2688,8 @@ var SearchIndexer = class {
2671
2688
  this.config.routingStrategy
2672
2689
  );
2673
2690
  this._mdxFileCount = mdxFileGlob.length;
2674
- const mdxIndex = mdxFileGlob.map((file) => this.compileMdxFile(file)).flat();
2691
+ const compiledFiles = mdxFileGlob.map((file) => this.compileMdxFile(file));
2692
+ const mdxIndex = compiledFiles.map((fileData) => fileData.pageSections).flat();
2675
2693
  filterFileGlob(
2676
2694
  fileGlob,
2677
2695
  "tsx",
@@ -2680,11 +2698,13 @@ var SearchIndexer = class {
2680
2698
  ).map((file) => this.compileTsxFile(file));
2681
2699
  this._searchIndex.push(...mdxIndex.filter((entry) => !entry.hideFromSearch));
2682
2700
  this.navBuilder.build();
2701
+ return compiledFiles;
2683
2702
  }
2684
2703
  };
2685
2704
 
2686
2705
  // src/docs-plugin/docs-plugin.ts
2687
2706
  var isDev = process.env.NODE_ENV === "development";
2707
+ var VIRTUAL_MODULE_ID2 = "\0@qualcomm-ui/mdx-vite-plugin";
2688
2708
  var PluginState = class {
2689
2709
  buildCount = 0;
2690
2710
  configFilePath = "";
@@ -2695,12 +2715,7 @@ var PluginState = class {
2695
2715
  servers = [];
2696
2716
  timeout = void 0;
2697
2717
  watching = false;
2698
- resolvedVirtualModuleId;
2699
- virtualModuleId = "@qualcomm-ui/mdx-vite-plugin";
2700
2718
  cwd;
2701
- constructor() {
2702
- this.resolvedVirtualModuleId = `\0${this.virtualModuleId}`;
2703
- }
2704
2719
  init(cwd) {
2705
2720
  this.cwd = cwd;
2706
2721
  }
@@ -2713,6 +2728,14 @@ var PluginState = class {
2713
2728
  this.docPropsFilePath.lastIndexOf("/")
2714
2729
  );
2715
2730
  }
2731
+ get siteData() {
2732
+ return {
2733
+ navItems: state.indexer.navItems,
2734
+ pageDocProps: state.indexer.pageDocProps,
2735
+ pageMap: state.indexer.pageMap,
2736
+ searchIndex: state.indexer.searchIndex
2737
+ };
2738
+ }
2716
2739
  resolveDocProps() {
2717
2740
  if (!this.docPropsFilePath) {
2718
2741
  return {};
@@ -2745,38 +2768,37 @@ var PluginState = class {
2745
2768
  }
2746
2769
  );
2747
2770
  if (!files.length) {
2748
- return;
2771
+ return [];
2749
2772
  }
2750
2773
  const startTime = Date.now();
2751
- this.indexer.buildIndex(files, shouldLog);
2774
+ const compiledMdxFiles = this.indexer.buildIndex(files, shouldLog);
2752
2775
  if (isDev && shouldLog) {
2753
2776
  console.debug(
2754
2777
  `${chalk4.magenta.bold(`@qualcomm-ui/mdx-vite/docs-plugin:`)} Compiled search index in: ${chalk4.blueBright.bold(prettyMilliseconds(Date.now() - startTime))}${state.indexer.cachedFileCount ? chalk4.greenBright.bold(` (${state.indexer.cachedFileCount}/${state.indexer.mdxFileCount} files cached)`) : ""}`
2755
2778
  );
2756
2779
  }
2780
+ return compiledMdxFiles;
2757
2781
  }
2758
2782
  /**
2759
- * When the user edits MDX content or modifies the plugin config, we re-index the
2760
- * site. This function handles module invalidation so that virtual file imports
2761
- * are refreshed as expected by the consumer's dev server.
2783
+ * When the user adds or removes mdx files, we re-index the site. This function
2784
+ * handles module invalidation so that virtual file imports are refreshed as
2785
+ * expected by the consumer's dev server.
2762
2786
  */
2763
2787
  sendUpdate() {
2764
2788
  for (const server of this.servers) {
2765
- const virtualModule = server.moduleGraph.getModuleById(
2766
- this.resolvedVirtualModuleId
2767
- );
2789
+ const virtualModule = server.moduleGraph.getModuleById(VIRTUAL_MODULE_ID2);
2768
2790
  if (virtualModule) {
2769
2791
  server.moduleGraph.invalidateModule(virtualModule);
2770
2792
  server.reloadModule(virtualModule);
2771
2793
  }
2772
2794
  }
2773
2795
  }
2774
- handleChange(callback) {
2796
+ handleChange(opts = {}) {
2775
2797
  clearTimeout(this.timeout);
2776
2798
  this.timeout = setTimeout(() => {
2777
2799
  this.buildIndex(true);
2778
2800
  this.sendUpdate();
2779
- callback?.();
2801
+ opts?.onComplete?.();
2780
2802
  }, 300);
2781
2803
  }
2782
2804
  initWatchers(configFile) {
@@ -2799,7 +2821,13 @@ var PluginState = class {
2799
2821
  const resolvedConfig = this.configLoader.loadConfig();
2800
2822
  this.configFilePath = resolvedConfig.filePath;
2801
2823
  this.createIndexer(resolvedConfig);
2802
- this.handleChange();
2824
+ this.handleChange({
2825
+ onComplete: () => {
2826
+ this.servers.forEach(
2827
+ (server) => server.ws.send({ type: "full-reload" })
2828
+ );
2829
+ }
2830
+ });
2803
2831
  });
2804
2832
  }
2805
2833
  };
@@ -2810,6 +2838,9 @@ function quiDocsPlugin(opts) {
2810
2838
  const config = configLoader.loadConfig();
2811
2839
  state.createIndexer(config);
2812
2840
  return {
2841
+ apply(config2, env) {
2842
+ return env.mode === "development" && env.command === "serve" || env.mode === "production" && env.command === "build";
2843
+ },
2813
2844
  buildStart: async () => {
2814
2845
  state.buildIndex(state.buildCount > 0);
2815
2846
  state.buildCount++;
@@ -2821,41 +2852,70 @@ function quiDocsPlugin(opts) {
2821
2852
  state.initWatchers(opts?.configFile);
2822
2853
  server.watcher.on("add", (path) => {
2823
2854
  if (path.endsWith(".mdx")) {
2824
- state.handleChange(() => {
2825
- server.ws.send({ type: "full-reload" });
2855
+ state.handleChange({
2856
+ onComplete: () => {
2857
+ server.ws.send({ type: "full-reload" });
2858
+ }
2826
2859
  });
2827
2860
  }
2828
2861
  });
2829
2862
  server.watcher.on("unlink", (path) => {
2830
2863
  if (path.endsWith(".mdx")) {
2831
- state.handleChange(() => {
2832
- server.ws.send({ type: "full-reload" });
2864
+ state.handleChange({
2865
+ onComplete: () => {
2866
+ server.ws.send({ type: "full-reload" });
2867
+ }
2833
2868
  });
2834
2869
  }
2835
2870
  });
2836
2871
  state.servers.push(server);
2837
2872
  },
2838
- handleHotUpdate: async ({ file: updateFile }) => {
2873
+ handleHotUpdate: async ({ file: updateFile, server }) => {
2839
2874
  const file = fixPath(updateFile);
2840
2875
  if ((!config.hotUpdateIgnore || !config.hotUpdateIgnore.test(file)) && // ignore watched files. We watch for these separately.
2841
2876
  file !== state.configFilePath) {
2842
2877
  if (state.docPropsDirectory && file.startsWith(state.docPropsFilePath)) {
2843
2878
  return [];
2844
2879
  }
2845
- state.handleChange();
2880
+ if (updateFile.endsWith(".mdx")) {
2881
+ const mods = [];
2882
+ const files = state.buildIndex(true);
2883
+ const moduleByFile = server.moduleGraph.getModulesByFile(updateFile);
2884
+ if (!moduleByFile?.size) {
2885
+ console.debug("no module found for file, returning", updateFile);
2886
+ return [];
2887
+ }
2888
+ const virtualModule = server.moduleGraph.getModuleById(VIRTUAL_MODULE_ID2);
2889
+ if (virtualModule) {
2890
+ server.moduleGraph.invalidateModule(virtualModule);
2891
+ server.ws.send({
2892
+ data: state.siteData,
2893
+ event: "qui-docs-plugin:refresh-site-data",
2894
+ type: "custom"
2895
+ });
2896
+ }
2897
+ if (files.some((file2) => file2.metadata.changed.frontmatter)) {
2898
+ console.debug(
2899
+ "Frontmatter changed, reloading plugin to reflect changes in the page configuration"
2900
+ );
2901
+ server.ws.send({ type: "full-reload" });
2902
+ return [];
2903
+ }
2904
+ return mods;
2905
+ }
2846
2906
  }
2847
2907
  return [];
2848
2908
  },
2849
2909
  load: (id) => {
2850
- if (id === state.resolvedVirtualModuleId) {
2851
- return `export const siteData = ${JSON.stringify({ navItems: state.indexer.navItems, pageDocProps: state.indexer.pageDocProps, pageMap: state.indexer.pageMap, searchIndex: state.indexer.searchIndex })}`;
2910
+ if (id === VIRTUAL_MODULE_ID2) {
2911
+ return `export const siteData = ${JSON.stringify(state.siteData)}`;
2852
2912
  }
2853
2913
  return void 0;
2854
2914
  },
2855
2915
  name: "qui-mdx-vite-plugin",
2856
2916
  resolveId: (id) => {
2857
- if (id === state.virtualModuleId) {
2858
- return state.resolvedVirtualModuleId;
2917
+ if (id === "@qualcomm-ui/mdx-vite-plugin") {
2918
+ return VIRTUAL_MODULE_ID2;
2859
2919
  }
2860
2920
  return void 0;
2861
2921
  }
@@ -2864,6 +2924,16 @@ function quiDocsPlugin(opts) {
2864
2924
 
2865
2925
  // src/docs-plugin/mdx-plugins.ts
2866
2926
  import rehypeShiki from "@shikijs/rehype";
2927
+ import {
2928
+ transformerNotationDiff,
2929
+ transformerNotationErrorLevel,
2930
+ transformerNotationFocus,
2931
+ transformerNotationHighlight,
2932
+ transformerNotationWordHighlight,
2933
+ transformerRemoveNotationEscape,
2934
+ transformerRenderIndentGuides as transformerRenderIndentGuides2
2935
+ } from "@shikijs/transformers";
2936
+ import { merge } from "lodash-es";
2867
2937
  import { quiCustomDarkTheme as quiCustomDarkTheme2 } from "@qualcomm-ui/mdx-common";
2868
2938
 
2869
2939
  // src/exports.ts
@@ -3214,12 +3284,43 @@ var remarkSpoilers = (options = {}) => {
3214
3284
  };
3215
3285
  };
3216
3286
 
3287
+ // src/docs-plugin/shiki/utils.ts
3288
+ function removeCodeAnnotations(code) {
3289
+ const annotationRegex = /\/\/\s*\[!code\s*(?:\S.*)?\]/;
3290
+ return code.split("\n").map((line) => {
3291
+ return line.replace(/(?:\/\/\s*)?\[!code \+\+\]/, "");
3292
+ }).filter((line) => !annotationRegex.test(line)).join("\n");
3293
+ }
3294
+
3295
+ // src/docs-plugin/shiki/shiki-transformer-code-attribute.ts
3296
+ function transformerCodeAttribute(opts = {}) {
3297
+ return {
3298
+ enforce: "post",
3299
+ name: "shiki-transformer-code-attribute",
3300
+ pre(node) {
3301
+ const strippedSource = removeCodeAnnotations(this.source);
3302
+ node.properties[opts.attributeName ?? "data-code"] = opts.formatter?.(strippedSource) ?? strippedSource;
3303
+ }
3304
+ };
3305
+ }
3306
+
3217
3307
  // src/docs-plugin/mdx-plugins.ts
3218
3308
  var quiRehypePlugins = [rehypeSectionize, rehypeSlug];
3309
+ function getShikiTransformers() {
3310
+ return [
3311
+ transformerNotationDiff(),
3312
+ transformerNotationFocus(),
3313
+ transformerNotationHighlight(),
3314
+ transformerNotationWordHighlight(),
3315
+ transformerNotationErrorLevel(),
3316
+ transformerRenderIndentGuides2(),
3317
+ transformerRemoveNotationEscape()
3318
+ ];
3319
+ }
3219
3320
  function getRehypePlugins(options = {}) {
3220
3321
  const config = new ConfigLoader(options).loadConfig();
3221
3322
  return [
3222
- rehypeMdxCodeProps,
3323
+ [rehypeMdxCodeProps, { enforce: "pre" }],
3223
3324
  [
3224
3325
  rehypeSlug,
3225
3326
  { allowedHeadings: config.headings }
@@ -3227,14 +3328,17 @@ function getRehypePlugins(options = {}) {
3227
3328
  rehypeSectionize,
3228
3329
  [
3229
3330
  rehypeShiki,
3230
- {
3231
- defaultColor: "light-dark()",
3232
- themes: {
3233
- dark: quiCustomDarkTheme2,
3234
- light: "github-light-high-contrast"
3331
+ merge(
3332
+ {
3333
+ defaultColor: "light-dark()",
3334
+ themes: {
3335
+ dark: quiCustomDarkTheme2,
3336
+ light: "github-light-high-contrast"
3337
+ },
3338
+ transformers: [...getShikiTransformers(), transformerCodeAttribute()]
3235
3339
  },
3236
- ...options.rehypeShikiOptions
3237
- }
3340
+ options.rehypeShikiOptions
3341
+ )
3238
3342
  ]
3239
3343
  ];
3240
3344
  }
@@ -3285,7 +3389,6 @@ var NODE_BUILTINS = [
3285
3389
 
3286
3390
  // src/react-demo-plugin/demo-plugin-utils.ts
3287
3391
  import chalk5 from "chalk";
3288
- import { createHash as createHash2 } from "node:crypto";
3289
3392
  import { existsSync as existsSync2, readFileSync as readFileSync3 } from "node:fs";
3290
3393
  import { readFile as readFile2 } from "node:fs/promises";
3291
3394
  import { dirname as dirname2, join as join3, relative as relative2, resolve as resolve3, sep } from "node:path";
@@ -3314,21 +3417,6 @@ async function extractFileImports(filePath) {
3314
3417
  return null;
3315
3418
  }
3316
3419
  }
3317
- function mergeImports(importMap, imports) {
3318
- for (const { source, specifiers } of imports) {
3319
- if (isNodeBuiltin(source)) {
3320
- continue;
3321
- }
3322
- let sourceSpecifiers = importMap.get(source);
3323
- if (!sourceSpecifiers) {
3324
- sourceSpecifiers = /* @__PURE__ */ new Set();
3325
- importMap.set(source, sourceSpecifiers);
3326
- }
3327
- for (const spec of specifiers) {
3328
- sourceSpecifiers.add(spec);
3329
- }
3330
- }
3331
- }
3332
3420
  function extractImports(code, fileName) {
3333
3421
  const sourceFile = ts2.createSourceFile(
3334
3422
  fileName,
@@ -3442,18 +3530,6 @@ function resolveRelativeImport(source, fromFile) {
3442
3530
  }
3443
3531
  return resolved;
3444
3532
  }
3445
- async function extractAllImports(files) {
3446
- const importMap = /* @__PURE__ */ new Map();
3447
- const relativeImports = [];
3448
- for (const filePath of files) {
3449
- const result = await extractFileImports(filePath);
3450
- if (result) {
3451
- mergeImports(importMap, result.thirdPartyImports);
3452
- relativeImports.push(...result.relativeImports);
3453
- }
3454
- }
3455
- return { importMap, relativeImports };
3456
- }
3457
3533
  function isRelativeImport(source) {
3458
3534
  return source.startsWith("./") || source.startsWith("../");
3459
3535
  }
@@ -3588,90 +3664,6 @@ function resolvePathAlias2(source, pathAliases) {
3588
3664
  }
3589
3665
  return null;
3590
3666
  }
3591
- function sanitizeSourceName(source) {
3592
- return source.replace(/@/g, "at_").replace(/\//g, "_").replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
3593
- }
3594
- function sanitizeIdentifier(str) {
3595
- return str.replace(/[^a-zA-Z0-9]/g, "_");
3596
- }
3597
- function createUniqueModuleName(source) {
3598
- const hash = createHash2("sha256").update(source).digest("hex").substring(0, 8);
3599
- const baseName = source.split("/").pop()?.replace(/[^a-zA-Z0-9]/g, "_")?.replace(/^_+|_+$/g, "")?.replace(/^(\d)/, "_$1") || "module";
3600
- return `mod_${baseName}_${hash}`;
3601
- }
3602
- function addReactImports(imports, scopeEntries) {
3603
- imports.push(`import React from "react"`);
3604
- imports.push(`import {
3605
- ${REACT_IMPORTS.join(", ")}
3606
- } from "react"`);
3607
- scopeEntries.push("React", ...REACT_IMPORTS);
3608
- }
3609
- function addThirdPartyImports(importMap, imports, scopeEntries) {
3610
- const sortedImports = Array.from(importMap.entries()).sort(
3611
- ([a], [b]) => a.localeCompare(b)
3612
- );
3613
- const usedNames = /* @__PURE__ */ new Set(["React", ...REACT_IMPORTS]);
3614
- for (const [source, specifiers] of sortedImports) {
3615
- const moduleName = createUniqueModuleName(source);
3616
- imports.push(`import * as ${moduleName} from "${source}"`);
3617
- addModuleToScope(source, specifiers, moduleName, scopeEntries, usedNames);
3618
- }
3619
- }
3620
- function addThirdPartyImportsNamespaced(importMap, imports, scopeEntries, demoName) {
3621
- const sortedImports = Array.from(importMap.entries()).sort(
3622
- ([a], [b]) => a.localeCompare(b)
3623
- );
3624
- const usedNames = /* @__PURE__ */ new Set(["React", ...REACT_IMPORTS]);
3625
- for (const [source, specifiers] of sortedImports) {
3626
- const moduleName = `${sanitizeIdentifier(demoName)}_${createUniqueModuleName(source)}`;
3627
- imports.push(`import * as ${moduleName} from "${source}"`);
3628
- addModuleToScope(source, specifiers, moduleName, scopeEntries, usedNames);
3629
- }
3630
- }
3631
- function addRelativeImportsNamespaced(relativeImports, imports, scopeEntries, demoName) {
3632
- const processedPaths = /* @__PURE__ */ new Set();
3633
- for (const { resolvedPath, specifiers } of relativeImports) {
3634
- if (processedPaths.has(resolvedPath)) {
3635
- continue;
3636
- }
3637
- processedPaths.add(resolvedPath);
3638
- const moduleName = `${sanitizeIdentifier(demoName)}_${createUniqueModuleName(resolvedPath)}`;
3639
- imports.push(`import * as ${moduleName} from "${resolvedPath}"`);
3640
- for (const { imported, local } of specifiers) {
3641
- if (imported === "default") {
3642
- scopeEntries.push(`${local}: ${moduleName}.default`);
3643
- } else if (imported === "*") {
3644
- scopeEntries.push(`...${moduleName}`);
3645
- } else {
3646
- scopeEntries.push(`${local}: ${moduleName}.${imported}`);
3647
- }
3648
- }
3649
- }
3650
- }
3651
- function addModuleToScope(source, specifiers, moduleName, scopeEntries, usedNames) {
3652
- const specArray = Array.from(specifiers);
3653
- const hasDefault = specArray.some((spec) => spec.imported === "default");
3654
- const hasNamespace = specArray.some((spec) => spec.imported === "*");
3655
- const namedImports = specArray.filter(
3656
- (spec) => spec.imported !== "default" && spec.imported !== "*"
3657
- );
3658
- if (hasNamespace) {
3659
- scopeEntries.push(`...${moduleName}`);
3660
- return;
3661
- }
3662
- const sanitizedSource = sanitizeSourceName(source);
3663
- if (hasDefault) {
3664
- scopeEntries.push(`"${sanitizedSource}__default": ${moduleName}.default`);
3665
- }
3666
- for (const { imported, local } of namedImports) {
3667
- const sanitizedKey = `${sanitizedSource}__${imported}`;
3668
- scopeEntries.push(`"${sanitizedKey}": ${moduleName}.${imported}`);
3669
- if (!usedNames.has(local)) {
3670
- scopeEntries.push(`${local}: ${moduleName}.${imported}`);
3671
- usedNames.add(local);
3672
- }
3673
- }
3674
- }
3675
3667
  function extractPageId(filePath, routesDir) {
3676
3668
  const relativePath = relative2(routesDir, filePath);
3677
3669
  const pathParts = relativePath.split(sep);
@@ -3686,20 +3678,14 @@ function isCssAsset(filePath) {
3686
3678
  }
3687
3679
  function isDemoFile(filePath) {
3688
3680
  try {
3689
- return filePath.includes("/demos/") && filePath.endsWith(".tsx") && // could also be in a comment, probably need to use TS parser
3690
- readFileSync3(filePath, "utf-8").includes("export default");
3681
+ return filePath.includes("/demos/") && filePath.endsWith(".tsx") && !readFileSync3(filePath).includes("export default");
3691
3682
  } catch (error) {
3692
3683
  return false;
3693
3684
  }
3694
3685
  }
3695
- function createEmptyScopeModule() {
3696
- return "export const createDemoScope = () => ({})";
3697
- }
3698
3686
 
3699
3687
  // src/react-demo-plugin/react-demo-plugin.ts
3700
- import { transformerRenderIndentGuides as transformerRenderIndentGuides2 } from "@shikijs/transformers";
3701
3688
  import chalk6 from "chalk";
3702
- import { watch as watch2 } from "chokidar";
3703
3689
  import { glob as glob3 } from "glob";
3704
3690
  import { readFile as readFile3 } from "node:fs/promises";
3705
3691
  import { basename as basename2, resolve as resolve4 } from "node:path";
@@ -3707,27 +3693,13 @@ import { createHighlighter as createHighlighter2 } from "shiki";
3707
3693
  import * as ts3 from "typescript";
3708
3694
  import { quiCustomDarkTheme as quiCustomDarkTheme3 } from "@qualcomm-ui/mdx-common";
3709
3695
  import { dedent } from "@qualcomm-ui/utils/dedent";
3710
- import { debounce } from "@qualcomm-ui/utils/functions";
3711
- var isDev2 = process.env.NODE_ENV === "development";
3712
3696
  var highlighter2 = null;
3713
- var initCount2 = 0;
3714
- var hmrState = {
3715
- windowScrollY: 0
3716
- };
3697
+ var initializingHighlighter = false;
3717
3698
  var demoRegistry2 = /* @__PURE__ */ new Map();
3718
- var pageScopes = /* @__PURE__ */ new Map();
3719
3699
  var pageFiles = /* @__PURE__ */ new Map();
3720
3700
  var relativeImportDependents = /* @__PURE__ */ new Map();
3721
- var hasWatcherInitialized2 = false;
3722
- function logDev2(...args) {
3723
- if (!hasWatcherInitialized2) {
3724
- return;
3725
- }
3726
- console.log(...args);
3727
- }
3728
3701
  function reactDemoPlugin({
3729
3702
  demoPattern = "src/routes/**/demos/*.tsx",
3730
- lazyLoadDevModules = true,
3731
3703
  routesDir = "src/routes",
3732
3704
  theme = {
3733
3705
  dark: quiCustomDarkTheme3,
@@ -3736,25 +3708,19 @@ function reactDemoPlugin({
3736
3708
  transformers = [],
3737
3709
  transformLine
3738
3710
  } = {}) {
3739
- let watcher = null;
3740
3711
  return {
3741
- async buildEnd() {
3742
- if (watcher) {
3743
- await watcher.close();
3744
- watcher = null;
3745
- hasWatcherInitialized2 = false;
3746
- }
3712
+ apply(config, env) {
3713
+ return env.mode === "development" && env.command === "serve" || env.mode === "production" && env.command === "build";
3747
3714
  },
3748
3715
  async buildStart() {
3749
- if (initCount2 === 0) {
3750
- initCount2++;
3751
- return;
3752
- }
3753
- if (!highlighter2) {
3716
+ if (!highlighter2 && !initializingHighlighter) {
3717
+ initializingHighlighter = true;
3754
3718
  try {
3755
3719
  highlighter2 = await createHighlighter2({
3756
3720
  langs: ["tsx", "typescript"],
3757
3721
  themes: [theme.dark, theme.light]
3722
+ }).finally(() => {
3723
+ initializingHighlighter = false;
3758
3724
  });
3759
3725
  console.log(
3760
3726
  `${chalk6.magenta.bold(LOG_PREFIX2)} Shiki highlighter initialized`
@@ -3766,135 +3732,51 @@ function reactDemoPlugin({
3766
3732
  );
3767
3733
  }
3768
3734
  }
3769
- try {
3770
- await collectReactDemos();
3771
- if (isDev2 && !hasWatcherInitialized2) {
3772
- hasWatcherInitialized2 = true;
3773
- await setupFileWatcher();
3774
- } else if (isDev2) {
3775
- logDev2(
3776
- `${chalk6.magenta.bold(LOG_PREFIX2)} skipping watch: watcher already initialized by another instance`
3777
- );
3778
- }
3779
- } catch (error) {
3780
- if (watcher) {
3781
- await watcher.close();
3782
- watcher = null;
3783
- hasWatcherInitialized2 = false;
3784
- }
3785
- throw error;
3786
- }
3735
+ await collectReactDemos();
3787
3736
  },
3788
- configureServer(server) {
3789
- const debouncedRestore = debounce((data) => {
3790
- hmrState.windowScrollY = data.scrollY;
3791
- }, 100);
3792
- server.ws.on("custom:store-scroll-position", debouncedRestore);
3793
- server.ws.on("custom:request-scroll-position", () => {
3794
- server.ws.send({
3795
- data: hmrState.windowScrollY,
3796
- event: "custom:restore-scroll-position",
3797
- type: "custom"
3798
- });
3799
- });
3800
- },
3801
- async handleHotUpdate({ file, server }) {
3737
+ async handleHotUpdate({ file, modules, server }) {
3802
3738
  if (isCssAsset(file)) {
3803
- return server.moduleGraph.getModulesByFile(file)?.values()?.toArray();
3739
+ return modules;
3804
3740
  }
3805
- if (!lazyLoadDevModules) {
3806
- let shouldUpdate = false;
3807
- if (isDemoFile(file)) {
3808
- await handleFileAdditionOrUpdate(file, false);
3809
- shouldUpdate = true;
3810
- }
3811
- const normalizedFile = resolve4(file);
3812
- const dependents = relativeImportDependents.get(normalizedFile);
3813
- if (dependents) {
3814
- shouldUpdate = true;
3815
- }
3816
- if (shouldUpdate) {
3817
- const autoModule = server.moduleGraph.getModuleById(
3818
- VIRTUAL_MODULE_IDS.AUTO
3819
- );
3820
- if (autoModule) {
3821
- server.moduleGraph.invalidateModule(autoModule);
3822
- await server.reloadModule(autoModule);
3823
- }
3824
- return [];
3825
- }
3741
+ if (file.endsWith(".mdx")) {
3742
+ return [];
3826
3743
  }
3827
3744
  if (isDemoFile(file)) {
3828
- logDev2(
3829
- `${chalk6.magenta.bold(LOG_PREFIX2)} Processing change: ${chalk6.blueBright.bold(file)}`
3830
- );
3831
- const pageId = extractPageId(file, routesDir);
3832
- const demoName = createDemoName(file);
3833
- const wasNew = !demoRegistry2.has(demoName);
3834
- await handleFileAdditionOrUpdate(file, false);
3835
- const pageModule = server.moduleGraph.getModuleById(
3836
- `${VIRTUAL_MODULE_IDS.PAGE_PREFIX}${pageId}`
3837
- );
3838
- if (pageModule) {
3839
- console.debug(
3840
- "invalidating:",
3841
- `virtual:qui-demo-scope/page:${pageId}`
3842
- );
3843
- server.moduleGraph.invalidateModule(pageModule);
3844
- await server.reloadModule(pageModule);
3845
- }
3846
- if (wasNew) {
3847
- const autoModule = server.moduleGraph.getModuleById(
3848
- VIRTUAL_MODULE_IDS.AUTO
3849
- );
3850
- if (autoModule) {
3851
- server.moduleGraph.invalidateModule(autoModule);
3852
- await server.reloadModule(autoModule);
3853
- }
3854
- }
3855
- server.ws.send({
3856
- data: demoRegistry2.get(createDemoName(file)),
3857
- event: "qui-demo-update",
3858
- type: "custom"
3859
- });
3745
+ await handleDemoAdditionOrUpdate({ filePath: file });
3860
3746
  } else {
3861
3747
  const normalizedFile = resolve4(file);
3862
- const dependents = relativeImportDependents.get(normalizedFile);
3863
- if (dependents) {
3864
- for (const demoName of dependents) {
3865
- server.ws.send({
3866
- data: { demoName },
3867
- event: "react-demo-updating",
3868
- type: "custom"
3748
+ const dependentDemos = relativeImportDependents.get(normalizedFile);
3749
+ if (!dependentDemos?.size) {
3750
+ return [];
3751
+ }
3752
+ for (const demoName of Array.from(dependentDemos)) {
3753
+ const demo = demoRegistry2.get(demoName);
3754
+ if (demo) {
3755
+ await handleDemoAdditionOrUpdate({
3756
+ filePath: demo.filePath
3869
3757
  });
3870
3758
  }
3871
3759
  }
3872
3760
  }
3761
+ const autoModule = server.moduleGraph.getModuleById(
3762
+ VIRTUAL_MODULE_IDS.AUTO
3763
+ );
3764
+ if (autoModule) {
3765
+ server.moduleGraph.invalidateModule(autoModule);
3766
+ await server.reloadModule(autoModule);
3767
+ }
3873
3768
  return [];
3874
3769
  },
3875
3770
  async load(id) {
3876
3771
  if (id === VIRTUAL_MODULE_IDS.AUTO) {
3877
3772
  return generateAutoScopeModule();
3878
3773
  }
3879
- if (id.startsWith(VIRTUAL_MODULE_IDS.PAGE_PREFIX)) {
3880
- const pageId = id.replace(VIRTUAL_MODULE_IDS.PAGE_PREFIX, "");
3881
- return pageScopes.get(pageId) || createEmptyScopeModule();
3882
- }
3883
- if (id === VIRTUAL_MODULE_IDS.CONFIG) {
3884
- return generateConfigModule();
3885
- }
3886
3774
  },
3887
3775
  name: "auto-demo-scope",
3888
3776
  resolveId(id) {
3889
3777
  if (id === "virtual:qui-demo-scope/auto") {
3890
3778
  return VIRTUAL_MODULE_IDS.AUTO;
3891
3779
  }
3892
- if (id.startsWith("virtual:qui-demo-scope/page:")) {
3893
- return `\0${id}`;
3894
- }
3895
- if (id === "virtual:qui-demo-scope/config") {
3896
- return VIRTUAL_MODULE_IDS.CONFIG;
3897
- }
3898
3780
  },
3899
3781
  writeBundle() {
3900
3782
  console.log(
@@ -3902,43 +3784,9 @@ function reactDemoPlugin({
3902
3784
  );
3903
3785
  }
3904
3786
  };
3905
- async function setupFileWatcher() {
3906
- watcher = watch2(routesDir, {
3907
- ignoreInitial: true,
3908
- persistent: true
3909
- });
3910
- watcher.on("ready", () => {
3911
- logDev2(
3912
- `${chalk6.blue.bold(LOG_PREFIX2)} Registered ${chalk6.green(demoRegistry2.size)} demo files. Watching for file changes...`
3913
- );
3914
- });
3915
- watcher.on("addDir", (dirPath) => {
3916
- if (dirPath.endsWith("/demos")) {
3917
- logDev2(
3918
- `${chalk6.magenta.bold(LOG_PREFIX2)} ${chalk6.greenBright("New demo directory detected:")} ${chalk6.blueBright.bold(dirPath)}`
3919
- );
3920
- }
3921
- });
3922
- watcher.on("unlink", async (filePath) => {
3923
- if (isDemoFile(filePath)) {
3924
- logDev2(
3925
- `${chalk6.magenta.bold(LOG_PREFIX2)} ${chalk6.redBright("Demo file deleted:")} ${chalk6.blueBright.bold(filePath)}`
3926
- );
3927
- await handleFileDeletion(filePath);
3928
- }
3929
- });
3930
- watcher.on("add", async (filePath) => {
3931
- if (isDemoFile(filePath)) {
3932
- logDev2(
3933
- `${chalk6.magenta.bold(LOG_PREFIX2)} ${chalk6.greenBright("Demo file added:")} ${chalk6.blueBright.bold(filePath)}`
3934
- );
3935
- await handleFileAdditionOrUpdate(filePath, true).catch(() => {
3936
- console.debug("failed to add file", filePath);
3937
- });
3938
- }
3939
- });
3940
- }
3941
- async function handleFileAdditionOrUpdate(filePath, isAdd) {
3787
+ async function handleDemoAdditionOrUpdate({
3788
+ filePath
3789
+ }) {
3942
3790
  const pageId = extractPageId(filePath, routesDir);
3943
3791
  const demoName = createDemoName(filePath);
3944
3792
  const existingFiles = pageFiles.get(pageId) ?? [];
@@ -3962,43 +3810,6 @@ function reactDemoPlugin({
3962
3810
  }
3963
3811
  }
3964
3812
  }
3965
- const previousScope = pageScopes.get(pageId);
3966
- const allPageFiles = pageFiles.get(pageId);
3967
- const scope = await generateScopeForPage(pageId, allPageFiles);
3968
- pageScopes.set(pageId, scope);
3969
- logDev2(
3970
- `${chalk6.magenta.bold(LOG_PREFIX2)} ${chalk6.greenBright(isAdd ? "Added demo:" : "Updated demo:")} ${chalk6.greenBright.bold(demoName)}`
3971
- );
3972
- return previousScope !== scope;
3973
- }
3974
- async function handleFileDeletion(deletedFile) {
3975
- const demoName = createDemoName(deletedFile);
3976
- const pageId = extractPageId(deletedFile, routesDir);
3977
- demoRegistry2.delete(demoName);
3978
- for (const [importPath, dependents] of relativeImportDependents.entries()) {
3979
- dependents.delete(demoName);
3980
- if (dependents.size === 0) {
3981
- relativeImportDependents.delete(importPath);
3982
- }
3983
- }
3984
- const files = pageFiles.get(pageId);
3985
- if (files) {
3986
- const updatedFiles = files.filter((f) => f !== deletedFile);
3987
- if (updatedFiles.length === 0) {
3988
- pageFiles.delete(pageId);
3989
- pageScopes.delete(pageId);
3990
- logDev2(
3991
- `${chalk6.magenta.bold(LOG_PREFIX2)} ${chalk6.redBright("Removed empty page:")} ${chalk6.blueBright.bold(pageId)}`
3992
- );
3993
- } else {
3994
- pageFiles.set(pageId, updatedFiles);
3995
- const scope = await generateScopeForPage(pageId, updatedFiles);
3996
- pageScopes.set(pageId, scope);
3997
- }
3998
- }
3999
- logDev2(
4000
- `${chalk6.magenta.bold(LOG_PREFIX2)} ${chalk6.redBright("Cleaned up deleted file:")} ${chalk6.blueBright.bold(deletedFile)}`
4001
- );
4002
3813
  }
4003
3814
  function isPreviewLine(trimmedLine) {
4004
3815
  return trimmedLine === "// preview" || /^\{\s*\/\*\s*preview\s*\*\/\s*\}$/.test(trimmedLine);
@@ -4048,7 +3859,17 @@ function reactDemoPlugin({
4048
3859
  dark: theme.dark,
4049
3860
  light: theme.light
4050
3861
  },
4051
- transformers: [transformerRenderIndentGuides2(), ...transformers]
3862
+ transformers: [
3863
+ ...getShikiTransformers(),
3864
+ {
3865
+ enforce: "post",
3866
+ name: "shiki-transformer-trim",
3867
+ preprocess(code2) {
3868
+ return code2.trim();
3869
+ }
3870
+ },
3871
+ ...transformers
3872
+ ]
4052
3873
  });
4053
3874
  } catch (error) {
4054
3875
  console.warn(
@@ -4059,10 +3880,7 @@ function reactDemoPlugin({
4059
3880
  }
4060
3881
  }
4061
3882
  async function collectReactDemos() {
4062
- if (demoRegistry2.size && pageScopes.size && pageFiles.size) {
4063
- logDev2(
4064
- `${chalk6.magenta.bold(LOG_PREFIX2)} Using cached ${chalk6.cyanBright.bold(demoRegistry2.size)} demos`
4065
- );
3883
+ if (demoRegistry2.size) {
4066
3884
  return;
4067
3885
  }
4068
3886
  const demoFiles = (await glob3(demoPattern)).filter(isDemoFile);
@@ -4089,243 +3907,15 @@ function reactDemoPlugin({
4089
3907
  }
4090
3908
  }
4091
3909
  }
4092
- for (const [pageId, files] of pageFiles.entries()) {
4093
- const scope = await generateScopeForPage(pageId, files);
4094
- pageScopes.set(pageId, scope);
4095
- }
4096
3910
  }
4097
- async function generateScopeForPage(pageId, files) {
4098
- const demosData = [];
4099
- const allThirdPartyImports = /* @__PURE__ */ new Map();
4100
- const allRelativeImports = [];
4101
- const demoImportData = /* @__PURE__ */ new Map();
4102
- for (const file of files) {
4103
- const demoName = createDemoName(file);
4104
- const demo = demoRegistry2.get(demoName);
4105
- if (!demo) {
4106
- continue;
4107
- }
4108
- demosData.push({
4109
- demoName,
4110
- fileName: demo.fileName,
4111
- imports: demo.imports,
4112
- pageId: demo.pageId,
4113
- sourceCode: demo.sourceCode
4114
- });
4115
- const { importMap, relativeImports } = await extractAllImports([file]);
4116
- demoImportData.set(demoName, {
4117
- relative: relativeImports.map((r) => ({
4118
- resolvedPath: r.resolvedPath,
4119
- specifiers: r.specifiers
4120
- })),
4121
- thirdParty: Array.from(importMap.entries()).map(([source, specs]) => ({
4122
- source,
4123
- specifiers: Array.from(specs)
4124
- }))
4125
- });
4126
- for (const [source, specifiers] of importMap) {
4127
- if (!allThirdPartyImports.has(source)) {
4128
- allThirdPartyImports.set(source, /* @__PURE__ */ new Set());
4129
- }
4130
- for (const spec of specifiers) {
4131
- allThirdPartyImports.get(source).add(spec);
4132
- }
4133
- }
4134
- for (const relImport of relativeImports) {
4135
- if (!allRelativeImports.some(
4136
- (r) => r.resolvedPath === relImport.resolvedPath
4137
- )) {
4138
- allRelativeImports.push(relImport);
4139
- }
4140
- }
4141
- }
4142
- const pageImports = [];
4143
- const reactScopeEntries = [];
4144
- addReactImports(pageImports, reactScopeEntries);
4145
- const moduleNames = /* @__PURE__ */ new Map();
4146
- const moduleRegistryEntries = [];
4147
- for (const [source] of Array.from(allThirdPartyImports.entries()).sort(
4148
- ([a], [b]) => a.localeCompare(b)
4149
- )) {
4150
- const moduleName = createUniqueModuleName(source);
4151
- moduleNames.set(source, moduleName);
4152
- pageImports.push(`import * as ${moduleName} from "${source}"`);
4153
- moduleRegistryEntries.push(` "${source}": ${moduleName}`);
4154
- }
4155
- for (const { resolvedPath } of allRelativeImports) {
4156
- const moduleName = createUniqueModuleName(resolvedPath);
4157
- moduleNames.set(resolvedPath, moduleName);
4158
- pageImports.push(`import * as ${moduleName} from "${resolvedPath}"`);
4159
- moduleRegistryEntries.push(` "${resolvedPath}": ${moduleName}`);
4160
- }
4161
- const demosJson = JSON.stringify(demosData);
4162
- const demoImportDataJson = JSON.stringify(
4163
- Array.from(demoImportData.entries())
4164
- );
4165
- const reactScopeEntriesCode = reactScopeEntries.map((e) => ` ${e}`).join(",\n");
4166
- return `// Auto-generated page scope for ${pageId}
4167
- ${pageImports.join("\n")}
4168
-
4169
- const modules = {
4170
- ${moduleRegistryEntries.join(",\n")}
4171
- }
4172
-
4173
- const demosData = ${demosJson}
4174
- const demoImportData = new Map(${demoImportDataJson})
4175
-
4176
- const reactScope = {
4177
- ${reactScopeEntriesCode}
4178
- }
4179
-
4180
- const scopeCache = new Map()
4181
-
4182
- function createScope(demoName) {
4183
- if (scopeCache.has(demoName)) {
4184
- return scopeCache.get(demoName)
4185
- }
4186
-
4187
- const imports = demoImportData.get(demoName)
4188
- if (!imports) return {}
4189
-
4190
- const scope = {...reactScope}
4191
-
4192
- for (const {source, specifiers} of imports.thirdParty) {
4193
- const mod = modules[source]
4194
- if (!mod) continue
4195
-
4196
- for (const {imported, local} of specifiers) {
4197
- if (imported === 'default') {
4198
- scope[local] = mod.default
4199
- } else if (imported === '*') {
4200
- Object.assign(scope, mod)
4201
- } else {
4202
- scope[local] = mod[imported]
4203
- }
4204
- }
4205
- }
4206
-
4207
- for (const {resolvedPath, specifiers} of imports.relative) {
4208
- const mod = modules[resolvedPath]
4209
- if (!mod) continue
4210
-
4211
- for (const {imported, local} of specifiers) {
4212
- if (imported === 'default') {
4213
- scope[local] = mod.default
4214
- } else if (imported === '*') {
4215
- Object.assign(scope, mod)
4216
- } else {
4217
- scope[local] = mod[imported]
4218
- }
4219
- }
4220
- }
4221
-
4222
- scopeCache.set(demoName, scope)
4223
- return scope
4224
- }
4225
-
4226
- export function getDemo(demoName) {
4227
- const demo = demosData.find(d => d.demoName === demoName)
4228
- if (!demo) return null
4229
- return {
4230
- ...demo,
4231
- scope: createScope(demoName)
4232
- }
4233
- }
4234
-
4235
- export function getDemos() {
4236
- return demosData.map(demo => ({
4237
- ...demo,
4238
- scope: createScope(demo.demoName)
4239
- }))
4240
- }
4241
- `;
4242
- }
4243
- async function generateAutoScopeModule() {
4244
- if (isDev2 && lazyLoadDevModules) {
4245
- return [
4246
- "// Auto-generated demo scope resolver (DEV MODE - Lazy by Page)",
4247
- generateLazyPageLoaders(),
4248
- generateDemoToPageMap(),
4249
- generateDevGetDemo()
4250
- ].join("\n\n");
4251
- }
3911
+ function generateAutoScopeModule() {
4252
3912
  const registryCode = generateDemoRegistry(demoRegistry2);
4253
3913
  return [
4254
3914
  "// Auto-generated demo scope resolver (PROD MODE)",
4255
- generatePageImports(),
4256
- generateScopeMap(),
4257
3915
  registryCode,
4258
3916
  generateExportedFunctions()
4259
3917
  ].join("\n\n");
4260
3918
  }
4261
- function generateConfigModule() {
4262
- return dedent`
4263
- export function getReactDemoConfig() {
4264
- return {lazyLoadDevModules: ${lazyLoadDevModules}}
4265
- }
4266
- `;
4267
- }
4268
- function generateLazyPageLoaders() {
4269
- const pageIds = Array.from(pageFiles.keys()).sort();
4270
- if (pageIds.length === 0) {
4271
- return "export const lazyDemoLoader = {}";
4272
- }
4273
- const entries = pageIds.map((pageId) => {
4274
- return ` "${pageId}": () => import("virtual:qui-demo-scope/page:${pageId}")`;
4275
- }).join(",\n");
4276
- return `export const lazyDemoLoader = {
4277
- ${entries}
4278
- }`;
4279
- }
4280
- function generateDemoToPageMap() {
4281
- const entries = Array.from(demoRegistry2.entries()).map(([demoName, { pageId }]) => {
4282
- return ` "${demoName}": "${pageId}"`;
4283
- }).join(",\n");
4284
- return `const demoToPageMap = {
4285
- ${entries}
4286
- }`;
4287
- }
4288
- function generateDevGetDemo() {
4289
- return dedent`
4290
- export async function getDemo(demoName) {
4291
- const pageId = demoToPageMap[demoName]
4292
- if (!pageId) {
4293
- return {
4294
- fileName: "",
4295
- imports: [],
4296
- errorMessage: \`Demo "\${demoName}" not found.\`,
4297
- scope: {},
4298
- pageId: "",
4299
- sourceCode: [],
4300
- }
4301
- }
4302
-
4303
- const loader = lazyDemoLoader[pageId]
4304
- if (!loader) {
4305
- return {
4306
- fileName: "",
4307
- imports: [],
4308
- errorMessage: \`Page "\${pageId}" not found.\`,
4309
- scope: {},
4310
- pageId: "",
4311
- sourceCode: [],
4312
- }
4313
- }
4314
-
4315
- const pageModule = await loader()
4316
- const demo = pageModule.getDemo(demoName)
4317
-
4318
- return demo || {
4319
- fileName: "",
4320
- imports: [],
4321
- errorMessage: \`Demo "\${demoName}" not found in page.\`,
4322
- scope: {},
4323
- pageId: "",
4324
- sourceCode: [],
4325
- }
4326
- }
4327
- `;
4328
- }
4329
3919
  function extractHighlightedVariants(highlightedHtml) {
4330
3920
  const preMatch = highlightedHtml.match(/^<pre[^>]*><code>/)?.[0] || "";
4331
3921
  const postMatch = highlightedHtml.match(/<\/code><\/pre>$/)?.[0] || "";
@@ -4454,23 +4044,18 @@ ${entries}
4454
4044
  withoutImports: importedCodeWithoutImports
4455
4045
  }
4456
4046
  });
4457
- } catch (error) {
4458
- logDev2(
4459
- `${chalk6.magenta.bold(LOG_PREFIX2)} ${chalk6.yellowBright("Failed to process relative import:")} ${chalk6.blueBright.bold(relativeImport.resolvedPath)}`
4460
- );
4047
+ } catch {
4461
4048
  }
4462
4049
  }
4463
4050
  }
4464
4051
  return {
4465
4052
  demoName: createDemoName(filePath),
4466
4053
  fileName,
4054
+ filePath,
4467
4055
  imports,
4468
4056
  sourceCode
4469
4057
  };
4470
- } catch (e) {
4471
- logDev2(
4472
- `${chalk6.magenta.bold(LOG_PREFIX2)} ${chalk6.yellowBright("Failed to parse")} ${chalk6.blueBright.bold(filePath)}. ${chalk6.yellowBright("Removing from registry")}`
4473
- );
4058
+ } catch {
4474
4059
  return null;
4475
4060
  }
4476
4061
  }
@@ -4517,36 +4102,12 @@ ${entries}
4517
4102
  strippedCode: strippedCode.replace(/^\n+/, "")
4518
4103
  };
4519
4104
  } catch (error) {
4520
- logDev2(
4521
- `${chalk6.magenta.bold(LOG_PREFIX2)} ${chalk6.redBright("Failed to strip imports from")} ${chalk6.blueBright.bold(fileName)}:`,
4522
- error
4523
- );
4524
4105
  return {
4525
4106
  imports: [],
4526
4107
  strippedCode: code
4527
4108
  };
4528
4109
  }
4529
4110
  }
4530
- function generatePageImports() {
4531
- const pageIds = Array.from(pageScopes.keys());
4532
- return pageIds.map((pageId) => {
4533
- const safeName = sanitizeIdentifier(pageId);
4534
- return `import * as page_${safeName} from "virtual:qui-demo-scope/page:${pageId}"`;
4535
- }).join("\n");
4536
- }
4537
- function generateScopeMap() {
4538
- const pageIds = Array.from(pageScopes.keys());
4539
- if (pageIds.length === 0) {
4540
- return "const pageModules = {}";
4541
- }
4542
- const entries = pageIds.map((pageId) => {
4543
- const safeName = sanitizeIdentifier(pageId);
4544
- return ` "${pageId}": page_${safeName}`;
4545
- }).join(",\n");
4546
- return `const pageModules = {
4547
- ${entries}
4548
- }`;
4549
- }
4550
4111
  function generateDemoRegistry(registry) {
4551
4112
  const entries = Array.from(registry.entries()).map(([demoName, { fileName, imports, pageId, sourceCode }]) => {
4552
4113
  return ` ["${demoName}", { fileName: "${fileName}", imports: ${JSON.stringify(imports)}, pageId: "${pageId}", sourceCode: ${JSON.stringify(sourceCode)}, demoName: "${demoName}" }]`;
@@ -4564,31 +4125,11 @@ ${entries}
4564
4125
  fileName: "",
4565
4126
  imports: [],
4566
4127
  errorMessage: \`Demo "\${demoName}" not found.\`,
4567
- scope: {},
4568
4128
  pageId: "",
4569
4129
  sourceCode: [],
4570
4130
  }
4571
4131
  }
4572
-
4573
- const pageModule = pageModules[demo.pageId]
4574
- if (!pageModule) {
4575
- return {
4576
- fileName: "",
4577
- imports: [],
4578
- errorMessage: \`Page module not found.\`,
4579
- scope: {},
4580
- pageId: demo.pageId,
4581
- sourceCode: [],
4582
- }
4583
- }
4584
-
4585
- return pageModule.getDemo(demoName) || {
4586
- fileName: demo.fileName,
4587
- imports: demo.imports,
4588
- scope: {},
4589
- pageId: demo.pageId,
4590
- sourceCode: demo.sourceCode,
4591
- }
4132
+ return demo
4592
4133
  }
4593
4134
  `;
4594
4135
  }
@@ -4598,21 +4139,15 @@ export {
4598
4139
  NODE_BUILTINS,
4599
4140
  REACT_IMPORTS,
4600
4141
  VIRTUAL_MODULE_IDS,
4601
- addReactImports,
4602
- addRelativeImportsNamespaced,
4603
- addThirdPartyImports,
4604
- addThirdPartyImportsNamespaced,
4605
4142
  angularDemoPlugin,
4606
4143
  createDemoName,
4607
- createEmptyScopeModule,
4608
- createUniqueModuleName,
4609
- extractAllImports,
4610
4144
  extractFileImports,
4611
4145
  extractPageId,
4612
4146
  getAlertIcon,
4613
4147
  getRehypePlugins,
4614
4148
  getRemarkPlugins,
4615
4149
  getScriptKind,
4150
+ getShikiTransformers,
4616
4151
  isCssAsset,
4617
4152
  isDemoFile,
4618
4153
  quiDocsPlugin,
@@ -4628,8 +4163,6 @@ export {
4628
4163
  remarkGfm2 as remarkGfm,
4629
4164
  remarkMdxFrontmatter,
4630
4165
  remarkSelfLinkHeadings,
4631
- remarkSpoilers,
4632
- sanitizeIdentifier,
4633
- sanitizeSourceName
4166
+ remarkSpoilers
4634
4167
  };
4635
4168
  //# sourceMappingURL=index.js.map