diff --git a/src/compiler/compile/render_dom/wrappers/Document.js b/src/compiler/compile/render_dom/wrappers/Document.js
index 05e1b77501..e32b7b48e8 100644
--- a/src/compiler/compile/render_dom/wrappers/Document.js
+++ b/src/compiler/compile/render_dom/wrappers/Document.js
@@ -3,6 +3,7 @@ import { b, x } from 'code-red';
import EventHandler from './Element/EventHandler.js';
import add_event_handlers from './shared/add_event_handlers.js';
import add_actions from './shared/add_actions.js';
+
const associated_events = {
fullscreenElement: ['fullscreenchange'],
visibilityState: ['visibilitychange']
diff --git a/src/compiler/compile/render_dom/wrappers/EachBlock.js b/src/compiler/compile/render_dom/wrappers/EachBlock.js
index ba366ff602..8701dcec2a 100644
--- a/src/compiler/compile/render_dom/wrappers/EachBlock.js
+++ b/src/compiler/compile/render_dom/wrappers/EachBlock.js
@@ -419,7 +419,7 @@ export default class EachBlockWrapper extends Wrapper {
* initial_mount_node: import('estree').Identifier;
* update_anchor_node: import('estree').Identifier;
* update_mount_node: import('estree').Identifier;
- * }}
+ * }} params
*/
render_keyed({
block,
diff --git a/src/compiler/compile/render_dom/wrappers/Fragment.ts b/src/compiler/compile/render_dom/wrappers/Fragment.ts
index 93410a5c42..fa8dadc788 100644
--- a/src/compiler/compile/render_dom/wrappers/Fragment.ts
+++ b/src/compiler/compile/render_dom/wrappers/Fragment.ts
@@ -1,170 +1,161 @@
-import Wrapper from './shared/Wrapper';
-import AwaitBlock from './AwaitBlock';
-import Body from './Body';
-import DebugTag from './DebugTag';
-import Document from './Document';
-import EachBlock from './EachBlock';
-import Element from './Element';
-import Head from './Head';
-import IfBlock from './IfBlock';
-import KeyBlock from './KeyBlock';
-import InlineComponent from './InlineComponent/index';
-import MustacheTag from './MustacheTag';
-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';
-import Renderer from '../Renderer';
-import Block from '../Block';
-import { trim_start, trim_end } from '../../../utils/trim';
-import { link } from '../../../utils/link';
-import { Identifier } from 'estree';
-import { regex_starts_with_whitespace } from '../../../utils/patterns';
-
+import AwaitBlock from './AwaitBlock.js';
+import Body from './Body.js';
+import DebugTag from './DebugTag.js';
+import Document from './Document.js';
+import EachBlock from './EachBlock.js';
+import Element from './Element.js';
+import Head from './Head.js';
+import IfBlock from './IfBlock.js';
+import KeyBlock from './KeyBlock.js';
+import InlineComponent from './InlineComponent/index.js';
+import MustacheTag from './MustacheTag.js';
+import RawMustacheTag from './RawMustacheTag.js';
+import Slot from './Slot.js';
+import SlotTemplate from './SlotTemplate.js';
+import Text from './Text.js';
+import Comment from './Comment.js';
+import Title from './Title.js';
+import Window from './Window.js';
+import { trim_start, trim_end } from '../../../utils/trim.js';
+import { link } from '../../../utils/link.js';
+import { regex_starts_with_whitespace } from '../../../utils/patterns.js';
const wrappers = {
- AwaitBlock,
- Body,
- Comment,
- DebugTag,
- Document,
- EachBlock,
- Element,
- Head,
- IfBlock,
- InlineComponent,
- KeyBlock,
- MustacheTag,
- Options: null,
- RawMustacheTag,
- Slot,
- SlotTemplate,
- Text,
- Title,
- Window
+ AwaitBlock,
+ Body,
+ Comment,
+ DebugTag,
+ Document,
+ EachBlock,
+ Element,
+ Head,
+ IfBlock,
+ InlineComponent,
+ KeyBlock,
+ MustacheTag,
+ Options: null,
+ RawMustacheTag,
+ Slot,
+ SlotTemplate,
+ Text,
+ Title,
+ Window
};
-function trimmable_at(child: INode, next_sibling: Wrapper): boolean {
- // Whitespace is trimmable if one of the following is true:
- // The child and its sibling share a common nearest each block (not at an each block boundary)
- // The next sibling's previous node is an each block
- return (
- next_sibling.node.find_nearest(/EachBlock/) === child.find_nearest(/EachBlock/) ||
- next_sibling.node.prev.type === 'EachBlock'
- );
+/**
+ * @param {import('../../nodes/interfaces.js').INode} child
+ * @param {import('./shared/Wrapper.js').default} next_sibling
+ * @returns {boolean}
+ */
+function trimmable_at(child, next_sibling) {
+ // Whitespace is trimmable if one of the following is true:
+ // The child and its sibling share a common nearest each block (not at an each block boundary)
+ // The next sibling's previous node is an each block
+ return (next_sibling.node.find_nearest(/EachBlock/) === child.find_nearest(/EachBlock/) ||
+ next_sibling.node.prev.type === 'EachBlock');
}
-
export default class FragmentWrapper {
- nodes: Wrapper[];
-
- constructor(
- renderer: Renderer,
- block: Block,
- nodes: INode[],
- parent: Wrapper,
- strip_whitespace: boolean,
- next_sibling: Wrapper
- ) {
- this.nodes = [];
-
- let last_child: Wrapper;
- let window_wrapper: Window | undefined;
-
- let i = nodes.length;
- while (i--) {
- const child = nodes[i];
-
- if (!child.type) {
- throw new Error('missing type');
- }
-
- if (!(child.type in wrappers)) {
- throw new Error(`TODO implement ${child.type}`);
- }
-
- // special case — this is an easy way to remove whitespace surrounding
- // . lil hacky but it works
- if (child.type === 'Window') {
- window_wrapper = new Window(renderer, block, parent, child);
- continue;
- }
-
- if (child.type === 'Text') {
- let { data } = child;
-
- // We want to remove trailing whitespace inside an element/component/block,
- // *unless* there is no whitespace between this node and its next sibling
- if (this.nodes.length === 0) {
- const should_trim = next_sibling
- ? next_sibling.node.type === 'Text' &&
- regex_starts_with_whitespace.test(next_sibling.node.data) &&
- trimmable_at(child, next_sibling)
- : !child.has_ancestor('EachBlock');
- if (should_trim && !child.keep_space()) {
- data = trim_end(data);
- if (!data) continue;
- }
- }
-
- // glue text nodes (which could e.g. be separated by comments) together
- if (last_child && last_child.node.type === 'Text') {
- (last_child as Text).data = data + (last_child as Text).data;
- continue;
- }
-
- const wrapper = new Text(renderer, block, parent, child, data);
- if (wrapper.skip) continue;
-
- this.nodes.unshift(wrapper);
-
- link(last_child, (last_child = wrapper));
- } else {
- const Wrapper = wrappers[child.type];
- 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);
-
- link(last_child, (last_child = wrapper));
- }
- }
-
- if (strip_whitespace) {
- const first = this.nodes[0] as Text;
+ /** @type {import('./shared/Wrapper.js').default[]} */
+ nodes;
+
+ /**
+ * @param {import('../Renderer.js').default} renderer
+ * @param {import('../Block.js').default} block
+ * @param {import('../../nodes/interfaces.js').INode[]} nodes
+ * @param {import('./shared/Wrapper.js').default} parent
+ * @param {boolean} strip_whitespace
+ * @param {import('./shared/Wrapper.js').default} next_sibling
+ */
+ constructor(renderer, block, nodes, parent, strip_whitespace, next_sibling) {
+ this.nodes = [];
+
+ /** @type {import('./shared/Wrapper.js').default} */
+ let last_child;
+
+ /** @type {import('./Window.js').default | undefined} */
+ let window_wrapper;
+ let i = nodes.length;
+ while (i--) {
+ const child = nodes[i];
+ if (!child.type) {
+ throw new Error('missing type');
+ }
+ if (!(child.type in wrappers)) {
+ throw new Error(`TODO implement ${child.type}`);
+ }
+ // special case — this is an easy way to remove whitespace surrounding
+ // . lil hacky but it works
+ if (child.type === 'Window') {
+ window_wrapper = new Window(renderer, block, parent, child);
+ continue;
+ }
+ if (child.type === 'Text') {
+ let { data } = child;
+ // We want to remove trailing whitespace inside an element/component/block,
+ // *unless* there is no whitespace between this node and its next sibling
+ if (this.nodes.length === 0) {
+ const should_trim = next_sibling
+ ? next_sibling.node.type === 'Text' &&
+ regex_starts_with_whitespace.test(next_sibling.node.data) &&
+ trimmable_at(child, next_sibling)
+ : !child.has_ancestor('EachBlock');
+ if (should_trim && !child.keep_space()) {
+ data = trim_end(data);
+ if (!data)
+ continue;
+ }
+ }
+ // glue text nodes (which could e.g. be separated by comments) together
+ if (last_child && last_child.node.type === 'Text') {
+ ( /** @type {import('./Text.js').default} */(last_child)).data = data + ( /** @type {import('./Text.js').default} */(last_child)).data;
+ continue;
+ }
+ const wrapper = new Text(renderer, block, parent, child, data);
+ if (wrapper.skip)
+ continue;
+ this.nodes.unshift(wrapper);
+ link(last_child, (last_child = wrapper));
+ }
+ else {
+ const Wrapper = wrappers[child.type];
+ 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);
+ link(last_child, (last_child = wrapper));
+ }
+ }
+ if (strip_whitespace) {
+ const first = /** @type {import('./Text.js').default} */ (this.nodes[0]);
+ if (first && first.node.type === 'Text' && !first.node.keep_space()) {
+ first.data = trim_start(first.data);
+ if (!first.data) {
+ first.var = null;
+ this.nodes.shift();
+ if (this.nodes[0]) {
+ this.nodes[0].prev = null;
+ }
+ }
+ }
+ }
+ if (window_wrapper) {
+ this.nodes.unshift(window_wrapper);
+ link(last_child, window_wrapper);
+ }
+ }
+
+ /**
+ * @param {import('../Block.js').default} block
+ * @param {import('estree').Identifier} parent_node
+ * @param {import('estree').Identifier} parent_nodes
+ */
+ render(block, parent_node, parent_nodes) {
+ for (let i = 0; i < this.nodes.length; i += 1) {
+ this.nodes[i].render(block, parent_node, parent_nodes);
+ }
+ }
+}
- if (first && first.node.type === 'Text' && !first.node.keep_space()) {
- first.data = trim_start(first.data);
- if (!first.data) {
- first.var = null;
- this.nodes.shift();
- if (this.nodes[0]) {
- this.nodes[0].prev = null;
- }
- }
- }
- }
- if (window_wrapper) {
- this.nodes.unshift(window_wrapper);
- link(last_child, window_wrapper);
- }
- }
- render(block: Block, parent_node: Identifier, parent_nodes: Identifier) {
- for (let i = 0; i < this.nodes.length; i += 1) {
- this.nodes[i].render(block, parent_node, parent_nodes);
- }
- }
-}