@qualcomm-ui/mdx-vite 2.5.1 → 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 -633
- 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,121 +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 = page.url ?? `#${kebabCase(page.title)}`;
|
|
5779
|
-
lines.push(`- [${page.title}](${url})`);
|
|
5780
|
-
}
|
|
5781
|
-
return lines.join("\n");
|
|
5782
|
-
}
|
|
5783
|
-
async function generateLlmsTxt(pages, projectName, description) {
|
|
5784
|
-
const lines = [getIntroLines(pages, projectName, description)];
|
|
5785
|
-
lines.push("");
|
|
5786
|
-
for (const page of pages) {
|
|
5787
|
-
const content = page.content.split("\n").map((line) => {
|
|
5788
|
-
if (line.startsWith("#")) {
|
|
5789
|
-
return `#${line}`;
|
|
5790
|
-
}
|
|
5791
|
-
return line;
|
|
5792
|
-
});
|
|
5793
|
-
if (content.every((line) => !line.trim())) {
|
|
5794
|
-
continue;
|
|
5795
|
-
}
|
|
5796
|
-
lines.push(`## ${page.title}`);
|
|
5797
|
-
lines.push("");
|
|
5798
|
-
lines.push(content.join("\n"));
|
|
5799
5603
|
lines.push("");
|
|
5604
|
+
lines.push(`> ${description}`);
|
|
5800
5605
|
}
|
|
5801
5606
|
return lines.join("\n");
|
|
5802
5607
|
}
|
|
@@ -5827,44 +5632,11 @@ async function resolveModulePath(importPath, fromFile) {
|
|
|
5827
5632
|
}
|
|
5828
5633
|
return null;
|
|
5829
5634
|
}
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
return [];
|
|
5834
|
-
}
|
|
5835
|
-
visited.add(normalizedPath);
|
|
5836
|
-
const modules = [];
|
|
5837
|
-
try {
|
|
5838
|
-
const content = await readFile(normalizedPath, "utf-8");
|
|
5839
|
-
const relativeImports = extractRelativeImports(content);
|
|
5840
|
-
for (const importPath of relativeImports) {
|
|
5841
|
-
const resolvedPath = await resolveModulePath(importPath, normalizedPath);
|
|
5842
|
-
if (!resolvedPath) {
|
|
5843
|
-
if (verbose) {
|
|
5844
|
-
console.log(
|
|
5845
|
-
` Could not resolve import: ${importPath} from ${normalizedPath}`
|
|
5846
|
-
);
|
|
5847
|
-
}
|
|
5848
|
-
continue;
|
|
5849
|
-
}
|
|
5850
|
-
const importContent = await readFile(resolvedPath, "utf-8");
|
|
5851
|
-
modules.push({
|
|
5852
|
-
content: importContent,
|
|
5853
|
-
path: resolvedPath
|
|
5854
|
-
});
|
|
5855
|
-
const nestedModules = await collectRelativeImports(
|
|
5856
|
-
resolvedPath,
|
|
5857
|
-
visited,
|
|
5858
|
-
verbose
|
|
5859
|
-
);
|
|
5860
|
-
modules.push(...nestedModules);
|
|
5861
|
-
}
|
|
5862
|
-
} catch (error) {
|
|
5863
|
-
if (verbose) {
|
|
5864
|
-
console.log(` Error processing ${normalizedPath}: ${error}`);
|
|
5865
|
-
}
|
|
5866
|
-
}
|
|
5867
|
-
return modules;
|
|
5635
|
+
function extractMetadata(metadata) {
|
|
5636
|
+
return (metadata ?? []).map((current) => {
|
|
5637
|
+
const [key, value] = current.split("=");
|
|
5638
|
+
return [key, value];
|
|
5639
|
+
});
|
|
5868
5640
|
}
|
|
5869
5641
|
var replaceNpmInstallTabs = () => {
|
|
5870
5642
|
return (tree, _file, done) => {
|
|
@@ -5885,376 +5657,606 @@ var replaceNpmInstallTabs = () => {
|
|
|
5885
5657
|
done();
|
|
5886
5658
|
};
|
|
5887
5659
|
};
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
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
|
+
() => {
|
|
5896
5699
|
}
|
|
5897
|
-
|
|
5898
|
-
|
|
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`
|
|
5899
5729
|
);
|
|
5900
|
-
|
|
5901
|
-
|
|
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
|
|
5902
5769
|
);
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
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"}`);
|
|
5908
5782
|
}
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
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);
|
|
5915
5789
|
}
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
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
|
+
);
|
|
5924
5812
|
}
|
|
5925
|
-
|
|
5926
|
-
}
|
|
5927
|
-
const propsDoc = extractProps(componentProps, Boolean(isPartial));
|
|
5928
|
-
if (verbose) {
|
|
5929
|
-
console.log(
|
|
5930
|
-
` Replaced TypeDocProps ${propsName} with API documentation`
|
|
5931
|
-
);
|
|
5813
|
+
continue;
|
|
5932
5814
|
}
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
value: JSON.stringify(propsDoc, null, 2)
|
|
5815
|
+
const importContent = await readFile(resolvedPath, "utf-8");
|
|
5816
|
+
modules.push({
|
|
5817
|
+
content: importContent,
|
|
5818
|
+
path: resolvedPath
|
|
5938
5819
|
});
|
|
5820
|
+
const nestedModules = await this.collectRelativeImports(
|
|
5821
|
+
resolvedPath,
|
|
5822
|
+
visited
|
|
5823
|
+
);
|
|
5824
|
+
modules.push(...nestedModules);
|
|
5939
5825
|
}
|
|
5940
|
-
)
|
|
5941
|
-
|
|
5942
|
-
};
|
|
5943
|
-
}
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
(
|
|
5951
|
-
|
|
5952
|
-
|
|
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
|
+
}
|
|
5953
5883
|
}
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
const
|
|
5965
|
-
if (
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
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);
|
|
5969
5944
|
}
|
|
5945
|
+
return;
|
|
5970
5946
|
}
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
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;
|
|
5975
5953
|
}
|
|
5976
|
-
|
|
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
|
+
});
|
|
5977
5977
|
}
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
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;
|
|
5988
6011
|
}
|
|
5989
|
-
return;
|
|
5990
6012
|
}
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
if (
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
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
|
+
}
|
|
6001
6028
|
if (parent && index !== void 0) {
|
|
6002
6029
|
parent.children.splice(index, 1);
|
|
6003
6030
|
}
|
|
6004
6031
|
return;
|
|
6005
6032
|
}
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
if (verbose) {
|
|
6022
|
-
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
|
+
}
|
|
6023
6048
|
}
|
|
6024
|
-
|
|
6025
|
-
|
|
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
|
+
}
|
|
6026
6069
|
}
|
|
6027
|
-
}
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
}
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
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;
|
|
6042
6087
|
processedContent = processedContent.replace(
|
|
6043
6088
|
/\[([^\]]+)\]\(\.\/#([^)]+)\)/g,
|
|
6044
|
-
(_, text, anchor) => `[${text}](${pageUrl}#${anchor})`
|
|
6089
|
+
(_, text, anchor) => pageUrl && this.config.outputMode === "per-page" ? `[${text}](${pageUrl}#${anchor})` : text
|
|
6045
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 };
|
|
6046
6096
|
}
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
}
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
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;
|
|
6058
6134
|
}
|
|
6059
|
-
const processor = unified4().use(remarkParse4).use(remarkMdx3).use(replaceNpmInstallTabs).use(remarkFrontmatter3, ["yaml"]).use(remarkParseFrontmatter2).use(remarkSelfLinkHeadings(component.url)).use(remarkStringify3);
|
|
6060
|
-
const parsed = await processor.process(mdxContent);
|
|
6061
|
-
const frontmatter = parsed.data?.frontmatter || {};
|
|
6062
|
-
const { content: processedContent, demoFiles } = await processMdxContent(
|
|
6063
|
-
String(parsed),
|
|
6064
|
-
component.url,
|
|
6065
|
-
component.demosFolder,
|
|
6066
|
-
docProps,
|
|
6067
|
-
verbose
|
|
6068
|
-
);
|
|
6069
|
-
const removeJsxProcessor = unified4().use(remarkParse4).use(remarkMdx3).use(remarkRemoveJsx).use(remarkStringify3);
|
|
6070
|
-
const removedJsx = String(
|
|
6071
|
-
await removeJsxProcessor.process(processedContent)
|
|
6072
|
-
);
|
|
6073
|
-
const contentWithoutFrontmatter = removedJsx.replace(
|
|
6074
|
-
/^---[\s\S]*?---\n/,
|
|
6075
|
-
""
|
|
6076
|
-
);
|
|
6077
|
-
const title = frontmatter.title || component.name;
|
|
6078
|
-
return {
|
|
6079
|
-
content: contentWithoutFrontmatter.trim(),
|
|
6080
|
-
demoFiles,
|
|
6081
|
-
frontmatter,
|
|
6082
|
-
title,
|
|
6083
|
-
url: component.url
|
|
6084
|
-
};
|
|
6085
|
-
} catch (error) {
|
|
6086
|
-
console.error(`Error processing component ${component.name}:`, error);
|
|
6087
|
-
throw error;
|
|
6088
6135
|
}
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
}) {
|
|
6099
|
-
await mkdir2(dirname(outputPath), { recursive: true }).catch();
|
|
6100
|
-
const count = processedPages.length;
|
|
6101
|
-
let totalSize = 0;
|
|
6102
|
-
await Promise.all(
|
|
6103
|
-
processedPages.map(async (processedPage, index) => {
|
|
6104
|
-
const page = pages[index];
|
|
6105
|
-
const lines = [];
|
|
6106
|
-
if (metadata.length || page.url) {
|
|
6107
|
-
lines.push("---");
|
|
6108
|
-
if (page.url) {
|
|
6109
|
-
lines.push(`url: ${page.url}`);
|
|
6110
|
-
}
|
|
6111
|
-
if (metadata.length) {
|
|
6112
|
-
for (const [key, value] of metadata) {
|
|
6113
|
-
lines.push(`${key}: ${value}`);
|
|
6114
|
-
}
|
|
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}`;
|
|
6115
6145
|
}
|
|
6116
|
-
|
|
6117
|
-
|
|
6146
|
+
return line;
|
|
6147
|
+
});
|
|
6148
|
+
if (content.every((line) => !line.trim())) {
|
|
6149
|
+
continue;
|
|
6118
6150
|
}
|
|
6119
|
-
lines.push(
|
|
6151
|
+
lines.push(`## ${page.title}`);
|
|
6120
6152
|
lines.push("");
|
|
6121
|
-
|
|
6122
|
-
page.name = processedPage.frontmatter.title;
|
|
6123
|
-
}
|
|
6124
|
-
let content = processedPage.content;
|
|
6125
|
-
if (pageTitlePrefix) {
|
|
6126
|
-
content = content.replace(
|
|
6127
|
-
`# ${page.name}`,
|
|
6128
|
-
`# ${pageTitlePrefix} ${page.name}`
|
|
6129
|
-
);
|
|
6130
|
-
page.name = `${pageTitlePrefix} ${page.name}`;
|
|
6131
|
-
}
|
|
6132
|
-
lines.push(content);
|
|
6153
|
+
lines.push(content.join("\n"));
|
|
6133
6154
|
lines.push("");
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
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("");
|
|
6139
6195
|
}
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
|
|
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}`
|
|
6146
6206
|
);
|
|
6147
|
-
|
|
6207
|
+
page.name = `${this.config.pageTitlePrefix} ${page.name}`;
|
|
6148
6208
|
}
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
)
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
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()
|
|
6155
6227
|
);
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
lines.push(
|
|
6163
|
-
lines.push("");
|
|
6164
|
-
lines.push(`\`\`\`${ext}`);
|
|
6165
|
-
lines.push(importedModule.content);
|
|
6166
|
-
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");
|
|
6167
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
|
+
}
|
|
6168
6245
|
}
|
|
6169
6246
|
}
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
})
|
|
6176
|
-
);
|
|
6177
|
-
console.log(`Generated ${count} component(s) in ${outputPath}`);
|
|
6178
|
-
console.log(`Folder size: ${totalSize.toFixed(1)} KB`);
|
|
6179
|
-
}
|
|
6180
|
-
function extractMetadata(metadata) {
|
|
6181
|
-
return (metadata ?? []).map((current) => {
|
|
6182
|
-
const [key, value] = current.split("=");
|
|
6183
|
-
return [key, value];
|
|
6184
|
-
});
|
|
6185
|
-
}
|
|
6186
|
-
async function generate({
|
|
6187
|
-
baseUrl,
|
|
6188
|
-
clean,
|
|
6189
|
-
description,
|
|
6190
|
-
docPropsPath,
|
|
6191
|
-
exclude,
|
|
6192
|
-
includeImports,
|
|
6193
|
-
metadata,
|
|
6194
|
-
name,
|
|
6195
|
-
outputMode,
|
|
6196
|
-
outputPath,
|
|
6197
|
-
pageTitlePrefix,
|
|
6198
|
-
routeDir,
|
|
6199
|
-
verbose
|
|
6200
|
-
}) {
|
|
6201
|
-
const extractedMetadata = extractMetadata(metadata);
|
|
6202
|
-
if (verbose) {
|
|
6203
|
-
console.log(`Scanning pages in: ${routeDir}`);
|
|
6204
|
-
if (exclude?.length) {
|
|
6205
|
-
console.log(`Excluding patterns: ${exclude.join(", ")}`);
|
|
6206
|
-
}
|
|
6207
|
-
}
|
|
6208
|
-
const [docProps, pages] = await Promise.all([
|
|
6209
|
-
loadDocProps(routeDir, docPropsPath, verbose),
|
|
6210
|
-
scanPages(routeDir, verbose, exclude, baseUrl)
|
|
6211
|
-
]);
|
|
6212
|
-
if (pages.length === 0) {
|
|
6213
|
-
console.log("No pages found.");
|
|
6214
|
-
return;
|
|
6215
|
-
}
|
|
6216
|
-
if (verbose) {
|
|
6217
|
-
console.log(`Found ${pages.length} page(s)`);
|
|
6218
|
-
}
|
|
6219
|
-
const processedPages = [];
|
|
6220
|
-
for (const page of pages) {
|
|
6221
|
-
try {
|
|
6222
|
-
const processed = await processComponent(page, docProps, verbose);
|
|
6223
|
-
processedPages.push(processed);
|
|
6224
|
-
} catch (error) {
|
|
6225
|
-
console.error(`Failed to process page: ${page.name}`);
|
|
6226
|
-
process.exit(1);
|
|
6227
|
-
}
|
|
6228
|
-
}
|
|
6229
|
-
if (clean) {
|
|
6230
|
-
await rm(outputPath, { force: true, recursive: true }).catch();
|
|
6231
|
-
}
|
|
6232
|
-
if (outputMode === "aggregated") {
|
|
6233
|
-
const llmsTxtContent = await generateLlmsTxt(
|
|
6234
|
-
processedPages,
|
|
6235
|
-
name,
|
|
6236
|
-
description
|
|
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
|
+
})
|
|
6237
6252
|
);
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
const outputStats = await stat(outputPath);
|
|
6241
|
-
const outputSizeKb = (outputStats.size / 1024).toFixed(1);
|
|
6242
|
-
console.log(
|
|
6243
|
-
`Generated ${outputPath} with ${pages.length} component(s) at: ${outputPath}`
|
|
6244
|
-
);
|
|
6245
|
-
console.log(`File size: ${outputSizeKb} KB`);
|
|
6246
|
-
} else {
|
|
6247
|
-
await mkdir2(outputPath, { recursive: true }).catch();
|
|
6248
|
-
await generatePerPageExports({
|
|
6249
|
-
includeImports,
|
|
6250
|
-
metadata: extractedMetadata,
|
|
6251
|
-
outputPath,
|
|
6252
|
-
pages,
|
|
6253
|
-
pageTitlePrefix,
|
|
6254
|
-
processedPages,
|
|
6255
|
-
verbose
|
|
6256
|
-
});
|
|
6253
|
+
console.log(`Generated ${count} component(s) in ${this.config.outputPath}`);
|
|
6254
|
+
console.log(`Folder size: ${totalSize.toFixed(1)} KB`);
|
|
6257
6255
|
}
|
|
6256
|
+
};
|
|
6257
|
+
async function generate(config2) {
|
|
6258
|
+
const generator = new KnowledgeGenerator(config2);
|
|
6259
|
+
await generator.run();
|
|
6258
6260
|
}
|
|
6259
6261
|
function addGenerateKnowledgeCommand() {
|
|
6260
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(
|
|
@@ -6276,14 +6278,7 @@ function addGenerateKnowledgeCommand() {
|
|
|
6276
6278
|
|
|
6277
6279
|
// src/open-web-ui-knowledge/upload-knowledge.ts
|
|
6278
6280
|
import { createHash as createHash2 } from "node:crypto";
|
|
6279
|
-
import {
|
|
6280
|
-
access as access2,
|
|
6281
|
-
mkdir as mkdir3,
|
|
6282
|
-
readdir as readdir2,
|
|
6283
|
-
readFile as readFile2,
|
|
6284
|
-
stat as stat2,
|
|
6285
|
-
writeFile as writeFile4
|
|
6286
|
-
} from "node:fs/promises";
|
|
6281
|
+
import { access as access2, readdir as readdir2, readFile as readFile2, stat as stat2 } from "node:fs/promises";
|
|
6287
6282
|
import { resolve as resolve6 } from "node:path";
|
|
6288
6283
|
import { setTimeout as setTimeout2 } from "node:timers/promises";
|
|
6289
6284
|
import ora from "ora";
|
|
@@ -6294,10 +6289,66 @@ function calculateFileHash(fileData) {
|
|
|
6294
6289
|
var Uploader = class {
|
|
6295
6290
|
config;
|
|
6296
6291
|
api;
|
|
6292
|
+
fileHashCache = /* @__PURE__ */ new Map();
|
|
6293
|
+
knowledgeFilesCache = null;
|
|
6297
6294
|
constructor(config2) {
|
|
6298
6295
|
this.config = config2;
|
|
6299
6296
|
this.api = new KnowledgeApi(config2);
|
|
6300
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
|
+
}
|
|
6301
6352
|
get headers() {
|
|
6302
6353
|
return {
|
|
6303
6354
|
Authorization: `Bearer ${this.config.webUiKey}`
|
|
@@ -6314,32 +6365,28 @@ var Uploader = class {
|
|
|
6314
6365
|
name
|
|
6315
6366
|
}))
|
|
6316
6367
|
);
|
|
6317
|
-
const
|
|
6368
|
+
const knowledge = await this.api.listKnowledgeFiles();
|
|
6369
|
+
this.knowledgeFilesCache = knowledge.files ?? [];
|
|
6370
|
+
await this.buildHashCache(this.knowledgeFilesCache);
|
|
6371
|
+
let skippedCount = 0;
|
|
6318
6372
|
let successCount = 0;
|
|
6319
6373
|
let failureCount = 0;
|
|
6320
|
-
await this.api.listKnowledgeFiles();
|
|
6321
6374
|
for (const file of files) {
|
|
6322
|
-
|
|
6323
|
-
while (!result.success && result.count && result.count < 5) {
|
|
6324
|
-
console.debug("Failed to upload, retrying with count: ", result.count);
|
|
6325
|
-
await setTimeout2(100);
|
|
6326
|
-
result = await this.uploadFile(file.name, file.contents, result.count);
|
|
6327
|
-
}
|
|
6375
|
+
const result = await this.uploadWithRetry(file.name, file.contents);
|
|
6328
6376
|
if (result.skipped) {
|
|
6329
|
-
|
|
6330
|
-
}
|
|
6331
|
-
if (result.success) {
|
|
6377
|
+
skippedCount++;
|
|
6378
|
+
} else if (result.success) {
|
|
6332
6379
|
successCount++;
|
|
6333
6380
|
} else {
|
|
6334
6381
|
failureCount++;
|
|
6335
6382
|
}
|
|
6336
6383
|
}
|
|
6337
|
-
if (
|
|
6384
|
+
if (skippedCount > 0) {
|
|
6338
6385
|
console.debug(
|
|
6339
|
-
`Skipped uploading ${
|
|
6386
|
+
`Skipped uploading ${skippedCount} files because their contents did not change`
|
|
6340
6387
|
);
|
|
6341
6388
|
}
|
|
6342
|
-
const uploadCount = successCount
|
|
6389
|
+
const uploadCount = Math.abs(successCount);
|
|
6343
6390
|
if (uploadCount) {
|
|
6344
6391
|
console.debug(`Successfully uploaded ${uploadCount} files`);
|
|
6345
6392
|
}
|
|
@@ -6347,67 +6394,38 @@ var Uploader = class {
|
|
|
6347
6394
|
console.debug(`Failed to upload ${failureCount} files`);
|
|
6348
6395
|
}
|
|
6349
6396
|
}
|
|
6350
|
-
async uploadFile(name, contents
|
|
6351
|
-
const
|
|
6352
|
-
const knowledgeFile = (
|
|
6353
|
-
|
|
6354
|
-
)
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
if (!this.config.force && data) {
|
|
6359
|
-
if (calculateFileHash(data) === calculateFileHash(contents)) {
|
|
6360
|
-
return { skipped: true, success: true };
|
|
6361
|
-
}
|
|
6362
|
-
await mkdir3(resolve6(process.cwd(), `./temp/diff`), {
|
|
6363
|
-
recursive: true
|
|
6364
|
-
}).catch();
|
|
6365
|
-
await writeFile4(
|
|
6366
|
-
resolve6(process.cwd(), `./temp/diff/${name}-current.md`),
|
|
6367
|
-
contents,
|
|
6368
|
-
"utf-8"
|
|
6369
|
-
);
|
|
6370
|
-
await writeFile4(
|
|
6371
|
-
resolve6(process.cwd(), `./temp/diff/${name}-owui.md`),
|
|
6372
|
-
data,
|
|
6373
|
-
"utf-8"
|
|
6374
|
-
);
|
|
6375
|
-
const dataLines = data.split("\n");
|
|
6376
|
-
const contentLines = contents.split("\n");
|
|
6377
|
-
if (dataLines.length === contentLines.length) {
|
|
6378
|
-
const allLinesMatch = dataLines.every(
|
|
6379
|
-
(line, i) => line === contentLines[i]
|
|
6380
|
-
);
|
|
6381
|
-
if (allLinesMatch) {
|
|
6382
|
-
return { skipped: true, success: true };
|
|
6383
|
-
}
|
|
6384
|
-
}
|
|
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 };
|
|
6385
6405
|
}
|
|
6386
6406
|
}
|
|
6387
|
-
const fileBuffer = await readFile2(
|
|
6388
|
-
resolve6(this.config.knowledgeFilePath, name)
|
|
6389
|
-
);
|
|
6390
6407
|
if (knowledgeFile) {
|
|
6391
6408
|
await this.api.removeKnowledgeFile(knowledgeFile.id);
|
|
6392
|
-
|
|
6409
|
+
await this.waitForFileDeletion(knowledgeFile.id, name);
|
|
6393
6410
|
}
|
|
6394
6411
|
const spinner = ora(`Uploading ${name}`).start();
|
|
6412
|
+
const fileBuffer = await readFile2(
|
|
6413
|
+
resolve6(this.config.knowledgeFilePath, name)
|
|
6414
|
+
);
|
|
6395
6415
|
const uploadResponse = await this.api.uploadFile(fileBuffer, name);
|
|
6396
6416
|
if (!uploadResponse.id || !uploadResponse.filename) {
|
|
6397
|
-
spinner.fail(`Error uploading ${name}
|
|
6398
|
-
|
|
6399
|
-
return { success: false };
|
|
6417
|
+
spinner.fail(`Error uploading ${name}`);
|
|
6418
|
+
return { response: uploadResponse, success: false };
|
|
6400
6419
|
}
|
|
6401
|
-
await setTimeout2(500);
|
|
6402
6420
|
spinner.text = `Associating ${name} with knowledge base`;
|
|
6403
6421
|
const addResponse = await this.api.associateFile(uploadResponse.id);
|
|
6404
6422
|
if (addResponse.name) {
|
|
6405
6423
|
spinner.succeed(`${name} associated with knowledge base`);
|
|
6424
|
+
this.fileHashCache.set(uploadResponse.id, contentHash);
|
|
6406
6425
|
return { success: true };
|
|
6407
6426
|
} else {
|
|
6408
|
-
spinner.
|
|
6409
|
-
|
|
6410
|
-
return { count: count + 1, success: false };
|
|
6427
|
+
spinner.stop();
|
|
6428
|
+
return { response: addResponse, success: false };
|
|
6411
6429
|
}
|
|
6412
6430
|
}
|
|
6413
6431
|
async uploadKnowledge() {
|
|
@@ -6447,7 +6465,7 @@ function addUploadKnowledgeCommand() {
|
|
|
6447
6465
|
// src/react-demo-plugin/generate-lazy-demo-map.ts
|
|
6448
6466
|
import { glob as glob3 } from "glob";
|
|
6449
6467
|
import { uniqBy } from "lodash-es";
|
|
6450
|
-
import { writeFile as
|
|
6468
|
+
import { writeFile as writeFile4 } from "node:fs/promises";
|
|
6451
6469
|
import { resolve as resolve8 } from "node:path";
|
|
6452
6470
|
import { dedent as dedent2 } from "@qualcomm-ui/utils/dedent";
|
|
6453
6471
|
|
|
@@ -6516,7 +6534,7 @@ async function generateLazyDemoMap(options) {
|
|
|
6516
6534
|
const demoPages = await scanForDemoPages({ routesDir });
|
|
6517
6535
|
console.log(`Found ${demoPages.length} pages with demos`);
|
|
6518
6536
|
const content = generateLazyDemoLoader(demoPages);
|
|
6519
|
-
await
|
|
6537
|
+
await writeFile4(outputPath, content, "utf-8");
|
|
6520
6538
|
console.log(`
|
|
6521
6539
|
Generated lazy demo loader at: ${outputPath}`);
|
|
6522
6540
|
}
|