You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

92 lines
3.5 KiB

import {TAG_LOGIC_PROPERTY} from '../../constants'
import addLinesOffset from '../../utils/add-lines-offset'
import generateAST from '../../utils/generate-ast'
import getPreprocessorTypeByAttribute from '../../utils/get-preprocessor-type-by-attribute'
import isEmptySourcemap from '../../utils/is-empty-sourcemap'
import {isExportDefaultStatement} from '../../utils/ast-nodes-checks'
import preprocess from '../../utils/preprocess-node'
import sourcemapToJSON from '../../utils/sourcemap-as-json'
import {types} from '../../utils/build-types'
/**
* Find the export default statement
* @param { Array } body - tree structure containing the program code
* @returns { Object } node containing only the code of the export default statement
*/
function findExportDefaultStatement(body) {
return body.find(isExportDefaultStatement)
}
/**
* Find all the code in an ast program except for the export default statements
* @param { Array } body - tree structure containing the program code
* @returns { Array } array containing all the program code except the export default expressions
*/
function filterNonExportDefaultStatements(body) {
return body.filter(node => !isExportDefaultStatement(node))
}
/**
* Get the body of the AST structure
* @param { Object } ast - ast object generated by recast
* @returns { Array } array containing the program code
*/
function getProgramBody(ast) {
return ast.body || ast.program.body
}
/**
* Extend the AST adding the new tag method containing our tag sourcecode
* @param { Object } ast - current output ast
* @param { Object } exportDefaultNode - tag export default node
* @returns { Object } the output ast having the "tag" key extended with the content of the export default
*/
function extendTagProperty(ast, exportDefaultNode) {
types.visit(ast, {
visitProperty(path) {
if (path.value.key.value === TAG_LOGIC_PROPERTY) {
path.value.value = exportDefaultNode.declaration
return false
}
this.traverse(path)
}
})
return ast
}
/**
* 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 bodyWithoutExportDefault = filterNonExportDefaultStatements(generatedAstBody)
const exportDefaultNode = findExportDefaultStatement(generatedAstBody)
const outputBody = getProgramBody(ast)
// add to the ast the "private" javascript content of our tag script node
outputBody.unshift(...bodyWithoutExportDefault)
// convert the export default adding its content to the "tag" property exported
if (exportDefaultNode) extendTagProperty(ast, exportDefaultNode)
return ast
}