-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmodify.js
69 lines (60 loc) · 1.53 KB
/
modify.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import crypto from 'crypto'
import recast from 'recast'
import { parse } from 'acorn'
import astTypes from 'ast-types'
import dedent from './dedent.js'
const cwd = process.cwd()
const hashIt = (x, algorithm) => crypto.createHash(algorithm).update(x).digest('hex')
export default function({
shouldDedent,
algorithm,
queries,
code,
tags,
salt,
path
}) {
const ast = recast.parse(code, {
parser: {
parse(source, opts) {
return parse(source, {
...opts,
ecmaVersion: 'latest',
sourceType: 'module'
})
}
},
sourceFileName: path
})
astTypes.visit(ast, {
visitTaggedTemplateExpression(x) {
const n = x.node
, tag = n.tag.name
if (!tags.includes(tag))
return this.traverse(x)
const query = n.quasi.quasis.map((x) => x.value.cooked)
const dedented = shouldDedent ? dedent(query) : query
const checksum = hashIt(
[salt, tag, ...dedented].map(x => x && hashIt(x, algorithm)).join(''),
algorithm
)
tag in queries === false && (queries[tag] = {})
queries[tag][checksum] = Object.assign(dedented, {
file: path.replace(cwd, ''),
line: n.loc.start.line,
column: n.loc.start.column
})
n.type = 'CallExpression'
n.arguments = [
{
type: 'Literal',
value: checksum
},
...n.quasi.expressions
]
n.callee = n.tag
this.traverse(x)
}
})
return recast.print(ast, { sourceMapName: 'map.json' })
}