Merge branch 'strict-order'

pull/3349/head
Maxim Matyunin 6 years ago
commit 837c93f16a

@ -203,6 +203,7 @@ result: {
}>,
options?: {
filename?: string
strictOrder?: boolean
}
)
```
@ -305,6 +306,30 @@ const { code } = svelte.preprocess(source, [
});
```
---
User may override default preprocessor order by passing `strictOrder` option.
```js
const svelte = require('svelte/compiler');
const { code } = svelte.preprocess(source, [
{
style: () => {
console.log('this runs first');
}
},
{
markup: () => {
console.log('this runs second');
}
}
], {
filename: 'App.svelte',
strictOrder: true
});
```
### `svelte.walk`

@ -26,7 +26,8 @@ const valid_options = [
'css',
'loopGuardTimeout',
'preserveComments',
'preserveWhitespace'
'preserveWhitespace',
'strictOrder'
];
function validate_options(options: CompileOptions, warnings: Warning[]) {

@ -67,31 +67,30 @@ async function replace_async(str: string, re: RegExp, func: (...any) => Promise<
return out;
}
export default async function preprocess(
async function process_markup(
source: string,
preprocessor: PreprocessorGroup | PreprocessorGroup[],
options?: { filename?: string }
func: (...any) => Processed | Promise<Processed>,
filename: string,
) {
// @ts-ignore todo: doublecheck
const filename = (options && options.filename) || preprocessor.filename; // legacy
const dependencies = [];
const preprocessors = Array.isArray(preprocessor) ? preprocessor : [preprocessor];
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);
for (const fn of markup) {
const processed = await fn({
const processed: Processed = await func({
content: source,
filename
});
if (processed && processed.dependencies) dependencies.push(...processed.dependencies);
source = processed ? processed.code : source;
return {
source: processed ? processed.code : source,
dependencies: processed.dependencies
};
}
for (const fn of script) {
async function process_script(
source: string,
func: (...any) => Processed | Promise<Processed>,
filename: string,
) {
const dependencies = [];
source = await replace_async(
source,
/<!--[^]*?-->|<script(\s[^]*?)?>([^]*?)<\/script>/gi,
@ -100,18 +99,32 @@ export default async function preprocess(
return match;
}
attributes = attributes || '';
const processed = await fn({
const processed: Processed = await func({
content,
attributes: parse_attributes(attributes),
filename
});
if (processed && processed.dependencies) dependencies.push(...processed.dependencies);
if (processed && processed.dependencies) {
dependencies.push(...processed.dependencies);
}
return processed ? `<script${attributes}>${processed.code}</script>` : match;
}
);
return {
source,
dependencies,
};
}
for (const fn of style) {
async function process_style(
source: string,
func: (...any) => Processed | Promise<Processed>,
filename: string,
) {
const dependencies = [];
source = await replace_async(
source,
/<!--[^]*?-->|<style(\s[^]*?)?>([^]*?)<\/style>/gi,
@ -119,17 +132,80 @@ export default async function preprocess(
if (!attributes && !content) {
return match;
}
const processed: Processed = await fn({
const processed: Processed = await func({
content,
attributes: parse_attributes(attributes),
filename
});
if (processed && processed.dependencies) dependencies.push(...processed.dependencies);
if (processed && processed.dependencies) {
dependencies.push(...processed.dependencies);
}
return processed ? `<style${attributes}>${processed.code}</style>` : match;
}
);
return {
source,
dependencies,
};
}
async function async_for_each(array, callback) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
}
export default async function preprocess(
source: string,
preprocessor: PreprocessorGroup | PreprocessorGroup[],
options?: { filename?: string; strictOrder?: boolean }
) {
// @ts-ignore todo: doublecheck
const filename = (options && options.filename) || preprocessor.filename; // legacy
const strictOrder = options && options.strictOrder;
const dependencies = [];
const preprocessors = Array.isArray(preprocessor) ? preprocessor : [preprocessor];
const order = strictOrder
? preprocessors
: [
...preprocessors.map(({ markup }) => ({ markup })),
...preprocessors.map(({ script }) => ({ script })),
...preprocessors.map(({ style }) => ({ style })),
];
await async_for_each(order, async p => {
let processed;
if (p.markup) {
processed = await process_markup(source, p.markup, filename);
source = processed.source;
if (processed.dependencies && processed.dependencies.length) {
dependencies.push(...processed.dependencies);
}
}
if (p.script) {
processed = await process_script(source, p.script, filename);
source = processed.source;
if (processed.dependencies && processed.dependencies.length) {
dependencies.push(...processed.dependencies);
}
}
if (p.style) {
processed = await process_style(source, p.style, filename);
source = processed.source;
if (processed.dependencies && processed.dependencies.length) {
dependencies.push(...processed.dependencies);
}
}
});
return {
// TODO return separated output, in future version where svelte.compile supports it:
// style: { code: styleCode, map: styleMap },

@ -14,10 +14,20 @@ describe('preprocess', () => {
}
(config.skip ? it.skip : solo ? it.only : it)(dir, async () => {
const input = fs.readFileSync(`${__dirname}/samples/${dir}/input.svelte`, 'utf-8');
const expected = fs.readFileSync(`${__dirname}/samples/${dir}/output.svelte`, 'utf-8');
const input = fs.readFileSync(
`${__dirname}/samples/${dir}/input.svelte`,
'utf-8'
);
const expected = fs.readFileSync(
`${__dirname}/samples/${dir}/output.svelte`,
'utf-8'
);
const result = await svelte.preprocess(input, config.preprocess);
const result = await svelte.preprocess(
input,
config.preprocess,
config.options
);
fs.writeFileSync(`${__dirname}/samples/${dir}/_actual.html`, result.code);
assert.equal(result.code, expected);

@ -0,0 +1,13 @@
export default {
options: {
strictOrder: false,
},
preprocess: [
{
style: ({ content }) => ({ code: content.replace(/one/g, 'two') }),
},
{
markup: ({ content }) => ({ code: content.replace(/two/g, 'three') }),
},
],
};

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

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

@ -0,0 +1,13 @@
export default {
options: {
strictOrder: true,
},
preprocess: [
{
style: ({ content }) => ({ code: content.replace(/one/g, 'two') }),
},
{
markup: ({ content }) => ({ code: content.replace(/two/g, 'three') }),
},
],
};

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

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