diff --git a/src/index.ts b/src/index.ts index ad1b6e255d..e4353fdff7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -67,7 +67,7 @@ async function replaceTagContents(source, type: 'script' | 'style', preprocessor if (processed && processed.code) { return ( source.slice(0, match.index) + - `<${type}>\n${processed.code}` + + `<${type}>${processed.code}` + source.slice(match.index + match[0].length) ); } diff --git a/test/preprocess/index.js b/test/preprocess/index.js index d01963a26f..ea1a519655 100644 --- a/test/preprocess/index.js +++ b/test/preprocess/index.js @@ -1,164 +1,147 @@ import assert from 'assert'; -import * as fs from 'fs'; -import {parse} from 'acorn'; -import {addLineNumbers, env, normalizeHtml, svelte} from '../helpers.js'; - -function tryRequire(file) { - try { - const mod = require(file); - return mod.default || mod; - } catch (err) { - if (err.code !== 'MODULE_NOT_FOUND') throw err; - return null; - } -} - -function normalizeWarning(warning) { - warning.frame = warning.frame.replace(/^\n/, ''). - replace(/^\t+/gm, ''). - replace(/\s+$/gm, ''); - delete warning.filename; - delete warning.toString; - return warning; -} - -function checkCodeIsValid(code) { - try { - parse(code); - } catch (err) { - console.error(addLineNumbers(code)); - throw new Error(err.message); - } -} +import {svelte} from '../helpers.js'; describe.only('preprocess', () => { - fs.readdirSync('test/preprocess/samples').forEach(dir => { - if (dir[0] === '.') return; - - // add .solo to a sample directory name to only run that test - const solo = /\.solo/.test(dir); - const skip = /\.skip/.test(dir); - - if (solo && process.env.CI) { - throw new Error('Forgot to remove `solo: true` from test'); - } - - (solo ? it.only : skip ? it.skip : it)(dir, () => { - const config = tryRequire(`./samples/${dir}/_config.js`) || {}; - const input = fs.existsSync(`test/preprocess/samples/${dir}/input.pug`) ? - read(`test/preprocess/samples/${dir}/input.pug`) : - read(`test/preprocess/samples/${dir}/input.html`); - - return svelte.preprocess(input, config) - .then(processed => processed.toString()) - .then(processed => { - const expectedWarnings = (config.warnings || []).map( - normalizeWarning); - const domWarnings = []; - const ssrWarnings = []; - - const dom = svelte.compile( - processed, - Object.assign(config, { - format: 'iife', - name: 'SvelteComponent', - onwarn: warning => { - domWarnings.push(warning); - }, - }) - ); - - const ssr = svelte.compile( - processed, - Object.assign(config, { - format: 'iife', - generate: 'ssr', - name: 'SvelteComponent', - onwarn: warning => { - ssrWarnings.push(warning); - }, - }) - ); - - // check the code is valid - checkCodeIsValid(dom.code); - checkCodeIsValid(ssr.code); - - assert.equal(dom.css, ssr.css); - - assert.deepEqual( - domWarnings.map(normalizeWarning), - ssrWarnings.map(normalizeWarning) - ); - assert.deepEqual(domWarnings.map(normalizeWarning), expectedWarnings); - - const expected = { - html: read(`test/preprocess/samples/${dir}/expected.html`), - css: read(`test/preprocess/samples/${dir}/expected.css`), - }; - - if (expected.css !== null) { - fs.writeFileSync(`test/preprocess/samples/${dir}/_actual.css`, - dom.css); - assert.equal(dom.css.replace(/svelte-\d+/g, 'svelte-xyz'), - expected.css); - } - - // verify that the right elements have scoping selectors - if (expected.html !== null) { - const window = env(); - - // dom - try { - const Component = eval( - `(function () { ${dom.code}; return SvelteComponent; }())` - ); - const target = window.document.querySelector('main'); - - new Component({target, data: config.data}); - const html = target.innerHTML; - - fs.writeFileSync(`test/preprocess/samples/${dir}/_actual.html`, - html); - - assert.equal( - normalizeHtml(window, - html.replace(/svelte-\d+/g, 'svelte-xyz')), - normalizeHtml(window, expected.html) - ); - } catch (err) { - console.log(dom.code); - throw err; - } - - // ssr - try { - const component = eval( - `(function () { ${ssr.code}; return SvelteComponent; }())` - ); - - assert.equal( - normalizeHtml( - window, - component.render(config.data). - replace(/svelte-\d+/g, 'svelte-xyz') - ), - normalizeHtml(window, expected.html) - ); - } catch (err) { - console.log(ssr.code); - throw err; - } - } + it('preprocesses entire component', () => { + const source = ` +

Hello __NAME__!

+ `; + + const expected = ` +

Hello world!

+ `; + + return svelte.preprocess(source, { + markup: ({ content }) => { + return { + code: content.replace('__NAME__', 'world') + }; + } + }).then(processed => { + assert.equal(processed.toString(), expected); + }); + }); + + it('preprocesses style', () => { + const source = ` +
$brand
+ + + `; + + const expected = ` +
$brand
+ + + `; + + return svelte.preprocess(source, { + style: ({ content }) => { + return { + code: content.replace('$brand', 'purple') + }; + } + }).then(processed => { + assert.equal(processed.toString(), expected); + }); + }); + + it('preprocesses style asynchronously', () => { + const source = ` +
$brand
+ + + `; + + const expected = ` +
$brand
+ + + `; + + return svelte.preprocess(source, { + style: ({ content }) => { + return Promise.resolve({ + code: content.replace('$brand', 'purple') }); + } + }).then(processed => { + assert.equal(processed.toString(), expected); + }); + }); + + it('preprocesses script', () => { + const source = ` + + `; + + const expected = ` + + `; + + return svelte.preprocess(source, { + script: ({ content }) => { + return { + code: content.replace('__THE_ANSWER__', '42') + }; + } + }).then(processed => { + assert.equal(processed.toString(), expected); + }); + }); + + it('parses attributes', () => { + const source = ` + + `; + + return svelte.preprocess(source, { + style: ({ attributes }) => { + assert.deepEqual(attributes, { + type: 'text/scss', + bool: true + }); + } + }); + }); + + it('ignores null/undefined returned from preprocessor', () => { + const source = ` + + `; + + const expected = ` + + `; + + return svelte.preprocess(source, { + script: () => null + }).then(processed => { + assert.equal(processed.toString(), expected); }); }); -}); - -function read(file) { - try { - return fs.readFileSync(file, 'utf-8'); - } catch (err) { - return null; - } -} +}); \ No newline at end of file diff --git a/test/preprocess/samples/use-coffeescript-preprocessor/_config.js b/test/preprocess/samples/use-coffeescript-preprocessor/_config.js index 1865fe4086..1fc6c44c64 100644 --- a/test/preprocess/samples/use-coffeescript-preprocessor/_config.js +++ b/test/preprocess/samples/use-coffeescript-preprocessor/_config.js @@ -4,16 +4,11 @@ export default { cascade: false, script: ({content, attributes}) => { if (attributes.type !== 'text/coffeescript') { - return {code: content}; + return null; } - return new Promise((fulfil, reject) => { - try { - const code = CoffeeScript.compile(content, {}); - fulfil({code}); - } catch (error) { - reject(error); - } - }); + return { + code: CoffeeScript.compile(content, {}) + }; }, }; diff --git a/test/preprocess/samples/use-pug-preprocessor/_config.js b/test/preprocess/samples/use-pug-preprocessor/_config.js index 7a345bfd91..99ac56ff7e 100644 --- a/test/preprocess/samples/use-pug-preprocessor/_config.js +++ b/test/preprocess/samples/use-pug-preprocessor/_config.js @@ -3,13 +3,8 @@ import * as pug from 'pug'; export default { cascade: false, markup: ({content}) => { - return new Promise((fulfil, reject) => { - try { - const code = pug.render(content); - fulfil({code}); - } catch (error) { - reject(error); - } - }); + return { + code: pug.render(content) + }; }, }; diff --git a/test/preprocess/samples/use-scss-preprocessor/_config.js b/test/preprocess/samples/use-scss-preprocessor/_config.js index cb3a1a505a..0aedea4659 100644 --- a/test/preprocess/samples/use-scss-preprocessor/_config.js +++ b/test/preprocess/samples/use-scss-preprocessor/_config.js @@ -4,7 +4,7 @@ export default { cascade: false, style: ({ content, attributes }) => { if (attributes.type !== 'text/scss') { - return {code: content}; + return null; } if (attributes['aria-hidden'] !== true) {