diff --git a/src/compiler/compile/render_dom/wrappers/Comment.ts b/src/compiler/compile/render_dom/wrappers/Comment.ts new file mode 100644 index 0000000000..a8c63b4227 --- /dev/null +++ b/src/compiler/compile/render_dom/wrappers/Comment.ts @@ -0,0 +1,41 @@ +import Renderer from '../Renderer'; +import Block from '../Block'; +import Comment from '../../nodes/Comment'; +import Wrapper from './shared/Wrapper'; +import { x } from 'code-red'; +import { Identifier } from 'estree'; + +export default class CommentWrapper extends Wrapper { + node: Comment; + var: Identifier; + + constructor( + renderer: Renderer, + block: Block, + parent: Wrapper, + node: Comment + ) { + super(renderer, block, parent, node); + this.var = x`c` as Identifier; + } + + render(block: Block, parent_node: Identifier, parent_nodes: Identifier) { + if (!this.renderer.options.preserveComments) return; + + const string_literal = { + type: 'Literal', + value: this.node.data, + loc: { + start: this.renderer.locate(this.node.start), + end: this.renderer.locate(this.node.end) + } + }; + + block.add_element( + this.var, + x`@comment(${string_literal})`, + parent_nodes && x`@claim_comment(${parent_nodes}, ${string_literal})`, + parent_node + ); + } +} diff --git a/src/compiler/compile/render_dom/wrappers/Fragment.ts b/src/compiler/compile/render_dom/wrappers/Fragment.ts index 463c8db24a..736cd4e1ef 100644 --- a/src/compiler/compile/render_dom/wrappers/Fragment.ts +++ b/src/compiler/compile/render_dom/wrappers/Fragment.ts @@ -14,6 +14,7 @@ import RawMustacheTag from './RawMustacheTag'; import Slot from './Slot'; import SlotTemplate from './SlotTemplate'; import Text from './Text'; +import Comment from './Comment'; import Title from './Title'; import Window from './Window'; import { INode } from '../../nodes/interfaces'; @@ -27,7 +28,7 @@ import { regex_starts_with_whitespace } from '../../../utils/patterns'; const wrappers = { AwaitBlock, Body, - Comment: null, + Comment, DebugTag, Document, EachBlock, @@ -118,7 +119,7 @@ export default class FragmentWrapper { link(last_child, last_child = wrapper); } else { const Wrapper = wrappers[child.type]; - if (!Wrapper) continue; + if (!Wrapper || (child.type === 'Comment' && !renderer.options.preserveComments)) continue; const wrapper = new Wrapper(renderer, block, parent, child, strip_whitespace, last_child || next_sibling); this.nodes.unshift(wrapper); diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index a746613170..34049b3580 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -254,6 +254,10 @@ export function empty() { return text(''); } +export function comment(content: string) { + return document.createComment(content); +} + export function listen(node: EventTarget, event: string, handler: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | EventListenerOptions) { node.addEventListener(event, handler, options); return () => node.removeEventListener(event, handler, options); @@ -550,6 +554,19 @@ export function claim_space(nodes) { return claim_text(nodes, ' '); } +export function claim_comment(nodes:ChildNodeArray, data) { + return claim_node( + nodes, + (node: ChildNode): node is Comment => node.nodeType === 8, + (node: Comment) => { + node.data = '' + data; + return undefined; + }, + () => comment(data), + true + ); +} + function find_comment(nodes, text, start) { for (let i = start; i < nodes.length; i += 1) { const node = nodes[i]; diff --git a/test/hydration/samples/claim-comment/_after.html b/test/hydration/samples/claim-comment/_after.html new file mode 100644 index 0000000000..3029a9dd64 --- /dev/null +++ b/test/hydration/samples/claim-comment/_after.html @@ -0,0 +1 @@ +
diff --git a/test/hydration/samples/claim-comment/_before.html b/test/hydration/samples/claim-comment/_before.html new file mode 100644 index 0000000000..736fb4602d --- /dev/null +++ b/test/hydration/samples/claim-comment/_before.html @@ -0,0 +1 @@ +
diff --git a/test/hydration/samples/claim-comment/_config.js b/test/hydration/samples/claim-comment/_config.js new file mode 100644 index 0000000000..0f69bd48f6 --- /dev/null +++ b/test/hydration/samples/claim-comment/_config.js @@ -0,0 +1,20 @@ +export default { + compileOptions: { + preserveComments:true + }, + snapshot(target) { + const div = target.querySelector('div'); + + return { + div, + comment: div.childNodes[0] + }; + }, + + test(assert, target, snapshot) { + const div = target.querySelector('div'); + assert.equal(div, snapshot.div); + assert.equal(div.childNodes[0], snapshot.comment); + assert.equal(div.childNodes[1].nodeType, 8); + } +}; diff --git a/test/hydration/samples/claim-comment/main.svelte b/test/hydration/samples/claim-comment/main.svelte new file mode 100644 index 0000000000..3029a9dd64 --- /dev/null +++ b/test/hydration/samples/claim-comment/main.svelte @@ -0,0 +1 @@ +
diff --git a/test/js/samples/dom-preserve-comments/_config.js b/test/js/samples/dom-preserve-comments/_config.js new file mode 100644 index 0000000000..76af4bb39a --- /dev/null +++ b/test/js/samples/dom-preserve-comments/_config.js @@ -0,0 +1,5 @@ +export default { + options: { + preserveComments: true + } +}; diff --git a/test/js/samples/dom-preserve-comments/expected.js b/test/js/samples/dom-preserve-comments/expected.js new file mode 100644 index 0000000000..aa9f509263 --- /dev/null +++ b/test/js/samples/dom-preserve-comments/expected.js @@ -0,0 +1,58 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + comment, + detach, + element, + init, + insert, + noop, + safe_not_equal, + space +} from "svelte/internal"; + +function create_fragment(ctx) { + let div0; + let t1; + let c; + let t2; + let div1; + + return { + c() { + div0 = element("div"); + div0.textContent = "content"; + t1 = space(); + c = comment(" comment "); + t2 = space(); + div1 = element("div"); + div1.textContent = "more content"; + }, + m(target, anchor) { + insert(target, div0, anchor); + insert(target, t1, anchor); + insert(target, c, anchor); + insert(target, t2, anchor); + insert(target, div1, anchor); + }, + p: noop, + i: noop, + o: noop, + d(detaching) { + if (detaching) detach(div0); + if (detaching) detach(t1); + if (detaching) detach(c); + if (detaching) detach(t2); + if (detaching) detach(div1); + } + }; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, null, create_fragment, safe_not_equal, {}); + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/dom-preserve-comments/input.svelte b/test/js/samples/dom-preserve-comments/input.svelte new file mode 100644 index 0000000000..7f7e291caa --- /dev/null +++ b/test/js/samples/dom-preserve-comments/input.svelte @@ -0,0 +1,3 @@ +
content
+ +
more content