add preprocessor nesting

This allows for developers to ensure that certain `markup` functions
are run *after* other `script` or `style` functions have run.
pull/6031/head
Don Denton 6 years ago
parent c4479d976b
commit f732bc53bc

@ -312,6 +312,51 @@ const { code } = await svelte.preprocess(source, [
});
```
An additional level of nesting allows more control over the timing of subsequent `markup` functions.
```js
const svelte = require('svelte/compiler');
const { code } = await svelte.preprocess(source, [
[
{
markup: () => {
console.log('this runs first');
},
script: () => {
console.log('this runs third');
},
style: () => {
console.log('this runs fifth');
}
},
{
markup: () => {
console.log('this runs second');
},
script: () => {
console.log('this runs fourth');
},
style: () => {
console.log('this runs sixth');
}
}
],
{
markup: () => {
console.log('this runs seventh');
},
script: () => {
console.log('this runs eighth');
},
style: () => {
console.log('this runs ninth');
}
}
], {
filename: 'App.svelte'
});
```
### `svelte.walk`

@ -195,27 +195,51 @@ async function process_markup(filename: string, process: MarkupPreprocessor, sou
}
}
export default async function preprocess(
source: string,
preprocessor: PreprocessorGroup | PreprocessorGroup[],
options?: { filename?: string }
): Promise<Processed> {
// @ts-ignore todo: doublecheck
const filename = (options && options.filename) || preprocessor.filename; // legacy
function ensureArray<T>(x: T): T extends readonly any[] ? T : T[] {
// @ts-ignore
return Array.isArray(x)? x : [x];
}
const preprocessors = preprocessor ? (Array.isArray(preprocessor) ? preprocessor : [preprocessor]) : [];
function groupPreprocessors(preprocessorsIn: Array<PreprocessorGroup|PreprocessorGroup[]>): PreprocessorGroup[][] {
const preprocessors = { completed: [], building: [] };
const markup = preprocessors.map(p => p.markup).filter(Boolean);
const script = preprocessors.map(p => p.script).filter(Boolean);
const style = preprocessors.map(p => p.style).filter(Boolean);
function cleanUpBuilding() {
if (preprocessors.building.length) {
preprocessors.completed.push(preprocessors.building);
preprocessors.building = [];
}
}
const result = new PreprocessResult(source, filename);
for (const current of preprocessorsIn) {
if (Array.isArray(current)) {
cleanUpBuilding();
preprocessors.completed.push(current);
} else {
preprocessors.building.push(current);
}
}
cleanUpBuilding();
return preprocessors.completed;
}
async function preprocessGrouped<T extends PreprocessResult>(
result: T,
preprocessorGroup: PreprocessorGroup[]|PreprocessorGroup
): Promise<void> {
const preprocessors = ensureArray(preprocessorGroup);
const markup = preprocessors.map((p) => p.markup).filter(Boolean);
const script = preprocessors.map((p) => p.script).filter(Boolean);
const style = preprocessors.map((p) => p.style).filter(Boolean);
// TODO keep track: what preprocessor generated what sourcemap?
// to make debugging easier = detect low-resolution sourcemaps in fn combine_mappings
for (const process of markup) {
result.update_source(await process_markup(filename, process, result));
result.update_source(await process_markup(result.filename, process, result));
}
for (const process of script) {
@ -226,5 +250,21 @@ export default async function preprocess(
result.update_source(await process_tag('style', preprocess, result));
}
return;
}
export default async function preprocess(
source: string,
preprocessor: PreprocessorGroup | Array<PreprocessorGroup | PreprocessorGroup[]> = [],
options?: { filename?: string }
): Promise<Processed> {
// @ts-ignore todo: doublecheck
const filename = (options && options.filename) || preprocessor.filename; // legacy
const result = new PreprocessResult(source, filename);
for (const preprocessorGrouping of groupPreprocessors(ensureArray(preprocessor))) {
await preprocessGrouped(result, preprocessorGrouping);
}
return result.to_processed();
}

@ -0,0 +1,37 @@
export default {
preprocess: [
[
{
markup: ({ content }) => ({ code: content.replace(/one/g, 'two') }),
script: ({ content }) => ({ code: content.replace(/three/g, 'four') }),
style: ({ content }) => ({ code: content.replace(/four/g, 'nine') })
},
{
markup: ({ content }) => ({ code: content.replace(/two/g, 'three') }),
script: ({ content }) => ({ code: content.replace(/four/g, 'five') }),
style: ({ content }) => ({ code: content.replace(/three/g, 'four') })
}
],
{
markup: ({ content }) => ({ code: content.replace(/three|four|five/g, 'reset-markup') }),
script: ({ content }) => ({ code: content.replace(/reset-markup/g, 'reset-script') }),
style: ({ content }) => ({ code: content.replace(/reset-markup/g, 'reset-style') })
},
[
{
markup: ({ content }) => ({
code: content
.replace(/reset-markup/, 'six')
.replace(/reset-style/, 'six')
.replace(/reset-script/, 'six') }),
script: ({ content }) => ({ code: content.replace(/seven/g, 'eight') }),
style: ({ content }) => ({ code: content.replace(/eight/g, 'nine') })
},
{
markup: ({ content }) => ({ code: content.replace(/six/g, 'seven') }),
script: ({ content }) => ({ code: content.replace(/eight/g, 'nine') }),
style: ({ content }) => ({ code: content.replace(/seven/g, 'eight') })
}
]
]
};

@ -0,0 +1,11 @@
<p>one</p>
<style>
.one {
color: red;
}
</style>
<script>
console.log('one');
</script>

@ -0,0 +1,11 @@
<p>seven</p>
<style>
.eight {
color: red;
}
</style>
<script>
console.log('nine');
</script>
Loading…
Cancel
Save