@ali-i18n-fe/dada-component
Version:
325 lines (270 loc) • 8.74 kB
JavaScript
const { getPackageConfig } = require("./utils");
const { getDefaultPublicPath } = require("./utils/def");
const path = require("path");
const fs = require("fs");
const { log } = require("@ali-i18n-fe/lsc-utils");
const get = require("lodash/get");
const glob = require("glob");
module.exports = {
currentPath: process.cwd(),
readmePath: path.resolve(process.cwd(), "README.md"),
readmeDocs: "",
demoDocs: "",
previewDocs: [],
usageDocs: [],
propsDocs: [],
load() {
this.outputPath = path.resolve(this.currentPath, "dist");
this.routeMap = require(path.resolve(this.outputPath, "routeMap.json"));
this.isLibraryComponent = Object.keys(this.routeMap).length > 1;
try {
this.writeReadmePreview();
} catch (e) {
log.error(e);
}
try {
this.writeReadmeDocs();
} catch (e) {
log.error(e);
}
try {
this.writeReadmeTypes();
} catch (e) {
log.error(e);
}
try {
this.writeDemo();
} catch (e) {
log.error(e);
}
try {
this.writeReadmeAll();
} catch (e) {
log.error(e);
}
},
writeReadmeTypes() {
if (!fs.existsSync(this.readmePath)) {
throw new Error("当前目录不存在README.md");
}
let typesDocs;
try {
const routeValues = Object.values(this.routeMap);
typesDocs = require(path.resolve(this.currentPath, "dist/typeFile.json"));
typesDocs = routeValues.map(displayName => typesDocs[displayName] || {});
} catch (e) {
throw new Error("读取typeFile异常");
}
if (!typesDocs) {
return;
}
this.propsDocs = typesDocs.map(typesDoc => {
const props = Object.values(typesDoc.props || {});
if (!props.length) {
return;
}
let propsTable = "property | propType | default | description\n";
propsTable += ":------: | :------: | :-----: | -----------\n";
const getType = function(path) {
return `${get(this, path, "")}`
.replace(/\n/g, "")
.replace(/[| ]+?undefined/g, "")
.replace(/[|]/g, "/");
};
props.forEach(propData => {
propData.getType = getType;
const name = propData.getType("name");
const type = propData.getType("type.name");
const defaultValue = propData.getType("defaultValue.value");
const description = propData.getType("description");
propsTable += `${name} | ${type} | ${defaultValue} | ${description} \n`;
});
return propsTable;
});
if (this.isLibraryComponent) {
return;
}
const readmeContent = fs.readFileSync(this.readmePath, "utf8");
const replaceContent = this.replaceContent(
readmeContent,
"DOCS_PROPS",
this.propsDocs[0]
);
fs.writeFileSync(this.readmePath, replaceContent, "utf8");
console.log("README 自动构建成功!", this.readmePath);
},
writeReadmeDocs() {
if (!fs.existsSync(this.readmePath)) {
throw new Error("当前目录不存在README.md");
}
const docsContent = this.getDocsContent();
if (!docsContent.length) {
throw new Error("未发现匹配Docs内容,请检查格式是否正确");
}
this.usageDocs = docsContent.map(
(content, index) =>
`\`\`\`tsx\n${this.getImports(
Object.values(this.routeMap)[index]
)}${content}\n\`\`\` `
);
if (this.isLibraryComponent) {
return;
}
const readmeContent = fs.readFileSync(this.readmePath, "utf8");
const writeContent = this.usageDocs[0];
const replaceContent = readmeContent.replace(
/\[!DOCS_USAGE.+?]/,
writeContent
);
fs.writeFileSync(this.readmePath, replaceContent, "utf8");
},
writeReadmePreview() {
if (!fs.existsSync(this.readmePath)) {
throw new Error("当前目录不存在README.md");
}
const previewUrl = this.getPreviewUrls();
this.previewDocs = previewUrl.map(url => ``);
if (this.isLibraryComponent) {
return;
}
const docsContent = this.previewDocs[0];
const readmeContent = fs.readFileSync(this.readmePath, "utf8");
const replaceContent = this.replaceContent(
readmeContent,
"DOCS_PREVIEW",
docsContent
);
fs.writeFileSync(this.readmePath, replaceContent, "utf8");
},
replaceContent(content, key, value) {
return content.replace(new RegExp(`(.+)?\\[!${key}.+?](.+)?`), () => value);
},
getPreviewUrls() {
const files = Object.keys(this.routeMap).map(route =>
route.replace(/docs\/(.+\/?)?index\.js$/, "$1preview.png")
);
if (!files.length) {
throw new Error("当前目录不存在Preview");
}
return files.map(file => `${getDefaultPublicPath()}docs/${file}`);
},
getDocsContent() {
const docsPaths = Object.keys(this.routeMap).map(route =>
route.replace(/docs\/(.+\/?)?index\.js$/, "$1docs.tsx")
);
return docsPaths.map(docsPath => {
const docsContent = fs.readFileSync(
path.resolve(this.currentPath, "src", docsPath),
"utf8"
);
const [, demoContent] =
/\/\*\*.+?DOCS_START.+?\*\*\/([\S\s]+?)\/\*\*.+?DOCS_END.+?\*\*\//.exec(
docsContent
) || [];
if (!demoContent) {
return null;
}
return demoContent.trim();
});
},
getImports(componentName) {
const packageInfo = getPackageConfig();
let imports = "";
imports += `import Components from '${packageInfo.name}';\n`;
imports += `import React from 'react';\n`;
imports += `import ReactDOM from 'react-dom';\n`;
imports += `\n`;
imports += `import '${packageInfo.name}/dist/index.css';\n`;
imports += `\n`;
if (this.isLibraryComponent) {
imports += `const Component = Components['${componentName}'];\n`;
} else {
imports += `const Component = Components;\n`;
}
imports += `\n`;
return imports;
},
writeDemo() {
if (!fs.existsSync(this.readmePath)) {
throw new Error("当前目录不存在README.md");
}
let demo;
if (fs.existsSync(path.resolve(this.outputPath, "stories/index.html"))) {
demo = `# Demo\n\n[Click to view demo](${getDefaultPublicPath()}stories/index.html)\n`;
} else {
demo = `[DOCS_DEMO]: [!DOCS_DEMO-自动生成,请勿修改]\n`;
}
const readmeContent = fs.readFileSync(this.readmePath, "utf8");
this.replaceContent(readmeContent, "DOCS_PROPS", this.propsDocs[0]);
const replaceContent = this.replaceContent(
readmeContent,
"DOCS_DEMO",
demo
);
if (replaceContent !== readmeContent) {
fs.writeFileSync(this.readmePath, replaceContent, "utf8");
}
this.demoDocs = demo;
},
writeReadmeAll() {
if (!fs.existsSync(this.readmePath)) {
throw new Error("当前目录不存在README.md");
}
const demo = this.demoDocs;
const componentNames = Object.values(this.routeMap);
const readmeAllItems = componentNames.map((key, index) => {
const preview = `# Preview\n\n${this.previewDocs[index] || ""}\n`;
const usage = `# Usage\n\n${this.usageDocs[index] || ""}\n`;
const props = `# Props\n\n${this.propsDocs[index] || ""}\n`;
return [preview, usage, props];
});
let replaceContent;
const readmeContent = fs.readFileSync(this.readmePath, "utf8");
if (!this.isLibraryComponent) {
const writeReadmeItems = readmeAllItems[0];
if (demo) {
writeReadmeItems.splice(1, 0, demo);
}
// single component
replaceContent = this.replaceContent(
readmeContent,
"DOCS_ALL",
writeReadmeItems.join("\n")
);
} else {
// lib components
const typeFile = require(path.resolve(
this.currentPath,
"dist/typeFile.json"
));
let writeContent = Object.values(this.routeMap)
.map(componentKey => {
const desc =
(typeFile[componentKey]
? typeFile[componentKey].description
: "") || "";
return `- **${componentKey}** ${desc}\n`;
})
.join("");
writeContent += "\n";
if (demo) {
writeContent += demo;
writeContent += "\n";
}
writeContent += readmeAllItems
.map((item, index) => {
const componentContent = item.map(con => "##" + con).join("\n");
return `## ${componentNames[index]}\n\n${componentContent}\n`;
})
.join("");
replaceContent = this.replaceContent(
readmeContent,
"DOCS_ALL",
writeContent
);
}
if (readmeContent !== replaceContent) {
fs.writeFileSync(this.readmePath, replaceContent, "utf8");
}
}
};