From b326a4b35f96148edf142a55dc4df80908ef6fe9 Mon Sep 17 00:00:00 2001 From: maxiruani Date: Thu, 6 Oct 2022 14:54:18 -0300 Subject: [PATCH 1/6] Support css "none" option --- src/compiler/compile/index.ts | 27 ++++++++++++++-- src/compiler/compile/render_dom/index.ts | 2 +- src/compiler/interfaces.ts | 3 +- src/compiler/parse/index.ts | 2 ++ src/compiler/parse/read/style.ts | 6 ++++ .../samples/css-option-none/input.svelte | 7 ++++ .../samples/css-option-none/options.json | 3 ++ .../samples/css-option-none/output.json | 32 +++++++++++++++++++ 8 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 test/parser/samples/css-option-none/input.svelte create mode 100644 test/parser/samples/css-option-none/options.json create mode 100644 test/parser/samples/css-option-none/output.json diff --git a/src/compiler/compile/index.ts b/src/compiler/compile/index.ts index afe9c56cf4c..3d47be1851b 100644 --- a/src/compiler/compile/index.ts +++ b/src/compiler/compile/index.ts @@ -35,8 +35,16 @@ const valid_options = [ 'cssHash' ]; +const valid_css_values = [ + true, + false, + 'injected', + 'external', + 'none' +]; + function validate_options(options: CompileOptions, warnings: Warning[]) { - const { name, filename, loopGuardTimeout, dev, namespace } = options; + const { name, filename, loopGuardTimeout, dev, namespace, css } = options; Object.keys(options).forEach(key => { if (!valid_options.includes(key)) { @@ -72,6 +80,21 @@ function validate_options(options: CompileOptions, warnings: Warning[]) { }); } + if (valid_css_values.indexOf(css) === -1) { + throw new Error(`options.css must be true, false, "injected", "external" or "none" (got '${css}')`); + } + + if (css === true || css === false) { + options.css = css === true ? 'injected' : 'external'; + const message = `options.css as a boolean is deprecated. Use "${options.css}" instead of ${css}.`; + warnings.push({ + code: 'options-css-boolean-deprecated', + message, + filename, + toString: () => message + }); + } + if (namespace && valid_namespaces.indexOf(namespace) === -1) { const match = fuzzymatch(namespace, valid_namespaces); if (match) { @@ -83,7 +106,7 @@ function validate_options(options: CompileOptions, warnings: Warning[]) { } export default function compile(source: string, options: CompileOptions = {}) { - options = Object.assign({ generate: 'dom', dev: false, enableSourcemap: true }, options); + options = Object.assign({ generate: 'dom', dev: false, enableSourcemap: true, css: 'injected' }, options); const stats = new Stats(); const warnings = []; diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index 173d93d5dda..b06c5b577c7 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -53,7 +53,7 @@ export default function dom( const should_add_css = ( !options.customElement && !!styles && - options.css !== false + options.css === 'injected' ); if (should_add_css) { diff --git a/src/compiler/interfaces.ts b/src/compiler/interfaces.ts index 248175da599..eb2cc336ede 100644 --- a/src/compiler/interfaces.ts +++ b/src/compiler/interfaces.ts @@ -179,7 +179,7 @@ export interface CompileOptions { legacy?: boolean; customElement?: boolean; tag?: string; - css?: boolean; + css?: 'injected' | 'external' | 'none' | boolean; loopGuardTimeout?: number; namespace?: string; cssHash?: CssHashGetter; @@ -191,6 +191,7 @@ export interface CompileOptions { export interface ParserOptions { filename?: string; customElement?: boolean; + css?: 'injected' | 'external' | 'none' | boolean; } export interface Visitor { diff --git a/src/compiler/parse/index.ts b/src/compiler/parse/index.ts index e5e2260bc0f..ce873c7d844 100644 --- a/src/compiler/parse/index.ts +++ b/src/compiler/parse/index.ts @@ -19,6 +19,7 @@ export class Parser { readonly template: string; readonly filename?: string; readonly customElement: boolean; + readonly css_mode: 'injected' | 'external' | 'none' | boolean; index = 0; stack: TemplateNode[] = []; @@ -37,6 +38,7 @@ export class Parser { this.template = template.trimRight(); this.filename = options.filename; this.customElement = options.customElement; + this.css_mode = options.css; this.html = { start: null, diff --git a/src/compiler/parse/read/style.ts b/src/compiler/parse/read/style.ts index e4a885a8cca..15e77d2ff62 100644 --- a/src/compiler/parse/read/style.ts +++ b/src/compiler/parse/read/style.ts @@ -16,6 +16,12 @@ export default function read_style(parser: Parser, start: number, attributes: No const content_end = parser.index; + // discard styles when css is disabled + if (parser.css_mode === 'none') { + parser.read(/<\/style\s*>/); + return null; + } + let ast; try { diff --git a/test/parser/samples/css-option-none/input.svelte b/test/parser/samples/css-option-none/input.svelte new file mode 100644 index 00000000000..659c4343f63 --- /dev/null +++ b/test/parser/samples/css-option-none/input.svelte @@ -0,0 +1,7 @@ +
foo
+ + diff --git a/test/parser/samples/css-option-none/options.json b/test/parser/samples/css-option-none/options.json new file mode 100644 index 00000000000..b10d517cc99 --- /dev/null +++ b/test/parser/samples/css-option-none/options.json @@ -0,0 +1,3 @@ +{ + "css": "none" +} diff --git a/test/parser/samples/css-option-none/output.json b/test/parser/samples/css-option-none/output.json new file mode 100644 index 00000000000..ef1f9c9a371 --- /dev/null +++ b/test/parser/samples/css-option-none/output.json @@ -0,0 +1,32 @@ +{ + "html": { + "start": 0, + "end": 14, + "type": "Fragment", + "children": [ + { + "start": 0, + "end": 14, + "type": "Element", + "name": "div", + "attributes": [], + "children": [ + { + "start": 5, + "end": 8, + "type": "Text", + "raw": "foo", + "data": "foo" + } + ] + }, + { + "start": 14, + "end": 16, + "type": "Text", + "raw": "\n\n", + "data": "\n\n" + } + ] + } +} From b219f80dd731af7cc2c869758413ee403c99b023 Mon Sep 17 00:00:00 2001 From: maxiruani Date: Thu, 6 Oct 2022 18:26:45 -0300 Subject: [PATCH 2/6] - Added pattern const --- src/compiler/parse/read/style.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/compiler/parse/read/style.ts b/src/compiler/parse/read/style.ts index 15e77d2ff62..c4788466ec7 100644 --- a/src/compiler/parse/read/style.ts +++ b/src/compiler/parse/read/style.ts @@ -8,7 +8,8 @@ import parser_errors from '../errors'; export default function read_style(parser: Parser, start: number, attributes: Node[]): Style { const content_start = parser.index; - const styles = parser.read_until(/<\/style\s*>/, parser_errors.unclosed_style); + const tag_close_pattern = /<\/style\s*>/; + const styles = parser.read_until(tag_close_pattern, parser_errors.unclosed_style); if (parser.index >= parser.template.length) { parser.error(parser_errors.unclosed_style); @@ -18,7 +19,7 @@ export default function read_style(parser: Parser, start: number, attributes: No // discard styles when css is disabled if (parser.css_mode === 'none') { - parser.read(/<\/style\s*>/); + parser.read(tag_close_pattern); return null; } @@ -73,7 +74,7 @@ export default function read_style(parser: Parser, start: number, attributes: No } }); - parser.read(/<\/style\s*>/); + parser.read(tag_close_pattern); const end = parser.index; return { From 83b0997f83e1cf17746f9ef71197b980bc99d78e Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 6 Oct 2022 14:42:04 -0700 Subject: [PATCH 3/6] Update src/compiler/compile/index.ts --- src/compiler/compile/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/compile/index.ts b/src/compiler/compile/index.ts index 3d47be1851b..41f6b30956f 100644 --- a/src/compiler/compile/index.ts +++ b/src/compiler/compile/index.ts @@ -81,7 +81,7 @@ function validate_options(options: CompileOptions, warnings: Warning[]) { } if (valid_css_values.indexOf(css) === -1) { - throw new Error(`options.css must be true, false, "injected", "external" or "none" (got '${css}')`); + throw new Error(`options.css must be true, false, 'injected', 'external', or 'none' (got '${css}')`); } if (css === true || css === false) { From 8e1c34cd673e2c12e3bbd63153d7875692cc513c Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 6 Oct 2022 14:42:33 -0700 Subject: [PATCH 4/6] Update src/compiler/compile/index.ts --- src/compiler/compile/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/compile/index.ts b/src/compiler/compile/index.ts index 41f6b30956f..ceae02a1f00 100644 --- a/src/compiler/compile/index.ts +++ b/src/compiler/compile/index.ts @@ -86,7 +86,7 @@ function validate_options(options: CompileOptions, warnings: Warning[]) { if (css === true || css === false) { options.css = css === true ? 'injected' : 'external'; - const message = `options.css as a boolean is deprecated. Use "${options.css}" instead of ${css}.`; + const message = `options.css as a boolean is deprecated. Use '${options.css}' instead of ${css}.`; warnings.push({ code: 'options-css-boolean-deprecated', message, From b55b87d3ff009d347c78bfaa7f86205e47bef406 Mon Sep 17 00:00:00 2001 From: maxiruani Date: Wed, 26 Oct 2022 09:06:02 -0300 Subject: [PATCH 5/6] - Added documentation --- site/content/docs/05-compile-time.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/docs/05-compile-time.md b/site/content/docs/05-compile-time.md index 35a57ced85b..b2fe19d7bfc 100644 --- a/site/content/docs/05-compile-time.md +++ b/site/content/docs/05-compile-time.md @@ -73,7 +73,7 @@ The following options can be passed to the compiler. None are required: | `accessors` | `false` | If `true`, getters and setters will be created for the component's props. If `false`, they will only be created for readonly exported values (i.e. those declared with `const`, `class` and `function`). If compiling with `customElement: true` this option defaults to `true`. | `customElement` | `false` | If `true`, tells the compiler to generate a custom element constructor instead of a regular Svelte component. | `tag` | `null` | A `string` that tells Svelte what tag name to register the custom element with. It must be a lowercase alphanumeric string with at least one hyphen, e.g. `"my-element"`. -| `css` | `true` | If `true`, styles will be included in the JavaScript class and injected at runtime for the components actually rendered. If `false`, the CSS will be returned in the `css` field of the compilation result. Most Svelte bundler plugins will set this to `false` and use the CSS that is statically generated for better performance, as it will result in smaller JavaScript bundles and the output can be served as cacheable `.css` files. +| `css` | `"injected"` | If `"injected"` (formerly `true`), styles will be included in the JavaScript class and injected at runtime for the components actually rendered. If `"external"` (formerly `false`), the CSS will be returned in the `css` field of the compilation result. Most Svelte bundler plugins will set this to `"external"` and use the CSS that is statically generated for better performance, as it will result in smaller JavaScript bundles and the output can be served as cacheable `.css` files. If `"none"`, styles are completely avoided and no CSS output is generated. | `cssHash` | See right | A function that takes a `{ hash, css, name, filename }` argument and returns the string that is used as a classname for scoped CSS. It defaults to returning `svelte-${hash(css)}` | `loopGuardTimeout` | 0 | A `number` that tells Svelte to break the loop if it blocks the thread for more than `loopGuardTimeout` ms. This is useful to prevent infinite loops. **Only available when `dev: true`** | `preserveComments` | `false` | If `true`, your HTML comments will be preserved during server-side rendering. By default, they are stripped out. From d99a02980bf2c128432b68510c00f841ed6ac962 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Wed, 2 Nov 2022 06:26:47 -0700 Subject: [PATCH 6/6] Update site/content/docs/05-compile-time.md --- site/content/docs/05-compile-time.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/docs/05-compile-time.md b/site/content/docs/05-compile-time.md index b2fe19d7bfc..45dd454ea01 100644 --- a/site/content/docs/05-compile-time.md +++ b/site/content/docs/05-compile-time.md @@ -73,7 +73,7 @@ The following options can be passed to the compiler. None are required: | `accessors` | `false` | If `true`, getters and setters will be created for the component's props. If `false`, they will only be created for readonly exported values (i.e. those declared with `const`, `class` and `function`). If compiling with `customElement: true` this option defaults to `true`. | `customElement` | `false` | If `true`, tells the compiler to generate a custom element constructor instead of a regular Svelte component. | `tag` | `null` | A `string` that tells Svelte what tag name to register the custom element with. It must be a lowercase alphanumeric string with at least one hyphen, e.g. `"my-element"`. -| `css` | `"injected"` | If `"injected"` (formerly `true`), styles will be included in the JavaScript class and injected at runtime for the components actually rendered. If `"external"` (formerly `false`), the CSS will be returned in the `css` field of the compilation result. Most Svelte bundler plugins will set this to `"external"` and use the CSS that is statically generated for better performance, as it will result in smaller JavaScript bundles and the output can be served as cacheable `.css` files. If `"none"`, styles are completely avoided and no CSS output is generated. +| `css` | `'injected'` | If `'injected'` (formerly `true`), styles will be included in the JavaScript class and injected at runtime for the components actually rendered. If `'external'` (formerly `false`), the CSS will be returned in the `css` field of the compilation result. Most Svelte bundler plugins will set this to `'external'` and use the CSS that is statically generated for better performance, as it will result in smaller JavaScript bundles and the output can be served as cacheable `.css` files. If `'none'`, styles are completely avoided and no CSS output is generated. | `cssHash` | See right | A function that takes a `{ hash, css, name, filename }` argument and returns the string that is used as a classname for scoped CSS. It defaults to returning `svelte-${hash(css)}` | `loopGuardTimeout` | 0 | A `number` that tells Svelte to break the loop if it blocks the thread for more than `loopGuardTimeout` ms. This is useful to prevent infinite loops. **Only available when `dev: true`** | `preserveComments` | `false` | If `true`, your HTML comments will be preserved during server-side rendering. By default, they are stripped out.