From 9118bbb897cf761faf37acda7b81ba59ccffe79a Mon Sep 17 00:00:00 2001 From: Maxim Matyunin Date: Mon, 6 Jan 2020 12:40:24 +0900 Subject: [PATCH 1/8] strict order option --- site/content/docs/04-compile-time.md | 1 + src/compiler/compile/index.ts | 3 +- src/compiler/preprocess/index.ts | 150 ++++++++++++++++++++------- 3 files changed, 113 insertions(+), 41 deletions(-) diff --git a/site/content/docs/04-compile-time.md b/site/content/docs/04-compile-time.md index e9126ccf1316..c6d950cd95d4 100644 --- a/site/content/docs/04-compile-time.md +++ b/site/content/docs/04-compile-time.md @@ -203,6 +203,7 @@ result: { }>, options?: { filename?: string + strictOrder?: boolean } ) ``` diff --git a/src/compiler/compile/index.ts b/src/compiler/compile/index.ts index 12b161aeeb0e..781bad71e92b 100644 --- a/src/compiler/compile/index.ts +++ b/src/compiler/compile/index.ts @@ -26,7 +26,8 @@ const valid_options = [ 'css', 'loopGuardTimeout', 'preserveComments', - 'preserveWhitespace' + 'preserveWhitespace', + 'strictOrder' ]; function validate_options(options: CompileOptions, warnings: Warning[]) { diff --git a/src/compiler/preprocess/index.ts b/src/compiler/preprocess/index.ts index 1a13b869e7af..26c89f01d609 100644 --- a/src/compiler/preprocess/index.ts +++ b/src/compiler/preprocess/index.ts @@ -67,32 +67,31 @@ 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, + filename: string, ) { - // @ts-ignore todo: doublecheck - const filename = (options && options.filename) || preprocessor.filename; // legacy - const dependencies = []; - const preprocessors = Array.isArray(preprocessor) ? preprocessor : [preprocessor]; + const processed: Processed = await func({ + content: source, + filename + }); - 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({ - 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, + }; +} + +async function process_script( + source: string, + func: (...any) => Processed | Promise, + filename: string, +) { + const dependencies = []; - for (const fn of script) { - source = await replace_async( + const s = await replace_async( source, /|([^]*?)<\/script>/gi, async (match, attributes = '', content) => { @@ -100,7 +99,7 @@ export default async function preprocess( return match; } attributes = attributes || ''; - const processed = await fn({ + const processed: Processed = await func({ content, attributes: parse_attributes(attributes), filename @@ -109,26 +108,97 @@ export default async function preprocess( return processed ? `${processed.code}` : match; } ); - } - for (const fn of style) { - source = await replace_async( - source, - /|([^]*?)<\/style>/gi, - async (match, attributes = '', content) => { - if (!attributes && !content) { - return match; - } - const processed: Processed = await fn({ - content, - attributes: parse_attributes(attributes), - filename - }); - if (processed && processed.dependencies) dependencies.push(...processed.dependencies); - return processed ? `${processed.code}` : match; + console.log(s, 'RETURREND'); + + return { + source: s, + dependencies, + }; +} + +async function process_style( + source: string, + func: (...any) => Processed | Promise, + filename: string, +) { + const dependencies = []; + + const s = await replace_async( + source, + /|([^]*?)<\/style>/gi, + async (match, attributes = '', content) => { + if (!attributes && !content) { + return match; } - ); - } + const processed: Processed = await func({ + content, + attributes: parse_attributes(attributes), + filename + }); + + if (processed && processed.dependencies) dependencies.push(...processed.dependencies); + return processed ? `${processed.code}` : match; + } + ); + + return { + source: s, + dependencies, + }; +} + +async function asyncForEach(array, callback) { + // eslint-disable-next-line + for (let index = 0; index < array.length; index++) { + // eslint-disable-next-line + 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 dependencies = []; + + const preprocessors = Array.isArray(preprocessor) ? preprocessor : [preprocessor]; + + const order = options.strictOrder + ? preprocessors + : [ + ...preprocessors.map(({ markup }) => ({ markup })), + ...preprocessors.map(({ script }) => ({ script })), + ...preprocessors.map(({ style }) => ({ style })), + ]; + + console.log(preprocessors); + + await asyncForEach(order, async p => { + let processed; + + if (p.markup) { + processed = await process_markup(source, p.markup, filename); + source = processed.source; + dependencies.push(processed.dependencies); + } + + if (p.script) { + processed = await process_script(source, p.script, filename); + source = processed.source; + dependencies.push(processed.dependencies); + } + + if (p.style) { + processed = await process_style(source, p.style, filename); + source = processed.source; + dependencies.push(processed.dependencies); + } + }); return { // TODO return separated output, in future version where svelte.compile supports it: From 4c4a39ca83ee735eac17b1b117ddc262c9432d4f Mon Sep 17 00:00:00 2001 From: Maxim Matyunin Date: Mon, 6 Jan 2020 13:17:50 +0900 Subject: [PATCH 2/8] lint --- src/compiler/preprocess/index.ts | 66 ++++++++++++++++---------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/compiler/preprocess/index.ts b/src/compiler/preprocess/index.ts index 26c89f01d609..0b83c05deb99 100644 --- a/src/compiler/preprocess/index.ts +++ b/src/compiler/preprocess/index.ts @@ -80,7 +80,7 @@ async function process_markup( return { source: processed ? processed.code : source, - dependencies: processed.dependencies, + dependencies: processed.dependencies }; } @@ -91,28 +91,29 @@ async function process_script( ) { const dependencies = []; - const s = await replace_async( - source, - /|([^]*?)<\/script>/gi, - async (match, attributes = '', content) => { - if (!attributes && !content) { - return match; - } - attributes = attributes || ''; - const processed: Processed = await func({ - content, - attributes: parse_attributes(attributes), - filename - }); - if (processed && processed.dependencies) dependencies.push(...processed.dependencies); - return processed ? `${processed.code}` : match; + source = await replace_async( + source, + /|([^]*?)<\/script>/gi, + async (match, attributes = '', content) => { + if (!attributes && !content) { + return match; + } + attributes = attributes || ''; + const processed: Processed = await func({ + content, + attributes: parse_attributes(attributes), + filename + }); + if (processed && processed.dependencies) { + dependencies.push(...processed.dependencies); } - ); - console.log(s, 'RETURREND'); + return processed ? `${processed.code}` : match; + } + ); return { - source: s, + source, dependencies, }; } @@ -124,7 +125,7 @@ async function process_style( ) { const dependencies = []; - const s = await replace_async( + source = await replace_async( source, /|([^]*?)<\/style>/gi, async (match, attributes = '', content) => { @@ -137,26 +138,26 @@ async function process_style( filename }); - if (processed && processed.dependencies) dependencies.push(...processed.dependencies); + if (processed && processed.dependencies) { + dependencies.push(...processed.dependencies); + } + return processed ? `${processed.code}` : match; } ); return { - source: s, + source, dependencies, }; } -async function asyncForEach(array, callback) { - // eslint-disable-next-line +async function async_for_each(array, callback) { for (let index = 0; index < array.length; index++) { - // eslint-disable-next-line await callback(array[index], index, array); } } - export default async function preprocess( source: string, preprocessor: PreprocessorGroup | PreprocessorGroup[], @@ -164,11 +165,12 @@ export default async function preprocess( ) { // @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 = options.strictOrder + const order = strictOrder ? preprocessors : [ ...preprocessors.map(({ markup }) => ({ markup })), @@ -176,27 +178,25 @@ export default async function preprocess( ...preprocessors.map(({ style }) => ({ style })), ]; - console.log(preprocessors); - - await asyncForEach(order, async p => { + await async_for_each(order, async p => { let processed; if (p.markup) { processed = await process_markup(source, p.markup, filename); source = processed.source; - dependencies.push(processed.dependencies); + if (processed.dependencies.length) dependencies.push(...processed.dependencies); } if (p.script) { processed = await process_script(source, p.script, filename); source = processed.source; - dependencies.push(processed.dependencies); + if (processed.dependencies.length) dependencies.push(...processed.dependencies); } if (p.style) { processed = await process_style(source, p.style, filename); source = processed.source; - dependencies.push(processed.dependencies); + if (processed.dependencies.length) dependencies.push(...processed.dependencies); } }); From cf39b8b3a43427929de526343406683f8c6b5d04 Mon Sep 17 00:00:00 2001 From: Maxim Matyunin Date: Mon, 6 Jan 2020 13:27:58 +0900 Subject: [PATCH 3/8] add test --- src/compiler/preprocess/index.ts | 12 +++++++++--- test/preprocess/samples/strict-order/_config.js | 11 +++++++++++ test/preprocess/samples/strict-order/input.svelte | 11 +++++++++++ test/preprocess/samples/strict-order/output.svelte | 11 +++++++++++ 4 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 test/preprocess/samples/strict-order/_config.js create mode 100644 test/preprocess/samples/strict-order/input.svelte create mode 100644 test/preprocess/samples/strict-order/output.svelte diff --git a/src/compiler/preprocess/index.ts b/src/compiler/preprocess/index.ts index 0b83c05deb99..60609f02753f 100644 --- a/src/compiler/preprocess/index.ts +++ b/src/compiler/preprocess/index.ts @@ -184,19 +184,25 @@ export default async function preprocess( if (p.markup) { processed = await process_markup(source, p.markup, filename); source = processed.source; - if (processed.dependencies.length) dependencies.push(...processed.dependencies); + 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.length) dependencies.push(...processed.dependencies); + 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.length) dependencies.push(...processed.dependencies); + if (processed.dependencies && processed.dependencies.length) { + dependencies.push(...processed.dependencies); + } } }); diff --git a/test/preprocess/samples/strict-order/_config.js b/test/preprocess/samples/strict-order/_config.js new file mode 100644 index 000000000000..e47e14b929a8 --- /dev/null +++ b/test/preprocess/samples/strict-order/_config.js @@ -0,0 +1,11 @@ +export default { + strictOrder: false, + preprocess: [ + { + style: ({ content }) => ({ code: content.replace(/one/g, 'two') }), + }, + { + markup: ({ content }) => ({ code: content.replace(/two/g, 'three') }), + }, + ], +}; diff --git a/test/preprocess/samples/strict-order/input.svelte b/test/preprocess/samples/strict-order/input.svelte new file mode 100644 index 000000000000..3bf89c6b959b --- /dev/null +++ b/test/preprocess/samples/strict-order/input.svelte @@ -0,0 +1,11 @@ +

one

+ + + + \ No newline at end of file diff --git a/test/preprocess/samples/strict-order/output.svelte b/test/preprocess/samples/strict-order/output.svelte new file mode 100644 index 000000000000..3bf89c6b959b --- /dev/null +++ b/test/preprocess/samples/strict-order/output.svelte @@ -0,0 +1,11 @@ +

one

+ + + + \ No newline at end of file From 54f9a79ff5e26a3cbd59b04494d8c2b7c27913c8 Mon Sep 17 00:00:00 2001 From: Maxim Matyunin Date: Tue, 7 Jan 2020 15:06:31 +0900 Subject: [PATCH 4/8] normal order test --- test/preprocess/index.js | 16 +++++++++++++--- test/preprocess/samples/normal-order/_config.js | 14 ++++++++++++++ .../preprocess/samples/normal-order/input.svelte | 11 +++++++++++ .../samples/normal-order/output.svelte | 11 +++++++++++ test/preprocess/samples/strict-order/_config.js | 4 +++- .../preprocess/samples/strict-order/input.svelte | 2 +- .../samples/strict-order/output.svelte | 2 +- 7 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 test/preprocess/samples/normal-order/_config.js create mode 100644 test/preprocess/samples/normal-order/input.svelte create mode 100644 test/preprocess/samples/normal-order/output.svelte diff --git a/test/preprocess/index.js b/test/preprocess/index.js index 5d83bb60590d..a3b37b00f0f9 100644 --- a/test/preprocess/index.js +++ b/test/preprocess/index.js @@ -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); diff --git a/test/preprocess/samples/normal-order/_config.js b/test/preprocess/samples/normal-order/_config.js new file mode 100644 index 000000000000..c3668385e6bd --- /dev/null +++ b/test/preprocess/samples/normal-order/_config.js @@ -0,0 +1,14 @@ +export default { + solo: true, + options: { + strictOrder: false, + }, + preprocess: [ + { + style: ({ content }) => ({ code: content.replace(/one/g, 'two') }), + }, + { + markup: ({ content }) => ({ code: content.replace(/two/g, 'three') }), + }, + ], +}; diff --git a/test/preprocess/samples/normal-order/input.svelte b/test/preprocess/samples/normal-order/input.svelte new file mode 100644 index 000000000000..6dbbfb47a9cf --- /dev/null +++ b/test/preprocess/samples/normal-order/input.svelte @@ -0,0 +1,11 @@ +

one

+ + + + \ No newline at end of file diff --git a/test/preprocess/samples/normal-order/output.svelte b/test/preprocess/samples/normal-order/output.svelte new file mode 100644 index 000000000000..3bf89c6b959b --- /dev/null +++ b/test/preprocess/samples/normal-order/output.svelte @@ -0,0 +1,11 @@ +

one

+ + + + \ No newline at end of file diff --git a/test/preprocess/samples/strict-order/_config.js b/test/preprocess/samples/strict-order/_config.js index e47e14b929a8..faa6371149e7 100644 --- a/test/preprocess/samples/strict-order/_config.js +++ b/test/preprocess/samples/strict-order/_config.js @@ -1,5 +1,7 @@ export default { - strictOrder: false, + options: { + strictOrder: true, + }, preprocess: [ { style: ({ content }) => ({ code: content.replace(/one/g, 'two') }), diff --git a/test/preprocess/samples/strict-order/input.svelte b/test/preprocess/samples/strict-order/input.svelte index 3bf89c6b959b..6dbbfb47a9cf 100644 --- a/test/preprocess/samples/strict-order/input.svelte +++ b/test/preprocess/samples/strict-order/input.svelte @@ -1,7 +1,7 @@

one

diff --git a/test/preprocess/samples/strict-order/output.svelte b/test/preprocess/samples/strict-order/output.svelte index 3bf89c6b959b..1ca1a0d4c1c8 100644 --- a/test/preprocess/samples/strict-order/output.svelte +++ b/test/preprocess/samples/strict-order/output.svelte @@ -1,7 +1,7 @@

one

From 16edc673c177f430e86c9d8a6915d6aa16f00c43 Mon Sep 17 00:00:00 2001 From: Maxim Matyunin Date: Tue, 7 Jan 2020 19:09:20 +0900 Subject: [PATCH 5/8] remove solo: true --- test/preprocess/samples/normal-order/_config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/preprocess/samples/normal-order/_config.js b/test/preprocess/samples/normal-order/_config.js index c3668385e6bd..cbac27884385 100644 --- a/test/preprocess/samples/normal-order/_config.js +++ b/test/preprocess/samples/normal-order/_config.js @@ -1,5 +1,4 @@ export default { - solo: true, options: { strictOrder: false, }, From 7f2b68e53df52a97f2f7b3bb2aec65189b18b333 Mon Sep 17 00:00:00 2001 From: Maxim Matyunin Date: Tue, 7 Jan 2020 19:14:19 +0900 Subject: [PATCH 6/8] add docs --- site/content/docs/04-compile-time.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/site/content/docs/04-compile-time.md b/site/content/docs/04-compile-time.md index c6d950cd95d4..45e4d3a4b424 100644 --- a/site/content/docs/04-compile-time.md +++ b/site/content/docs/04-compile-time.md @@ -306,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` From 00910fe792211112382384b28674544f3717d13a Mon Sep 17 00:00:00 2001 From: Maxim Matyunin Date: Tue, 7 Jan 2020 19:19:50 +0900 Subject: [PATCH 7/8] tests reversed --- test/preprocess/samples/normal-order/output.svelte | 2 +- test/preprocess/samples/strict-order/output.svelte | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/preprocess/samples/normal-order/output.svelte b/test/preprocess/samples/normal-order/output.svelte index 3bf89c6b959b..1ca1a0d4c1c8 100644 --- a/test/preprocess/samples/normal-order/output.svelte +++ b/test/preprocess/samples/normal-order/output.svelte @@ -1,7 +1,7 @@

