Skip to content

Commit f732bc5

Browse files
add preprocessor nesting
This allows for developers to ensure that certain `markup` functions are run *after* other `script` or `style` functions have run.
1 parent c4479d9 commit f732bc5

File tree

5 files changed

+157
-13
lines changed

5 files changed

+157
-13
lines changed

site/content/docs/04-compile-time.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,51 @@ const { code } = await svelte.preprocess(source, [
312312
});
313313
```
314314

315+
An additional level of nesting allows more control over the timing of subsequent `markup` functions.
316+
317+
```js
318+
const svelte = require('svelte/compiler');
319+
320+
const { code } = await svelte.preprocess(source, [
321+
[
322+
{
323+
markup: () => {
324+
console.log('this runs first');
325+
},
326+
script: () => {
327+
console.log('this runs third');
328+
},
329+
style: () => {
330+
console.log('this runs fifth');
331+
}
332+
},
333+
{
334+
markup: () => {
335+
console.log('this runs second');
336+
},
337+
script: () => {
338+
console.log('this runs fourth');
339+
},
340+
style: () => {
341+
console.log('this runs sixth');
342+
}
343+
}
344+
],
345+
{
346+
markup: () => {
347+
console.log('this runs seventh');
348+
},
349+
script: () => {
350+
console.log('this runs eighth');
351+
},
352+
style: () => {
353+
console.log('this runs ninth');
354+
}
355+
}
356+
], {
357+
filename: 'App.svelte'
358+
});
359+
```
315360

316361
### `svelte.walk`
317362

src/compiler/preprocess/index.ts

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -195,27 +195,51 @@ async function process_markup(filename: string, process: MarkupPreprocessor, sou
195195
}
196196
}
197197

198-
export default async function preprocess(
199-
source: string,
200-
preprocessor: PreprocessorGroup | PreprocessorGroup[],
201-
options?: { filename?: string }
202-
): Promise<Processed> {
203-
// @ts-ignore todo: doublecheck
204-
const filename = (options && options.filename) || preprocessor.filename; // legacy
198+
function ensureArray<T>(x: T): T extends readonly any[] ? T : T[] {
199+
// @ts-ignore
200+
return Array.isArray(x)? x : [x];
201+
}
205202

206-
const preprocessors = preprocessor ? (Array.isArray(preprocessor) ? preprocessor : [preprocessor]) : [];
203+
function groupPreprocessors(preprocessorsIn: Array<PreprocessorGroup|PreprocessorGroup[]>): PreprocessorGroup[][] {
204+
const preprocessors = { completed: [], building: [] };
207205

208-
const markup = preprocessors.map(p => p.markup).filter(Boolean);
209-
const script = preprocessors.map(p => p.script).filter(Boolean);
210-
const style = preprocessors.map(p => p.style).filter(Boolean);
206+
function cleanUpBuilding() {
207+
if (preprocessors.building.length) {
208+
preprocessors.completed.push(preprocessors.building);
209+
preprocessors.building = [];
210+
}
211+
}
211212

212-
const result = new PreprocessResult(source, filename);
213+
for (const current of preprocessorsIn) {
214+
if (Array.isArray(current)) {
215+
cleanUpBuilding();
216+
preprocessors.completed.push(current);
217+
} else {
218+
preprocessors.building.push(current);
219+
}
220+
}
221+
222+
cleanUpBuilding();
223+
224+
return preprocessors.completed;
225+
226+
}
227+
228+
async function preprocessGrouped<T extends PreprocessResult>(
229+
result: T,
230+
preprocessorGroup: PreprocessorGroup[]|PreprocessorGroup
231+
): Promise<void> {
232+
const preprocessors = ensureArray(preprocessorGroup);
233+
234+
const markup = preprocessors.map((p) => p.markup).filter(Boolean);
235+
const script = preprocessors.map((p) => p.script).filter(Boolean);
236+
const style = preprocessors.map((p) => p.style).filter(Boolean);
213237

214238
// TODO keep track: what preprocessor generated what sourcemap?
215239
// to make debugging easier = detect low-resolution sourcemaps in fn combine_mappings
216240

217241
for (const process of markup) {
218-
result.update_source(await process_markup(filename, process, result));
242+
result.update_source(await process_markup(result.filename, process, result));
219243
}
220244

221245
for (const process of script) {
@@ -226,5 +250,21 @@ export default async function preprocess(
226250
result.update_source(await process_tag('style', preprocess, result));
227251
}
228252

253+
return;
254+
}
255+
256+
export default async function preprocess(
257+
source: string,
258+
preprocessor: PreprocessorGroup | Array<PreprocessorGroup | PreprocessorGroup[]> = [],
259+
options?: { filename?: string }
260+
): Promise<Processed> {
261+
// @ts-ignore todo: doublecheck
262+
const filename = (options && options.filename) || preprocessor.filename; // legacy
263+
const result = new PreprocessResult(source, filename);
264+
265+
for (const preprocessorGrouping of groupPreprocessors(ensureArray(preprocessor))) {
266+
await preprocessGrouped(result, preprocessorGrouping);
267+
}
268+
229269
return result.to_processed();
230270
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
export default {
2+
preprocess: [
3+
[
4+
{
5+
markup: ({ content }) => ({ code: content.replace(/one/g, 'two') }),
6+
script: ({ content }) => ({ code: content.replace(/three/g, 'four') }),
7+
style: ({ content }) => ({ code: content.replace(/four/g, 'nine') })
8+
},
9+
{
10+
markup: ({ content }) => ({ code: content.replace(/two/g, 'three') }),
11+
script: ({ content }) => ({ code: content.replace(/four/g, 'five') }),
12+
style: ({ content }) => ({ code: content.replace(/three/g, 'four') })
13+
}
14+
],
15+
{
16+
markup: ({ content }) => ({ code: content.replace(/three|four|five/g, 'reset-markup') }),
17+
script: ({ content }) => ({ code: content.replace(/reset-markup/g, 'reset-script') }),
18+
style: ({ content }) => ({ code: content.replace(/reset-markup/g, 'reset-style') })
19+
},
20+
[
21+
{
22+
markup: ({ content }) => ({
23+
code: content
24+
.replace(/reset-markup/, 'six')
25+
.replace(/reset-style/, 'six')
26+
.replace(/reset-script/, 'six') }),
27+
script: ({ content }) => ({ code: content.replace(/seven/g, 'eight') }),
28+
style: ({ content }) => ({ code: content.replace(/eight/g, 'nine') })
29+
},
30+
{
31+
markup: ({ content }) => ({ code: content.replace(/six/g, 'seven') }),
32+
script: ({ content }) => ({ code: content.replace(/eight/g, 'nine') }),
33+
style: ({ content }) => ({ code: content.replace(/seven/g, 'eight') })
34+
}
35+
]
36+
]
37+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<p>one</p>
2+
3+
<style>
4+
.one {
5+
color: red;
6+
}
7+
</style>
8+
9+
<script>
10+
console.log('one');
11+
</script>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<p>seven</p>
2+
3+
<style>
4+
.eight {
5+
color: red;
6+
}
7+
</style>
8+
9+
<script>
10+
console.log('nine');
11+
</script>

0 commit comments

Comments
 (0)