mirror of https://github.com/sveltejs/svelte
parent
dfa3d7fa74
commit
69804ecaf8
@ -1,27 +1,3 @@
|
||||
import Node from './shared/Node';
|
||||
import Tag from './shared/Tag';
|
||||
import Block from '../render-dom/Block';
|
||||
|
||||
export default class MustacheTag extends Tag {
|
||||
build(
|
||||
block: Block,
|
||||
parentNode: string,
|
||||
parentNodes: string
|
||||
) {
|
||||
const { init } = this.renameThisMethod(
|
||||
block,
|
||||
value => `@setData(${this.var}, ${value});`
|
||||
);
|
||||
|
||||
block.addElement(
|
||||
this.var,
|
||||
`@createText(${init})`,
|
||||
parentNodes && `@claimText(${parentNodes}, ${init})`,
|
||||
parentNode
|
||||
);
|
||||
}
|
||||
|
||||
remount(name: string) {
|
||||
return `@append(${name}._slotted.default, ${this.var});`;
|
||||
}
|
||||
}
|
||||
export default class MustacheTag extends Tag {}
|
@ -1,96 +1,3 @@
|
||||
import deindent from '../../utils/deindent';
|
||||
import Node from './shared/Node';
|
||||
import Tag from './shared/Tag';
|
||||
import Block from '../render-dom/Block';
|
||||
|
||||
export default class RawMustacheTag extends Tag {
|
||||
build(
|
||||
block: Block,
|
||||
parentNode: string,
|
||||
parentNodes: string
|
||||
) {
|
||||
const name = this.var;
|
||||
|
||||
const needsAnchorBefore = this.prev ? this.prev.type !== 'Element' : !parentNode;
|
||||
const needsAnchorAfter = this.next ? this.next.type !== 'Element' : !parentNode;
|
||||
|
||||
const anchorBefore = needsAnchorBefore
|
||||
? block.getUniqueName(`${name}_before`)
|
||||
: (this.prev && this.prev.var) || 'null';
|
||||
|
||||
const anchorAfter = needsAnchorAfter
|
||||
? block.getUniqueName(`${name}_after`)
|
||||
: (this.next && this.next.var) || 'null';
|
||||
|
||||
let detach: string;
|
||||
let insert: (content: string) => string;
|
||||
let useInnerHTML = false;
|
||||
|
||||
if (anchorBefore === 'null' && anchorAfter === 'null') {
|
||||
useInnerHTML = true;
|
||||
detach = `${parentNode}.innerHTML = '';`;
|
||||
insert = content => `${parentNode}.innerHTML = ${content};`;
|
||||
} else if (anchorBefore === 'null') {
|
||||
detach = `@detachBefore(${anchorAfter});`;
|
||||
insert = content => `${anchorAfter}.insertAdjacentHTML("beforebegin", ${content});`;
|
||||
} else if (anchorAfter === 'null') {
|
||||
detach = `@detachAfter(${anchorBefore});`;
|
||||
insert = content => `${anchorBefore}.insertAdjacentHTML("afterend", ${content});`;
|
||||
} else {
|
||||
detach = `@detachBetween(${anchorBefore}, ${anchorAfter});`;
|
||||
insert = content => `${anchorBefore}.insertAdjacentHTML("afterend", ${content});`;
|
||||
}
|
||||
|
||||
const { init } = this.renameThisMethod(
|
||||
block,
|
||||
content => deindent`
|
||||
${!useInnerHTML && detach}
|
||||
${insert(content)}
|
||||
`
|
||||
);
|
||||
|
||||
// we would have used comments here, but the `insertAdjacentHTML` api only
|
||||
// exists for `Element`s.
|
||||
if (needsAnchorBefore) {
|
||||
block.addElement(
|
||||
anchorBefore,
|
||||
`@createElement('noscript')`,
|
||||
parentNodes && `@createElement('noscript')`,
|
||||
parentNode,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
function addAnchorAfter() {
|
||||
block.addElement(
|
||||
anchorAfter,
|
||||
`@createElement('noscript')`,
|
||||
parentNodes && `@createElement('noscript')`,
|
||||
parentNode
|
||||
);
|
||||
}
|
||||
|
||||
if (needsAnchorAfter && anchorBefore === 'null') {
|
||||
// anchorAfter needs to be in the DOM before we
|
||||
// insert the HTML...
|
||||
addAnchorAfter();
|
||||
}
|
||||
|
||||
block.builders.mount.addLine(insert(init));
|
||||
|
||||
if (!parentNode) {
|
||||
block.builders.destroy.addConditional('detach', needsAnchorBefore
|
||||
? `${detach}\n@detachNode(${anchorBefore});`
|
||||
: detach);
|
||||
}
|
||||
|
||||
if (needsAnchorAfter && anchorBefore !== 'null') {
|
||||
// ...otherwise it should go afterwards
|
||||
addAnchorAfter();
|
||||
}
|
||||
}
|
||||
|
||||
remount(name: string) {
|
||||
return `@append(${name}._slotted.default, ${this.var});`;
|
||||
}
|
||||
}
|
||||
export default class RawMustacheTag extends Tag {}
|
@ -0,0 +1,56 @@
|
||||
import Binding from '../../../../nodes/Binding';
|
||||
import Element from '../../../../nodes/Element';
|
||||
import ElementWrapper from '..';
|
||||
import Block from '../../../Block';
|
||||
import Renderer from '../../../Renderer';
|
||||
import flattenReference from '../../../../../utils/flattenReference';
|
||||
import { Node } from '../../../../../interfaces';
|
||||
import BindingWrapper from './Binding';
|
||||
|
||||
export default class SelectBinding extends BindingWrapper {
|
||||
element: ElementWrapper;
|
||||
node: Binding;
|
||||
|
||||
static filter(
|
||||
node: Element,
|
||||
binding_lookup: Record<string, Binding>,
|
||||
type: string
|
||||
) {
|
||||
return node.name === 'select' && binding_lookup.value;
|
||||
}
|
||||
|
||||
constructor(
|
||||
element: ElementWrapper,
|
||||
binding_lookup: Record<string, Binding>
|
||||
) {
|
||||
super(element, binding_lookup.value);
|
||||
this.events = ['change'];
|
||||
|
||||
element.renderer.hasComplexBindings = true;
|
||||
|
||||
// TODO does this also apply to e.g. `<input type='checkbox' bind:group='foo'>`?
|
||||
const dependencies = this.binding.value.dependencies;
|
||||
this.element.selectBindingDependencies = dependencies;
|
||||
dependencies.forEach((prop: string) => {
|
||||
element.renderer.component.indirectDependencies.set(prop, new Set());
|
||||
});
|
||||
}
|
||||
|
||||
fromDom() {
|
||||
return this.element.node.getStaticAttributeValue('multiple') === true ?
|
||||
`@selectMultipleValue(${this.element.var})` :
|
||||
`@selectValue(${this.element.var})`;
|
||||
}
|
||||
|
||||
toDom() {
|
||||
return this.element.getStaticAttributeValue('multiple') === true ?
|
||||
`@selectOptions(${this.element.var}, ${this.binding.value.snippet});` :
|
||||
`@selectOption(${this.element.var}, ${this.binding.value.snippet});`;
|
||||
}
|
||||
|
||||
render(block: Block) {
|
||||
|
||||
|
||||
super.render(block);
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
import Renderer from '../Renderer';
|
||||
import Block from '../Block';
|
||||
import Node from '../../nodes/shared/Node';
|
||||
import Tag from './shared/Tag';
|
||||
import Wrapper from './shared/wrapper';
|
||||
import deindent from '../../../utils/deindent';
|
||||
|
||||
export default class RawMustacheTagWrapper extends Tag {
|
||||
constructor(
|
||||
renderer: Renderer,
|
||||
block: Block,
|
||||
parent: Wrapper,
|
||||
node: Node
|
||||
) {
|
||||
super(renderer, block, parent, node);
|
||||
this.cannotUseInnerHTML();
|
||||
}
|
||||
|
||||
render(block: Block, parentNode: string, parentNodes: string) {
|
||||
const name = this.var;
|
||||
|
||||
// TODO use isDomNode instead of type === 'Element'?
|
||||
const needsAnchorBefore = this.prev ? this.prev.node.type !== 'Element' : !parentNode;
|
||||
const needsAnchorAfter = this.next ? this.next.node.type !== 'Element' : !parentNode;
|
||||
|
||||
const anchorBefore = needsAnchorBefore
|
||||
? block.getUniqueName(`${name}_before`)
|
||||
: (this.prev && this.prev.var) || 'null';
|
||||
|
||||
const anchorAfter = needsAnchorAfter
|
||||
? block.getUniqueName(`${name}_after`)
|
||||
: (this.next && this.next.var) || 'null';
|
||||
|
||||
let detach: string;
|
||||
let insert: (content: string) => string;
|
||||
let useInnerHTML = false;
|
||||
|
||||
if (anchorBefore === 'null' && anchorAfter === 'null') {
|
||||
useInnerHTML = true;
|
||||
detach = `${parentNode}.innerHTML = '';`;
|
||||
insert = content => `${parentNode}.innerHTML = ${content};`;
|
||||
} else if (anchorBefore === 'null') {
|
||||
detach = `@detachBefore(${anchorAfter});`;
|
||||
insert = content => `${anchorAfter}.insertAdjacentHTML("beforebegin", ${content});`;
|
||||
} else if (anchorAfter === 'null') {
|
||||
detach = `@detachAfter(${anchorBefore});`;
|
||||
insert = content => `${anchorBefore}.insertAdjacentHTML("afterend", ${content});`;
|
||||
} else {
|
||||
detach = `@detachBetween(${anchorBefore}, ${anchorAfter});`;
|
||||
insert = content => `${anchorBefore}.insertAdjacentHTML("afterend", ${content});`;
|
||||
}
|
||||
|
||||
const { init } = this.renameThisMethod(
|
||||
block,
|
||||
content => deindent`
|
||||
${!useInnerHTML && detach}
|
||||
${insert(content)}
|
||||
`
|
||||
);
|
||||
|
||||
// we would have used comments here, but the `insertAdjacentHTML` api only
|
||||
// exists for `Element`s.
|
||||
if (needsAnchorBefore) {
|
||||
block.addElement(
|
||||
anchorBefore,
|
||||
`@createElement('noscript')`,
|
||||
parentNodes && `@createElement('noscript')`,
|
||||
parentNode,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
function addAnchorAfter() {
|
||||
block.addElement(
|
||||
anchorAfter,
|
||||
`@createElement('noscript')`,
|
||||
parentNodes && `@createElement('noscript')`,
|
||||
parentNode
|
||||
);
|
||||
}
|
||||
|
||||
if (needsAnchorAfter && anchorBefore === 'null') {
|
||||
// anchorAfter needs to be in the DOM before we
|
||||
// insert the HTML...
|
||||
addAnchorAfter();
|
||||
}
|
||||
|
||||
block.builders.mount.addLine(insert(init));
|
||||
|
||||
if (!parentNode) {
|
||||
block.builders.destroy.addConditional('detach', needsAnchorBefore
|
||||
? `${detach}\n@detachNode(${anchorBefore});`
|
||||
: detach);
|
||||
}
|
||||
|
||||
if (needsAnchorAfter && anchorBefore !== 'null') {
|
||||
// ...otherwise it should go afterwards
|
||||
addAnchorAfter();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue