import deindent from '../../../../utils/deindent'; import visit from '../../visit'; import visitSlot from '../Slot'; import visitComponent from '../Component'; import visitWindow from './meta/Window'; import visitAttribute from './Attribute'; import addBindings from './addBindings'; import flattenReference from '../../../../utils/flattenReference'; import validCalleeObjects from '../../../../utils/validCalleeObjects'; import * as namespaces from '../../../../utils/namespaces'; import getStaticAttributeValue from '../../../../utils/getStaticAttributeValue'; import isVoidElementName from '../../../../utils/isVoidElementName'; import addTransitions from './addTransitions'; import { DomGenerator } from '../../index'; import Block from '../../Block'; import { Node } from '../../../../interfaces'; import { State } from '../../interfaces'; import reservedNames from '../../../../utils/reservedNames'; import { stringify } from '../../../../utils/stringify'; const meta: Record = { ':Window': visitWindow, }; export default function visitElement( generator: DomGenerator, block: Block, state: State, node: Node, elementStack: Node[], componentStack: Node[] ) { if (node.name in meta) { return meta[node.name](generator, block, node); } if (node.name === 'slot') { if (generator.customElement) { const slotName = getStaticAttributeValue(node, 'name') || 'default'; generator.slots.add(slotName); } else { return visitSlot(generator, block, state, node, elementStack, componentStack); } } if (generator.components.has(node.name) || node.name === ':Self' || node.name === ':Switch') { return visitComponent(generator, block, state, node, elementStack, componentStack); } const childState = node._state; const name = childState.parentNode; const slot = node.attributes.find((attribute: Node) => attribute.name === 'slot'); const parentNode = node.slotted ? `${componentStack[componentStack.length - 1].var}._slotted.${slot.value[0].data}` : // TODO this looks bonkers state.parentNode; block.addVariable(name); block.builders.create.addLine( `${name} = ${getRenderStatement( generator, childState.namespace, node.name )};` ); if (generator.hydratable) { block.builders.claim.addBlock(deindent` ${name} = ${getClaimStatement(generator, childState.namespace, state.parentNodes, node)}; var ${childState.parentNodes} = @children(${name}); `); } if (parentNode) { block.builders.mount.addLine( `@appendNode(${name}, ${parentNode});` ); } else { block.builders.mount.addLine(`@insertNode(${name}, #target, anchor);`); // TODO we eventually need to consider what happens to elements // that belong to the same outgroup as an outroing element... block.builders.unmount.addLine(`@detachNode(${name});`); } // add CSS encapsulation attribute if (node._needsCssAttribute && !generator.customElement) { generator.needsEncapsulateHelper = true; block.builders.hydrate.addLine( `@encapsulateStyles(${name});` ); if (node._cssRefAttribute) { block.builders.hydrate.addLine( `@setAttribute(${name}, "svelte-ref-${node._cssRefAttribute}", "");` ) } } if (node.name === 'textarea') { // this is an egregious hack, but it's the easiest way to get