Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/compiler/compile/nodes/Body.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Node from './shared/Node';
import EventHandler from './EventHandler';
import Action from './Action';
import Class from './Class';
import Component from '../Component';
import TemplateScope from './shared/TemplateScope';
import { Element } from '../../interfaces';
Expand All @@ -9,6 +10,7 @@ export default class Body extends Node {
type: 'Body';
handlers: EventHandler[] = [];
actions: Action[] = [];
classes: Class[] = [];

constructor(component: Component, parent: Node, scope: TemplateScope, info: Element) {
super(component, parent, scope, info);
Expand All @@ -18,6 +20,8 @@ export default class Body extends Node {
this.handlers.push(new EventHandler(component, this, scope, node));
} else if (node.type === 'Action') {
this.actions.push(new Action(component, this, scope, node));
} else if (node.type === 'Class') {
this.classes.push(new Class(component, this, scope, node));
} else {
// TODO there shouldn't be anything else here...
}
Expand Down
45 changes: 43 additions & 2 deletions src/compiler/compile/render_dom/wrappers/Body.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,66 @@
import Block from '../Block';
import Wrapper from './shared/Wrapper';
import { x } from 'code-red';
import { b, x } from 'code-red';
import Body from '../../nodes/Body';
import { Identifier } from 'estree';
import { Node, Identifier } from 'estree';
import EventHandler from './Element/EventHandler';
import add_event_handlers from './shared/add_event_handlers';
import { TemplateNode } from '../../../interfaces';
import Renderer from '../Renderer';
import add_actions from './shared/add_actions';
import is_dynamic from './shared/is_dynamic';

export default class BodyWrapper extends Wrapper {
node: Body;
handlers: EventHandler[];
class_dependencies: string[];

constructor(renderer: Renderer, block: Block, parent: Wrapper, node: TemplateNode) {
super(renderer, block, parent, node);
this.handlers = this.node.handlers.map(handler => new EventHandler(handler, this));
this.class_dependencies = [];
}

add_classes(block: Block) {
this.node.classes.forEach(class_directive => {
const { expression, name } = class_directive;
let snippet: Node | string;
let dependencies: Set<string>;
if (expression) {
snippet = expression.manipulate(block);
dependencies = expression.dependencies;
} else {
snippet = name;
dependencies = new Set([name]);
}
const updater = b`@toggle_class(@_document.body, "${name}", ${snippet});`;

block.chunks.hydrate.push(updater);

if ((dependencies && dependencies.size > -1) || this.class_dependencies.length) {
const all_dependencies = this.class_dependencies.concat(...dependencies);
const condition = block.renderer.dirty(all_dependencies);

// If all of the dependencies are non-dynamic (don't get updated) then there is no reason
// to add an updater for this.
const any_dynamic_dependencies = all_dependencies.some((dep) => {
const variable = this.renderer.component.var_lookup.get(dep);
return !variable || is_dynamic(variable);
});
if (any_dynamic_dependencies) {
block.chunks.update.push(b`
if (${condition}) {
${updater}
}
`);
}
}
});
}

render(block: Block, _parent_node: Identifier, _parent_nodes: Identifier) {
add_event_handlers(block, x`@_document.body`, this.handlers);
add_actions(block, x`@_document.body`, this.node.actions);
this.add_classes(block);
}
}
3 changes: 3 additions & 0 deletions test/runtime/samples/class-body-boolean/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
html: '<body class="one"></body>'
};
1 change: 1 addition & 0 deletions test/runtime/samples/class-body-boolean/main.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<svelte:body class:one={true} />
16 changes: 16 additions & 0 deletions test/runtime/samples/class-body-shortcut/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export default {
props: {
foo: true,
bar: true
},

html: '<body class="foo bar"></body>',

test({ assert, component, target }) {
component.foo = false;

assert.htmlEqual(target.innerHTML, `
<body class="bar"></body>
`);
}
};
7 changes: 7 additions & 0 deletions test/runtime/samples/class-body-shortcut/main.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
export let foo;
export let bar;
export let unused;
</script>

<svelte:body class:foo class:bar class:unused />