@qualcomm-ui/mdx-vite 2.5.0 → 2.5.2
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/dist/cli.js +651 -645
- package/dist/cli.js.map +3 -3
- package/dist/open-web-ui-knowledge/common.d.ts +1 -0
- package/dist/open-web-ui-knowledge/common.d.ts.map +1 -1
- package/dist/open-web-ui-knowledge/generate-knowledge.d.ts +5 -1
- package/dist/open-web-ui-knowledge/generate-knowledge.d.ts.map +1 -1
- package/dist/open-web-ui-knowledge/load-config-from-env.d.ts.map +1 -1
- package/dist/open-web-ui-knowledge/types.d.ts +3 -8
- package/dist/open-web-ui-knowledge/types.d.ts.map +1 -1
- package/dist/open-web-ui-knowledge/upload-knowledge.d.ts.map +1 -1
- package/dist/tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5545,13 +5545,9 @@ import { dedent } from "@qualcomm-ui/utils/dedent";
|
|
|
5545
5545
|
import { existsSync } from "node:fs";
|
|
5546
5546
|
import { join as join2, resolve as resolve4 } from "node:path";
|
|
5547
5547
|
function loadKnowledgeConfigFromEnv(options) {
|
|
5548
|
-
const knowledgeId = process.env.KNOWLEDGE_ID;
|
|
5549
5548
|
const exclude = options.exclude || (process.env.FILE_EXCLUDE_PATTERN ?? "").split(",");
|
|
5550
5549
|
const outputPath = options.outputPath || process.env.KNOWLEDGE_OUTPUT_PATH;
|
|
5551
5550
|
const prefix = process.env.PAGE_TITLE_PREFIX;
|
|
5552
|
-
if (!knowledgeId) {
|
|
5553
|
-
throw new Error("Missing required KNOWLEDGE_ID environment variable");
|
|
5554
|
-
}
|
|
5555
5551
|
if (!outputPath) {
|
|
5556
5552
|
throw new Error("Missing required outputPath");
|
|
5557
5553
|
}
|
|
@@ -5569,7 +5565,6 @@ function loadKnowledgeConfigFromEnv(options) {
|
|
|
5569
5565
|
baseUrl: options.baseUrl || process.env.DOCS_SITE_BASE_URL,
|
|
5570
5566
|
docPropsPath: resolvedConfig.typeDocProps,
|
|
5571
5567
|
exclude,
|
|
5572
|
-
knowledgeId,
|
|
5573
5568
|
outputPath,
|
|
5574
5569
|
pageTitlePrefix: prefix,
|
|
5575
5570
|
routeDir
|
|
@@ -5580,95 +5575,6 @@ function loadKnowledgeConfigFromEnv(options) {
|
|
|
5580
5575
|
async function exists(dirPath) {
|
|
5581
5576
|
return access(dirPath).then(() => true).catch(() => false);
|
|
5582
5577
|
}
|
|
5583
|
-
async function loadDocProps(routesFolder, docPropsPath, verbose) {
|
|
5584
|
-
const resolvedDocPropsPath = docPropsPath ? await exists(docPropsPath) ? docPropsPath : resolve5(process.cwd(), docPropsPath) : join3(dirname(routesFolder), "doc-props.json");
|
|
5585
|
-
if (!await exists(resolvedDocPropsPath)) {
|
|
5586
|
-
if (verbose) {
|
|
5587
|
-
console.log(`Doc props file not found at: ${resolvedDocPropsPath}`);
|
|
5588
|
-
}
|
|
5589
|
-
return null;
|
|
5590
|
-
}
|
|
5591
|
-
try {
|
|
5592
|
-
const content = await readFile(resolvedDocPropsPath, "utf-8");
|
|
5593
|
-
const docProps = JSON.parse(content);
|
|
5594
|
-
if (verbose) {
|
|
5595
|
-
console.log(`Loaded doc props from: ${resolvedDocPropsPath}`);
|
|
5596
|
-
console.log(`Found ${Object.keys(docProps.props).length} component types`);
|
|
5597
|
-
}
|
|
5598
|
-
return docProps;
|
|
5599
|
-
} catch (error) {
|
|
5600
|
-
if (verbose) {
|
|
5601
|
-
console.log(`Error loading doc props: ${error}`);
|
|
5602
|
-
}
|
|
5603
|
-
return null;
|
|
5604
|
-
}
|
|
5605
|
-
}
|
|
5606
|
-
function formatComment(comment) {
|
|
5607
|
-
if (!comment) {
|
|
5608
|
-
return "";
|
|
5609
|
-
}
|
|
5610
|
-
const parts = [];
|
|
5611
|
-
if (comment.summary && comment.summary.length > 0) {
|
|
5612
|
-
const summaryText = formatCommentParts(comment.summary);
|
|
5613
|
-
if (summaryText.trim()) {
|
|
5614
|
-
parts.push(summaryText.trim());
|
|
5615
|
-
}
|
|
5616
|
-
}
|
|
5617
|
-
if (comment.blockTags && comment.blockTags.length > 0) {
|
|
5618
|
-
for (const blockTag of comment.blockTags) {
|
|
5619
|
-
const tagContent = formatCommentParts(blockTag.content);
|
|
5620
|
-
if (tagContent.trim()) {
|
|
5621
|
-
const tagName = blockTag.tag.replace("@", "");
|
|
5622
|
-
if (tagName === "default" || tagName === "defaultValue") {
|
|
5623
|
-
continue;
|
|
5624
|
-
}
|
|
5625
|
-
if (tagName === "example") {
|
|
5626
|
-
parts.push(`**Example:**
|
|
5627
|
-
\`\`\`
|
|
5628
|
-
${tagContent.trim()}
|
|
5629
|
-
\`\`\``);
|
|
5630
|
-
} else {
|
|
5631
|
-
parts.push(`**${tagName}:** ${tagContent.trim()}`);
|
|
5632
|
-
}
|
|
5633
|
-
}
|
|
5634
|
-
}
|
|
5635
|
-
}
|
|
5636
|
-
return parts.join("\n\n");
|
|
5637
|
-
}
|
|
5638
|
-
function formatCommentParts(parts) {
|
|
5639
|
-
return parts.map((part) => {
|
|
5640
|
-
switch (part.kind) {
|
|
5641
|
-
case "text":
|
|
5642
|
-
return part.text;
|
|
5643
|
-
case "code":
|
|
5644
|
-
const codeText = part.text.replace(/```\w*\n?/g, "").replace(/\n?```/g, "").trim();
|
|
5645
|
-
if (codeText.includes("\n")) {
|
|
5646
|
-
return `\`\`\`
|
|
5647
|
-
${codeText}
|
|
5648
|
-
\`\`\``;
|
|
5649
|
-
} else {
|
|
5650
|
-
return codeText;
|
|
5651
|
-
}
|
|
5652
|
-
default:
|
|
5653
|
-
if ("tag" in part && part.tag === "@link" && typeof part.target === "string") {
|
|
5654
|
-
return `[${part.text}](${part.target})`;
|
|
5655
|
-
}
|
|
5656
|
-
return part.text;
|
|
5657
|
-
}
|
|
5658
|
-
}).join("").replace(/\n/g, " ").replace(/\s+/g, " ").trim();
|
|
5659
|
-
}
|
|
5660
|
-
function convertPropInfo(propInfo, isPartial, propType = void 0) {
|
|
5661
|
-
return {
|
|
5662
|
-
name: propInfo.name,
|
|
5663
|
-
type: extractBestType(propInfo),
|
|
5664
|
-
...propInfo.defaultValue && {
|
|
5665
|
-
defaultValue: cleanDefaultValue(propInfo.defaultValue)
|
|
5666
|
-
},
|
|
5667
|
-
description: formatComment(propInfo.comment || null),
|
|
5668
|
-
propType,
|
|
5669
|
-
required: extractRequired(propInfo, isPartial) || void 0
|
|
5670
|
-
};
|
|
5671
|
-
}
|
|
5672
5578
|
function extractBestType(propInfo) {
|
|
5673
5579
|
const type = propInfo.resolvedType?.prettyType || propInfo.type;
|
|
5674
5580
|
return cleanType(type.startsWith("| ") ? type.substring(2) : type);
|
|
@@ -5682,133 +5588,20 @@ function cleanType(type) {
|
|
|
5682
5588
|
function cleanDefaultValue(defaultValue) {
|
|
5683
5589
|
return defaultValue.replace(/^\n+/, "").replace(/\n+$/, "").trim();
|
|
5684
5590
|
}
|
|
5685
|
-
async function scanPages(routesFolder, verbose, excludePatterns = [], baseUrl) {
|
|
5686
|
-
const components = [];
|
|
5687
|
-
function shouldExclude(fileOrDir) {
|
|
5688
|
-
const dirName = basename(fileOrDir);
|
|
5689
|
-
return excludePatterns.some((pattern) => {
|
|
5690
|
-
if (pattern.includes("*")) {
|
|
5691
|
-
const regex = new RegExp(`^${pattern.replace(/\*/g, ".*")}$`);
|
|
5692
|
-
return regex.test(dirName);
|
|
5693
|
-
}
|
|
5694
|
-
return dirName === pattern;
|
|
5695
|
-
});
|
|
5696
|
-
}
|
|
5697
|
-
async function scanDirectory(dirPath) {
|
|
5698
|
-
if (shouldExclude(dirPath)) {
|
|
5699
|
-
if (verbose) {
|
|
5700
|
-
console.log(`Excluding directory: ${basename(dirPath)}`);
|
|
5701
|
-
}
|
|
5702
|
-
return;
|
|
5703
|
-
}
|
|
5704
|
-
const entries = await readdir(dirPath, { withFileTypes: true });
|
|
5705
|
-
const mdxFiles = entries.filter(
|
|
5706
|
-
(f) => f.name.endsWith(".mdx") && !shouldExclude(f.name)
|
|
5707
|
-
) ?? [];
|
|
5708
|
-
for (const mdxFile of mdxFiles) {
|
|
5709
|
-
const demosFolder = entries.find((f) => f.name === "demos");
|
|
5710
|
-
const demosFolderPath = demosFolder ? join3(dirPath, demosFolder.name) : void 0;
|
|
5711
|
-
const segments = getPathSegmentsFromFileName(
|
|
5712
|
-
join3(dirPath, mdxFile.name),
|
|
5713
|
-
routesFolder
|
|
5714
|
-
);
|
|
5715
|
-
const url = getPathnameFromPathSegments(segments);
|
|
5716
|
-
components.push({
|
|
5717
|
-
demosFolder: demosFolderPath,
|
|
5718
|
-
id: segments.join("-").trim(),
|
|
5719
|
-
mdxFile: join3(dirPath, mdxFile.name),
|
|
5720
|
-
name: segments.at(-1),
|
|
5721
|
-
path: dirPath,
|
|
5722
|
-
url: baseUrl ? new URL(url, baseUrl).toString() : void 0
|
|
5723
|
-
});
|
|
5724
|
-
if (verbose) {
|
|
5725
|
-
console.log(`Found component: ${basename(dirPath)}`);
|
|
5726
|
-
console.log(` Demos folder: ${demosFolderPath || "NOT FOUND"}`);
|
|
5727
|
-
}
|
|
5728
|
-
}
|
|
5729
|
-
for (const entry of entries) {
|
|
5730
|
-
const fullPath = join3(dirPath, entry.name);
|
|
5731
|
-
const stats = await stat(fullPath);
|
|
5732
|
-
if (stats.isDirectory()) {
|
|
5733
|
-
await scanDirectory(fullPath);
|
|
5734
|
-
}
|
|
5735
|
-
}
|
|
5736
|
-
}
|
|
5737
|
-
await scanDirectory(routesFolder);
|
|
5738
|
-
return components;
|
|
5739
|
-
}
|
|
5740
5591
|
function isPreviewLine(trimmedLine) {
|
|
5741
5592
|
return trimmedLine === "// preview" || /^\{\s*\/\*\s*preview\s*\*\/\s*\}$/.test(trimmedLine) || /^<!--\s*preview\s*-->$/.test(trimmedLine);
|
|
5742
5593
|
}
|
|
5743
|
-
function extractProps(props, isPartial) {
|
|
5744
|
-
const propsInfo = [];
|
|
5745
|
-
if (props.props?.length) {
|
|
5746
|
-
propsInfo.push(
|
|
5747
|
-
...props.props.map((prop) => convertPropInfo(prop, isPartial))
|
|
5748
|
-
);
|
|
5749
|
-
}
|
|
5750
|
-
if (props.input?.length) {
|
|
5751
|
-
propsInfo.push(
|
|
5752
|
-
...props.input.map((prop) => convertPropInfo(prop, isPartial, "input"))
|
|
5753
|
-
);
|
|
5754
|
-
}
|
|
5755
|
-
if (props.output?.length) {
|
|
5756
|
-
propsInfo.push(
|
|
5757
|
-
...props.output.map((prop) => convertPropInfo(prop, isPartial, "output"))
|
|
5758
|
-
);
|
|
5759
|
-
}
|
|
5760
|
-
return propsInfo;
|
|
5761
|
-
}
|
|
5762
5594
|
function removePreviewLines(code) {
|
|
5763
5595
|
return code.split("\n").filter((line) => !isPreviewLine(line.trim())).join("\n");
|
|
5764
5596
|
}
|
|
5765
|
-
function getIntroLines(
|
|
5597
|
+
function getIntroLines(projectName, description) {
|
|
5766
5598
|
const lines = [];
|
|
5767
5599
|
if (projectName) {
|
|
5768
5600
|
lines.push(`# ${projectName}`);
|
|
5769
|
-
lines.push("");
|
|
5770
5601
|
}
|
|
5771
5602
|
if (description) {
|
|
5772
|
-
lines.push(`> ${description}`);
|
|
5773
|
-
lines.push("");
|
|
5774
|
-
}
|
|
5775
|
-
lines.push("## Components and Integrations");
|
|
5776
|
-
lines.push("");
|
|
5777
|
-
for (const page of pages) {
|
|
5778
|
-
const url = baseUrl ? `${baseUrl}/${kebabCase(page.title)}` : `#${kebabCase(page.title)}`;
|
|
5779
|
-
if (page.title.includes("Introduction")) {
|
|
5780
|
-
lines.push(`- [${page.title}](${url}): introduction and getting started`);
|
|
5781
|
-
} else if (page.title.includes("Tailwind")) {
|
|
5782
|
-
lines.push(
|
|
5783
|
-
`- [${page.title}](${url}): integration documentation and examples`
|
|
5784
|
-
);
|
|
5785
|
-
} else {
|
|
5786
|
-
lines.push(
|
|
5787
|
-
`- [${page.title}](${url}): component documentation and examples`
|
|
5788
|
-
);
|
|
5789
|
-
}
|
|
5790
|
-
}
|
|
5791
|
-
return lines.join("\n");
|
|
5792
|
-
}
|
|
5793
|
-
async function generateLlmsTxt(pages, projectName, description, baseUrl) {
|
|
5794
|
-
const lines = [
|
|
5795
|
-
getIntroLines(pages, projectName, description, baseUrl)
|
|
5796
|
-
];
|
|
5797
|
-
lines.push("");
|
|
5798
|
-
for (const page of pages) {
|
|
5799
|
-
const content = page.content.split("\n").map((line) => {
|
|
5800
|
-
if (line.startsWith("#")) {
|
|
5801
|
-
return `#${line}`;
|
|
5802
|
-
}
|
|
5803
|
-
return line;
|
|
5804
|
-
});
|
|
5805
|
-
if (content.every((line) => !line.trim())) {
|
|
5806
|
-
continue;
|
|
5807
|
-
}
|
|
5808
|
-
lines.push(`## ${page.title}`);
|
|
5809
|
-
lines.push("");
|
|
5810
|
-
lines.push(content.join("\n"));
|
|
5811
5603
|
lines.push("");
|
|
5604
|
+
lines.push(`> ${description}`);
|
|
5812
5605
|
}
|
|
5813
5606
|
return lines.join("\n");
|
|
5814
5607
|
}
|
|
@@ -5839,44 +5632,11 @@ async function resolveModulePath(importPath, fromFile) {
|
|
|
5839
5632
|
}
|
|
5840
5633
|
return null;
|
|
5841
5634
|
}
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
return [];
|
|
5846
|
-
}
|
|
5847
|
-
visited.add(normalizedPath);
|
|
5848
|
-
const modules = [];
|
|
5849
|
-
try {
|
|
5850
|
-
const content = await readFile(normalizedPath, "utf-8");
|
|
5851
|
-
const relativeImports = extractRelativeImports(content);
|
|
5852
|
-
for (const importPath of relativeImports) {
|
|
5853
|
-
const resolvedPath = await resolveModulePath(importPath, normalizedPath);
|
|
5854
|
-
if (!resolvedPath) {
|
|
5855
|
-
if (verbose) {
|
|
5856
|
-
console.log(
|
|
5857
|
-
` Could not resolve import: ${importPath} from ${normalizedPath}`
|
|
5858
|
-
);
|
|
5859
|
-
}
|
|
5860
|
-
continue;
|
|
5861
|
-
}
|
|
5862
|
-
const importContent = await readFile(resolvedPath, "utf-8");
|
|
5863
|
-
modules.push({
|
|
5864
|
-
content: importContent,
|
|
5865
|
-
path: resolvedPath
|
|
5866
|
-
});
|
|
5867
|
-
const nestedModules = await collectRelativeImports(
|
|
5868
|
-
resolvedPath,
|
|
5869
|
-
visited,
|
|
5870
|
-
verbose
|
|
5871
|
-
);
|
|
5872
|
-
modules.push(...nestedModules);
|
|
5873
|
-
}
|
|
5874
|
-
} catch (error) {
|
|
5875
|
-
if (verbose) {
|
|
5876
|
-
console.log(` Error processing ${normalizedPath}: ${error}`);
|
|
5877
|
-
}
|
|
5878
|
-
}
|
|
5879
|
-
return modules;
|
|
5635
|
+
function extractMetadata(metadata) {
|
|
5636
|
+
return (metadata ?? []).map((current) => {
|
|
5637
|
+
const [key, value] = current.split("=");
|
|
5638
|
+
return [key, value];
|
|
5639
|
+
});
|
|
5880
5640
|
}
|
|
5881
5641
|
var replaceNpmInstallTabs = () => {
|
|
5882
5642
|
return (tree, _file, done) => {
|
|
@@ -5897,376 +5657,606 @@ var replaceNpmInstallTabs = () => {
|
|
|
5897
5657
|
done();
|
|
5898
5658
|
};
|
|
5899
5659
|
};
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5660
|
+
var KnowledgeGenerator = class {
|
|
5661
|
+
config;
|
|
5662
|
+
docProps = null;
|
|
5663
|
+
constructor(config2) {
|
|
5664
|
+
this.config = config2;
|
|
5665
|
+
}
|
|
5666
|
+
async run() {
|
|
5667
|
+
const extractedMetadata = extractMetadata(this.config.metadata);
|
|
5668
|
+
if (this.config.verbose) {
|
|
5669
|
+
console.log(`Scanning pages in: ${this.config.routeDir}`);
|
|
5670
|
+
if (this.config.exclude?.length) {
|
|
5671
|
+
console.log(`Excluding patterns: ${this.config.exclude.join(", ")}`);
|
|
5672
|
+
}
|
|
5673
|
+
}
|
|
5674
|
+
const [docProps, pages] = await Promise.all([
|
|
5675
|
+
this.loadDocProps(),
|
|
5676
|
+
this.scanPages()
|
|
5677
|
+
]);
|
|
5678
|
+
this.docProps = docProps;
|
|
5679
|
+
if (pages.length === 0) {
|
|
5680
|
+
console.log("No pages found.");
|
|
5681
|
+
return;
|
|
5682
|
+
}
|
|
5683
|
+
if (this.config.verbose) {
|
|
5684
|
+
console.log(`Found ${pages.length} page(s)`);
|
|
5685
|
+
}
|
|
5686
|
+
const processedPages = [];
|
|
5687
|
+
for (const page of pages) {
|
|
5688
|
+
try {
|
|
5689
|
+
const processed = await this.processComponent(page);
|
|
5690
|
+
processedPages.push(processed);
|
|
5691
|
+
} catch (error) {
|
|
5692
|
+
console.error(`Failed to process page: ${page.name}`);
|
|
5693
|
+
process.exit(1);
|
|
5694
|
+
}
|
|
5695
|
+
}
|
|
5696
|
+
if (this.config.clean) {
|
|
5697
|
+
await rm(this.config.outputPath, { force: true, recursive: true }).catch(
|
|
5698
|
+
() => {
|
|
5908
5699
|
}
|
|
5909
|
-
|
|
5910
|
-
|
|
5700
|
+
);
|
|
5701
|
+
}
|
|
5702
|
+
if (this.config.outputMode === "aggregated") {
|
|
5703
|
+
await this.generateAggregatedOutput(processedPages, pages);
|
|
5704
|
+
} else {
|
|
5705
|
+
await mkdir2(this.config.outputPath, { recursive: true }).catch(() => {
|
|
5706
|
+
});
|
|
5707
|
+
await this.generatePerPageExports(
|
|
5708
|
+
pages,
|
|
5709
|
+
processedPages,
|
|
5710
|
+
extractedMetadata
|
|
5711
|
+
);
|
|
5712
|
+
}
|
|
5713
|
+
}
|
|
5714
|
+
async loadDocProps() {
|
|
5715
|
+
const resolvedDocPropsPath = this.config.docPropsPath ? await exists(this.config.docPropsPath) ? this.config.docPropsPath : resolve5(process.cwd(), this.config.docPropsPath) : join3(dirname(this.config.routeDir), "doc-props.json");
|
|
5716
|
+
if (!await exists(resolvedDocPropsPath)) {
|
|
5717
|
+
if (this.config.verbose) {
|
|
5718
|
+
console.log(`Doc props file not found at: ${resolvedDocPropsPath}`);
|
|
5719
|
+
}
|
|
5720
|
+
return null;
|
|
5721
|
+
}
|
|
5722
|
+
try {
|
|
5723
|
+
const content = await readFile(resolvedDocPropsPath, "utf-8");
|
|
5724
|
+
const docProps = JSON.parse(content);
|
|
5725
|
+
if (this.config.verbose) {
|
|
5726
|
+
console.log(`Loaded doc props from: ${resolvedDocPropsPath}`);
|
|
5727
|
+
console.log(
|
|
5728
|
+
`Found ${Object.keys(docProps.props).length} component types`
|
|
5911
5729
|
);
|
|
5912
|
-
|
|
5913
|
-
|
|
5730
|
+
}
|
|
5731
|
+
return docProps;
|
|
5732
|
+
} catch (error) {
|
|
5733
|
+
if (this.config.verbose) {
|
|
5734
|
+
console.log(`Error loading doc props: ${error}`);
|
|
5735
|
+
}
|
|
5736
|
+
return null;
|
|
5737
|
+
}
|
|
5738
|
+
}
|
|
5739
|
+
async scanPages() {
|
|
5740
|
+
const components = [];
|
|
5741
|
+
const excludePatterns = this.config.exclude ?? [];
|
|
5742
|
+
const shouldExclude = (fileOrDir) => {
|
|
5743
|
+
const dirName = basename(fileOrDir);
|
|
5744
|
+
return excludePatterns.some((pattern) => {
|
|
5745
|
+
if (pattern.includes("*")) {
|
|
5746
|
+
const regex = new RegExp(`^${pattern.replace(/\*/g, ".*")}$`);
|
|
5747
|
+
return regex.test(dirName);
|
|
5748
|
+
}
|
|
5749
|
+
return dirName === pattern;
|
|
5750
|
+
});
|
|
5751
|
+
};
|
|
5752
|
+
const scanDirectory = async (dirPath) => {
|
|
5753
|
+
if (shouldExclude(dirPath)) {
|
|
5754
|
+
if (this.config.verbose) {
|
|
5755
|
+
console.log(`Excluding directory: ${basename(dirPath)}`);
|
|
5756
|
+
}
|
|
5757
|
+
return;
|
|
5758
|
+
}
|
|
5759
|
+
const entries = await readdir(dirPath, { withFileTypes: true });
|
|
5760
|
+
const mdxFiles = entries.filter(
|
|
5761
|
+
(f) => f.name.endsWith(".mdx") && !shouldExclude(f.name)
|
|
5762
|
+
) ?? [];
|
|
5763
|
+
for (const mdxFile of mdxFiles) {
|
|
5764
|
+
const demosFolder = entries.find((f) => f.name === "demos");
|
|
5765
|
+
const demosFolderPath = demosFolder ? join3(dirPath, demosFolder.name) : void 0;
|
|
5766
|
+
const segments = getPathSegmentsFromFileName(
|
|
5767
|
+
join3(dirPath, mdxFile.name),
|
|
5768
|
+
this.config.routeDir
|
|
5914
5769
|
);
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5770
|
+
const url = getPathnameFromPathSegments(segments);
|
|
5771
|
+
components.push({
|
|
5772
|
+
demosFolder: demosFolderPath,
|
|
5773
|
+
id: segments.join("-").trim(),
|
|
5774
|
+
mdxFile: join3(dirPath, mdxFile.name),
|
|
5775
|
+
name: segments.at(-1),
|
|
5776
|
+
path: dirPath,
|
|
5777
|
+
url: this.config.baseUrl ? new URL(url, this.config.baseUrl).toString() : void 0
|
|
5778
|
+
});
|
|
5779
|
+
if (this.config.verbose) {
|
|
5780
|
+
console.log(`Found component: ${basename(dirPath)}`);
|
|
5781
|
+
console.log(` Demos folder: ${demosFolderPath || "NOT FOUND"}`);
|
|
5920
5782
|
}
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5783
|
+
}
|
|
5784
|
+
for (const entry of entries) {
|
|
5785
|
+
const fullPath = join3(dirPath, entry.name);
|
|
5786
|
+
const stats = await stat(fullPath);
|
|
5787
|
+
if (stats.isDirectory()) {
|
|
5788
|
+
await scanDirectory(fullPath);
|
|
5927
5789
|
}
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5790
|
+
}
|
|
5791
|
+
};
|
|
5792
|
+
await scanDirectory(this.config.routeDir);
|
|
5793
|
+
return components;
|
|
5794
|
+
}
|
|
5795
|
+
async collectRelativeImports(filePath, visited = /* @__PURE__ */ new Set()) {
|
|
5796
|
+
const normalizedPath = resolve5(filePath);
|
|
5797
|
+
if (visited.has(normalizedPath)) {
|
|
5798
|
+
return [];
|
|
5799
|
+
}
|
|
5800
|
+
visited.add(normalizedPath);
|
|
5801
|
+
const modules = [];
|
|
5802
|
+
try {
|
|
5803
|
+
const content = await readFile(normalizedPath, "utf-8");
|
|
5804
|
+
const relativeImports = extractRelativeImports(content);
|
|
5805
|
+
for (const importPath of relativeImports) {
|
|
5806
|
+
const resolvedPath = await resolveModulePath(importPath, normalizedPath);
|
|
5807
|
+
if (!resolvedPath) {
|
|
5808
|
+
if (this.config.verbose) {
|
|
5809
|
+
console.log(
|
|
5810
|
+
` Could not resolve import: ${importPath} from ${normalizedPath}`
|
|
5811
|
+
);
|
|
5936
5812
|
}
|
|
5937
|
-
|
|
5938
|
-
}
|
|
5939
|
-
const propsDoc = extractProps(componentProps, Boolean(isPartial));
|
|
5940
|
-
if (verbose) {
|
|
5941
|
-
console.log(
|
|
5942
|
-
` Replaced TypeDocProps ${propsName} with API documentation`
|
|
5943
|
-
);
|
|
5813
|
+
continue;
|
|
5944
5814
|
}
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
value: JSON.stringify(propsDoc, null, 2)
|
|
5815
|
+
const importContent = await readFile(resolvedPath, "utf-8");
|
|
5816
|
+
modules.push({
|
|
5817
|
+
content: importContent,
|
|
5818
|
+
path: resolvedPath
|
|
5950
5819
|
});
|
|
5820
|
+
const nestedModules = await this.collectRelativeImports(
|
|
5821
|
+
resolvedPath,
|
|
5822
|
+
visited
|
|
5823
|
+
);
|
|
5824
|
+
modules.push(...nestedModules);
|
|
5951
5825
|
}
|
|
5952
|
-
)
|
|
5953
|
-
|
|
5954
|
-
};
|
|
5955
|
-
}
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
(
|
|
5963
|
-
|
|
5964
|
-
|
|
5826
|
+
} catch (error) {
|
|
5827
|
+
if (this.config.verbose) {
|
|
5828
|
+
console.log(` Error processing ${normalizedPath}: ${error}`);
|
|
5829
|
+
}
|
|
5830
|
+
}
|
|
5831
|
+
return modules;
|
|
5832
|
+
}
|
|
5833
|
+
extractProps(props, isPartial) {
|
|
5834
|
+
const propsInfo = [];
|
|
5835
|
+
if (props.props?.length) {
|
|
5836
|
+
propsInfo.push(
|
|
5837
|
+
...props.props.map((prop) => this.convertPropInfo(prop, isPartial))
|
|
5838
|
+
);
|
|
5839
|
+
}
|
|
5840
|
+
if (props.input?.length) {
|
|
5841
|
+
propsInfo.push(
|
|
5842
|
+
...props.input.map(
|
|
5843
|
+
(prop) => this.convertPropInfo(prop, isPartial, "input")
|
|
5844
|
+
)
|
|
5845
|
+
);
|
|
5846
|
+
}
|
|
5847
|
+
if (props.output?.length) {
|
|
5848
|
+
propsInfo.push(
|
|
5849
|
+
...props.output.map(
|
|
5850
|
+
(prop) => this.convertPropInfo(prop, isPartial, "output")
|
|
5851
|
+
)
|
|
5852
|
+
);
|
|
5853
|
+
}
|
|
5854
|
+
return propsInfo;
|
|
5855
|
+
}
|
|
5856
|
+
formatComment(comment) {
|
|
5857
|
+
if (!comment) {
|
|
5858
|
+
return "";
|
|
5859
|
+
}
|
|
5860
|
+
const parts = [];
|
|
5861
|
+
if (comment.summary && comment.summary.length > 0) {
|
|
5862
|
+
const summaryText = this.formatCommentParts(comment.summary);
|
|
5863
|
+
if (summaryText.trim()) {
|
|
5864
|
+
parts.push(summaryText.trim());
|
|
5865
|
+
}
|
|
5866
|
+
}
|
|
5867
|
+
if (comment.blockTags && comment.blockTags.length > 0) {
|
|
5868
|
+
for (const blockTag of comment.blockTags) {
|
|
5869
|
+
const tagContent = this.formatCommentParts(blockTag.content);
|
|
5870
|
+
if (tagContent.trim()) {
|
|
5871
|
+
const tagName = blockTag.tag.replace("@", "");
|
|
5872
|
+
if (tagName === "default" || tagName === "defaultValue") {
|
|
5873
|
+
continue;
|
|
5874
|
+
}
|
|
5875
|
+
if (tagName === "example") {
|
|
5876
|
+
parts.push(`**Example:**
|
|
5877
|
+
\`\`\`
|
|
5878
|
+
${tagContent.trim()}
|
|
5879
|
+
\`\`\``);
|
|
5880
|
+
} else {
|
|
5881
|
+
parts.push(`**${tagName}:** ${tagContent.trim()}`);
|
|
5882
|
+
}
|
|
5965
5883
|
}
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
const
|
|
5977
|
-
if (
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5884
|
+
}
|
|
5885
|
+
}
|
|
5886
|
+
return parts.join("\n\n");
|
|
5887
|
+
}
|
|
5888
|
+
formatCommentParts(parts) {
|
|
5889
|
+
return parts.map((part) => {
|
|
5890
|
+
switch (part.kind) {
|
|
5891
|
+
case "text":
|
|
5892
|
+
return part.text;
|
|
5893
|
+
case "code":
|
|
5894
|
+
const codeText = part.text.replace(/```\w*\n?/g, "").replace(/\n?```/g, "").trim();
|
|
5895
|
+
if (codeText.includes("\n")) {
|
|
5896
|
+
return `\`\`\`
|
|
5897
|
+
${codeText}
|
|
5898
|
+
\`\`\``;
|
|
5899
|
+
} else {
|
|
5900
|
+
return codeText;
|
|
5901
|
+
}
|
|
5902
|
+
default:
|
|
5903
|
+
if (this.config.outputMode === "per-page" && "tag" in part && part.tag === "@link" && typeof part.target === "string") {
|
|
5904
|
+
return `[${part.text}](${part.target})`;
|
|
5905
|
+
}
|
|
5906
|
+
return part.text;
|
|
5907
|
+
}
|
|
5908
|
+
}).join("").replace(/\n/g, " ").replace(/\s+/g, " ").trim();
|
|
5909
|
+
}
|
|
5910
|
+
convertPropInfo(propInfo, isPartial, propType = void 0) {
|
|
5911
|
+
return {
|
|
5912
|
+
name: propInfo.name,
|
|
5913
|
+
type: extractBestType(propInfo),
|
|
5914
|
+
...propInfo.defaultValue && {
|
|
5915
|
+
defaultValue: cleanDefaultValue(propInfo.defaultValue)
|
|
5916
|
+
},
|
|
5917
|
+
description: this.formatComment(propInfo.comment || null),
|
|
5918
|
+
propType,
|
|
5919
|
+
required: extractRequired(propInfo, isPartial) || void 0
|
|
5920
|
+
};
|
|
5921
|
+
}
|
|
5922
|
+
/**
|
|
5923
|
+
* Creates a remark plugin that replaces TypeDocProps JSX elements with JSON
|
|
5924
|
+
* code blocks containing component prop documentation.
|
|
5925
|
+
*/
|
|
5926
|
+
replaceTypeDocProps() {
|
|
5927
|
+
return () => (tree, _file, done) => {
|
|
5928
|
+
visit7(
|
|
5929
|
+
tree,
|
|
5930
|
+
"mdxJsxFlowElement",
|
|
5931
|
+
(node, index, parent) => {
|
|
5932
|
+
if (node?.name !== "TypeDocProps") {
|
|
5933
|
+
return;
|
|
5934
|
+
}
|
|
5935
|
+
const nameAttr = node.attributes?.find(
|
|
5936
|
+
(attr) => attr.type === "mdxJsxAttribute" && attr.name === "name"
|
|
5937
|
+
);
|
|
5938
|
+
const isPartial = node.attributes?.some(
|
|
5939
|
+
(attr) => attr.type === "mdxJsxAttribute" && attr.name === "partial"
|
|
5940
|
+
);
|
|
5941
|
+
if (!this.docProps || !nameAttr) {
|
|
5942
|
+
if (parent && index !== void 0) {
|
|
5943
|
+
parent.children.splice(index, 1);
|
|
5981
5944
|
}
|
|
5945
|
+
return;
|
|
5982
5946
|
}
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5947
|
+
const propsNames = extractNamesFromAttribute(nameAttr);
|
|
5948
|
+
if (propsNames.length === 0) {
|
|
5949
|
+
if (parent && index !== void 0) {
|
|
5950
|
+
parent.children.splice(index, 1);
|
|
5951
|
+
}
|
|
5952
|
+
return;
|
|
5987
5953
|
}
|
|
5988
|
-
|
|
5954
|
+
const propsName = propsNames[0];
|
|
5955
|
+
const componentProps = this.docProps.props[propsName];
|
|
5956
|
+
if (!componentProps) {
|
|
5957
|
+
if (this.config.verbose) {
|
|
5958
|
+
console.log(` TypeDocProps not found: ${propsName}`);
|
|
5959
|
+
}
|
|
5960
|
+
if (parent && index !== void 0) {
|
|
5961
|
+
parent.children.splice(index, 1);
|
|
5962
|
+
}
|
|
5963
|
+
return;
|
|
5964
|
+
}
|
|
5965
|
+
const propsDoc = this.extractProps(componentProps, Boolean(isPartial));
|
|
5966
|
+
if (this.config.verbose) {
|
|
5967
|
+
console.log(
|
|
5968
|
+
` Replaced TypeDocProps ${propsName} with API documentation`
|
|
5969
|
+
);
|
|
5970
|
+
}
|
|
5971
|
+
Object.assign(node, {
|
|
5972
|
+
lang: "json",
|
|
5973
|
+
meta: null,
|
|
5974
|
+
type: "code",
|
|
5975
|
+
value: JSON.stringify(propsDoc, null, 2)
|
|
5976
|
+
});
|
|
5989
5977
|
}
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
5978
|
+
);
|
|
5979
|
+
done();
|
|
5980
|
+
};
|
|
5981
|
+
}
|
|
5982
|
+
/**
|
|
5983
|
+
* Creates a remark plugin that replaces demo JSX elements (QdsDemo, CodeDemo,
|
|
5984
|
+
* Demo) with code blocks containing the demo source code from the demos folder.
|
|
5985
|
+
*/
|
|
5986
|
+
replaceDemos(demosFolder, demoFiles) {
|
|
5987
|
+
return () => async (tree) => {
|
|
5988
|
+
const promises = [];
|
|
5989
|
+
visit7(
|
|
5990
|
+
tree,
|
|
5991
|
+
"mdxJsxFlowElement",
|
|
5992
|
+
(node, index, parent) => {
|
|
5993
|
+
if (!node?.name || !["QdsDemo", "CodeDemo", "Demo"].includes(node.name)) {
|
|
5994
|
+
return;
|
|
5995
|
+
}
|
|
5996
|
+
const nameAttr = node.attributes?.find(
|
|
5997
|
+
(attr) => attr.type === "mdxJsxAttribute" && attr.name === "name"
|
|
5998
|
+
);
|
|
5999
|
+
const nodeAttr = node.attributes?.find(
|
|
6000
|
+
(attr) => attr.type === "mdxJsxAttribute" && attr.name === "node"
|
|
6001
|
+
);
|
|
6002
|
+
let demoName;
|
|
6003
|
+
if (nameAttr && typeof nameAttr.value === "string") {
|
|
6004
|
+
demoName = nameAttr.value;
|
|
6005
|
+
} else if (nodeAttr?.value && typeof nodeAttr.value !== "string") {
|
|
6006
|
+
const estree = nodeAttr.value.data?.estree;
|
|
6007
|
+
if (estree?.body?.[0]?.type === "ExpressionStatement") {
|
|
6008
|
+
const expression = estree.body[0].expression;
|
|
6009
|
+
if (expression.type === "MemberExpression" && expression.object.type === "Identifier" && expression.object.name === "Demo" && expression.property.type === "Identifier") {
|
|
6010
|
+
demoName = expression.property.name;
|
|
6000
6011
|
}
|
|
6001
|
-
return;
|
|
6002
6012
|
}
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
if (
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
+
}
|
|
6014
|
+
if (!demoName) {
|
|
6015
|
+
if (parent && index !== void 0) {
|
|
6016
|
+
parent.children.splice(index, 1);
|
|
6017
|
+
}
|
|
6018
|
+
return;
|
|
6019
|
+
}
|
|
6020
|
+
promises.push(
|
|
6021
|
+
(async () => {
|
|
6022
|
+
const kebabName = kebabCase(demoName);
|
|
6023
|
+
let filePath = `${kebabName}.tsx`;
|
|
6024
|
+
if (!demosFolder) {
|
|
6025
|
+
if (this.config.verbose) {
|
|
6026
|
+
console.log(` No demos folder for ${demoName}`);
|
|
6027
|
+
}
|
|
6013
6028
|
if (parent && index !== void 0) {
|
|
6014
6029
|
parent.children.splice(index, 1);
|
|
6015
6030
|
}
|
|
6016
6031
|
return;
|
|
6017
6032
|
}
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
if (verbose) {
|
|
6034
|
-
console.log(` Error reading demo ${demoName}: ${error}`);
|
|
6033
|
+
let demoFilePath = join3(demosFolder, filePath);
|
|
6034
|
+
let isAngularDemo = false;
|
|
6035
|
+
if (!await exists(demoFilePath)) {
|
|
6036
|
+
demoFilePath = join3(demosFolder, `${kebabName}.ts`);
|
|
6037
|
+
if (await exists(demoFilePath)) {
|
|
6038
|
+
isAngularDemo = true;
|
|
6039
|
+
filePath = `${kebabCase(demoName).replace("-component", ".component")}.ts`;
|
|
6040
|
+
demoFilePath = join3(demosFolder, filePath);
|
|
6041
|
+
} else {
|
|
6042
|
+
console.log(` Demo not found ${demoName}`);
|
|
6043
|
+
if (parent && index !== void 0) {
|
|
6044
|
+
parent.children.splice(index, 1);
|
|
6045
|
+
}
|
|
6046
|
+
return;
|
|
6047
|
+
}
|
|
6035
6048
|
}
|
|
6036
|
-
|
|
6037
|
-
|
|
6049
|
+
try {
|
|
6050
|
+
const demoCode = await readFile(demoFilePath, "utf-8");
|
|
6051
|
+
const cleanedCode = removePreviewLines(demoCode);
|
|
6052
|
+
if (this.config.verbose) {
|
|
6053
|
+
console.log(` Replaced demo ${demoName} with source code`);
|
|
6054
|
+
}
|
|
6055
|
+
demoFiles.push(demoFilePath);
|
|
6056
|
+
Object.assign(node, {
|
|
6057
|
+
lang: isAngularDemo ? "angular-ts" : "tsx",
|
|
6058
|
+
meta: null,
|
|
6059
|
+
type: "code",
|
|
6060
|
+
value: cleanedCode
|
|
6061
|
+
});
|
|
6062
|
+
} catch (error) {
|
|
6063
|
+
if (this.config.verbose) {
|
|
6064
|
+
console.log(` Error reading demo ${demoName}: ${error}`);
|
|
6065
|
+
}
|
|
6066
|
+
if (parent && index !== void 0) {
|
|
6067
|
+
parent.children.splice(index, 1);
|
|
6068
|
+
}
|
|
6038
6069
|
}
|
|
6039
|
-
}
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
|
|
6044
|
-
|
|
6045
|
-
}
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6070
|
+
})()
|
|
6071
|
+
);
|
|
6072
|
+
}
|
|
6073
|
+
);
|
|
6074
|
+
await Promise.all(promises);
|
|
6075
|
+
};
|
|
6076
|
+
}
|
|
6077
|
+
/**
|
|
6078
|
+
* Processes MDX content by transforming JSX elements (TypeDocProps, demos)
|
|
6079
|
+
* into markdown, resolving relative links, and cleaning up formatting.
|
|
6080
|
+
*/
|
|
6081
|
+
async processMdxContent(mdxContent, pageUrl, demosFolder) {
|
|
6082
|
+
const demoFiles = [];
|
|
6083
|
+
let processedContent = mdxContent;
|
|
6084
|
+
const lines = processedContent.split("\n");
|
|
6085
|
+
const titleLine = lines.findIndex((line) => line.startsWith("# "));
|
|
6086
|
+
processedContent = titleLine >= 0 ? lines.slice(titleLine + 1).join("\n") : processedContent;
|
|
6054
6087
|
processedContent = processedContent.replace(
|
|
6055
6088
|
/\[([^\]]+)\]\(\.\/#([^)]+)\)/g,
|
|
6056
|
-
(_, text, anchor) => `[${text}](${pageUrl}#${anchor})`
|
|
6089
|
+
(_, text, anchor) => pageUrl && this.config.outputMode === "per-page" ? `[${text}](${pageUrl}#${anchor})` : text
|
|
6057
6090
|
);
|
|
6091
|
+
const processor = unified4().use(remarkParse4).use(remarkMdx3).use(this.replaceTypeDocProps()).use(this.replaceDemos(demosFolder, demoFiles)).use(remarkStringify3);
|
|
6092
|
+
const processed = await processor.process(processedContent);
|
|
6093
|
+
processedContent = String(processed);
|
|
6094
|
+
processedContent = processedContent.replace(/\n\s*\n\s*\n/g, "\n\n");
|
|
6095
|
+
return { content: processedContent, demoFiles };
|
|
6058
6096
|
}
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
}
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6097
|
+
async processComponent(component) {
|
|
6098
|
+
try {
|
|
6099
|
+
const mdxContent = await readFile(component.mdxFile, "utf-8");
|
|
6100
|
+
if (this.config.verbose) {
|
|
6101
|
+
console.log(`Processing page: ${component.name}`);
|
|
6102
|
+
}
|
|
6103
|
+
const processor = unified4().use(remarkParse4).use(remarkMdx3).use(replaceNpmInstallTabs).use(remarkFrontmatter3, ["yaml"]).use(remarkParseFrontmatter2);
|
|
6104
|
+
if (this.config.outputMode === "per-page") {
|
|
6105
|
+
processor.use(remarkSelfLinkHeadings(component.url));
|
|
6106
|
+
}
|
|
6107
|
+
processor.use(remarkStringify3);
|
|
6108
|
+
const parsed = await processor.process(mdxContent);
|
|
6109
|
+
const frontmatter = parsed.data?.frontmatter || {};
|
|
6110
|
+
const { content: processedContent, demoFiles } = await this.processMdxContent(
|
|
6111
|
+
String(parsed),
|
|
6112
|
+
component.url,
|
|
6113
|
+
component.demosFolder
|
|
6114
|
+
);
|
|
6115
|
+
const removeJsxProcessor = unified4().use(remarkParse4).use(remarkMdx3).use(remarkRemoveJsx).use(remarkStringify3);
|
|
6116
|
+
const removedJsx = String(
|
|
6117
|
+
await removeJsxProcessor.process(processedContent)
|
|
6118
|
+
);
|
|
6119
|
+
const contentWithoutFrontmatter = removedJsx.replace(
|
|
6120
|
+
/^---[\s\S]*?---\n/,
|
|
6121
|
+
""
|
|
6122
|
+
);
|
|
6123
|
+
const title = frontmatter.title || component.name;
|
|
6124
|
+
return {
|
|
6125
|
+
content: contentWithoutFrontmatter.trim(),
|
|
6126
|
+
demoFiles,
|
|
6127
|
+
frontmatter,
|
|
6128
|
+
title,
|
|
6129
|
+
url: component.url
|
|
6130
|
+
};
|
|
6131
|
+
} catch (error) {
|
|
6132
|
+
console.error(`Error processing component ${component.name}:`, error);
|
|
6133
|
+
throw error;
|
|
6070
6134
|
}
|
|
6071
|
-
const processor = unified4().use(remarkParse4).use(remarkMdx3).use(replaceNpmInstallTabs).use(remarkFrontmatter3, ["yaml"]).use(remarkParseFrontmatter2).use(remarkSelfLinkHeadings(component.url)).use(remarkStringify3);
|
|
6072
|
-
const parsed = await processor.process(mdxContent);
|
|
6073
|
-
const frontmatter = parsed.data?.frontmatter || {};
|
|
6074
|
-
const { content: processedContent, demoFiles } = await processMdxContent(
|
|
6075
|
-
String(parsed),
|
|
6076
|
-
component.url,
|
|
6077
|
-
component.demosFolder,
|
|
6078
|
-
docProps,
|
|
6079
|
-
verbose
|
|
6080
|
-
);
|
|
6081
|
-
const removeJsxProcessor = unified4().use(remarkParse4).use(remarkMdx3).use(remarkRemoveJsx).use(remarkStringify3);
|
|
6082
|
-
const removedJsx = String(
|
|
6083
|
-
await removeJsxProcessor.process(processedContent)
|
|
6084
|
-
);
|
|
6085
|
-
const contentWithoutFrontmatter = removedJsx.replace(
|
|
6086
|
-
/^---[\s\S]*?---\n/,
|
|
6087
|
-
""
|
|
6088
|
-
);
|
|
6089
|
-
const title = frontmatter.title || component.name;
|
|
6090
|
-
return {
|
|
6091
|
-
content: contentWithoutFrontmatter.trim(),
|
|
6092
|
-
demoFiles,
|
|
6093
|
-
frontmatter,
|
|
6094
|
-
title
|
|
6095
|
-
};
|
|
6096
|
-
} catch (error) {
|
|
6097
|
-
console.error(`Error processing component ${component.name}:`, error);
|
|
6098
|
-
throw error;
|
|
6099
6135
|
}
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
}) {
|
|
6110
|
-
await mkdir2(dirname(outputPath), { recursive: true }).catch();
|
|
6111
|
-
const count = processedPages.length;
|
|
6112
|
-
let totalSize = 0;
|
|
6113
|
-
await Promise.all(
|
|
6114
|
-
processedPages.map(async (processedPage, index) => {
|
|
6115
|
-
const page = pages[index];
|
|
6116
|
-
const lines = [];
|
|
6117
|
-
if (metadata.length || page.url) {
|
|
6118
|
-
lines.push("---");
|
|
6119
|
-
if (page.url) {
|
|
6120
|
-
lines.push(`url: ${page.url}`);
|
|
6121
|
-
}
|
|
6122
|
-
if (metadata.length) {
|
|
6123
|
-
for (const [key, value] of metadata) {
|
|
6124
|
-
lines.push(`${key}: ${value}`);
|
|
6125
|
-
}
|
|
6136
|
+
async generateLlmsTxt(pages) {
|
|
6137
|
+
const lines = [
|
|
6138
|
+
getIntroLines(this.config.name, this.config.description)
|
|
6139
|
+
];
|
|
6140
|
+
lines.push("");
|
|
6141
|
+
for (const page of pages) {
|
|
6142
|
+
const content = page.content.split("\n").map((line) => {
|
|
6143
|
+
if (line.startsWith("#")) {
|
|
6144
|
+
return `#${line}`;
|
|
6126
6145
|
}
|
|
6127
|
-
|
|
6128
|
-
|
|
6146
|
+
return line;
|
|
6147
|
+
});
|
|
6148
|
+
if (content.every((line) => !line.trim())) {
|
|
6149
|
+
continue;
|
|
6129
6150
|
}
|
|
6130
|
-
lines.push(
|
|
6151
|
+
lines.push(`## ${page.title}`);
|
|
6131
6152
|
lines.push("");
|
|
6132
|
-
|
|
6133
|
-
page.name = processedPage.frontmatter.title;
|
|
6134
|
-
}
|
|
6135
|
-
let content = processedPage.content;
|
|
6136
|
-
if (pageTitlePrefix) {
|
|
6137
|
-
content = content.replace(
|
|
6138
|
-
`# ${page.name}`,
|
|
6139
|
-
`# ${pageTitlePrefix} ${page.name}`
|
|
6140
|
-
);
|
|
6141
|
-
page.name = `${pageTitlePrefix} ${page.name}`;
|
|
6142
|
-
}
|
|
6143
|
-
lines.push(content);
|
|
6153
|
+
lines.push(content.join("\n"));
|
|
6144
6154
|
lines.push("");
|
|
6145
|
-
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
|
|
6155
|
+
}
|
|
6156
|
+
return lines.join("\n");
|
|
6157
|
+
}
|
|
6158
|
+
async generateAggregatedOutput(processedPages, pages) {
|
|
6159
|
+
const llmsTxtContent = await this.generateLlmsTxt(processedPages);
|
|
6160
|
+
await mkdir2(dirname(this.config.outputPath), { recursive: true }).catch(
|
|
6161
|
+
() => {
|
|
6162
|
+
}
|
|
6163
|
+
);
|
|
6164
|
+
await writeFile3(this.config.outputPath, llmsTxtContent, "utf-8");
|
|
6165
|
+
const outputStats = await stat(this.config.outputPath);
|
|
6166
|
+
const outputSizeKb = (outputStats.size / 1024).toFixed(1);
|
|
6167
|
+
console.log(
|
|
6168
|
+
`Generated ${this.config.outputPath} with ${pages.length} component(s) at: ${this.config.outputPath}`
|
|
6169
|
+
);
|
|
6170
|
+
console.log(`File size: ${outputSizeKb} KB`);
|
|
6171
|
+
}
|
|
6172
|
+
async generatePerPageExports(pages, processedPages, metadata) {
|
|
6173
|
+
await mkdir2(dirname(this.config.outputPath), { recursive: true }).catch(
|
|
6174
|
+
() => {
|
|
6175
|
+
}
|
|
6176
|
+
);
|
|
6177
|
+
const count = processedPages.length;
|
|
6178
|
+
let totalSize = 0;
|
|
6179
|
+
await Promise.all(
|
|
6180
|
+
processedPages.map(async (processedPage, index) => {
|
|
6181
|
+
const page = pages[index];
|
|
6182
|
+
const lines = [];
|
|
6183
|
+
if (metadata.length || page.url) {
|
|
6184
|
+
lines.push("---");
|
|
6185
|
+
if (page.url) {
|
|
6186
|
+
lines.push(`url: ${page.url}`);
|
|
6187
|
+
}
|
|
6188
|
+
if (metadata.length) {
|
|
6189
|
+
for (const [key, value] of metadata) {
|
|
6190
|
+
lines.push(`${key}: ${value}`);
|
|
6191
|
+
}
|
|
6192
|
+
}
|
|
6193
|
+
lines.push("---");
|
|
6194
|
+
lines.push("");
|
|
6150
6195
|
}
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6196
|
+
lines.push(`# ${processedPage.title}`);
|
|
6197
|
+
lines.push("");
|
|
6198
|
+
if (processedPage.frontmatter?.title) {
|
|
6199
|
+
page.name = processedPage.frontmatter.title;
|
|
6200
|
+
}
|
|
6201
|
+
let content = processedPage.content;
|
|
6202
|
+
if (this.config.pageTitlePrefix) {
|
|
6203
|
+
content = content.replace(
|
|
6204
|
+
`# ${page.name}`,
|
|
6205
|
+
`# ${this.config.pageTitlePrefix} ${page.name}`
|
|
6157
6206
|
);
|
|
6158
|
-
|
|
6207
|
+
page.name = `${this.config.pageTitlePrefix} ${page.name}`;
|
|
6159
6208
|
}
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
)
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6209
|
+
lines.push(content);
|
|
6210
|
+
lines.push("");
|
|
6211
|
+
if (this.config.includeImports && processedPage.demoFiles.length > 0) {
|
|
6212
|
+
if (this.config.verbose) {
|
|
6213
|
+
console.log(
|
|
6214
|
+
`Collecting imports for ${page.name} from ${processedPage.demoFiles.length} demo files`
|
|
6215
|
+
);
|
|
6216
|
+
}
|
|
6217
|
+
const allImports = [];
|
|
6218
|
+
for (const demoFile of processedPage.demoFiles) {
|
|
6219
|
+
const imports = await this.collectRelativeImports(
|
|
6220
|
+
demoFile,
|
|
6221
|
+
/* @__PURE__ */ new Set()
|
|
6222
|
+
);
|
|
6223
|
+
allImports.push(...imports);
|
|
6224
|
+
}
|
|
6225
|
+
const uniqueImports = Array.from(
|
|
6226
|
+
new Map(allImports.map((m) => [m.path, m])).values()
|
|
6166
6227
|
);
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
lines.push(
|
|
6174
|
-
lines.push("");
|
|
6175
|
-
lines.push(`\`\`\`${ext}`);
|
|
6176
|
-
lines.push(importedModule.content);
|
|
6177
|
-
lines.push("```");
|
|
6228
|
+
if (this.config.verbose) {
|
|
6229
|
+
console.log(
|
|
6230
|
+
` Collected ${uniqueImports.length} unique import modules`
|
|
6231
|
+
);
|
|
6232
|
+
}
|
|
6233
|
+
if (uniqueImports.length > 0) {
|
|
6234
|
+
lines.push("## Related Source Files");
|
|
6178
6235
|
lines.push("");
|
|
6236
|
+
for (const importedModule of uniqueImports) {
|
|
6237
|
+
const ext = extname(importedModule.path).slice(1);
|
|
6238
|
+
lines.push(`### ${basename(importedModule.path)}`);
|
|
6239
|
+
lines.push("");
|
|
6240
|
+
lines.push(`\`\`\`${ext}`);
|
|
6241
|
+
lines.push(importedModule.content);
|
|
6242
|
+
lines.push("```");
|
|
6243
|
+
lines.push("");
|
|
6244
|
+
}
|
|
6179
6245
|
}
|
|
6180
6246
|
}
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
})
|
|
6187
|
-
);
|
|
6188
|
-
console.log(`Generated ${count} component(s) in ${outputPath}`);
|
|
6189
|
-
console.log(`Folder size: ${totalSize.toFixed(1)} KB`);
|
|
6190
|
-
}
|
|
6191
|
-
function extractMetadata(metadata) {
|
|
6192
|
-
return (metadata ?? []).map((current) => {
|
|
6193
|
-
const [key, value] = current.split("=");
|
|
6194
|
-
return [key, value];
|
|
6195
|
-
});
|
|
6196
|
-
}
|
|
6197
|
-
async function generate({
|
|
6198
|
-
baseUrl,
|
|
6199
|
-
clean,
|
|
6200
|
-
description,
|
|
6201
|
-
docPropsPath,
|
|
6202
|
-
exclude,
|
|
6203
|
-
includeImports,
|
|
6204
|
-
metadata,
|
|
6205
|
-
name,
|
|
6206
|
-
outputMode,
|
|
6207
|
-
outputPath,
|
|
6208
|
-
pageTitlePrefix,
|
|
6209
|
-
routeDir,
|
|
6210
|
-
verbose
|
|
6211
|
-
}) {
|
|
6212
|
-
const extractedMetadata = extractMetadata(metadata);
|
|
6213
|
-
if (verbose) {
|
|
6214
|
-
console.log(`Scanning pages in: ${routeDir}`);
|
|
6215
|
-
if (exclude?.length) {
|
|
6216
|
-
console.log(`Excluding patterns: ${exclude.join(", ")}`);
|
|
6217
|
-
}
|
|
6218
|
-
}
|
|
6219
|
-
const [docProps, pages] = await Promise.all([
|
|
6220
|
-
loadDocProps(routeDir, docPropsPath, verbose),
|
|
6221
|
-
scanPages(routeDir, verbose, exclude, baseUrl)
|
|
6222
|
-
]);
|
|
6223
|
-
if (pages.length === 0) {
|
|
6224
|
-
console.log("No pages found.");
|
|
6225
|
-
return;
|
|
6226
|
-
}
|
|
6227
|
-
if (verbose) {
|
|
6228
|
-
console.log(`Found ${pages.length} page(s)`);
|
|
6229
|
-
}
|
|
6230
|
-
const processedPages = [];
|
|
6231
|
-
for (const page of pages) {
|
|
6232
|
-
try {
|
|
6233
|
-
const processed = await processComponent(page, docProps, verbose);
|
|
6234
|
-
processedPages.push(processed);
|
|
6235
|
-
} catch (error) {
|
|
6236
|
-
console.error(`Failed to process page: ${page.name}`);
|
|
6237
|
-
process.exit(1);
|
|
6238
|
-
}
|
|
6239
|
-
}
|
|
6240
|
-
if (clean) {
|
|
6241
|
-
await rm(outputPath, { force: true, recursive: true }).catch();
|
|
6242
|
-
}
|
|
6243
|
-
if (outputMode === "aggregated") {
|
|
6244
|
-
const llmsTxtContent = await generateLlmsTxt(
|
|
6245
|
-
processedPages,
|
|
6246
|
-
name,
|
|
6247
|
-
description,
|
|
6248
|
-
baseUrl
|
|
6249
|
-
);
|
|
6250
|
-
await mkdir2(dirname(outputPath), { recursive: true }).catch();
|
|
6251
|
-
await writeFile3(outputPath, llmsTxtContent, "utf-8");
|
|
6252
|
-
const outputStats = await stat(outputPath);
|
|
6253
|
-
const outputSizeKb = (outputStats.size / 1024).toFixed(1);
|
|
6254
|
-
console.log(
|
|
6255
|
-
`Generated ${outputPath} with ${pages.length} component(s) at: ${outputPath}`
|
|
6247
|
+
const outfile = `${resolve5(this.config.outputPath)}/${kebabCase(page.id || page.name)}.md`;
|
|
6248
|
+
await writeFile3(outfile, lines.join("\n"), "utf-8");
|
|
6249
|
+
const stats = await stat(outfile);
|
|
6250
|
+
totalSize += stats.size / 1024;
|
|
6251
|
+
})
|
|
6256
6252
|
);
|
|
6257
|
-
console.log(`
|
|
6258
|
-
|
|
6259
|
-
await mkdir2(outputPath, { recursive: true }).catch();
|
|
6260
|
-
await generatePerPageExports({
|
|
6261
|
-
includeImports,
|
|
6262
|
-
metadata: extractedMetadata,
|
|
6263
|
-
outputPath,
|
|
6264
|
-
pages,
|
|
6265
|
-
pageTitlePrefix,
|
|
6266
|
-
processedPages,
|
|
6267
|
-
verbose
|
|
6268
|
-
});
|
|
6253
|
+
console.log(`Generated ${count} component(s) in ${this.config.outputPath}`);
|
|
6254
|
+
console.log(`Folder size: ${totalSize.toFixed(1)} KB`);
|
|
6269
6255
|
}
|
|
6256
|
+
};
|
|
6257
|
+
async function generate(config2) {
|
|
6258
|
+
const generator = new KnowledgeGenerator(config2);
|
|
6259
|
+
await generator.run();
|
|
6270
6260
|
}
|
|
6271
6261
|
function addGenerateKnowledgeCommand() {
|
|
6272
6262
|
program.description("Generate llms.txt from QUI Docs documentation").command("generate-llms-txt").option("-n, --name <name>", "Project name for llms.txt header").requiredOption("-m, --output-mode <outputMode>").option("-o, --outputPath <outputPath>", "Output file or directory.").option(
|
|
@@ -6288,14 +6278,7 @@ function addGenerateKnowledgeCommand() {
|
|
|
6288
6278
|
|
|
6289
6279
|
// src/open-web-ui-knowledge/upload-knowledge.ts
|
|
6290
6280
|
import { createHash as createHash2 } from "node:crypto";
|
|
6291
|
-
import {
|
|
6292
|
-
access as access2,
|
|
6293
|
-
mkdir as mkdir3,
|
|
6294
|
-
readdir as readdir2,
|
|
6295
|
-
readFile as readFile2,
|
|
6296
|
-
stat as stat2,
|
|
6297
|
-
writeFile as writeFile4
|
|
6298
|
-
} from "node:fs/promises";
|
|
6281
|
+
import { access as access2, readdir as readdir2, readFile as readFile2, stat as stat2 } from "node:fs/promises";
|
|
6299
6282
|
import { resolve as resolve6 } from "node:path";
|
|
6300
6283
|
import { setTimeout as setTimeout2 } from "node:timers/promises";
|
|
6301
6284
|
import ora from "ora";
|
|
@@ -6306,10 +6289,66 @@ function calculateFileHash(fileData) {
|
|
|
6306
6289
|
var Uploader = class {
|
|
6307
6290
|
config;
|
|
6308
6291
|
api;
|
|
6292
|
+
fileHashCache = /* @__PURE__ */ new Map();
|
|
6293
|
+
knowledgeFilesCache = null;
|
|
6309
6294
|
constructor(config2) {
|
|
6310
6295
|
this.config = config2;
|
|
6311
6296
|
this.api = new KnowledgeApi(config2);
|
|
6312
6297
|
}
|
|
6298
|
+
async buildHashCache(files) {
|
|
6299
|
+
const results = await Promise.allSettled(
|
|
6300
|
+
files.map(async (f) => {
|
|
6301
|
+
const data = await this.api.downloadFile(f.id);
|
|
6302
|
+
if (data) {
|
|
6303
|
+
this.fileHashCache.set(f.id, calculateFileHash(data));
|
|
6304
|
+
}
|
|
6305
|
+
})
|
|
6306
|
+
);
|
|
6307
|
+
const failures = results.filter((r) => r.status === "rejected");
|
|
6308
|
+
if (failures.length > 0) {
|
|
6309
|
+
console.warn(`Failed to cache ${failures.length} file hashes`);
|
|
6310
|
+
}
|
|
6311
|
+
}
|
|
6312
|
+
async waitForFileDeletion(fileId, fileName, maxAttempts = 15) {
|
|
6313
|
+
const spinner = ora(`File changed, deleting ${fileName}`).start();
|
|
6314
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
6315
|
+
this.knowledgeFilesCache = null;
|
|
6316
|
+
const knowledge = await this.api.listKnowledgeFiles();
|
|
6317
|
+
const stillExists = (knowledge.files ?? []).some((f) => f.id === fileId);
|
|
6318
|
+
if (!stillExists) {
|
|
6319
|
+
this.fileHashCache.delete(fileId);
|
|
6320
|
+
spinner.succeed(`File ${fileId} deleted`);
|
|
6321
|
+
return true;
|
|
6322
|
+
}
|
|
6323
|
+
await setTimeout2(100 * (i + 1));
|
|
6324
|
+
}
|
|
6325
|
+
spinner.stop();
|
|
6326
|
+
console.debug(`File ${fileId} may not have been fully deleted`);
|
|
6327
|
+
return false;
|
|
6328
|
+
}
|
|
6329
|
+
async uploadWithRetry(name, contents, maxRetries = 10) {
|
|
6330
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
6331
|
+
const result = await this.uploadFile(name, contents);
|
|
6332
|
+
if (result.success) {
|
|
6333
|
+
return result;
|
|
6334
|
+
}
|
|
6335
|
+
if (result.response?.detail?.includes("Duplicate content detected")) {
|
|
6336
|
+
console.warn(
|
|
6337
|
+
`Duplicate content: ${name} is already in knowledge base, skipping`
|
|
6338
|
+
);
|
|
6339
|
+
return { skipped: true, success: true };
|
|
6340
|
+
}
|
|
6341
|
+
if (attempt < maxRetries - 1) {
|
|
6342
|
+
const delay = 100 * Math.pow(2, attempt);
|
|
6343
|
+
console.debug(
|
|
6344
|
+
`Retrying ${name} in ${delay}ms (attempt ${attempt + 2}/${maxRetries})`
|
|
6345
|
+
);
|
|
6346
|
+
await setTimeout2(delay);
|
|
6347
|
+
}
|
|
6348
|
+
}
|
|
6349
|
+
console.debug(`Failed to upload ${name}`);
|
|
6350
|
+
return { success: false };
|
|
6351
|
+
}
|
|
6313
6352
|
get headers() {
|
|
6314
6353
|
return {
|
|
6315
6354
|
Authorization: `Bearer ${this.config.webUiKey}`
|
|
@@ -6326,32 +6365,28 @@ var Uploader = class {
|
|
|
6326
6365
|
name
|
|
6327
6366
|
}))
|
|
6328
6367
|
);
|
|
6329
|
-
const
|
|
6368
|
+
const knowledge = await this.api.listKnowledgeFiles();
|
|
6369
|
+
this.knowledgeFilesCache = knowledge.files ?? [];
|
|
6370
|
+
await this.buildHashCache(this.knowledgeFilesCache);
|
|
6371
|
+
let skippedCount = 0;
|
|
6330
6372
|
let successCount = 0;
|
|
6331
6373
|
let failureCount = 0;
|
|
6332
|
-
await this.api.listKnowledgeFiles();
|
|
6333
6374
|
for (const file of files) {
|
|
6334
|
-
|
|
6335
|
-
while (!result.success && result.count && result.count < 5) {
|
|
6336
|
-
console.debug("Failed to upload, retrying with count: ", result.count);
|
|
6337
|
-
await setTimeout2(100);
|
|
6338
|
-
result = await this.uploadFile(file.name, file.contents, result.count);
|
|
6339
|
-
}
|
|
6375
|
+
const result = await this.uploadWithRetry(file.name, file.contents);
|
|
6340
6376
|
if (result.skipped) {
|
|
6341
|
-
|
|
6342
|
-
}
|
|
6343
|
-
if (result.success) {
|
|
6377
|
+
skippedCount++;
|
|
6378
|
+
} else if (result.success) {
|
|
6344
6379
|
successCount++;
|
|
6345
6380
|
} else {
|
|
6346
6381
|
failureCount++;
|
|
6347
6382
|
}
|
|
6348
6383
|
}
|
|
6349
|
-
if (
|
|
6384
|
+
if (skippedCount > 0) {
|
|
6350
6385
|
console.debug(
|
|
6351
|
-
`Skipped uploading ${
|
|
6386
|
+
`Skipped uploading ${skippedCount} files because their contents did not change`
|
|
6352
6387
|
);
|
|
6353
6388
|
}
|
|
6354
|
-
const uploadCount = successCount
|
|
6389
|
+
const uploadCount = Math.abs(successCount);
|
|
6355
6390
|
if (uploadCount) {
|
|
6356
6391
|
console.debug(`Successfully uploaded ${uploadCount} files`);
|
|
6357
6392
|
}
|
|
@@ -6359,67 +6394,38 @@ var Uploader = class {
|
|
|
6359
6394
|
console.debug(`Failed to upload ${failureCount} files`);
|
|
6360
6395
|
}
|
|
6361
6396
|
}
|
|
6362
|
-
async uploadFile(name, contents
|
|
6363
|
-
const
|
|
6364
|
-
const knowledgeFile = (
|
|
6365
|
-
|
|
6366
|
-
)
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
if (!this.config.force && data) {
|
|
6371
|
-
if (calculateFileHash(data) === calculateFileHash(contents)) {
|
|
6372
|
-
return { skipped: true, success: true };
|
|
6373
|
-
}
|
|
6374
|
-
await mkdir3(resolve6(process.cwd(), `./temp/diff`), {
|
|
6375
|
-
recursive: true
|
|
6376
|
-
}).catch();
|
|
6377
|
-
await writeFile4(
|
|
6378
|
-
resolve6(process.cwd(), `./temp/diff/${name}-current.md`),
|
|
6379
|
-
contents,
|
|
6380
|
-
"utf-8"
|
|
6381
|
-
);
|
|
6382
|
-
await writeFile4(
|
|
6383
|
-
resolve6(process.cwd(), `./temp/diff/${name}-owui.md`),
|
|
6384
|
-
data,
|
|
6385
|
-
"utf-8"
|
|
6386
|
-
);
|
|
6387
|
-
const dataLines = data.split("\n");
|
|
6388
|
-
const contentLines = contents.split("\n");
|
|
6389
|
-
if (dataLines.length === contentLines.length) {
|
|
6390
|
-
const allLinesMatch = dataLines.every(
|
|
6391
|
-
(line, i) => line === contentLines[i]
|
|
6392
|
-
);
|
|
6393
|
-
if (allLinesMatch) {
|
|
6394
|
-
return { skipped: true, success: true };
|
|
6395
|
-
}
|
|
6396
|
-
}
|
|
6397
|
+
async uploadFile(name, contents) {
|
|
6398
|
+
const knowledgeFiles = this.knowledgeFilesCache ?? [];
|
|
6399
|
+
const knowledgeFile = knowledgeFiles.find((f) => f.meta.name === name);
|
|
6400
|
+
const contentHash = calculateFileHash(contents);
|
|
6401
|
+
if (knowledgeFile && !this.config.force) {
|
|
6402
|
+
const existingHash = this.fileHashCache.get(knowledgeFile.id);
|
|
6403
|
+
if (existingHash === contentHash) {
|
|
6404
|
+
return { skipped: true, success: true };
|
|
6397
6405
|
}
|
|
6398
6406
|
}
|
|
6399
|
-
const fileBuffer = await readFile2(
|
|
6400
|
-
resolve6(this.config.knowledgeFilePath, name)
|
|
6401
|
-
);
|
|
6402
6407
|
if (knowledgeFile) {
|
|
6403
6408
|
await this.api.removeKnowledgeFile(knowledgeFile.id);
|
|
6404
|
-
|
|
6409
|
+
await this.waitForFileDeletion(knowledgeFile.id, name);
|
|
6405
6410
|
}
|
|
6406
6411
|
const spinner = ora(`Uploading ${name}`).start();
|
|
6412
|
+
const fileBuffer = await readFile2(
|
|
6413
|
+
resolve6(this.config.knowledgeFilePath, name)
|
|
6414
|
+
);
|
|
6407
6415
|
const uploadResponse = await this.api.uploadFile(fileBuffer, name);
|
|
6408
6416
|
if (!uploadResponse.id || !uploadResponse.filename) {
|
|
6409
|
-
spinner.fail(`Error uploading ${name}
|
|
6410
|
-
|
|
6411
|
-
return { success: false };
|
|
6417
|
+
spinner.fail(`Error uploading ${name}`);
|
|
6418
|
+
return { response: uploadResponse, success: false };
|
|
6412
6419
|
}
|
|
6413
|
-
await setTimeout2(500);
|
|
6414
6420
|
spinner.text = `Associating ${name} with knowledge base`;
|
|
6415
6421
|
const addResponse = await this.api.associateFile(uploadResponse.id);
|
|
6416
6422
|
if (addResponse.name) {
|
|
6417
6423
|
spinner.succeed(`${name} associated with knowledge base`);
|
|
6424
|
+
this.fileHashCache.set(uploadResponse.id, contentHash);
|
|
6418
6425
|
return { success: true };
|
|
6419
6426
|
} else {
|
|
6420
|
-
spinner.
|
|
6421
|
-
|
|
6422
|
-
return { count: count + 1, success: false };
|
|
6427
|
+
spinner.stop();
|
|
6428
|
+
return { response: addResponse, success: false };
|
|
6423
6429
|
}
|
|
6424
6430
|
}
|
|
6425
6431
|
async uploadKnowledge() {
|
|
@@ -6459,7 +6465,7 @@ function addUploadKnowledgeCommand() {
|
|
|
6459
6465
|
// src/react-demo-plugin/generate-lazy-demo-map.ts
|
|
6460
6466
|
import { glob as glob3 } from "glob";
|
|
6461
6467
|
import { uniqBy } from "lodash-es";
|
|
6462
|
-
import { writeFile as
|
|
6468
|
+
import { writeFile as writeFile4 } from "node:fs/promises";
|
|
6463
6469
|
import { resolve as resolve8 } from "node:path";
|
|
6464
6470
|
import { dedent as dedent2 } from "@qualcomm-ui/utils/dedent";
|
|
6465
6471
|
|
|
@@ -6528,7 +6534,7 @@ async function generateLazyDemoMap(options) {
|
|
|
6528
6534
|
const demoPages = await scanForDemoPages({ routesDir });
|
|
6529
6535
|
console.log(`Found ${demoPages.length} pages with demos`);
|
|
6530
6536
|
const content = generateLazyDemoLoader(demoPages);
|
|
6531
|
-
await
|
|
6537
|
+
await writeFile4(outputPath, content, "utf-8");
|
|
6532
6538
|
console.log(`
|
|
6533
6539
|
Generated lazy demo loader at: ${outputPath}`);
|
|
6534
6540
|
}
|