@diplodoc/transform 4.31.0 → 4.31.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/css/print.css.map +1 -1
- package/dist/css/yfm.css.map +1 -1
- package/dist/css/yfm.min.css.map +1 -1
- package/lib/liquid/conditions.d.ts +1 -0
- package/lib/liquid/conditions.js +7 -0
- package/lib/liquid/conditions.js.map +1 -1
- package/lib/liquid/index.js +3 -2
- package/lib/liquid/index.js.map +1 -1
- package/lib/liquid/legacyConditions.d.ts +4 -0
- package/lib/liquid/legacyConditions.js +174 -0
- package/lib/liquid/legacyConditions.js.map +1 -0
- package/lib/liquid/services/argv.d.ts +1 -0
- package/lib/liquid/services/argv.js.map +1 -1
- package/lib/plugins/includes/collect.js +13 -9
- package/lib/plugins/includes/collect.js.map +1 -1
- package/lib/sanitize.js +3 -1
- package/lib/sanitize.js.map +1 -1
- package/package.json +2 -2
- package/src/transform/liquid/conditions.ts +6 -0
- package/src/transform/liquid/index.ts +3 -1
- package/src/transform/liquid/legacyConditions.ts +252 -0
- package/src/transform/liquid/services/argv.ts +1 -0
- package/src/transform/plugins/includes/collect.ts +27 -22
- package/src/transform/sanitize.ts +3 -1
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import {bold} from 'chalk';
|
|
2
|
+
|
|
3
|
+
import {log} from '../log';
|
|
4
|
+
|
|
5
|
+
import evalExp from './evaluation';
|
|
6
|
+
import {tagLine} from './lexical';
|
|
7
|
+
import {getPreparedLeftContent, removeIndentBlock} from './utils';
|
|
8
|
+
import {createSourceMapApi, getLineNumber} from './sourceMap';
|
|
9
|
+
|
|
10
|
+
type Options = {
|
|
11
|
+
firstLineNumber: number;
|
|
12
|
+
lastLineNumber: number;
|
|
13
|
+
resFirstLineNumber: number;
|
|
14
|
+
resLastLineNumber: number;
|
|
15
|
+
linesTotal: number;
|
|
16
|
+
sourceMap: Record<number, number>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function changeSourceMap({
|
|
20
|
+
firstLineNumber,
|
|
21
|
+
lastLineNumber,
|
|
22
|
+
resFirstLineNumber,
|
|
23
|
+
resLastLineNumber,
|
|
24
|
+
linesTotal,
|
|
25
|
+
sourceMap,
|
|
26
|
+
}: Options) {
|
|
27
|
+
if (!sourceMap) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const {getSourceMapValue, moveLines, removeLines} = createSourceMapApi(sourceMap);
|
|
32
|
+
|
|
33
|
+
let offsetRestLines;
|
|
34
|
+
if (resFirstLineNumber) {
|
|
35
|
+
// Move condition's content to the top
|
|
36
|
+
const offsetContentLines = firstLineNumber - resFirstLineNumber;
|
|
37
|
+
moveLines({
|
|
38
|
+
start: resFirstLineNumber,
|
|
39
|
+
end: resLastLineNumber - 1,
|
|
40
|
+
offset: offsetContentLines,
|
|
41
|
+
withReplace: true,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Remove the rest lines of the condition block
|
|
45
|
+
removeLines({start: firstLineNumber, end: resFirstLineNumber - 1});
|
|
46
|
+
removeLines({start: resLastLineNumber, end: lastLineNumber});
|
|
47
|
+
|
|
48
|
+
// Calculate an offset of the rest lines
|
|
49
|
+
offsetRestLines = getSourceMapValue(resLastLineNumber - 1) - lastLineNumber;
|
|
50
|
+
} else {
|
|
51
|
+
// Remove the whole condition block
|
|
52
|
+
removeLines({start: firstLineNumber, end: lastLineNumber});
|
|
53
|
+
|
|
54
|
+
// Calculate offset of the rest lines
|
|
55
|
+
offsetRestLines = firstLineNumber - lastLineNumber - 1;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Offset the rest lines
|
|
59
|
+
moveLines({start: lastLineNumber + 1, end: linesTotal, offset: offsetRestLines});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function getElseProp<B extends keyof Elses>({elses}: {elses: Elses[]}, propName: B, index = 0) {
|
|
63
|
+
if (!elses.length || index >= elses.length) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return elses[index][propName];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
type Opts = {
|
|
71
|
+
ifTag: Tag;
|
|
72
|
+
vars: Record<string, unknown>;
|
|
73
|
+
content: string;
|
|
74
|
+
match: RegExpExecArray;
|
|
75
|
+
lastIndex: number;
|
|
76
|
+
sourceMap: Record<number, number>;
|
|
77
|
+
linesTotal: number;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
function inlineConditions({ifTag, vars, content, match, lastIndex, sourceMap, linesTotal}: Opts) {
|
|
81
|
+
let res = '';
|
|
82
|
+
const firstLineNumber = getLineNumber(content, ifTag.startPos);
|
|
83
|
+
const lastLineNumber = getLineNumber(content, lastIndex);
|
|
84
|
+
let resFirstLineNumber = 0;
|
|
85
|
+
let resLastLineNumber = 0;
|
|
86
|
+
|
|
87
|
+
if (evalExp(ifTag.condition, vars)) {
|
|
88
|
+
const ifRawLastIndex = ifTag.startPos + ifTag.ifRaw.length;
|
|
89
|
+
const contentLastIndex = getElseProp(ifTag, 'startPos') || match.index;
|
|
90
|
+
|
|
91
|
+
res = content.substring(ifRawLastIndex, contentLastIndex);
|
|
92
|
+
resFirstLineNumber = getLineNumber(content, ifRawLastIndex + 1);
|
|
93
|
+
resLastLineNumber = getLineNumber(content, contentLastIndex + 1);
|
|
94
|
+
} else {
|
|
95
|
+
ifTag.elses.some(({condition, startPos, raw}, index) => {
|
|
96
|
+
const isTruthy = !condition || evalExp(condition, vars);
|
|
97
|
+
|
|
98
|
+
if (isTruthy) {
|
|
99
|
+
const elseRawLastIndex = startPos + raw.length;
|
|
100
|
+
const contentLastIndex = getElseProp(ifTag, 'startPos', index + 1) || match.index;
|
|
101
|
+
|
|
102
|
+
res = content.substring(elseRawLastIndex, contentLastIndex);
|
|
103
|
+
resFirstLineNumber = getLineNumber(content, elseRawLastIndex + 1);
|
|
104
|
+
resLastLineNumber = getLineNumber(content, contentLastIndex + 1);
|
|
105
|
+
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return false;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
changeSourceMap({
|
|
114
|
+
firstLineNumber,
|
|
115
|
+
lastLineNumber,
|
|
116
|
+
resFirstLineNumber,
|
|
117
|
+
resLastLineNumber,
|
|
118
|
+
linesTotal,
|
|
119
|
+
sourceMap,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const preparedLeftContent = getPreparedLeftContent({
|
|
123
|
+
content,
|
|
124
|
+
tagStartPos: ifTag.startPos,
|
|
125
|
+
tagContent: res,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
let shift = 0;
|
|
129
|
+
if (
|
|
130
|
+
res === '' &&
|
|
131
|
+
preparedLeftContent[preparedLeftContent.length - 1] === '\n' &&
|
|
132
|
+
content[lastIndex] === '\n'
|
|
133
|
+
) {
|
|
134
|
+
shift = 1;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (res !== '') {
|
|
138
|
+
if (res[0] === '\n') {
|
|
139
|
+
res = res.substring(1);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
res = removeIndentBlock(res);
|
|
143
|
+
|
|
144
|
+
if (res[res.length - 1] === '\n') {
|
|
145
|
+
res = res.slice(0, -1);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const leftPart = preparedLeftContent + res;
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
result: leftPart + content.substring(lastIndex + shift),
|
|
153
|
+
idx: leftPart.length,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
type Elses = {startPos: number; raw: string; condition?: string};
|
|
158
|
+
|
|
159
|
+
type Tag = {
|
|
160
|
+
isOpen: Boolean;
|
|
161
|
+
condition: string;
|
|
162
|
+
startPos: number;
|
|
163
|
+
ifRaw: string;
|
|
164
|
+
elses: Elses[];
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export = function legacyConditions(
|
|
168
|
+
originInput: string,
|
|
169
|
+
vars: Record<string, unknown>,
|
|
170
|
+
path?: string,
|
|
171
|
+
settings?: {
|
|
172
|
+
sourceMap: Record<number, number>;
|
|
173
|
+
},
|
|
174
|
+
) {
|
|
175
|
+
const sourceMap = settings?.sourceMap || {};
|
|
176
|
+
|
|
177
|
+
const R_LIQUID = /({%-?([\s\S]*?)-?%})/g;
|
|
178
|
+
|
|
179
|
+
let match;
|
|
180
|
+
const tagStack: Tag[] = [];
|
|
181
|
+
let input = originInput;
|
|
182
|
+
let linesTotal = originInput.split('\n').length;
|
|
183
|
+
|
|
184
|
+
while ((match = R_LIQUID.exec(input)) !== null) {
|
|
185
|
+
if (!match[1]) {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const tagMatch = match[2].trim().match(tagLine);
|
|
190
|
+
if (!tagMatch) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const [type, args] = tagMatch.slice(1);
|
|
195
|
+
|
|
196
|
+
switch (type) {
|
|
197
|
+
case 'if':
|
|
198
|
+
tagStack.push({
|
|
199
|
+
isOpen: true,
|
|
200
|
+
condition: args,
|
|
201
|
+
startPos: match.index,
|
|
202
|
+
ifRaw: match[1],
|
|
203
|
+
elses: [],
|
|
204
|
+
});
|
|
205
|
+
break;
|
|
206
|
+
case 'else':
|
|
207
|
+
tagStack[tagStack.length - 1].elses.push({
|
|
208
|
+
startPos: match.index,
|
|
209
|
+
raw: match[1],
|
|
210
|
+
});
|
|
211
|
+
break;
|
|
212
|
+
case 'elsif':
|
|
213
|
+
tagStack[tagStack.length - 1].elses.push({
|
|
214
|
+
condition: args,
|
|
215
|
+
startPos: match.index,
|
|
216
|
+
raw: match[1],
|
|
217
|
+
});
|
|
218
|
+
break;
|
|
219
|
+
case 'endif': {
|
|
220
|
+
const ifTag = tagStack.pop();
|
|
221
|
+
|
|
222
|
+
if (!ifTag) {
|
|
223
|
+
log.error(
|
|
224
|
+
`If block must be opened before close${path ? ` in ${bold(path)}` : ''}`,
|
|
225
|
+
);
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const {idx, result} = inlineConditions({
|
|
230
|
+
ifTag,
|
|
231
|
+
vars,
|
|
232
|
+
content: input,
|
|
233
|
+
match,
|
|
234
|
+
lastIndex: R_LIQUID.lastIndex,
|
|
235
|
+
sourceMap,
|
|
236
|
+
linesTotal,
|
|
237
|
+
});
|
|
238
|
+
R_LIQUID.lastIndex = idx;
|
|
239
|
+
input = result;
|
|
240
|
+
linesTotal = result.split('\n').length;
|
|
241
|
+
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (tagStack.length !== 0) {
|
|
248
|
+
log.error(`Condition block must be closed${path ? ` in ${bold(path)}` : ''}`);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return input;
|
|
252
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {relative} from 'path';
|
|
2
2
|
import {bold} from 'chalk';
|
|
3
|
+
import {readFileSync} from 'fs';
|
|
3
4
|
|
|
4
5
|
import {getRelativePath, isFileExists, resolveRelativePath} from '../../utilsFS';
|
|
5
6
|
|
|
@@ -23,30 +24,34 @@ function processRecursive(
|
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
try {
|
|
26
|
-
const
|
|
27
|
+
const contentProcessed = copyFile(includePath, targetDestPath, includeOptions);
|
|
27
28
|
|
|
28
29
|
// To reduce file reading we can include the file content into the generated content
|
|
29
|
-
if (included
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
30
|
+
if (included) {
|
|
31
|
+
const content = contentProcessed ?? readFileSync(targetDestPath, 'utf8');
|
|
32
|
+
|
|
33
|
+
if (content) {
|
|
34
|
+
const includedRelativePath = getRelativePath(includedParentPath, includePath);
|
|
35
|
+
|
|
36
|
+
// The appendix is the map that protects from multiple include files
|
|
37
|
+
if (!appendix.has(includedRelativePath)) {
|
|
38
|
+
// Recursive function to include the depth structure
|
|
39
|
+
const includeContent = collectRecursive(
|
|
40
|
+
content,
|
|
41
|
+
{
|
|
42
|
+
...options,
|
|
43
|
+
path: includePath,
|
|
44
|
+
includedParentPath,
|
|
45
|
+
},
|
|
46
|
+
appendix,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
// Add to appendix set structure
|
|
50
|
+
appendix.set(
|
|
51
|
+
includedRelativePath,
|
|
52
|
+
`{% included (${includedRelativePath}) %}\n${includeContent}\n{% endincluded %}`,
|
|
53
|
+
);
|
|
54
|
+
}
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
57
|
} catch (e) {
|