Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] Compiler option css: 'none' support #7914

Merged
merged 7 commits into from Nov 9, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 25 additions & 2 deletions src/compiler/compile/index.ts
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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 = [];
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/compile/render_dom/index.ts
Expand Up @@ -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) {
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/interfaces.ts
Expand Up @@ -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;
Expand All @@ -191,6 +191,7 @@ export interface CompileOptions {
export interface ParserOptions {
filename?: string;
customElement?: boolean;
css?: 'injected' | 'external' | 'none' | boolean;
}

export interface Visitor {
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/parse/index.ts
Expand Up @@ -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[] = [];
Expand All @@ -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,
Expand Down
11 changes: 9 additions & 2 deletions src/compiler/parse/read/style.ts
Expand Up @@ -8,14 +8,21 @@ 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);
}

const content_end = parser.index;

// discard styles when css is disabled
if (parser.css_mode === 'none') {
parser.read(tag_close_pattern);
return null;
}

let ast;

try {
Expand Down Expand Up @@ -67,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 {
Expand Down
7 changes: 7 additions & 0 deletions test/parser/samples/css-option-none/input.svelte
@@ -0,0 +1,7 @@
<div>foo</div>

<style>
div {
color: red;
}
</style>
3 changes: 3 additions & 0 deletions test/parser/samples/css-option-none/options.json
@@ -0,0 +1,3 @@
{
"css": "none"
}
32 changes: 32 additions & 0 deletions 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"
}
]
}
}