1 | "use strict";
|
---|
2 |
|
---|
3 | Object.defineProperty(exports, "__esModule", {
|
---|
4 | value: true
|
---|
5 | });
|
---|
6 | exports.default = parseAndBuildMetadata;
|
---|
7 |
|
---|
8 | var t = require("@babel/types");
|
---|
9 |
|
---|
10 | var _parser = require("@babel/parser");
|
---|
11 |
|
---|
12 | var _codeFrame = require("@babel/code-frame");
|
---|
13 |
|
---|
14 | const PATTERN = /^[_$A-Z0-9]+$/;
|
---|
15 |
|
---|
16 | function parseAndBuildMetadata(formatter, code, opts) {
|
---|
17 | const {
|
---|
18 | placeholderWhitelist,
|
---|
19 | placeholderPattern,
|
---|
20 | preserveComments,
|
---|
21 | syntacticPlaceholders
|
---|
22 | } = opts;
|
---|
23 | const ast = parseWithCodeFrame(code, opts.parser, syntacticPlaceholders);
|
---|
24 | t.removePropertiesDeep(ast, {
|
---|
25 | preserveComments
|
---|
26 | });
|
---|
27 | formatter.validate(ast);
|
---|
28 | const syntactic = {
|
---|
29 | placeholders: [],
|
---|
30 | placeholderNames: new Set()
|
---|
31 | };
|
---|
32 | const legacy = {
|
---|
33 | placeholders: [],
|
---|
34 | placeholderNames: new Set()
|
---|
35 | };
|
---|
36 | const isLegacyRef = {
|
---|
37 | value: undefined
|
---|
38 | };
|
---|
39 | t.traverse(ast, placeholderVisitorHandler, {
|
---|
40 | syntactic,
|
---|
41 | legacy,
|
---|
42 | isLegacyRef,
|
---|
43 | placeholderWhitelist,
|
---|
44 | placeholderPattern,
|
---|
45 | syntacticPlaceholders
|
---|
46 | });
|
---|
47 | return Object.assign({
|
---|
48 | ast
|
---|
49 | }, isLegacyRef.value ? legacy : syntactic);
|
---|
50 | }
|
---|
51 |
|
---|
52 | function placeholderVisitorHandler(node, ancestors, state) {
|
---|
53 | var _state$placeholderWhi;
|
---|
54 |
|
---|
55 | let name;
|
---|
56 |
|
---|
57 | if (t.isPlaceholder(node)) {
|
---|
58 | if (state.syntacticPlaceholders === false) {
|
---|
59 | throw new Error("%%foo%%-style placeholders can't be used when " + "'.syntacticPlaceholders' is false.");
|
---|
60 | } else {
|
---|
61 | name = node.name.name;
|
---|
62 | state.isLegacyRef.value = false;
|
---|
63 | }
|
---|
64 | } else if (state.isLegacyRef.value === false || state.syntacticPlaceholders) {
|
---|
65 | return;
|
---|
66 | } else if (t.isIdentifier(node) || t.isJSXIdentifier(node)) {
|
---|
67 | name = node.name;
|
---|
68 | state.isLegacyRef.value = true;
|
---|
69 | } else if (t.isStringLiteral(node)) {
|
---|
70 | name = node.value;
|
---|
71 | state.isLegacyRef.value = true;
|
---|
72 | } else {
|
---|
73 | return;
|
---|
74 | }
|
---|
75 |
|
---|
76 | if (!state.isLegacyRef.value && (state.placeholderPattern != null || state.placeholderWhitelist != null)) {
|
---|
77 | throw new Error("'.placeholderWhitelist' and '.placeholderPattern' aren't compatible" + " with '.syntacticPlaceholders: true'");
|
---|
78 | }
|
---|
79 |
|
---|
80 | if (state.isLegacyRef.value && (state.placeholderPattern === false || !(state.placeholderPattern || PATTERN).test(name)) && !((_state$placeholderWhi = state.placeholderWhitelist) != null && _state$placeholderWhi.has(name))) {
|
---|
81 | return;
|
---|
82 | }
|
---|
83 |
|
---|
84 | ancestors = ancestors.slice();
|
---|
85 | const {
|
---|
86 | node: parent,
|
---|
87 | key
|
---|
88 | } = ancestors[ancestors.length - 1];
|
---|
89 | let type;
|
---|
90 |
|
---|
91 | if (t.isStringLiteral(node) || t.isPlaceholder(node, {
|
---|
92 | expectedNode: "StringLiteral"
|
---|
93 | })) {
|
---|
94 | type = "string";
|
---|
95 | } else if (t.isNewExpression(parent) && key === "arguments" || t.isCallExpression(parent) && key === "arguments" || t.isFunction(parent) && key === "params") {
|
---|
96 | type = "param";
|
---|
97 | } else if (t.isExpressionStatement(parent) && !t.isPlaceholder(node)) {
|
---|
98 | type = "statement";
|
---|
99 | ancestors = ancestors.slice(0, -1);
|
---|
100 | } else if (t.isStatement(node) && t.isPlaceholder(node)) {
|
---|
101 | type = "statement";
|
---|
102 | } else {
|
---|
103 | type = "other";
|
---|
104 | }
|
---|
105 |
|
---|
106 | const {
|
---|
107 | placeholders,
|
---|
108 | placeholderNames
|
---|
109 | } = state.isLegacyRef.value ? state.legacy : state.syntactic;
|
---|
110 | placeholders.push({
|
---|
111 | name,
|
---|
112 | type,
|
---|
113 | resolve: ast => resolveAncestors(ast, ancestors),
|
---|
114 | isDuplicate: placeholderNames.has(name)
|
---|
115 | });
|
---|
116 | placeholderNames.add(name);
|
---|
117 | }
|
---|
118 |
|
---|
119 | function resolveAncestors(ast, ancestors) {
|
---|
120 | let parent = ast;
|
---|
121 |
|
---|
122 | for (let i = 0; i < ancestors.length - 1; i++) {
|
---|
123 | const {
|
---|
124 | key,
|
---|
125 | index
|
---|
126 | } = ancestors[i];
|
---|
127 |
|
---|
128 | if (index === undefined) {
|
---|
129 | parent = parent[key];
|
---|
130 | } else {
|
---|
131 | parent = parent[key][index];
|
---|
132 | }
|
---|
133 | }
|
---|
134 |
|
---|
135 | const {
|
---|
136 | key,
|
---|
137 | index
|
---|
138 | } = ancestors[ancestors.length - 1];
|
---|
139 | return {
|
---|
140 | parent,
|
---|
141 | key,
|
---|
142 | index
|
---|
143 | };
|
---|
144 | }
|
---|
145 |
|
---|
146 | function parseWithCodeFrame(code, parserOpts, syntacticPlaceholders) {
|
---|
147 | const plugins = (parserOpts.plugins || []).slice();
|
---|
148 |
|
---|
149 | if (syntacticPlaceholders !== false) {
|
---|
150 | plugins.push("placeholders");
|
---|
151 | }
|
---|
152 |
|
---|
153 | parserOpts = Object.assign({
|
---|
154 | allowReturnOutsideFunction: true,
|
---|
155 | allowSuperOutsideMethod: true,
|
---|
156 | sourceType: "module"
|
---|
157 | }, parserOpts, {
|
---|
158 | plugins
|
---|
159 | });
|
---|
160 |
|
---|
161 | try {
|
---|
162 | return (0, _parser.parse)(code, parserOpts);
|
---|
163 | } catch (err) {
|
---|
164 | const loc = err.loc;
|
---|
165 |
|
---|
166 | if (loc) {
|
---|
167 | err.message += "\n" + (0, _codeFrame.codeFrameColumns)(code, {
|
---|
168 | start: loc
|
---|
169 | });
|
---|
170 | err.code = "BABEL_TEMPLATE_PARSE_ERROR";
|
---|
171 | }
|
---|
172 |
|
---|
173 | throw err;
|
---|
174 | }
|
---|
175 | } |
---|