one

diff --git a/test/preprocess/samples/strict-order/output.svelte b/test/preprocess/samples/strict-order/output.svelte index 1ca1a0d4c1c8..3bf89c6b959b 100644 --- a/test/preprocess/samples/strict-order/output.svelte +++ b/test/preprocess/samples/strict-order/output.svelte @@ -1,7 +1,7 @@

one

From f7d3be1a54bd536cb29f0ae6b83e612a77fbcef9 Mon Sep 17 00:00:00 2001 From: Maxim Matyunin Date: Tue, 4 Aug 2020 14:56:14 +0900 Subject: [PATCH 8/8] get rid of async_for_each --- src/compiler/preprocess/index.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/compiler/preprocess/index.ts b/src/compiler/preprocess/index.ts index 60609f02753f..5b330e6c936c 100644 --- a/src/compiler/preprocess/index.ts +++ b/src/compiler/preprocess/index.ts @@ -152,10 +152,12 @@ async function process_style( }; } -async function async_for_each(array, callback) { - for (let index = 0; index < array.length; index++) { - await callback(array[index], index, array); - } +function merge_preprocessors(preprocessors: PreprocessorGroup[]): PreprocessorGroup[] { + return [ + ...preprocessors.map(({ markup }) => ({ markup })), + ...preprocessors.map(({ script }) => ({ script })), + ...preprocessors.map(({ style }) => ({ style })), + ]; } export default async function preprocess( @@ -172,13 +174,9 @@ export default async function preprocess( const order = strictOrder ? preprocessors - : [ - ...preprocessors.map(({ markup }) => ({ markup })), - ...preprocessors.map(({ script }) => ({ script })), - ...preprocessors.map(({ style }) => ({ style })), - ]; + : merge_preprocessors(preprocessors); - await async_for_each(order, async p => { + for (const p of order) { let processed; if (p.markup) { @@ -204,7 +202,7 @@ export default async function preprocess( dependencies.push(...processed.dependencies); } } - }); + } return { // TODO return separated output, in future version where svelte.compile supports it: