@zohodesk/docs-builder
Version:
docs-builder is used to build your own docs
129 lines (108 loc) • 4.07 kB
JavaScript
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const t = require("@babel/types");
const path = require('path');
function getFilename(originalFilePath) {
return path.basename(originalFilePath).split('.')[0];
}
function convertKeyToValue(object = {}) {
return Object.keys(object).map(key => `["${object[key]}".trim()]: ${key}`).join(",");
}
function mergeDuplicateValues(obj) {
let mergedObj = {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
let value = obj[key];
let existingKey = Object.keys(mergedObj).find(k => mergedObj[k] === value);
if (existingKey) {
mergedObj[`${existingKey}, ${key}`] = value;
delete mergedObj[existingKey];
} else {
mergedObj[key] = value;
}
}
}
return mergedObj;
}
function createImportStatements(imports) {
return Object.entries(imports)
.map(([key, value]) => `import ${key} from '${value}';`)
.join("\n");
}
function reactLiveProcessor(source, originalFilePath, src) {
if (!source) { return '' };
const fileName = getFilename(originalFilePath);
let docCode = '';
let remainingBlock = '';
let hasReactImport = false;
let hasReactNamespaceImport = false;
const fileContent = source.trim();
const ast = parser.parse(fileContent, {
sourceType: 'module',
plugins: ['jsx', 'classProperties']
});
const importBlock = {};
const printableCode = {};
traverse(ast, {
ImportDeclaration(path) {
const importSource = path.node.source.value;
path.node.specifiers.forEach(specifier => {
let importName = specifier.local.name;
if (importSource === 'react') {
if (t.isImportDefaultSpecifier(specifier)) {
hasReactImport = true;
} else if (t.isImportNamespaceSpecifier(specifier)) {
hasReactNamespaceImport = true;
}
}
if (t.isImportSpecifier(specifier)) {
importBlock[`{ ${importName} }`] = importSource;
printableCode[`{ ${importName} }`] = importSource;
} else if (t.isImportDefaultSpecifier(specifier)) {
importBlock[importName] = importSource;
printableCode[importName] = importSource;
} else if (t.isImportNamespaceSpecifier(specifier)) {
importBlock[`* as ${importName}`] = importSource;
printableCode[importName] = importSource;
}
});
},
ExpressionStatement(path) {
const expression = path.get('expression');
const expressionLeft = expression.get('left');
if (expression.isAssignmentExpression() && expressionLeft.isMemberExpression()) {
const docCheck = expressionLeft.toString();
if (docCheck === `${fileName}.docs`) {
docCode = expression.toString();
path.remove();
} else if (docCheck.includes(fileName)) {
remainingBlock += fileContent.slice(path.node.start, path.node.end);
}
}
}
});
let importStatements = createImportStatements(importBlock);
if (!hasReactImport && hasReactNamespaceImport) {
importStatements = `import React from 'react';\n` + importStatements;
}
return `
${importStatements}
import { LiveProviderv3, LiveEditorv3, LiveErrorv3, LivePreviewv3, Wrapper, EditorWrapper, ErrorWrapper, PreviewWrapper } from '@zohodesk-private/react-live/es/index';
import lightTheme from '@zohodesk-private/react-live/es/v3/Editor/lightTheme';
export default class ${fileName} extends React.Component {
render() {
return (
<LiveProviderv3 needToolBox theme={lightTheme} scope={{import: {${convertKeyToValue(mergeDuplicateValues(printableCode))}}}} code={${JSON.stringify(src)}}>
<Wrapper>
<EditorWrapper><LiveEditorv3 /></EditorWrapper>
<PreviewWrapper><LivePreviewv3 /></PreviewWrapper>
<LiveErrorv3 needStyle />
</Wrapper>
</LiveProviderv3>
);
}
}
${docCode}
`;
}
module.exports = reactLiveProcessor;