From d4af674ea213b4e3a8fa87399d8dbcc8b90cbb93 Mon Sep 17 00:00:00 2001 From: Thorben Ziegler Date: Fri, 10 Jan 2020 09:10:00 +0100 Subject: [PATCH] bug(parser): fix parsing of multiline class attribute value (#4242) --- src/compiler/parse/state/tag.ts | 25 ++++++++++++++++--- .../expected.css | 1 + .../expected.html | 1 + .../input.svelte | 14 +++++++++++ 4 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 test/css/samples/omit-scoping-attribute-class-static-multiline/expected.css create mode 100644 test/css/samples/omit-scoping-attribute-class-static-multiline/expected.html create mode 100644 test/css/samples/omit-scoping-attribute-class-static-multiline/input.svelte diff --git a/src/compiler/parse/state/tag.ts b/src/compiler/parse/state/tag.ts index c7e761afc220..ee16c7195f73 100644 --- a/src/compiler/parse/state/tag.ts +++ b/src/compiler/parse/state/tag.ts @@ -439,13 +439,13 @@ function read_attribute_value(parser: Parser) { /(\/>|[\s"'=<>`])/ ); - const value = read_sequence(parser, () => !!parser.match_regex(regex)); + const value = read_sequence(parser, () => !!parser.match_regex(regex), true); if (quote_mark) parser.index += 1; return value; } -function read_sequence(parser: Parser, done: () => boolean): TemplateNode[] { +function read_sequence(parser: Parser, done: () => boolean, is_attribute_value: boolean = false): TemplateNode[] { let current_chunk: Text = { start: parser.index, end: null, @@ -454,9 +454,13 @@ function read_sequence(parser: Parser, done: () => boolean): TemplateNode[] { data: null }; + let is_text_attribute_value = false; + function flush() { if (current_chunk.raw) { - current_chunk.data = decode_character_references(current_chunk.raw); + current_chunk.data = (is_text_attribute_value) ? + decode_character_references(current_chunk.raw.trim()) : + decode_character_references(current_chunk.raw); current_chunk.end = parser.index; chunks.push(current_chunk); } @@ -493,7 +497,20 @@ function read_sequence(parser: Parser, done: () => boolean): TemplateNode[] { data: null }; } else { - current_chunk.raw += parser.template[parser.index++]; + let char: string = parser.template[parser.index++]; + + // remove newlines and tabs + if (is_attribute_value && ['\n', '\r', '\t'].includes(char)) { + is_text_attribute_value = true; + const previous_char_position = current_chunk.raw.length - 1; + const previous_char = current_chunk.raw[previous_char_position]; + + // prevent two spaces after each other + if (previous_char && previous_char !== ' ') char = ' '; + else char = ''; + } + + current_chunk.raw += char; } } diff --git a/test/css/samples/omit-scoping-attribute-class-static-multiline/expected.css b/test/css/samples/omit-scoping-attribute-class-static-multiline/expected.css new file mode 100644 index 000000000000..431f7041061e --- /dev/null +++ b/test/css/samples/omit-scoping-attribute-class-static-multiline/expected.css @@ -0,0 +1 @@ +.foo.svelte-xyz{color:red} \ No newline at end of file diff --git a/test/css/samples/omit-scoping-attribute-class-static-multiline/expected.html b/test/css/samples/omit-scoping-attribute-class-static-multiline/expected.html new file mode 100644 index 000000000000..64bc194b9441 --- /dev/null +++ b/test/css/samples/omit-scoping-attribute-class-static-multiline/expected.html @@ -0,0 +1 @@ +

this is styled

diff --git a/test/css/samples/omit-scoping-attribute-class-static-multiline/input.svelte b/test/css/samples/omit-scoping-attribute-class-static-multiline/input.svelte new file mode 100644 index 000000000000..856168982a2f --- /dev/null +++ b/test/css/samples/omit-scoping-attribute-class-static-multiline/input.svelte @@ -0,0 +1,14 @@ +

+ this is styled +

+ +