diff --git a/CHANGELOG.md b/CHANGELOG.md index 924413bc02..40acabf61c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ Also: * Fix `{#each}` context not shadowing outer scope when using `bind:` ([#1565](https://github.com/sveltejs/svelte/issues/1565)) * Fix edge cases in matching selectors against elements ([#1710](https://github.com/sveltejs/svelte/issues/1710)) -* Fix several bugs related to interaction of `{...spread}` attributes with other features ([#2721](https://github.com/sveltejs/svelte/issues/2721), [#3421](https://github.com/sveltejs/svelte/issues/3421), [#3681](https://github.com/sveltejs/svelte/issues/3681), [#3764](https://github.com/sveltejs/svelte/issues/3764), [#3790](https://github.com/sveltejs/svelte/issues/3790)) +* Fix several bugs related to interaction of `{...spread}` attributes with other features ([#2721](https://github.com/sveltejs/svelte/issues/2721), [#2916](https://github.com/sveltejs/svelte/issues/2916), [#3421](https://github.com/sveltejs/svelte/issues/3421), [#3681](https://github.com/sveltejs/svelte/issues/3681), [#3764](https://github.com/sveltejs/svelte/issues/3764), [#3790](https://github.com/sveltejs/svelte/issues/3790)) * Allow exiting a reactive block early with `break $` ([#2828](https://github.com/sveltejs/svelte/issues/2828)) * Fix application of style scoping class in cases of ambiguity ([#3544](https://github.com/sveltejs/svelte/issues/3544)) * Check attributes have changed before setting them to avoid image flicker ([#3579](https://github.com/sveltejs/svelte/pull/3579)) diff --git a/src/compiler/compile/render_ssr/handlers/Element.ts b/src/compiler/compile/render_ssr/handlers/Element.ts index 65013a8d07..c77a44990c 100644 --- a/src/compiler/compile/render_ssr/handlers/Element.ts +++ b/src/compiler/compile/render_ssr/handlers/Element.ts @@ -1,52 +1,12 @@ import { is_void } from '../../../utils/names'; import { get_attribute_value, get_class_attribute_value } from './shared/get_attribute_value'; import { get_slot_scope } from './shared/get_slot_scope'; +import { boolean_attributes } from './shared/boolean_attributes'; import Renderer, { RenderOptions } from '../Renderer'; import Element from '../../nodes/Element'; import { x } from 'code-red'; import Expression from '../../nodes/shared/Expression'; -// source: https://gist.github.com/ArjanSchouten/0b8574a6ad7f5065a5e7 -const boolean_attributes = new Set([ - 'async', - 'autocomplete', - 'autofocus', - 'autoplay', - 'border', - 'challenge', - 'checked', - 'compact', - 'contenteditable', - 'controls', - 'default', - 'defer', - 'disabled', - 'formnovalidate', - 'frameborder', - 'hidden', - 'indeterminate', - 'ismap', - 'loop', - 'multiple', - 'muted', - 'nohref', - 'noresize', - 'noshade', - 'novalidate', - 'nowrap', - 'open', - 'readonly', - 'required', - 'reversed', - 'scoped', - 'scrolling', - 'seamless', - 'selected', - 'sortable', - 'spellcheck', - 'translate' -]); - export default function(node: Element, renderer: Renderer, options: RenderOptions & { slot_scopes: Map; }) { diff --git a/src/compiler/compile/render_ssr/handlers/shared/boolean_attributes.ts b/src/compiler/compile/render_ssr/handlers/shared/boolean_attributes.ts new file mode 100644 index 0000000000..4520a2064e --- /dev/null +++ b/src/compiler/compile/render_ssr/handlers/shared/boolean_attributes.ts @@ -0,0 +1,27 @@ +// source: https://html.spec.whatwg.org/multipage/indices.html +export const boolean_attributes = new Set([ + 'allowfullscreen', + 'allowpaymentrequest', + 'async', + 'autofocus', + 'autoplay', + 'checked', + 'controls', + 'default', + 'defer', + 'disabled', + 'formnovalidate', + 'hidden', + 'ismap', + 'loop', + 'multiple', + 'muted', + 'nomodule', + 'novalidate', + 'open', + 'playsinline', + 'readonly', + 'required', + 'reversed', + 'selected' +]); diff --git a/src/runtime/internal/ssr.ts b/src/runtime/internal/ssr.ts index 83e585a899..274006f243 100644 --- a/src/runtime/internal/ssr.ts +++ b/src/runtime/internal/ssr.ts @@ -1,5 +1,6 @@ import { set_current_component, current_component } from './lifecycle'; import { run_all, blank_object } from './utils'; +import { boolean_attributes } from '../../compiler/compile/render_ssr/handlers/shared/boolean_attributes'; export const invalid_attribute_name_character = /[\s'">/=\u{FDD0}-\u{FDEF}\u{FFFE}\u{FFFF}\u{1FFFE}\u{1FFFF}\u{2FFFE}\u{2FFFF}\u{3FFFE}\u{3FFFF}\u{4FFFE}\u{4FFFF}\u{5FFFE}\u{5FFFF}\u{6FFFE}\u{6FFFF}\u{7FFFE}\u{7FFFF}\u{8FFFE}\u{8FFFF}\u{9FFFE}\u{9FFFF}\u{AFFFE}\u{AFFFF}\u{BFFFE}\u{BFFFF}\u{CFFFE}\u{CFFFF}\u{DFFFE}\u{DFFFF}\u{EFFFE}\u{EFFFF}\u{FFFFE}\u{FFFFF}\u{10FFFE}\u{10FFFF}]/u; // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 @@ -20,14 +21,14 @@ export function spread(args, classes_to_add) { if (invalid_attribute_name_character.test(name)) return; const value = attributes[name]; - if (value == null) return; if (value === true) str += " " + name; - - const escaped = String(value) - .replace(/"/g, '"') - .replace(/'/g, '''); - - str += " " + name + "=" + JSON.stringify(escaped); + else if (boolean_attributes.has(name.toLowerCase())) { + if (value) str += " " + name; + } else if (value != null) { + str += " " + name + "=" + JSON.stringify(String(value) + .replace(/"/g, '"') + .replace(/'/g, ''')); + } }); return str; diff --git a/test/server-side-rendering/samples/attribute-boolean/_expected.html b/test/server-side-rendering/samples/attribute-boolean/_expected.html index 3ca3bfd9a8..5b36bb6c3f 100644 --- a/test/server-side-rendering/samples/attribute-boolean/_expected.html +++ b/test/server-side-rendering/samples/attribute-boolean/_expected.html @@ -1 +1,2 @@ + diff --git a/test/server-side-rendering/samples/attribute-boolean/main.svelte b/test/server-side-rendering/samples/attribute-boolean/main.svelte index 3ca3bfd9a8..0852e12418 100644 --- a/test/server-side-rendering/samples/attribute-boolean/main.svelte +++ b/test/server-side-rendering/samples/attribute-boolean/main.svelte @@ -1 +1,2 @@ + diff --git a/test/server-side-rendering/samples/spread-attributes-boolean/_expected.html b/test/server-side-rendering/samples/spread-attributes-boolean/_expected.html new file mode 100644 index 0000000000..06048d3efa --- /dev/null +++ b/test/server-side-rendering/samples/spread-attributes-boolean/_expected.html @@ -0,0 +1,2 @@ + + diff --git a/test/server-side-rendering/samples/spread-attributes-boolean/main.svelte b/test/server-side-rendering/samples/spread-attributes-boolean/main.svelte new file mode 100644 index 0000000000..3d865c0082 --- /dev/null +++ b/test/server-side-rendering/samples/spread-attributes-boolean/main.svelte @@ -0,0 +1,2 @@ + +