From ffdae43b7058066e57bb7a5332983d1ea5922ee2 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 12 Dec 2017 19:48:15 -0500 Subject: [PATCH] allow components without slots to have whitespace as only child - fixes #1007 --- src/generators/nodes/Element.ts | 6 +++--- src/generators/nodes/Text.ts | 15 +++++++++++++-- src/generators/nodes/shared/Node.ts | 6 +++--- .../samples/component-slot-empty/Nested.html | 1 + .../samples/component-slot-empty/_config.js | 3 +++ .../samples/component-slot-empty/main.html | 12 ++++++++++++ 6 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 test/runtime/samples/component-slot-empty/Nested.html create mode 100644 test/runtime/samples/component-slot-empty/_config.js create mode 100644 test/runtime/samples/component-slot-empty/main.html diff --git a/src/generators/nodes/Element.ts b/src/generators/nodes/Element.ts index 62b76eb6ed..9a11cbde25 100644 --- a/src/generators/nodes/Element.ts +++ b/src/generators/nodes/Element.ts @@ -29,7 +29,7 @@ export default class Element extends Node { this.cannotUseInnerHTML(); } - const parentElement = this.parent && this.parent.findNearest('Element'); + const parentElement = this.parent && this.parent.findNearest(/^Element/); this.namespace = this.name === 'svg' ? namespaces.svg : parentElement ? parentElement.namespace : this.generator.namespace; @@ -133,7 +133,7 @@ export default class Element extends Node { this.cannotUseInnerHTML(); this.slotted = true; // TODO validate slots — no nesting, no dynamic names... - const component = this.findNearest('Component'); + const component = this.findNearest(/^Component/); component._slots.add(slot); } @@ -171,7 +171,7 @@ export default class Element extends Node { const slot = this.attributes.find((attribute: Node) => attribute.name === 'slot'); const initialMountNode = this.slotted ? - `${this.findNearest('Component').var}._slotted.${slot.value[0].data}` : // TODO this looks bonkers + `${this.findNearest(/^Component/).var}._slotted.${slot.value[0].data}` : // TODO this looks bonkers parentNode; block.addVariable(name); diff --git a/src/generators/nodes/Text.ts b/src/generators/nodes/Text.ts index 2a68656836..3d7770a0f7 100644 --- a/src/generators/nodes/Text.ts +++ b/src/generators/nodes/Text.ts @@ -17,15 +17,26 @@ const elementsWithoutText = new Set([ 'video', ]); +function shouldSkip(node: Text) { + if (/\S/.test(node.data)) return false; + + const parentElement = node.findNearest(/(?:Element|Component)/); + if (!parentElement) return false; + + if (parentElement.type === 'Component') return parentElement.children.length === 1 && node === parentElement.children[0]; + + return parentElement.namespace || elementsWithoutText.has(parentElement.name); +} + export default class Text extends Node { type: 'Text'; data: string; shouldSkip: boolean; init(block: Block) { - const parentElement = this.findNearest('Element'); + const parentElement = this.findNearest(/(?:Element|Component)/); - if (!/\S/.test(this.data) && parentElement && (parentElement.namespace || elementsWithoutText.has(parentElement.name))) { + if (shouldSkip(this)) { this.shouldSkip = true; return; } diff --git a/src/generators/nodes/shared/Node.ts b/src/generators/nodes/shared/Node.ts index e19e83819f..0658524bf5 100644 --- a/src/generators/nodes/shared/Node.ts +++ b/src/generators/nodes/shared/Node.ts @@ -133,9 +133,9 @@ export default class Node { false; } - findNearest(type: string) { - if (this.type === type) return this; - if (this.parent) return this.parent.findNearest(type); + findNearest(selector: RegExp) { + if (selector.test(this.type)) return this; + if (this.parent) return this.parent.findNearest(selector); } getOrCreateAnchor(block: Block, parentNode: string) { diff --git a/test/runtime/samples/component-slot-empty/Nested.html b/test/runtime/samples/component-slot-empty/Nested.html new file mode 100644 index 0000000000..ea4c0fb6d3 --- /dev/null +++ b/test/runtime/samples/component-slot-empty/Nested.html @@ -0,0 +1 @@ +

no slot here

\ No newline at end of file diff --git a/test/runtime/samples/component-slot-empty/_config.js b/test/runtime/samples/component-slot-empty/_config.js new file mode 100644 index 0000000000..21c3572730 --- /dev/null +++ b/test/runtime/samples/component-slot-empty/_config.js @@ -0,0 +1,3 @@ +export default { + html: '

no slot here

' +}; diff --git a/test/runtime/samples/component-slot-empty/main.html b/test/runtime/samples/component-slot-empty/main.html new file mode 100644 index 0000000000..30b5cc73e3 --- /dev/null +++ b/test/runtime/samples/component-slot-empty/main.html @@ -0,0 +1,12 @@ + + + +