UNPKG

@zohodesk/docs-builder

Version:

docs-builder is used to build your own docs

129 lines (108 loc) 4.07 kB
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;