UNPKG

@riotjs/compiler

Version:

Compiler for Riot.js .riot files

85 lines (78 loc) 3.42 kB
import { addComponentInterfaceToExportedObject, createDefaultExportFromLegacySyntax, extendTagProperty, filterNonExportDefaultStatements, findAllExportNamedDeclarations, findAllImportDeclarations, findComponentInterface, findExportDefaultStatement, getProgramBody, } from './utils.js' import addLinesOffset from '../../utils/add-lines-offset.js' import generateAST from '../../utils/generate-ast.js' import getPreprocessorTypeByAttribute from '../../utils/get-preprocessor-type-by-attribute.js' import isEmptySourcemap from '../../utils/is-empty-sourcemap.js' import { isNil } from '@riotjs/util/checks' import { isThisExpressionStatement } from '../../utils/ast-nodes-checks.js' import preprocess from '../../utils/preprocess-node.js' import sourcemapToJSON from '../../utils/sourcemap-as-json.js' /** * Generate the component javascript logic * @param { Object } sourceNode - node generated by the riot compiler * @param { string } source - original component source code * @param { Object } meta - compilation meta information * @param { AST } ast - current AST output * @returns { AST } the AST generated */ export default function javascript(sourceNode, source, meta, ast) { const preprocessorName = getPreprocessorTypeByAttribute(sourceNode) const javascriptNode = addLinesOffset( sourceNode.text.text, source, sourceNode, ) const { options } = meta const preprocessorOutput = preprocess('javascript', preprocessorName, meta, { ...sourceNode, text: javascriptNode, }) const inputSourceMap = sourcemapToJSON(preprocessorOutput.map) const generatedAst = generateAST(preprocessorOutput.code, { sourceFileName: options.file, inputSourceMap: isEmptySourcemap(inputSourceMap) ? null : inputSourceMap, }) const generatedAstBody = getProgramBody(generatedAst) const exportDefaultNode = findExportDefaultStatement(generatedAstBody) const isLegacyRiotSyntax = isNil(exportDefaultNode) const outputBody = getProgramBody(ast) const componentInterface = findComponentInterface(generatedAstBody) // throw in case of mixed component exports if (exportDefaultNode && generatedAstBody.some(isThisExpressionStatement)) throw new Error( 'You can\t use "export default {}" and root this statements in the same component', ) // add to the ast the "private" javascript content of our tag script node outputBody.unshift( ...// for the legacy riot syntax we need to move all the import and (named) export statements outside of the function body (isLegacyRiotSyntax ? [ ...findAllImportDeclarations(generatedAstBody), ...findAllExportNamedDeclarations(generatedAstBody), ] : // modern riot syntax will hoist all the private stuff outside of the export default statement filterNonExportDefaultStatements(generatedAstBody)), ) // create the public component export properties from the root this statements if (isLegacyRiotSyntax) extendTagProperty( ast, createDefaultExportFromLegacySyntax(generatedAstBody), ) // convert the export default adding its content to the component property exported if (exportDefaultNode) extendTagProperty(ast, exportDefaultNode) return componentInterface ? // add the component interface to the component object exported addComponentInterfaceToExportedObject(ast, componentInterface) : ast }