mirror of https://github.com/sveltejs/svelte
allow to use class directive on <svelte:body> (#3105)
parent
d5370f23d3
commit
9a5fd562d5
@ -1,25 +1,66 @@
|
|||||||
import Block from '../Block';
|
import Block from '../Block';
|
||||||
import Wrapper from './shared/Wrapper';
|
import Wrapper from './shared/Wrapper';
|
||||||
import { x } from 'code-red';
|
import { b, x } from 'code-red';
|
||||||
import Body from '../../nodes/Body';
|
import Body from '../../nodes/Body';
|
||||||
import { Identifier } from 'estree';
|
import { Node, Identifier } from 'estree';
|
||||||
import EventHandler from './Element/EventHandler';
|
import EventHandler from './Element/EventHandler';
|
||||||
import add_event_handlers from './shared/add_event_handlers';
|
import add_event_handlers from './shared/add_event_handlers';
|
||||||
import { TemplateNode } from '../../../interfaces';
|
import { TemplateNode } from '../../../interfaces';
|
||||||
import Renderer from '../Renderer';
|
import Renderer from '../Renderer';
|
||||||
import add_actions from './shared/add_actions';
|
import add_actions from './shared/add_actions';
|
||||||
|
import is_dynamic from './shared/is_dynamic';
|
||||||
|
|
||||||
export default class BodyWrapper extends Wrapper {
|
export default class BodyWrapper extends Wrapper {
|
||||||
node: Body;
|
node: Body;
|
||||||
handlers: EventHandler[];
|
handlers: EventHandler[];
|
||||||
|
class_dependencies: string[];
|
||||||
|
|
||||||
constructor(renderer: Renderer, block: Block, parent: Wrapper, node: TemplateNode) {
|
constructor(renderer: Renderer, block: Block, parent: Wrapper, node: TemplateNode) {
|
||||||
super(renderer, block, parent, node);
|
super(renderer, block, parent, node);
|
||||||
this.handlers = this.node.handlers.map(handler => new EventHandler(handler, this));
|
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) {
|
render(block: Block, _parent_node: Identifier, _parent_nodes: Identifier) {
|
||||||
add_event_handlers(block, x`@_document.body`, this.handlers);
|
add_event_handlers(block, x`@_document.body`, this.handlers);
|
||||||
add_actions(block, x`@_document.body`, this.node.actions);
|
add_actions(block, x`@_document.body`, this.node.actions);
|
||||||
|
this.add_classes(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
html: '<body class="one"></body>'
|
||||||
|
};
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<svelte:body class:one={true} />
|
||||||
@ -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>
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
export let foo;
|
||||||
|
export let bar;
|
||||||
|
export let unused;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:body class:foo class:bar class:unused />
|
||||||
Loading…
Reference in new issue