Skip to content

Commit 3768c62

Browse files
added: the javascript parser for the tag logic
1 parent a59dacf commit 3768c62

File tree

6 files changed

+76
-7
lines changed

6 files changed

+76
-7
lines changed

.eslintignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
**/coverage/
22
**/dist/
33
**/test/expected/
4-
**/test/fixtures/
4+
**/test/fixtures/

src/generators/css/index.js

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ function wrapOutput(code) {
1515
return `${CSS_EXPORT_PREFIX}${minifyString(code)}${CSS_EXPORT_POSTFIX}`
1616
}
1717

18-
1918
/**
2019
* Generate the component css
2120
* @param { Object } sourceNode - node generated by the riot compiler
+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export const IMPORT_DECLARATION = 'ImportDeclaration'
2+
export const DEFAULT_EXPORT_DECLARATION = 'ExportDefaultDeclaration'
23
export const JS_EXPORT = 'export default (function tag() {})();'

src/generators/javascript/index.js

+70-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
1-
import {IMPORT_DECLARATION, JS_EXPORT} from './constants'
1+
import {DEFAULT_EXPORT_DECLARATION, IMPORT_DECLARATION, JS_EXPORT} from './constants'
2+
import compose from '../../utils/compose'
23
import getPreprocessorTypeByAttribute from '../../utils/get-preprocessor-type-by-attribute'
34
import mergeOutputChunks from '../../utils/merge-output-chunks'
45
import preprocess from '../../utils/preprocess-node'
56
import recast from 'recast'
67

8+
const builders = recast.types.builders
9+
710
/**
811
* Find all the import statements
9-
* @param { Array } ast - tree structure containing the program code
12+
* @param { Array } body - tree structure containing the program code
1013
* @returns { Array } array containing only the import statements
1114
*/
12-
function findImports(ast) {
13-
return ast.filter(node => node.type === IMPORT_DECLARATION)
15+
function findImports(body) {
16+
return body.filter(node => node.type === IMPORT_DECLARATION)
17+
}
18+
19+
/**
20+
* Find all the code in an ast program except for the import statements
21+
* @param { Array } body - tree structure containing the program code
22+
* @returns { Array } array containing all the program code except the import expressions
23+
*/
24+
function filterNonImport(body) {
25+
return body.filter(node => node.type !== IMPORT_DECLARATION)
1426
}
1527

1628
/**
@@ -22,6 +34,51 @@ function getProgramBody(ast) {
2234
return ast.program.body
2335
}
2436

37+
/**
38+
* Find the `export default` expression
39+
* @param { Array } body - program ast
40+
* @returns { Object } the content of the default export statement
41+
*/
42+
function getDefaultExportDeclaration(body) {
43+
return body.find(node => node.type === DEFAULT_EXPORT_DECLARATION)
44+
}
45+
46+
/**
47+
* Get the body of an expression call function (() => )()
48+
* @param { Object } node node to parse
49+
* @returns { Array } expression body
50+
*/
51+
function getCallExpressionBody(node) {
52+
return node.declaration.callee.body.body
53+
}
54+
55+
/**
56+
* Get the path to the body array where we will inject the tag logic code
57+
* @param { Object } ast - ast program
58+
* @returns { Array } the empty array where we will inject our tag logic
59+
*/
60+
function getOutputInnerBodyScope(ast) {
61+
return compose(
62+
getCallExpressionBody,
63+
getDefaultExportDeclaration,
64+
getProgramBody
65+
)(ast)
66+
}
67+
68+
/**
69+
* Remap the content of an ast converting the default export declaration into a return statement
70+
* @param { Array } body - tree structure containing the program code
71+
* @returns { Array } the body remapped containing the return statement
72+
*/
73+
function transformExportDefaultIntoReturn(body) {
74+
return body.map(node => {
75+
if (node.type === DEFAULT_EXPORT_DECLARATION)
76+
return builders.returnStatement(node.declaration)
77+
78+
return node
79+
})
80+
}
81+
2582
/**
2683
* Generate the component javascript logic
2784
* @param { Object } sourceNode - node generated by the riot compiler
@@ -36,10 +93,18 @@ export default async function javascript(sourceNode, source, options, { code, ma
3693
const preprocessorOutput = await preprocess('js', preprocessorName, options, source, javascriptNode)
3794
const outputAST = recast.parse(JS_EXPORT)
3895
const sourceAST = recast.parse(preprocessorOutput.code)
96+
const sourceAstBody = getProgramBody(sourceAST)
97+
const outputInnerBody = getOutputInnerBodyScope(outputAST)
98+
99+
// insert the code into the scoped context filtering the import statements
100+
// and convert the export default into "return" statement
101+
outputInnerBody.push(
102+
...compose(transformExportDefaultIntoReturn, filterNonImport)(sourceAstBody)
103+
)
39104

40105
// move the imports to the top of the output
41106
outputAST.program.body = [
42-
...findImports(getProgramBody(sourceAST)),
107+
...findImports(sourceAstBody),
43108
...getProgramBody(outputAST)
44109
]
45110

src/utils/compose.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/* eslint-disable */
2+
// source: https://30secondsofcode.org/function#compose
3+
export default (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)))

test/generators/javascript.spec.js

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ describe('Generators - javascript', () => {
2929

3030
expect(code).to.be.a('string')
3131
expect(code).to.have.string('import moment')
32+
expect(code).to.have.string('return')
3233
expect(code.length).to.be.ok
3334
})
3435
})

0 commit comments

Comments
 (0)