1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | "use strict";
|
7 |
|
8 | const { parseResource } = require("../util/identifier");
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 | const quoteMeta = str => {
|
24 | return str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&");
|
25 | };
|
26 |
|
27 | const splitContextFromPrefix = prefix => {
|
28 | const idx = prefix.lastIndexOf("/");
|
29 | let context = ".";
|
30 | if (idx >= 0) {
|
31 | context = prefix.slice(0, idx);
|
32 | prefix = `.${prefix.slice(idx)}`;
|
33 | }
|
34 | return {
|
35 | context,
|
36 | prefix
|
37 | };
|
38 | };
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 | exports.create = (Dep, range, param, expr, options, contextOptions, parser) => {
|
55 | if (param.isTemplateString()) {
|
56 | let prefixRaw = param.quasis[0].string;
|
57 | let postfixRaw =
|
58 | param.quasis.length > 1
|
59 | ? param.quasis[param.quasis.length - 1].string
|
60 | : "";
|
61 |
|
62 | const valueRange = param.range;
|
63 | const { context, prefix } = splitContextFromPrefix(prefixRaw);
|
64 | const {
|
65 | path: postfix,
|
66 | query,
|
67 | fragment
|
68 | } = parseResource(postfixRaw, parser);
|
69 |
|
70 |
|
71 |
|
72 | const innerQuasis = param.quasis.slice(1, param.quasis.length - 1);
|
73 | const innerRegExp =
|
74 | options.wrappedContextRegExp.source +
|
75 | innerQuasis
|
76 | .map(q => quoteMeta(q.string) + options.wrappedContextRegExp.source)
|
77 | .join("");
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 | const regExp = new RegExp(
|
89 | `^${quoteMeta(prefix)}${innerRegExp}${quoteMeta(postfix)}$`
|
90 | );
|
91 | const dep = new Dep(
|
92 | {
|
93 | request: context + query + fragment,
|
94 | recursive: options.wrappedContextRecursive,
|
95 | regExp,
|
96 | mode: "sync",
|
97 | ...contextOptions
|
98 | },
|
99 | range,
|
100 | valueRange
|
101 | );
|
102 | dep.loc = expr.loc;
|
103 | const replaces = [];
|
104 |
|
105 | param.parts.forEach((part, i) => {
|
106 | if (i % 2 === 0) {
|
107 |
|
108 | let range = part.range;
|
109 | let value = part.string;
|
110 | if (param.templateStringKind === "cooked") {
|
111 | value = JSON.stringify(value);
|
112 | value = value.slice(1, value.length - 1);
|
113 | }
|
114 | if (i === 0) {
|
115 |
|
116 | value = prefix;
|
117 | range = [param.range[0], part.range[1]];
|
118 | value =
|
119 | (param.templateStringKind === "cooked" ? "`" : "String.raw`") +
|
120 | value;
|
121 | } else if (i === param.parts.length - 1) {
|
122 |
|
123 | value = postfix;
|
124 | range = [part.range[0], param.range[1]];
|
125 | value = value + "`";
|
126 | } else if (
|
127 | part.expression &&
|
128 | part.expression.type === "TemplateElement" &&
|
129 | part.expression.value.raw === value
|
130 | ) {
|
131 |
|
132 | return;
|
133 | }
|
134 | replaces.push({
|
135 | range,
|
136 | value
|
137 | });
|
138 | } else {
|
139 |
|
140 | parser.walkExpression(part.expression);
|
141 | }
|
142 | });
|
143 |
|
144 | dep.replaces = replaces;
|
145 | dep.critical =
|
146 | options.wrappedContextCritical &&
|
147 | "a part of the request of a dependency is an expression";
|
148 | return dep;
|
149 | } else if (
|
150 | param.isWrapped() &&
|
151 | ((param.prefix && param.prefix.isString()) ||
|
152 | (param.postfix && param.postfix.isString()))
|
153 | ) {
|
154 | let prefixRaw =
|
155 | param.prefix && param.prefix.isString() ? param.prefix.string : "";
|
156 | let postfixRaw =
|
157 | param.postfix && param.postfix.isString() ? param.postfix.string : "";
|
158 | const prefixRange =
|
159 | param.prefix && param.prefix.isString() ? param.prefix.range : null;
|
160 | const postfixRange =
|
161 | param.postfix && param.postfix.isString() ? param.postfix.range : null;
|
162 | const valueRange = param.range;
|
163 | const { context, prefix } = splitContextFromPrefix(prefixRaw);
|
164 | const {
|
165 | path: postfix,
|
166 | query,
|
167 | fragment
|
168 | } = parseResource(postfixRaw, parser);
|
169 | const regExp = new RegExp(
|
170 | `^${quoteMeta(prefix)}${options.wrappedContextRegExp.source}${quoteMeta(
|
171 | postfix
|
172 | )}$`
|
173 | );
|
174 | const dep = new Dep(
|
175 | {
|
176 | request: context + query + fragment,
|
177 | recursive: options.wrappedContextRecursive,
|
178 | regExp,
|
179 | mode: "sync",
|
180 | ...contextOptions
|
181 | },
|
182 | range,
|
183 | valueRange
|
184 | );
|
185 | dep.loc = expr.loc;
|
186 | const replaces = [];
|
187 | if (prefixRange) {
|
188 | replaces.push({
|
189 | range: prefixRange,
|
190 | value: JSON.stringify(prefix)
|
191 | });
|
192 | }
|
193 | if (postfixRange) {
|
194 | replaces.push({
|
195 | range: postfixRange,
|
196 | value: JSON.stringify(postfix)
|
197 | });
|
198 | }
|
199 | dep.replaces = replaces;
|
200 | dep.critical =
|
201 | options.wrappedContextCritical &&
|
202 | "a part of the request of a dependency is an expression";
|
203 |
|
204 | if (parser && param.wrappedInnerExpressions) {
|
205 | for (const part of param.wrappedInnerExpressions) {
|
206 | if (part.expression) parser.walkExpression(part.expression);
|
207 | }
|
208 | }
|
209 |
|
210 | return dep;
|
211 | } else {
|
212 | const dep = new Dep(
|
213 | {
|
214 | request: options.exprContextRequest,
|
215 | recursive: options.exprContextRecursive,
|
216 | regExp: (options.exprContextRegExp),
|
217 | mode: "sync",
|
218 | ...contextOptions
|
219 | },
|
220 | range,
|
221 | param.range
|
222 | );
|
223 | dep.loc = expr.loc;
|
224 | dep.critical =
|
225 | options.exprContextCritical &&
|
226 | "the request of a dependency is an expression";
|
227 |
|
228 | parser.walkExpression(param.expression);
|
229 |
|
230 | return dep;
|
231 | }
|
232 | };
|