-
Notifications
You must be signed in to change notification settings - Fork 18
/
.intlBabelPlugin.js
89 lines (85 loc) · 2.75 KB
/
.intlBabelPlugin.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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
const path = require('path')
const fs = require('fs-extra')
const jsonOutputPath = path.join(__dirname, './.intlNewEn.json')
// only add brackets if there's no existing brackets
const withBrackets = (exprName, rawTemplate, i) =>
!findBrackets(rawTemplate, i, '{') ||
!findBrackets(rawTemplate, i + exprName.length, '}')
? `{{${exprName}}}`
: exprName
const findBrackets = (rawTemplate, i, bracket) => {
const d = bracket === '{' ? -1 : 1
const negBracket = bracket === '{' ? '}' : '{'
while (true) {
if (i <= 0 || i >= rawTemplate.length) {
return false
}
const c1 = rawTemplate.charAt(i)
const c2 = rawTemplate.charAt(i + d)
if (c1 === c2 && c1 === bracket) {
return true
}
if (c1 === c2 && c1 === negBracket) {
return false
}
i += d
}
}
const intlBabelPlugin = () => ({
visitor: {
TaggedTemplateExpression(p, s) {
//
const tagName = p.node.tag.name
const tl = tagName && tagName.toLowerCase()
if (!tl || (tl.indexOf('intl') < 0 && tl.indexOf('debug') < 0)) {
return
}
// get raw expressions from source code
const exprs = p.node.quasi.expressions.map(e =>
s.file.code.substring(e.start, e.end),
)
// build data keys from expressions with their name as camelCase
const exprNames = exprs.map((e, i) => `$${i}`)
// build the locations to automatically add brackets for fields
const quasis = p.node.quasi.quasis.map(q => q.value.raw)
const [rawTemplate, fieldLocations] = quasis.reduce(
([r, a], q, i) => {
r += q
if (i < exprNames.length) {
a.push(r.length)
r += exprNames[i]
}
return [r, a]
},
['', []],
)
// get the template
const normalizedTemplate = quasis
.reduce((a, q, i) => {
a.push(q)
if (i < exprNames.length) {
a.push(withBrackets(exprNames[i], rawTemplate, fieldLocations[i]))
}
return a
}, [])
.join('')
.replace('\\`', '`')
// extract the normalized template
if (process.env.EXTRACT_INTL) {
let arr = fs.existsSync(jsonOutputPath)
? JSON.parse(fs.readFileSync(jsonOutputPath))
: []
if (!arr.includes(normalizedTemplate)) {
arr.push(normalizedTemplate)
arr = arr.sort()
}
fs.outputFileSync(jsonOutputPath, `${JSON.stringify(arr, null, 2)}\n`)
}
// replace the tagged template with a function call
const p1 = JSON.stringify(normalizedTemplate)
const p2 = `{${exprNames.map((v, i) => `${v}:${exprs[i]}`).join(',')}}`
p.replaceWithSourceString(`${tagName}(${p1}, ${p2})`)
},
},
})
module.exports = intlBabelPlugin