@qualcomm-ui/mdx-vite 2.3.0 → 2.5.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.
- package/README.md +1 -2
- package/dist/angular-demo-plugin/angular-demo-plugin.d.ts +7 -1
- package/dist/angular-demo-plugin/angular-demo-plugin.d.ts.map +1 -1
- package/dist/cli.js +12 -0
- package/dist/cli.js.map +2 -2
- package/dist/docs-plugin/docs-plugin.d.ts.map +1 -1
- package/dist/docs-plugin/internal/search-indexer.d.ts.map +1 -1
- package/dist/docs-plugin/internal/services/markdown/markdown.types.d.ts +5 -1
- package/dist/docs-plugin/internal/services/markdown/markdown.types.d.ts.map +1 -1
- package/dist/docs-plugin/shiki/internal/index.d.ts +2 -0
- package/dist/docs-plugin/shiki/internal/index.d.ts.map +1 -0
- package/dist/docs-plugin/shiki/internal/shiki-transformer-tailwind.d.ts +50 -0
- package/dist/docs-plugin/shiki/internal/shiki-transformer-tailwind.d.ts.map +1 -0
- package/dist/docs-plugin/shiki/internal/tests/shiki-transformer-tailwind.spec.d.ts +2 -0
- package/dist/docs-plugin/shiki/internal/tests/shiki-transformer-tailwind.spec.d.ts.map +1 -0
- package/dist/docs-plugin/shiki/shiki-transformer-preview-block.d.ts.map +1 -1
- package/dist/docs-plugin/shiki/utils.d.ts +1 -0
- package/dist/docs-plugin/shiki/utils.d.ts.map +1 -1
- package/dist/index.js +681 -185
- package/dist/index.js.map +4 -4
- package/dist/react-demo-plugin/demo-plugin-types.d.ts +7 -0
- package/dist/react-demo-plugin/demo-plugin-types.d.ts.map +1 -1
- package/dist/react-demo-plugin/react-demo-plugin.d.ts +1 -1
- package/dist/react-demo-plugin/react-demo-plugin.d.ts.map +1 -1
- package/dist/tsbuildinfo +1 -1
- package/package.json +8 -2
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import chalk4 from "chalk";
|
|
|
5
5
|
import { watch } from "chokidar";
|
|
6
6
|
import { glob as glob2 } from "glob";
|
|
7
7
|
import { existsSync } from "node:fs";
|
|
8
|
-
import { readFile, stat } from "node:fs/promises";
|
|
8
|
+
import { readFile as readFile2, stat } from "node:fs/promises";
|
|
9
9
|
import { basename, dirname, join as join2, relative, resolve as resolve2 } from "node:path";
|
|
10
10
|
import {
|
|
11
11
|
createHighlighter
|
|
@@ -14,6 +14,7 @@ import * as ts from "typescript";
|
|
|
14
14
|
import {
|
|
15
15
|
quiCustomDarkTheme as quiCustomDarkTheme2
|
|
16
16
|
} from "@qualcomm-ui/mdx-common";
|
|
17
|
+
import { dedent as dedent2 } from "@qualcomm-ui/utils/dedent";
|
|
17
18
|
|
|
18
19
|
// src/docs-plugin/docs-plugin.ts
|
|
19
20
|
import chalk3 from "chalk";
|
|
@@ -1495,11 +1496,13 @@ var SearchIndexer = class {
|
|
|
1495
1496
|
changed: {},
|
|
1496
1497
|
filePath
|
|
1497
1498
|
};
|
|
1499
|
+
let previousPage = void 0;
|
|
1498
1500
|
if (!cached) {
|
|
1499
1501
|
const previousData = this.fileCache.readCache(filePath);
|
|
1500
1502
|
if (previousData) {
|
|
1501
1503
|
const cachedFm = JSON.stringify(previousData.frontmatter);
|
|
1502
1504
|
const currentFm = JSON.stringify(frontmatter);
|
|
1505
|
+
previousPage = previousData.page;
|
|
1503
1506
|
if (cachedFm !== currentFm) {
|
|
1504
1507
|
metadata.changed.frontmatter = true;
|
|
1505
1508
|
}
|
|
@@ -1527,6 +1530,16 @@ var SearchIndexer = class {
|
|
|
1527
1530
|
return { metadata, pageSections: [defaultSection] };
|
|
1528
1531
|
}
|
|
1529
1532
|
const { sections, toc } = indexedPage;
|
|
1533
|
+
if (previousPage) {
|
|
1534
|
+
for (let i = 0; i < toc.length; i++) {
|
|
1535
|
+
const previousHeading = previousPage.toc[i];
|
|
1536
|
+
const currentHeading = toc[i];
|
|
1537
|
+
if (previousHeading?.id !== currentHeading.id) {
|
|
1538
|
+
metadata.changed.toc = true;
|
|
1539
|
+
break;
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1530
1543
|
if (toc.length) {
|
|
1531
1544
|
this._pageMap[defaultSection.pathname].toc = toc;
|
|
1532
1545
|
}
|
|
@@ -1805,6 +1818,7 @@ function quiDocsPlugin(opts) {
|
|
|
1805
1818
|
}
|
|
1806
1819
|
const virtualModule = server.moduleGraph.getModuleById(VIRTUAL_MODULE_ID);
|
|
1807
1820
|
if (virtualModule) {
|
|
1821
|
+
server.moduleGraph.invalidateModule(virtualModule);
|
|
1808
1822
|
server.ws.send({
|
|
1809
1823
|
data: state.siteData,
|
|
1810
1824
|
event: "qui-docs-plugin:refresh-site-data",
|
|
@@ -2240,6 +2254,55 @@ function removeCodeAnnotations(code) {
|
|
|
2240
2254
|
return true;
|
|
2241
2255
|
}).map(({ processed }) => processed).join("\n");
|
|
2242
2256
|
}
|
|
2257
|
+
function extractPreviewFromHighlightedHtml(highlightedHtml) {
|
|
2258
|
+
const preMatch = highlightedHtml.match(/<pre((?:\s+[\w-]+="[^"]*")*)>/);
|
|
2259
|
+
const codeMatch = highlightedHtml.match(/<code([^>]*)>(.*?)<\/code>/s);
|
|
2260
|
+
if (!preMatch || !codeMatch) {
|
|
2261
|
+
return null;
|
|
2262
|
+
}
|
|
2263
|
+
const codeContent = codeMatch[2];
|
|
2264
|
+
const parts = codeContent.split(/<span class="line/);
|
|
2265
|
+
const previewLineParts = parts.slice(1).filter((part) => part.includes('data-preview-line="true"'));
|
|
2266
|
+
const indents = previewLineParts.map((part) => {
|
|
2267
|
+
const indentMatches = part.match(/<span class="indent">(.+?)<\/span>/g) || [];
|
|
2268
|
+
let total = 0;
|
|
2269
|
+
for (const match of indentMatches) {
|
|
2270
|
+
const content = match.match(/<span class="indent">(.+?)<\/span>/);
|
|
2271
|
+
if (content) {
|
|
2272
|
+
total += content[1].length;
|
|
2273
|
+
} else {
|
|
2274
|
+
break;
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
return total;
|
|
2278
|
+
});
|
|
2279
|
+
const minIndent = Math.min(...indents.filter((n) => n > 0));
|
|
2280
|
+
const previewLines = previewLineParts.map((part) => {
|
|
2281
|
+
let processed = `<span class="line${part}`;
|
|
2282
|
+
let remaining = minIndent;
|
|
2283
|
+
while (remaining > 0 && processed.includes('<span class="indent">')) {
|
|
2284
|
+
const before = processed;
|
|
2285
|
+
processed = processed.replace(
|
|
2286
|
+
/<span class="indent">(.+?)<\/span>/,
|
|
2287
|
+
(match, spaces) => {
|
|
2288
|
+
if (spaces.length <= remaining) {
|
|
2289
|
+
remaining -= spaces.length;
|
|
2290
|
+
return "";
|
|
2291
|
+
} else {
|
|
2292
|
+
const kept = spaces.substring(remaining);
|
|
2293
|
+
remaining = 0;
|
|
2294
|
+
return `<span class="indent">${kept}</span>`;
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
);
|
|
2298
|
+
if (before === processed) {
|
|
2299
|
+
break;
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
return processed;
|
|
2303
|
+
});
|
|
2304
|
+
return `<pre${preMatch[1]}><code${codeMatch[1]}>${previewLines.join("")}</code></pre>`;
|
|
2305
|
+
}
|
|
2243
2306
|
|
|
2244
2307
|
// src/docs-plugin/shiki/shiki-transformer-code-attribute.ts
|
|
2245
2308
|
function transformerCodeAttribute(opts = { attributeName: "data-code" }) {
|
|
@@ -2315,10 +2378,11 @@ function transformerPreviewBlock(options = {
|
|
|
2315
2378
|
},
|
|
2316
2379
|
name: "transformer-preview-block",
|
|
2317
2380
|
pre(node) {
|
|
2318
|
-
|
|
2319
|
-
|
|
2381
|
+
const content = previewContent ? removeCodeAnnotations(previewContent) : null;
|
|
2382
|
+
if (content && options.attributeName != null) {
|
|
2383
|
+
node.properties[options.attributeName] = content;
|
|
2320
2384
|
}
|
|
2321
|
-
options.onComplete?.(
|
|
2385
|
+
options.onComplete?.(content || null);
|
|
2322
2386
|
},
|
|
2323
2387
|
preprocess(code) {
|
|
2324
2388
|
previewContent = null;
|
|
@@ -2412,6 +2476,406 @@ function getRemarkPlugins() {
|
|
|
2412
2476
|
];
|
|
2413
2477
|
}
|
|
2414
2478
|
|
|
2479
|
+
// src/docs-plugin/shiki/internal/shiki-transformer-tailwind.ts
|
|
2480
|
+
import { fromHtml as fromHtml2 } from "hast-util-from-html";
|
|
2481
|
+
import { toHtml } from "hast-util-to-html";
|
|
2482
|
+
import { readFile } from "node:fs/promises";
|
|
2483
|
+
import postcss from "postcss";
|
|
2484
|
+
import selectorParser from "postcss-selector-parser";
|
|
2485
|
+
import { compile } from "tailwindcss";
|
|
2486
|
+
import { visit as visit7 } from "unist-util-visit";
|
|
2487
|
+
import { camelCase } from "@qualcomm-ui/utils/change-case";
|
|
2488
|
+
async function loadStylesheetContent(id) {
|
|
2489
|
+
const resolveId = id === "tailwindcss" ? "tailwindcss/index.css" : id;
|
|
2490
|
+
let resolvedPath;
|
|
2491
|
+
if (typeof createRequire !== "undefined") {
|
|
2492
|
+
resolvedPath = createRequire(import.meta.url).resolve(resolveId);
|
|
2493
|
+
} else {
|
|
2494
|
+
const createRequire2 = await import("node:module").then(
|
|
2495
|
+
(module) => module.createRequire
|
|
2496
|
+
);
|
|
2497
|
+
resolvedPath = createRequire2(import.meta.url).resolve(resolveId);
|
|
2498
|
+
}
|
|
2499
|
+
return readFile(resolvedPath, "utf-8");
|
|
2500
|
+
}
|
|
2501
|
+
async function createCompiler(styles) {
|
|
2502
|
+
return compile(styles, {
|
|
2503
|
+
loadStylesheet: async (id, base) => {
|
|
2504
|
+
const content = await loadStylesheetContent(id);
|
|
2505
|
+
return {
|
|
2506
|
+
base,
|
|
2507
|
+
content,
|
|
2508
|
+
path: `virtual:${id}`
|
|
2509
|
+
};
|
|
2510
|
+
}
|
|
2511
|
+
});
|
|
2512
|
+
}
|
|
2513
|
+
function extractCssVariables(css) {
|
|
2514
|
+
const variables = /* @__PURE__ */ new Map();
|
|
2515
|
+
const root = postcss.parse(css);
|
|
2516
|
+
root.walkAtRules("layer", (atRule) => {
|
|
2517
|
+
if (atRule.params !== "theme") {
|
|
2518
|
+
return;
|
|
2519
|
+
}
|
|
2520
|
+
atRule.walkRules(":root, :host", (rule) => {
|
|
2521
|
+
rule.walkDecls((decl) => {
|
|
2522
|
+
if (decl.prop.startsWith("--")) {
|
|
2523
|
+
variables.set(decl.prop, decl.value);
|
|
2524
|
+
}
|
|
2525
|
+
});
|
|
2526
|
+
});
|
|
2527
|
+
});
|
|
2528
|
+
return variables;
|
|
2529
|
+
}
|
|
2530
|
+
function evaluateCalc(expression) {
|
|
2531
|
+
const expr = expression.trim();
|
|
2532
|
+
const withUnitFirst = expr.match(
|
|
2533
|
+
/^([\d.]+)(rem|px|em|%|vh|vw)\s*([*/+-])\s*([\d.]+)$/
|
|
2534
|
+
);
|
|
2535
|
+
if (withUnitFirst) {
|
|
2536
|
+
const [, num1, unit, op, num2] = withUnitFirst;
|
|
2537
|
+
const result = evaluateOperation(parseFloat(num1), op, parseFloat(num2));
|
|
2538
|
+
if (!Number.isFinite(result)) {
|
|
2539
|
+
return null;
|
|
2540
|
+
}
|
|
2541
|
+
return formatNumber(result) + unit;
|
|
2542
|
+
}
|
|
2543
|
+
const withUnitSecond = expr.match(
|
|
2544
|
+
/^([\d.]+)\s*([*/+-])\s*([\d.]+)(rem|px|em|%|vh|vw)$/
|
|
2545
|
+
);
|
|
2546
|
+
if (withUnitSecond) {
|
|
2547
|
+
const [, num1, op, num2, unit] = withUnitSecond;
|
|
2548
|
+
const result = evaluateOperation(parseFloat(num1), op, parseFloat(num2));
|
|
2549
|
+
if (!Number.isFinite(result)) {
|
|
2550
|
+
return null;
|
|
2551
|
+
}
|
|
2552
|
+
return formatNumber(result) + unit;
|
|
2553
|
+
}
|
|
2554
|
+
const unitless = expr.match(/^([\d.]+)\s*([*/+-])\s*([\d.]+)$/);
|
|
2555
|
+
if (unitless) {
|
|
2556
|
+
const [, num1, op, num2] = unitless;
|
|
2557
|
+
const result = evaluateOperation(parseFloat(num1), op, parseFloat(num2));
|
|
2558
|
+
if (!Number.isFinite(result)) {
|
|
2559
|
+
return null;
|
|
2560
|
+
}
|
|
2561
|
+
return formatNumber(result);
|
|
2562
|
+
}
|
|
2563
|
+
return null;
|
|
2564
|
+
}
|
|
2565
|
+
function evaluateOperation(a, op, b) {
|
|
2566
|
+
switch (op) {
|
|
2567
|
+
case "*":
|
|
2568
|
+
return a * b;
|
|
2569
|
+
case "/":
|
|
2570
|
+
return a / b;
|
|
2571
|
+
case "+":
|
|
2572
|
+
return a + b;
|
|
2573
|
+
case "-":
|
|
2574
|
+
return a - b;
|
|
2575
|
+
default:
|
|
2576
|
+
return NaN;
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
function formatNumber(num) {
|
|
2580
|
+
const rounded = Math.round(num * 1e4) / 1e4;
|
|
2581
|
+
return String(rounded);
|
|
2582
|
+
}
|
|
2583
|
+
function remToPx(value) {
|
|
2584
|
+
return value.replace(/([\d.]+)rem/g, (_, num) => {
|
|
2585
|
+
const px = parseFloat(num) * 16;
|
|
2586
|
+
return `${formatNumber(px)}px`;
|
|
2587
|
+
});
|
|
2588
|
+
}
|
|
2589
|
+
function findVarEnd(str, start) {
|
|
2590
|
+
let depth = 0;
|
|
2591
|
+
for (let i = start; i < str.length; i++) {
|
|
2592
|
+
if (str[i] === "(") {
|
|
2593
|
+
depth++;
|
|
2594
|
+
} else if (str[i] === ")") {
|
|
2595
|
+
depth--;
|
|
2596
|
+
if (depth === 0) {
|
|
2597
|
+
return i;
|
|
2598
|
+
}
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2601
|
+
return -1;
|
|
2602
|
+
}
|
|
2603
|
+
function parseVar(str, startIndex) {
|
|
2604
|
+
const varStart = str.indexOf("var(", startIndex);
|
|
2605
|
+
if (varStart === -1) {
|
|
2606
|
+
return null;
|
|
2607
|
+
}
|
|
2608
|
+
const contentStart = varStart + 4;
|
|
2609
|
+
const end = findVarEnd(str, varStart);
|
|
2610
|
+
if (end === -1) {
|
|
2611
|
+
return null;
|
|
2612
|
+
}
|
|
2613
|
+
const content = str.slice(contentStart, end);
|
|
2614
|
+
let commaIndex = -1;
|
|
2615
|
+
let depth = 0;
|
|
2616
|
+
for (let i = 0; i < content.length; i++) {
|
|
2617
|
+
if (content[i] === "(") {
|
|
2618
|
+
depth++;
|
|
2619
|
+
} else if (content[i] === ")") {
|
|
2620
|
+
depth--;
|
|
2621
|
+
} else if (content[i] === "," && depth === 0) {
|
|
2622
|
+
commaIndex = i;
|
|
2623
|
+
break;
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
if (commaIndex === -1) {
|
|
2627
|
+
return {
|
|
2628
|
+
end,
|
|
2629
|
+
fallback: null,
|
|
2630
|
+
varName: content.trim()
|
|
2631
|
+
};
|
|
2632
|
+
}
|
|
2633
|
+
return {
|
|
2634
|
+
end,
|
|
2635
|
+
fallback: content.slice(commaIndex + 1).trim(),
|
|
2636
|
+
varName: content.slice(0, commaIndex).trim()
|
|
2637
|
+
};
|
|
2638
|
+
}
|
|
2639
|
+
function resolveCssValue(value, variables, depth = 0) {
|
|
2640
|
+
if (depth > 10) {
|
|
2641
|
+
return value;
|
|
2642
|
+
}
|
|
2643
|
+
let resolved = value;
|
|
2644
|
+
let searchStart = 0;
|
|
2645
|
+
while (true) {
|
|
2646
|
+
const parsed = parseVar(resolved, searchStart);
|
|
2647
|
+
if (!parsed) {
|
|
2648
|
+
break;
|
|
2649
|
+
}
|
|
2650
|
+
const { end, fallback, varName } = parsed;
|
|
2651
|
+
const varStart = resolved.indexOf("var(", searchStart);
|
|
2652
|
+
let replacement;
|
|
2653
|
+
const varValue = variables.get(varName);
|
|
2654
|
+
if (varValue !== void 0) {
|
|
2655
|
+
replacement = resolveCssValue(varValue, variables, depth + 1);
|
|
2656
|
+
} else if (fallback) {
|
|
2657
|
+
replacement = resolveCssValue(fallback, variables, depth + 1);
|
|
2658
|
+
} else {
|
|
2659
|
+
searchStart = end + 1;
|
|
2660
|
+
continue;
|
|
2661
|
+
}
|
|
2662
|
+
resolved = resolved.slice(0, varStart) + replacement + resolved.slice(end + 1);
|
|
2663
|
+
}
|
|
2664
|
+
resolved = resolved.replace(
|
|
2665
|
+
/calc\(([^)]+)\)/g,
|
|
2666
|
+
(match, expression) => {
|
|
2667
|
+
const evaluated = evaluateCalc(expression);
|
|
2668
|
+
return evaluated ?? match;
|
|
2669
|
+
}
|
|
2670
|
+
);
|
|
2671
|
+
resolved = remToPx(resolved);
|
|
2672
|
+
return resolved;
|
|
2673
|
+
}
|
|
2674
|
+
function analyzeSelector(selector) {
|
|
2675
|
+
let inlineable = true;
|
|
2676
|
+
let className = null;
|
|
2677
|
+
const processor = selectorParser((selectors) => {
|
|
2678
|
+
if (selectors.nodes.length !== 1) {
|
|
2679
|
+
inlineable = false;
|
|
2680
|
+
return;
|
|
2681
|
+
}
|
|
2682
|
+
const selectorNode = selectors.nodes[0];
|
|
2683
|
+
if (selectorNode.nodes.length !== 1) {
|
|
2684
|
+
inlineable = false;
|
|
2685
|
+
return;
|
|
2686
|
+
}
|
|
2687
|
+
const node = selectorNode.nodes[0];
|
|
2688
|
+
if (node.type !== "class") {
|
|
2689
|
+
inlineable = false;
|
|
2690
|
+
return;
|
|
2691
|
+
}
|
|
2692
|
+
className = node.value;
|
|
2693
|
+
selectorNode.walk((n) => {
|
|
2694
|
+
if (n.type === "pseudo" || n.type === "combinator" || n.type === "nesting" || n.type === "attribute") {
|
|
2695
|
+
inlineable = false;
|
|
2696
|
+
}
|
|
2697
|
+
});
|
|
2698
|
+
});
|
|
2699
|
+
processor.processSync(selector);
|
|
2700
|
+
return { className, inlineable };
|
|
2701
|
+
}
|
|
2702
|
+
function parseCompiledCss(css) {
|
|
2703
|
+
const rules = [];
|
|
2704
|
+
const root = postcss.parse(css);
|
|
2705
|
+
const variables = extractCssVariables(css);
|
|
2706
|
+
function processRule(rule, insideAtRule) {
|
|
2707
|
+
const { className, inlineable } = analyzeSelector(rule.selector);
|
|
2708
|
+
if (!className) {
|
|
2709
|
+
return;
|
|
2710
|
+
}
|
|
2711
|
+
let hasNestedAtRule = false;
|
|
2712
|
+
rule.walkAtRules(() => {
|
|
2713
|
+
hasNestedAtRule = true;
|
|
2714
|
+
});
|
|
2715
|
+
const declarations = [];
|
|
2716
|
+
rule.each((node) => {
|
|
2717
|
+
if (node.type === "decl") {
|
|
2718
|
+
const resolvedValue = resolveCssValue(node.value, variables);
|
|
2719
|
+
declarations.push(`${node.prop}: ${resolvedValue}`);
|
|
2720
|
+
}
|
|
2721
|
+
});
|
|
2722
|
+
if (declarations.length === 0 && !hasNestedAtRule) {
|
|
2723
|
+
return;
|
|
2724
|
+
}
|
|
2725
|
+
rules.push({
|
|
2726
|
+
className,
|
|
2727
|
+
declarations: declarations.join("; "),
|
|
2728
|
+
inlineable: inlineable && !insideAtRule && !hasNestedAtRule,
|
|
2729
|
+
originalRule: rule.toString()
|
|
2730
|
+
});
|
|
2731
|
+
}
|
|
2732
|
+
root.walkAtRules("layer", (atRule) => {
|
|
2733
|
+
atRule.walkRules((rule) => {
|
|
2734
|
+
const parent = rule.parent;
|
|
2735
|
+
const insideNestedAtRule = parent?.type === "atrule" && parent.name !== "layer";
|
|
2736
|
+
processRule(rule, insideNestedAtRule);
|
|
2737
|
+
});
|
|
2738
|
+
atRule.walkAtRules((nested) => {
|
|
2739
|
+
if (nested.name !== "layer") {
|
|
2740
|
+
nested.walkRules((rule) => {
|
|
2741
|
+
processRule(rule, true);
|
|
2742
|
+
});
|
|
2743
|
+
}
|
|
2744
|
+
});
|
|
2745
|
+
});
|
|
2746
|
+
root.walkRules((rule) => {
|
|
2747
|
+
if (rule.parent?.type === "root") {
|
|
2748
|
+
processRule(rule, false);
|
|
2749
|
+
}
|
|
2750
|
+
});
|
|
2751
|
+
return rules;
|
|
2752
|
+
}
|
|
2753
|
+
function compileClasses(classes, compiler) {
|
|
2754
|
+
const compiledCss = compiler.build(classes);
|
|
2755
|
+
const parsedRules = parseCompiledCss(compiledCss);
|
|
2756
|
+
const inlineableStyles = /* @__PURE__ */ new Map();
|
|
2757
|
+
const residualRules = /* @__PURE__ */ new Map();
|
|
2758
|
+
for (const rule of parsedRules) {
|
|
2759
|
+
if (rule.inlineable) {
|
|
2760
|
+
inlineableStyles.set(rule.className, rule.declarations);
|
|
2761
|
+
} else {
|
|
2762
|
+
residualRules.set(rule.className, rule.originalRule);
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
const inlineStyles = [];
|
|
2766
|
+
const remainingClasses = [];
|
|
2767
|
+
for (const cls of classes) {
|
|
2768
|
+
const style = inlineableStyles.get(cls);
|
|
2769
|
+
if (style) {
|
|
2770
|
+
inlineStyles.push(style);
|
|
2771
|
+
} else {
|
|
2772
|
+
remainingClasses.push(cls);
|
|
2773
|
+
}
|
|
2774
|
+
}
|
|
2775
|
+
return { inlineStyles, remainingClasses, residualRules };
|
|
2776
|
+
}
|
|
2777
|
+
function cssToJsxObject(cssDeclarations) {
|
|
2778
|
+
const props = cssDeclarations.flatMap((decl) => {
|
|
2779
|
+
return decl.split(";").map((d) => d.trim()).filter(Boolean);
|
|
2780
|
+
}).map((declaration) => {
|
|
2781
|
+
const colonIndex = declaration.indexOf(":");
|
|
2782
|
+
if (colonIndex === -1) {
|
|
2783
|
+
return null;
|
|
2784
|
+
}
|
|
2785
|
+
const prop = declaration.slice(0, colonIndex).trim();
|
|
2786
|
+
const value = declaration.slice(colonIndex + 1).trim();
|
|
2787
|
+
const camelProp = camelCase(prop);
|
|
2788
|
+
return `${camelProp}: '${value}'`;
|
|
2789
|
+
}).filter(Boolean);
|
|
2790
|
+
return `{ ${props.join(", ")} }`;
|
|
2791
|
+
}
|
|
2792
|
+
function computeLineReplacements(lineText, compiler, styleFormat = "html") {
|
|
2793
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
2794
|
+
const allResidualRules = /* @__PURE__ */ new Map();
|
|
2795
|
+
const classAttrPattern = /(className|class)=(["'`])([^"'`]*)\2/g;
|
|
2796
|
+
let match;
|
|
2797
|
+
while ((match = classAttrPattern.exec(lineText)) !== null) {
|
|
2798
|
+
const fullMatch = match[0];
|
|
2799
|
+
const attrName = match[1];
|
|
2800
|
+
const quote = match[2];
|
|
2801
|
+
const classValue = match[3];
|
|
2802
|
+
const classes = classValue.split(/\s+/).filter(Boolean);
|
|
2803
|
+
if (classes.length === 0) {
|
|
2804
|
+
continue;
|
|
2805
|
+
}
|
|
2806
|
+
const { inlineStyles, remainingClasses, residualRules } = compileClasses(
|
|
2807
|
+
classes,
|
|
2808
|
+
compiler
|
|
2809
|
+
);
|
|
2810
|
+
for (const [className, rule] of residualRules) {
|
|
2811
|
+
allResidualRules.set(className, rule);
|
|
2812
|
+
}
|
|
2813
|
+
if (inlineStyles.length === 0) {
|
|
2814
|
+
continue;
|
|
2815
|
+
}
|
|
2816
|
+
let replacement;
|
|
2817
|
+
if (styleFormat === "jsx") {
|
|
2818
|
+
const jsxStyleObj = cssToJsxObject(inlineStyles);
|
|
2819
|
+
replacement = `style={${jsxStyleObj}}`;
|
|
2820
|
+
} else {
|
|
2821
|
+
replacement = `style=${quote}${inlineStyles.join("; ")}${quote}`;
|
|
2822
|
+
}
|
|
2823
|
+
if (remainingClasses.length > 0) {
|
|
2824
|
+
replacement += ` ${attrName}=${quote}${remainingClasses.join(" ")}${quote}`;
|
|
2825
|
+
}
|
|
2826
|
+
replacements.set(fullMatch, replacement);
|
|
2827
|
+
}
|
|
2828
|
+
return { replacements, residualRules: allResidualRules };
|
|
2829
|
+
}
|
|
2830
|
+
function transformSourceCode(source, compiler, styleFormat = "html") {
|
|
2831
|
+
const allResidualRules = /* @__PURE__ */ new Map();
|
|
2832
|
+
let classesDetected = false;
|
|
2833
|
+
const { replacements, residualRules } = computeLineReplacements(
|
|
2834
|
+
source,
|
|
2835
|
+
compiler,
|
|
2836
|
+
styleFormat
|
|
2837
|
+
);
|
|
2838
|
+
if (replacements.size > 0 || residualRules.size > 0) {
|
|
2839
|
+
classesDetected = true;
|
|
2840
|
+
}
|
|
2841
|
+
for (const [cls, rule] of residualRules) {
|
|
2842
|
+
allResidualRules.set(cls, rule);
|
|
2843
|
+
}
|
|
2844
|
+
let transformed = source;
|
|
2845
|
+
for (const [original, replacement] of replacements) {
|
|
2846
|
+
transformed = transformed.replaceAll(original, replacement);
|
|
2847
|
+
}
|
|
2848
|
+
return {
|
|
2849
|
+
classesDetected,
|
|
2850
|
+
residualRules: allResidualRules,
|
|
2851
|
+
source: transformed
|
|
2852
|
+
};
|
|
2853
|
+
}
|
|
2854
|
+
async function createShikiTailwindTransformer(options) {
|
|
2855
|
+
const {
|
|
2856
|
+
onClassesDetected,
|
|
2857
|
+
onResidualCss,
|
|
2858
|
+
styleFormat = "html",
|
|
2859
|
+
styles
|
|
2860
|
+
} = options;
|
|
2861
|
+
const compiler = await createCompiler(styles);
|
|
2862
|
+
return {
|
|
2863
|
+
name: "shiki-transformer-tailwind-to-inline",
|
|
2864
|
+
preprocess(code) {
|
|
2865
|
+
const { classesDetected, residualRules, source } = transformSourceCode(
|
|
2866
|
+
code,
|
|
2867
|
+
compiler,
|
|
2868
|
+
styleFormat
|
|
2869
|
+
);
|
|
2870
|
+
onClassesDetected?.(classesDetected);
|
|
2871
|
+
if (onResidualCss && residualRules.size > 0) {
|
|
2872
|
+
onResidualCss(residualRules);
|
|
2873
|
+
}
|
|
2874
|
+
return source;
|
|
2875
|
+
}
|
|
2876
|
+
};
|
|
2877
|
+
}
|
|
2878
|
+
|
|
2415
2879
|
// src/angular-demo-plugin/angular-demo-plugin.ts
|
|
2416
2880
|
var VIRTUAL_MODULE_ID2 = "\0virtual:angular-demo-registry";
|
|
2417
2881
|
var LOG_PREFIX = "[angular-demo]";
|
|
@@ -2434,7 +2898,8 @@ function angularDemoPlugin({
|
|
|
2434
2898
|
theme = {
|
|
2435
2899
|
dark: quiCustomDarkTheme2,
|
|
2436
2900
|
light: "github-light-high-contrast"
|
|
2437
|
-
}
|
|
2901
|
+
},
|
|
2902
|
+
transformTailwindStyles
|
|
2438
2903
|
} = {}) {
|
|
2439
2904
|
let watcher = null;
|
|
2440
2905
|
let devServer = null;
|
|
@@ -2461,7 +2926,7 @@ function angularDemoPlugin({
|
|
|
2461
2926
|
if (!highlighter) {
|
|
2462
2927
|
try {
|
|
2463
2928
|
highlighter = await createHighlighter({
|
|
2464
|
-
langs: ["angular-ts", "angular-html"],
|
|
2929
|
+
langs: ["angular-ts", "angular-html", "css"],
|
|
2465
2930
|
themes: [theme.dark, theme.light]
|
|
2466
2931
|
});
|
|
2467
2932
|
logDev(`${chalk4.blue.bold(LOG_PREFIX)} Shiki highlighter initialized`);
|
|
@@ -2539,7 +3004,7 @@ function angularDemoPlugin({
|
|
|
2539
3004
|
logDev(
|
|
2540
3005
|
`${chalk4.blue.bold(LOG_PREFIX)} Processing Angular demo change: ${chalk4.cyan(file)}`
|
|
2541
3006
|
);
|
|
2542
|
-
const code = await
|
|
3007
|
+
const code = await readFile2(file, "utf-8");
|
|
2543
3008
|
const demoInfo = await parseAngularDemo(file, code);
|
|
2544
3009
|
if (!demoInfo || !isAngularDemoEntrypoint(file)) {
|
|
2545
3010
|
const affectedDemos = await scanDemosForFileImport(file);
|
|
@@ -2605,7 +3070,7 @@ function angularDemoPlugin({
|
|
|
2605
3070
|
const demoFiles = await glob2(demoPattern);
|
|
2606
3071
|
demoRegistry.clear();
|
|
2607
3072
|
for (const filePath of demoFiles) {
|
|
2608
|
-
const code = await
|
|
3073
|
+
const code = await readFile2(filePath, "utf-8");
|
|
2609
3074
|
const demoInfo = await parseAngularDemo(filePath, code);
|
|
2610
3075
|
if (demoInfo) {
|
|
2611
3076
|
demoRegistry.set(demoInfo.id, demoInfo);
|
|
@@ -2619,7 +3084,7 @@ function angularDemoPlugin({
|
|
|
2619
3084
|
logDev(
|
|
2620
3085
|
`${chalk4.blue.bold(LOG_PREFIX)} Reloading demo ${chalk4.cyan(demoId)} due to imported file change: ${chalk4.yellow(file)}`
|
|
2621
3086
|
);
|
|
2622
|
-
const code = await
|
|
3087
|
+
const code = await readFile2(demo.filePath, "utf-8");
|
|
2623
3088
|
const updatedDemo = await parseAngularDemo(demo.filePath, code);
|
|
2624
3089
|
if (updatedDemo) {
|
|
2625
3090
|
delete demoDimensionsCache[updatedDemo.id];
|
|
@@ -2631,29 +3096,44 @@ function angularDemoPlugin({
|
|
|
2631
3096
|
}
|
|
2632
3097
|
return affectedDemos;
|
|
2633
3098
|
}
|
|
2634
|
-
async function highlightCode(code, language = "angular-ts") {
|
|
3099
|
+
async function highlightCode(code, language = "angular-ts", options = {}) {
|
|
3100
|
+
const { onClassesDetected, onResidualCss } = options;
|
|
2635
3101
|
if (!highlighter) {
|
|
2636
|
-
return {
|
|
3102
|
+
return { full: code };
|
|
2637
3103
|
}
|
|
2638
3104
|
let previewCode = null;
|
|
2639
|
-
|
|
3105
|
+
const tailwindTransformers = [];
|
|
3106
|
+
if (transformTailwindStyles && onResidualCss) {
|
|
3107
|
+
const transformer = await createShikiTailwindTransformer({
|
|
3108
|
+
onClassesDetected: (detected) => {
|
|
3109
|
+
onClassesDetected?.(detected);
|
|
3110
|
+
},
|
|
3111
|
+
onResidualCss,
|
|
3112
|
+
styleFormat: "html",
|
|
3113
|
+
styles: dedent2`
|
|
3114
|
+
@layer theme, base, components, utilities;
|
|
3115
|
+
@import "tailwindcss/theme.css" layer(theme);
|
|
3116
|
+
@import "tailwindcss/utilities.css" layer(utilities);
|
|
3117
|
+
@import "@qualcomm-ui/tailwind-plugin/qui-strict.css";
|
|
3118
|
+
`
|
|
3119
|
+
});
|
|
3120
|
+
tailwindTransformers.push(transformer);
|
|
3121
|
+
}
|
|
2640
3122
|
try {
|
|
2641
3123
|
const highlightedCode = highlighter.codeToHtml(code, {
|
|
2642
3124
|
...defaultShikiOptions,
|
|
2643
3125
|
lang: language,
|
|
2644
3126
|
transformers: [
|
|
2645
3127
|
...getShikiTransformers(),
|
|
3128
|
+
...tailwindTransformers,
|
|
2646
3129
|
transformerPreviewBlock({
|
|
2647
|
-
attributeName:
|
|
3130
|
+
attributeName: "data-preview",
|
|
2648
3131
|
onComplete: (extractedPreview) => {
|
|
2649
|
-
previewCode = extractedPreview
|
|
3132
|
+
previewCode = extractedPreview;
|
|
2650
3133
|
}
|
|
2651
3134
|
}),
|
|
2652
3135
|
transformerCodeAttribute({
|
|
2653
|
-
attributeName:
|
|
2654
|
-
onComplete: (formattedSource) => {
|
|
2655
|
-
codeWithoutSnippets = formattedSource;
|
|
2656
|
-
}
|
|
3136
|
+
attributeName: "data-code"
|
|
2657
3137
|
}),
|
|
2658
3138
|
{
|
|
2659
3139
|
enforce: "post",
|
|
@@ -2665,22 +3145,20 @@ function angularDemoPlugin({
|
|
|
2665
3145
|
]
|
|
2666
3146
|
});
|
|
2667
3147
|
return {
|
|
2668
|
-
|
|
2669
|
-
highlightedCode
|
|
2670
|
-
highlightedPreview: previewCode ? extractPreviewFromHighlightedHtml(highlightedCode) : null,
|
|
2671
|
-
previewCodeWithoutSnippets: previewCode
|
|
3148
|
+
full: highlightedCode,
|
|
3149
|
+
preview: previewCode ? extractPreviewFromHighlightedHtml(highlightedCode) : null
|
|
2672
3150
|
};
|
|
2673
3151
|
} catch (error) {
|
|
2674
3152
|
console.warn(
|
|
2675
3153
|
`${chalk4.blue.bold(LOG_PREFIX)} Failed to highlight code with ${language} language:`,
|
|
2676
3154
|
error
|
|
2677
3155
|
);
|
|
2678
|
-
return {
|
|
3156
|
+
return { full: code };
|
|
2679
3157
|
}
|
|
2680
3158
|
}
|
|
2681
3159
|
async function extractRelativeImports(filePath) {
|
|
2682
3160
|
try {
|
|
2683
|
-
let
|
|
3161
|
+
let visit9 = function(node) {
|
|
2684
3162
|
if (ts.isImportDeclaration(node)) {
|
|
2685
3163
|
const moduleSpecifier = node.moduleSpecifier;
|
|
2686
3164
|
if (ts.isStringLiteral(moduleSpecifier)) {
|
|
@@ -2699,10 +3177,10 @@ function angularDemoPlugin({
|
|
|
2699
3177
|
}
|
|
2700
3178
|
}
|
|
2701
3179
|
}
|
|
2702
|
-
ts.forEachChild(node,
|
|
3180
|
+
ts.forEachChild(node, visit9);
|
|
2703
3181
|
};
|
|
2704
|
-
var
|
|
2705
|
-
const content = await
|
|
3182
|
+
var visit8 = visit9;
|
|
3183
|
+
const content = await readFile2(filePath, "utf-8");
|
|
2706
3184
|
const sourceFile = ts.createSourceFile(
|
|
2707
3185
|
filePath,
|
|
2708
3186
|
content,
|
|
@@ -2711,7 +3189,7 @@ function angularDemoPlugin({
|
|
|
2711
3189
|
ts.ScriptKind.TS
|
|
2712
3190
|
);
|
|
2713
3191
|
const relativeImports = [];
|
|
2714
|
-
|
|
3192
|
+
visit9(sourceFile);
|
|
2715
3193
|
return relativeImports;
|
|
2716
3194
|
} catch (error) {
|
|
2717
3195
|
logDev(
|
|
@@ -2734,16 +3212,16 @@ function angularDemoPlugin({
|
|
|
2734
3212
|
}
|
|
2735
3213
|
function stripImports(code, fileName) {
|
|
2736
3214
|
try {
|
|
2737
|
-
let
|
|
3215
|
+
let visit9 = function(node) {
|
|
2738
3216
|
if (ts.isImportDeclaration(node)) {
|
|
2739
3217
|
importRanges.push({
|
|
2740
3218
|
end: node.getEnd(),
|
|
2741
3219
|
start: node.getFullStart()
|
|
2742
3220
|
});
|
|
2743
3221
|
}
|
|
2744
|
-
ts.forEachChild(node,
|
|
3222
|
+
ts.forEachChild(node, visit9);
|
|
2745
3223
|
};
|
|
2746
|
-
var
|
|
3224
|
+
var visit8 = visit9;
|
|
2747
3225
|
const sourceFile = ts.createSourceFile(
|
|
2748
3226
|
fileName,
|
|
2749
3227
|
code,
|
|
@@ -2752,7 +3230,7 @@ function angularDemoPlugin({
|
|
|
2752
3230
|
ts.ScriptKind.TS
|
|
2753
3231
|
);
|
|
2754
3232
|
const importRanges = [];
|
|
2755
|
-
|
|
3233
|
+
visit9(sourceFile);
|
|
2756
3234
|
return importRanges.map((range) => {
|
|
2757
3235
|
let endPos = range.end;
|
|
2758
3236
|
if (code[endPos] === "\n") {
|
|
@@ -2785,24 +3263,51 @@ function angularDemoPlugin({
|
|
|
2785
3263
|
const fileName = basename(filePath);
|
|
2786
3264
|
const importsWithoutStrip = stripImports(code, filePath);
|
|
2787
3265
|
const sourceCode = [];
|
|
3266
|
+
const aggregatedRules = /* @__PURE__ */ new Map();
|
|
2788
3267
|
const mainSourceEntry = await buildAngularSourceEntry({
|
|
2789
3268
|
code,
|
|
2790
3269
|
fileName,
|
|
2791
3270
|
filePath,
|
|
2792
3271
|
language: "angular-ts"
|
|
2793
3272
|
});
|
|
2794
|
-
sourceCode.push(mainSourceEntry);
|
|
3273
|
+
sourceCode.push(mainSourceEntry.sourceCodeData);
|
|
3274
|
+
if (mainSourceEntry.residualRules) {
|
|
3275
|
+
for (const [className, rule] of mainSourceEntry.residualRules) {
|
|
3276
|
+
aggregatedRules.set(className, rule);
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
2795
3279
|
if (templateUrl) {
|
|
2796
3280
|
const templateEntry = await maybeBuildTemplateSourceEntry(
|
|
2797
3281
|
templateUrl,
|
|
2798
3282
|
filePath
|
|
2799
3283
|
);
|
|
2800
3284
|
if (templateEntry) {
|
|
2801
|
-
sourceCode.push(templateEntry);
|
|
3285
|
+
sourceCode.push(templateEntry.sourceCodeData);
|
|
3286
|
+
if (templateEntry.residualRules) {
|
|
3287
|
+
for (const [className, rule] of templateEntry.residualRules) {
|
|
3288
|
+
aggregatedRules.set(className, rule);
|
|
3289
|
+
}
|
|
3290
|
+
}
|
|
2802
3291
|
}
|
|
2803
3292
|
}
|
|
2804
3293
|
const importedEntries = await buildImportedSourceEntries(filePath);
|
|
2805
|
-
|
|
3294
|
+
for (const entry of importedEntries) {
|
|
3295
|
+
sourceCode.push(entry.sourceCodeData);
|
|
3296
|
+
if (entry.residualRules) {
|
|
3297
|
+
for (const [className, rule] of entry.residualRules) {
|
|
3298
|
+
aggregatedRules.set(className, rule);
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
}
|
|
3302
|
+
const aggregatedResidualCss = aggregatedRules.size > 0 ? [...aggregatedRules.values()].join("\n\n") : void 0;
|
|
3303
|
+
if (aggregatedResidualCss) {
|
|
3304
|
+
const cssHighlighted = await highlightCode(aggregatedResidualCss, "css");
|
|
3305
|
+
sourceCode.push({
|
|
3306
|
+
fileName: "styles.css",
|
|
3307
|
+
highlighted: cssHighlighted,
|
|
3308
|
+
type: "residual-css"
|
|
3309
|
+
});
|
|
3310
|
+
}
|
|
2806
3311
|
return {
|
|
2807
3312
|
componentClass,
|
|
2808
3313
|
filePath: importPath.startsWith(".") ? importPath : `./${importPath}`,
|
|
@@ -2837,7 +3342,7 @@ function angularDemoPlugin({
|
|
|
2837
3342
|
let templateUrl = null;
|
|
2838
3343
|
let hasDefaultExport = false;
|
|
2839
3344
|
const importsFromAst = [];
|
|
2840
|
-
function
|
|
3345
|
+
function visit8(node) {
|
|
2841
3346
|
if (ts.isImportDeclaration(node)) {
|
|
2842
3347
|
importsFromAst.push(node.getFullText(sourceFile).trim());
|
|
2843
3348
|
}
|
|
@@ -2885,9 +3390,9 @@ function angularDemoPlugin({
|
|
|
2885
3390
|
if (ts.isExportAssignment(node) && !node.isExportEquals) {
|
|
2886
3391
|
hasDefaultExport = true;
|
|
2887
3392
|
}
|
|
2888
|
-
ts.forEachChild(node,
|
|
3393
|
+
ts.forEachChild(node, visit8);
|
|
2889
3394
|
}
|
|
2890
|
-
|
|
3395
|
+
visit8(sourceFile);
|
|
2891
3396
|
return {
|
|
2892
3397
|
componentClass,
|
|
2893
3398
|
hasDefaultExport,
|
|
@@ -2899,24 +3404,34 @@ function angularDemoPlugin({
|
|
|
2899
3404
|
}
|
|
2900
3405
|
async function buildAngularSourceEntry(params) {
|
|
2901
3406
|
const { code, fileName, filePath, language } = params;
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
3407
|
+
const baseResult = await highlightCode(code, language);
|
|
3408
|
+
let inlineResult;
|
|
3409
|
+
let classesDetected = false;
|
|
3410
|
+
let residualRules;
|
|
3411
|
+
if (transformTailwindStyles) {
|
|
3412
|
+
inlineResult = await highlightCode(code, language, {
|
|
3413
|
+
onClassesDetected: (detected) => {
|
|
3414
|
+
classesDetected = detected;
|
|
3415
|
+
},
|
|
3416
|
+
onResidualCss: (rules) => {
|
|
3417
|
+
residualRules = rules;
|
|
3418
|
+
}
|
|
3419
|
+
});
|
|
3420
|
+
}
|
|
2910
3421
|
return {
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
3422
|
+
residualRules,
|
|
3423
|
+
sourceCodeData: {
|
|
3424
|
+
fileName,
|
|
3425
|
+
filePath,
|
|
3426
|
+
highlighted: {
|
|
3427
|
+
full: baseResult.full,
|
|
3428
|
+
preview: baseResult.preview
|
|
3429
|
+
},
|
|
3430
|
+
highlightedInline: classesDetected && inlineResult ? {
|
|
3431
|
+
full: inlineResult.full,
|
|
3432
|
+
preview: inlineResult.preview
|
|
3433
|
+
} : void 0,
|
|
3434
|
+
type: "file"
|
|
2920
3435
|
}
|
|
2921
3436
|
};
|
|
2922
3437
|
}
|
|
@@ -2926,7 +3441,7 @@ function angularDemoPlugin({
|
|
|
2926
3441
|
return null;
|
|
2927
3442
|
}
|
|
2928
3443
|
try {
|
|
2929
|
-
const templateCode = await
|
|
3444
|
+
const templateCode = await readFile2(templatePath, "utf-8");
|
|
2930
3445
|
return buildAngularSourceEntry({
|
|
2931
3446
|
code: templateCode,
|
|
2932
3447
|
fileName: basename(templatePath),
|
|
@@ -2942,25 +3457,25 @@ function angularDemoPlugin({
|
|
|
2942
3457
|
}
|
|
2943
3458
|
}
|
|
2944
3459
|
async function buildImportedSourceEntries(fromFilePath) {
|
|
2945
|
-
const
|
|
3460
|
+
const entries = [];
|
|
2946
3461
|
const relativeImports = await collectAllImports(fromFilePath);
|
|
2947
3462
|
for (const resolvedPath of relativeImports) {
|
|
2948
3463
|
try {
|
|
2949
|
-
const importedCode = await
|
|
3464
|
+
const importedCode = await readFile2(resolvedPath, "utf-8");
|
|
2950
3465
|
const entry = await buildAngularSourceEntry({
|
|
2951
3466
|
code: importedCode,
|
|
2952
3467
|
fileName: basename(resolvedPath),
|
|
2953
3468
|
filePath: resolvedPath,
|
|
2954
3469
|
language: "angular-ts"
|
|
2955
3470
|
});
|
|
2956
|
-
|
|
3471
|
+
entries.push(entry);
|
|
2957
3472
|
} catch (error) {
|
|
2958
3473
|
logDev(
|
|
2959
3474
|
`${chalk4.blue.bold(LOG_PREFIX)} ${chalk4.yellowBright("Failed to process relative import:")} ${chalk4.cyan(resolvedPath)}`
|
|
2960
3475
|
);
|
|
2961
3476
|
}
|
|
2962
3477
|
}
|
|
2963
|
-
return
|
|
3478
|
+
return entries;
|
|
2964
3479
|
}
|
|
2965
3480
|
function generateRegistryModule() {
|
|
2966
3481
|
const demos = Array.from(demoRegistry.values());
|
|
@@ -3039,7 +3554,7 @@ export function getAngularDemoInfo(demoId) {
|
|
|
3039
3554
|
function resolveRelativeImport2(source, fromFile) {
|
|
3040
3555
|
const fromDir = dirname(fromFile);
|
|
3041
3556
|
const resolved = resolve2(fromDir, source);
|
|
3042
|
-
const extensions = [".ts", ".
|
|
3557
|
+
const extensions = [".ts", ".js"];
|
|
3043
3558
|
for (const ext of extensions) {
|
|
3044
3559
|
const withExt = resolved + ext;
|
|
3045
3560
|
if (existsSync(withExt)) {
|
|
@@ -3149,7 +3664,7 @@ export function getAngularDemoInfo(demoId) {
|
|
|
3149
3664
|
});
|
|
3150
3665
|
}
|
|
3151
3666
|
async function handleAngularDemoUpdate(filePath) {
|
|
3152
|
-
const code = await
|
|
3667
|
+
const code = await readFile2(filePath, "utf-8");
|
|
3153
3668
|
const demoInfo = await parseAngularDemo(filePath, code);
|
|
3154
3669
|
if (demoInfo) {
|
|
3155
3670
|
demoRegistry.set(demoInfo.id, demoInfo);
|
|
@@ -3223,7 +3738,7 @@ function resolvePathAlias(source, pathAliases) {
|
|
|
3223
3738
|
for (const alias of pathAliases) {
|
|
3224
3739
|
if (alias.pattern.test(source)) {
|
|
3225
3740
|
const resolvedPath = source.replace(alias.pattern, alias.replacement);
|
|
3226
|
-
const extensions = [".ts", ".
|
|
3741
|
+
const extensions = [".ts", ".js"];
|
|
3227
3742
|
for (const ext of extensions) {
|
|
3228
3743
|
const withExt = resolvedPath + ext;
|
|
3229
3744
|
if (existsSync(withExt)) {
|
|
@@ -3255,55 +3770,6 @@ function resolveTemplateFile(templateUrl, fromFile) {
|
|
|
3255
3770
|
}
|
|
3256
3771
|
return resolved;
|
|
3257
3772
|
}
|
|
3258
|
-
function extractPreviewFromHighlightedHtml(highlightedHtml) {
|
|
3259
|
-
const preMatch = highlightedHtml.match(/<pre([^>]*)>/);
|
|
3260
|
-
const codeMatch = highlightedHtml.match(/<code([^>]*)>(.*?)<\/code>/s);
|
|
3261
|
-
if (!preMatch || !codeMatch) {
|
|
3262
|
-
return null;
|
|
3263
|
-
}
|
|
3264
|
-
const codeContent = codeMatch[2];
|
|
3265
|
-
const parts = codeContent.split(/<span class="line/);
|
|
3266
|
-
const previewLineParts = parts.slice(1).filter((part) => part.includes('data-preview-line="true"'));
|
|
3267
|
-
const indents = previewLineParts.map((part) => {
|
|
3268
|
-
const indentMatches = part.match(/<span class="indent">(.+?)<\/span>/g) || [];
|
|
3269
|
-
let total = 0;
|
|
3270
|
-
for (const match of indentMatches) {
|
|
3271
|
-
const content = match.match(/<span class="indent">(.+?)<\/span>/);
|
|
3272
|
-
if (content) {
|
|
3273
|
-
total += content[1].length;
|
|
3274
|
-
} else {
|
|
3275
|
-
break;
|
|
3276
|
-
}
|
|
3277
|
-
}
|
|
3278
|
-
return total;
|
|
3279
|
-
});
|
|
3280
|
-
const minIndent = Math.min(...indents.filter((n) => n > 0));
|
|
3281
|
-
const previewLines = previewLineParts.map((part) => {
|
|
3282
|
-
let processed = `<span class="line${part}`;
|
|
3283
|
-
let remaining = minIndent;
|
|
3284
|
-
while (remaining > 0 && processed.includes('<span class="indent">')) {
|
|
3285
|
-
const before = processed;
|
|
3286
|
-
processed = processed.replace(
|
|
3287
|
-
/<span class="indent">(.+?)<\/span>/,
|
|
3288
|
-
(match, spaces) => {
|
|
3289
|
-
if (spaces.length <= remaining) {
|
|
3290
|
-
remaining -= spaces.length;
|
|
3291
|
-
return "";
|
|
3292
|
-
} else {
|
|
3293
|
-
const kept = spaces.substring(remaining);
|
|
3294
|
-
remaining = 0;
|
|
3295
|
-
return `<span class="indent">${kept}</span>`;
|
|
3296
|
-
}
|
|
3297
|
-
}
|
|
3298
|
-
);
|
|
3299
|
-
if (before === processed) {
|
|
3300
|
-
break;
|
|
3301
|
-
}
|
|
3302
|
-
}
|
|
3303
|
-
return processed;
|
|
3304
|
-
});
|
|
3305
|
-
return `<pre${preMatch[1]}><code${codeMatch[1]}>${previewLines.join("")}</code></pre>`;
|
|
3306
|
-
}
|
|
3307
3773
|
|
|
3308
3774
|
// src/react-demo-plugin/demo-plugin-constants.ts
|
|
3309
3775
|
var VIRTUAL_MODULE_IDS = {
|
|
@@ -3341,7 +3807,7 @@ var NODE_BUILTINS = [
|
|
|
3341
3807
|
// src/react-demo-plugin/demo-plugin-utils.ts
|
|
3342
3808
|
import chalk5 from "chalk";
|
|
3343
3809
|
import { existsSync as existsSync2, readFileSync as readFileSync3 } from "node:fs";
|
|
3344
|
-
import { readFile as
|
|
3810
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
3345
3811
|
import { dirname as dirname2, join as join3, relative as relative2, resolve as resolve3, sep } from "node:path";
|
|
3346
3812
|
import * as ts2 from "typescript";
|
|
3347
3813
|
import { pascalCase } from "@qualcomm-ui/utils/change-case";
|
|
@@ -3358,7 +3824,7 @@ function createDemoName(filePath) {
|
|
|
3358
3824
|
}
|
|
3359
3825
|
async function extractFileImports(filePath) {
|
|
3360
3826
|
try {
|
|
3361
|
-
const content = await
|
|
3827
|
+
const content = await readFile3(filePath, "utf-8");
|
|
3362
3828
|
return extractImports(content, filePath);
|
|
3363
3829
|
} catch (error) {
|
|
3364
3830
|
console.log(
|
|
@@ -3378,7 +3844,7 @@ function extractImports(code, fileName) {
|
|
|
3378
3844
|
);
|
|
3379
3845
|
const thirdPartyImports = [];
|
|
3380
3846
|
const relativeImports = [];
|
|
3381
|
-
function
|
|
3847
|
+
function visit8(node) {
|
|
3382
3848
|
if (ts2.isImportDeclaration(node)) {
|
|
3383
3849
|
const importSpec = parseImportDeclaration(node, fileName);
|
|
3384
3850
|
if (importSpec) {
|
|
@@ -3389,9 +3855,9 @@ function extractImports(code, fileName) {
|
|
|
3389
3855
|
}
|
|
3390
3856
|
}
|
|
3391
3857
|
}
|
|
3392
|
-
ts2.forEachChild(node,
|
|
3858
|
+
ts2.forEachChild(node, visit8);
|
|
3393
3859
|
}
|
|
3394
|
-
|
|
3860
|
+
visit8(sourceFile);
|
|
3395
3861
|
return { relativeImports, thirdPartyImports };
|
|
3396
3862
|
}
|
|
3397
3863
|
function getScriptKind(fileName) {
|
|
@@ -3638,14 +4104,14 @@ function isDemoFile(filePath) {
|
|
|
3638
4104
|
// src/react-demo-plugin/react-demo-plugin.ts
|
|
3639
4105
|
import chalk6 from "chalk";
|
|
3640
4106
|
import { glob as glob3 } from "glob";
|
|
3641
|
-
import { readFile as
|
|
4107
|
+
import { readFile as readFile4 } from "node:fs/promises";
|
|
3642
4108
|
import { basename as basename2, resolve as resolve4 } from "node:path";
|
|
3643
4109
|
import { createHighlighter as createHighlighter2 } from "shiki";
|
|
3644
4110
|
import * as ts3 from "typescript";
|
|
3645
4111
|
import {
|
|
3646
4112
|
quiCustomDarkTheme as quiCustomDarkTheme3
|
|
3647
4113
|
} from "@qualcomm-ui/mdx-common";
|
|
3648
|
-
import { dedent as
|
|
4114
|
+
import { dedent as dedent3 } from "@qualcomm-ui/utils/dedent";
|
|
3649
4115
|
var highlighter2 = null;
|
|
3650
4116
|
var initializingHighlighter = false;
|
|
3651
4117
|
var demoRegistry2 = /* @__PURE__ */ new Map();
|
|
@@ -3659,7 +4125,8 @@ function reactDemoPlugin({
|
|
|
3659
4125
|
light: "github-light-high-contrast"
|
|
3660
4126
|
},
|
|
3661
4127
|
transformers = [],
|
|
3662
|
-
transformLine
|
|
4128
|
+
transformLine,
|
|
4129
|
+
transformTailwindStyles
|
|
3663
4130
|
} = {}) {
|
|
3664
4131
|
const defaultShikiOptions = {
|
|
3665
4132
|
defaultColor: "light-dark()",
|
|
@@ -3678,10 +4145,8 @@ function reactDemoPlugin({
|
|
|
3678
4145
|
initializingHighlighter = true;
|
|
3679
4146
|
try {
|
|
3680
4147
|
highlighter2 = await createHighlighter2({
|
|
3681
|
-
langs: ["tsx", "typescript"],
|
|
4148
|
+
langs: ["tsx", "typescript", "css"],
|
|
3682
4149
|
themes: [theme.dark, theme.light]
|
|
3683
|
-
}).finally(() => {
|
|
3684
|
-
initializingHighlighter = false;
|
|
3685
4150
|
});
|
|
3686
4151
|
console.log(
|
|
3687
4152
|
`${chalk6.magenta.bold(LOG_PREFIX2)} Shiki highlighter initialized`
|
|
@@ -3691,6 +4156,8 @@ function reactDemoPlugin({
|
|
|
3691
4156
|
`${chalk6.magenta.bold(LOG_PREFIX2)} Failed to initialize highlighter:`,
|
|
3692
4157
|
error
|
|
3693
4158
|
);
|
|
4159
|
+
} finally {
|
|
4160
|
+
initializingHighlighter = false;
|
|
3694
4161
|
}
|
|
3695
4162
|
}
|
|
3696
4163
|
await collectReactDemos();
|
|
@@ -3772,26 +4239,46 @@ function reactDemoPlugin({
|
|
|
3772
4239
|
}
|
|
3773
4240
|
}
|
|
3774
4241
|
}
|
|
3775
|
-
async function highlightCode(code) {
|
|
4242
|
+
async function highlightCode(code, options = {}) {
|
|
4243
|
+
const { extraTransformers = [], onResidualCss } = options;
|
|
3776
4244
|
if (!highlighter2) {
|
|
3777
|
-
return {
|
|
4245
|
+
return { full: code };
|
|
3778
4246
|
}
|
|
3779
4247
|
let previewCode = null;
|
|
3780
|
-
|
|
4248
|
+
const tailwindTransformers = [];
|
|
4249
|
+
if (transformTailwindStyles && onResidualCss) {
|
|
4250
|
+
const transformer = await createShikiTailwindTransformer({
|
|
4251
|
+
onClassesDetected: (detected) => {
|
|
4252
|
+
options.onClassesDetected?.(detected);
|
|
4253
|
+
},
|
|
4254
|
+
onResidualCss,
|
|
4255
|
+
styleFormat: "jsx",
|
|
4256
|
+
styles: dedent3`
|
|
4257
|
+
@layer theme, base, components, utilities;
|
|
4258
|
+
@import "tailwindcss/theme.css" layer(theme);
|
|
4259
|
+
@import "tailwindcss/utilities.css" layer(utilities);
|
|
4260
|
+
@import "@qualcomm-ui/tailwind-plugin/qui-strict.css";
|
|
4261
|
+
`
|
|
4262
|
+
});
|
|
4263
|
+
tailwindTransformers.push(transformer);
|
|
4264
|
+
} else if (extraTransformers.length > 0) {
|
|
4265
|
+
tailwindTransformers.push(...extraTransformers);
|
|
4266
|
+
}
|
|
3781
4267
|
try {
|
|
3782
|
-
const
|
|
4268
|
+
const highlightedCode = highlighter2.codeToHtml(code, {
|
|
3783
4269
|
...defaultShikiOptions,
|
|
3784
4270
|
transformers: [
|
|
3785
4271
|
...getShikiTransformers(),
|
|
4272
|
+
...transformers,
|
|
4273
|
+
...tailwindTransformers,
|
|
3786
4274
|
transformerPreviewBlock({
|
|
4275
|
+
attributeName: "data-preview",
|
|
3787
4276
|
onComplete: (extractedPreview) => {
|
|
3788
|
-
previewCode = extractedPreview
|
|
4277
|
+
previewCode = extractedPreview;
|
|
3789
4278
|
}
|
|
3790
4279
|
}),
|
|
3791
4280
|
transformerCodeAttribute({
|
|
3792
|
-
|
|
3793
|
-
codeWithoutSnippets = formattedSource;
|
|
3794
|
-
}
|
|
4281
|
+
attributeName: "data-code"
|
|
3795
4282
|
}),
|
|
3796
4283
|
{
|
|
3797
4284
|
enforce: "post",
|
|
@@ -3803,38 +4290,16 @@ function reactDemoPlugin({
|
|
|
3803
4290
|
...transformers
|
|
3804
4291
|
]
|
|
3805
4292
|
});
|
|
3806
|
-
let highlightedPreview = null;
|
|
3807
|
-
if (previewCode) {
|
|
3808
|
-
highlightedPreview = highlighter2.codeToHtml(code, {
|
|
3809
|
-
...defaultShikiOptions,
|
|
3810
|
-
transformers: [
|
|
3811
|
-
...getShikiTransformers(),
|
|
3812
|
-
transformerPreviewBlock({
|
|
3813
|
-
displayMode: "only-preview"
|
|
3814
|
-
}),
|
|
3815
|
-
{
|
|
3816
|
-
enforce: "post",
|
|
3817
|
-
name: "shiki-transformer-trim",
|
|
3818
|
-
preprocess(code2) {
|
|
3819
|
-
return code2.trim();
|
|
3820
|
-
}
|
|
3821
|
-
},
|
|
3822
|
-
...transformers
|
|
3823
|
-
]
|
|
3824
|
-
});
|
|
3825
|
-
}
|
|
3826
4293
|
return {
|
|
3827
|
-
|
|
3828
|
-
highlightedCode:
|
|
3829
|
-
highlightedPreview,
|
|
3830
|
-
previewCodeWithoutSnippets: previewCode
|
|
4294
|
+
full: highlightedCode,
|
|
4295
|
+
preview: previewCode ? extractPreviewFromHighlightedHtml(highlightedCode) : null
|
|
3831
4296
|
};
|
|
3832
4297
|
} catch (error) {
|
|
3833
4298
|
console.warn(
|
|
3834
4299
|
`${chalk6.magenta.bold(LOG_PREFIX2)} Failed to highlight code:`,
|
|
3835
4300
|
error
|
|
3836
4301
|
);
|
|
3837
|
-
return {
|
|
4302
|
+
return { full: code };
|
|
3838
4303
|
}
|
|
3839
4304
|
}
|
|
3840
4305
|
async function collectReactDemos() {
|
|
@@ -3894,22 +4359,34 @@ function reactDemoPlugin({
|
|
|
3894
4359
|
async function extractHighlightedCode(filePath, code) {
|
|
3895
4360
|
try {
|
|
3896
4361
|
const fileName = basename2(filePath);
|
|
3897
|
-
const
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
4362
|
+
const baseResult = await highlightCode(code);
|
|
4363
|
+
let inlineResult;
|
|
4364
|
+
let classesDetected = false;
|
|
4365
|
+
let residualRules;
|
|
4366
|
+
if (transformTailwindStyles) {
|
|
4367
|
+
inlineResult = await highlightCode(code, {
|
|
4368
|
+
onClassesDetected: (detected) => {
|
|
4369
|
+
classesDetected = detected;
|
|
4370
|
+
},
|
|
4371
|
+
onResidualCss: (rules) => {
|
|
4372
|
+
residualRules = rules;
|
|
4373
|
+
}
|
|
4374
|
+
});
|
|
4375
|
+
}
|
|
3903
4376
|
return {
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
4377
|
+
residualRules,
|
|
4378
|
+
sourceCodeData: {
|
|
4379
|
+
fileName,
|
|
4380
|
+
filePath,
|
|
4381
|
+
highlighted: {
|
|
4382
|
+
full: baseResult.full,
|
|
4383
|
+
preview: baseResult.preview
|
|
4384
|
+
},
|
|
4385
|
+
highlightedInline: classesDetected && inlineResult ? {
|
|
4386
|
+
full: inlineResult.full,
|
|
4387
|
+
preview: inlineResult.preview
|
|
4388
|
+
} : void 0,
|
|
4389
|
+
type: "file"
|
|
3913
4390
|
}
|
|
3914
4391
|
};
|
|
3915
4392
|
} catch {
|
|
@@ -3918,36 +4395,55 @@ function reactDemoPlugin({
|
|
|
3918
4395
|
}
|
|
3919
4396
|
async function extractFileData(filePath) {
|
|
3920
4397
|
try {
|
|
3921
|
-
const code = await
|
|
4398
|
+
const code = await readFile4(filePath, "utf-8").then(transformLines);
|
|
3922
4399
|
const imports = stripImports(code, filePath);
|
|
3923
4400
|
const sourceCode = [];
|
|
3924
|
-
const
|
|
3925
|
-
|
|
3926
|
-
|
|
4401
|
+
const aggregatedRules = /* @__PURE__ */ new Map();
|
|
4402
|
+
const extractedMain = await extractHighlightedCode(filePath, code);
|
|
4403
|
+
if (extractedMain) {
|
|
4404
|
+
sourceCode.push(extractedMain.sourceCodeData);
|
|
4405
|
+
if (extractedMain.residualRules) {
|
|
4406
|
+
for (const [className, rule] of extractedMain.residualRules) {
|
|
4407
|
+
aggregatedRules.set(className, rule);
|
|
4408
|
+
}
|
|
4409
|
+
}
|
|
3927
4410
|
}
|
|
3928
4411
|
const fileImports = await extractFileImports(filePath);
|
|
3929
4412
|
if (fileImports) {
|
|
3930
4413
|
for (const relativeImport of fileImports.relativeImports) {
|
|
3931
4414
|
try {
|
|
3932
|
-
const importedCode = await
|
|
4415
|
+
const importedCode = await readFile4(
|
|
3933
4416
|
relativeImport.resolvedPath,
|
|
3934
4417
|
"utf-8"
|
|
3935
4418
|
).then(transformLines);
|
|
3936
|
-
const
|
|
4419
|
+
const extracted = await extractHighlightedCode(
|
|
3937
4420
|
relativeImport.resolvedPath,
|
|
3938
4421
|
importedCode
|
|
3939
4422
|
);
|
|
3940
|
-
if (
|
|
3941
|
-
sourceCode.push(
|
|
4423
|
+
if (extracted) {
|
|
4424
|
+
sourceCode.push(extracted.sourceCodeData);
|
|
4425
|
+
if (extracted.residualRules) {
|
|
4426
|
+
for (const [className, rule] of extracted.residualRules) {
|
|
4427
|
+
aggregatedRules.set(className, rule);
|
|
4428
|
+
}
|
|
4429
|
+
}
|
|
3942
4430
|
}
|
|
3943
4431
|
} catch {
|
|
3944
4432
|
console.debug("Failed to process file", relativeImport.resolvedPath);
|
|
3945
4433
|
}
|
|
3946
4434
|
}
|
|
3947
4435
|
}
|
|
4436
|
+
const aggregatedResidualCss = aggregatedRules.size > 0 ? [...aggregatedRules.values()].join("\n\n") : void 0;
|
|
4437
|
+
if (aggregatedResidualCss) {
|
|
4438
|
+
sourceCode.push({
|
|
4439
|
+
fileName: "styles.css",
|
|
4440
|
+
highlighted: await highlightCode(aggregatedResidualCss),
|
|
4441
|
+
type: "residual-css"
|
|
4442
|
+
});
|
|
4443
|
+
}
|
|
3948
4444
|
return {
|
|
3949
4445
|
demoName: createDemoName(filePath),
|
|
3950
|
-
fileName: sourceCodeData
|
|
4446
|
+
fileName: extractedMain?.sourceCodeData.fileName || basename2(filePath),
|
|
3951
4447
|
filePath,
|
|
3952
4448
|
imports,
|
|
3953
4449
|
sourceCode
|
|
@@ -3958,16 +4454,16 @@ function reactDemoPlugin({
|
|
|
3958
4454
|
}
|
|
3959
4455
|
function stripImports(code, fileName) {
|
|
3960
4456
|
try {
|
|
3961
|
-
let
|
|
4457
|
+
let visit9 = function(node) {
|
|
3962
4458
|
if (ts3.isImportDeclaration(node)) {
|
|
3963
4459
|
importRanges.push({
|
|
3964
4460
|
end: node.getEnd(),
|
|
3965
4461
|
start: node.getFullStart()
|
|
3966
4462
|
});
|
|
3967
4463
|
}
|
|
3968
|
-
ts3.forEachChild(node,
|
|
4464
|
+
ts3.forEachChild(node, visit9);
|
|
3969
4465
|
};
|
|
3970
|
-
var
|
|
4466
|
+
var visit8 = visit9;
|
|
3971
4467
|
const sourceFile = ts3.createSourceFile(
|
|
3972
4468
|
fileName,
|
|
3973
4469
|
code,
|
|
@@ -3976,7 +4472,7 @@ function reactDemoPlugin({
|
|
|
3976
4472
|
getScriptKind(fileName)
|
|
3977
4473
|
);
|
|
3978
4474
|
const importRanges = [];
|
|
3979
|
-
|
|
4475
|
+
visit9(sourceFile);
|
|
3980
4476
|
return importRanges.map((range) => {
|
|
3981
4477
|
let endPos = range.end;
|
|
3982
4478
|
if (code[endPos] === "\n") {
|
|
@@ -3997,7 +4493,7 @@ ${entries}
|
|
|
3997
4493
|
])`;
|
|
3998
4494
|
}
|
|
3999
4495
|
function generateExportedFunctions() {
|
|
4000
|
-
return
|
|
4496
|
+
return dedent3`
|
|
4001
4497
|
export function getDemo(demoName) {
|
|
4002
4498
|
const demo = demoRegistry.get(demoName)
|
|
4003
4499
|
if (!demo) {
|