diff --git a/src/compiler/compile/render_ssr/Renderer.ts b/src/compiler/compile/render_ssr/Renderer.ts index 997392572e..cc89745ec4 100644 --- a/src/compiler/compile/render_ssr/Renderer.ts +++ b/src/compiler/compile/render_ssr/Renderer.ts @@ -1,7 +1,6 @@ import AwaitBlock from './handlers/AwaitBlock'; import Comment from './handlers/Comment'; import DebugTag from './handlers/DebugTag'; -import DynamicElement from './handlers/DynamicElement'; import EachBlock from './handlers/EachBlock'; import Element from './handlers/Element'; import Head from './handlers/Head'; @@ -28,7 +27,6 @@ const handlers: Record = { Body: noop, Comment, DebugTag, - DynamicElement, EachBlock, Element, Head, @@ -113,14 +111,7 @@ export default class Renderer { render(nodes: INode[], options: RenderOptions) { nodes.forEach(node => { - const handler = (function () { - if (node.type === 'Element' && node.dynamic_tag_expr) { - return handlers['DynamicElement']; - } else { - return handlers[node.type]; - } - }()); - + const handler = handlers[node.type]; if (!handler) { throw new Error(`No handler for '${node.type}' nodes`); } diff --git a/src/compiler/compile/render_ssr/handlers/DynamicElement.ts b/src/compiler/compile/render_ssr/handlers/DynamicElement.ts deleted file mode 100644 index 356d545b27..0000000000 --- a/src/compiler/compile/render_ssr/handlers/DynamicElement.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { get_attribute_expression, get_attribute_value, get_class_attribute_value } from './shared/get_attribute_value'; -import { boolean_attributes } from './shared/boolean_attributes'; -import Renderer, { RenderOptions } from '../Renderer'; -import { x } from 'code-red'; -import Expression from '../../nodes/shared/Expression'; -import remove_whitespace_children from './utils/remove_whitespace_children'; -import Element from '../../nodes/Element'; -import { Expression as ESExpression } from 'estree'; -import fix_attribute_casing from '../../render_dom/wrappers/Element/fix_attribute_casing'; -import { namespaces } from '../../../utils/namespaces'; - -export default function (node: Element, renderer: Renderer, options: RenderOptions) { - - const children = remove_whitespace_children(node.children, node.next); - - // awkward special case - let node_contents; - - const contenteditable = ( - node.name !== 'textarea' && - node.name !== 'input' && - node.attributes.some((attribute) => attribute.name === 'contenteditable') - ); - - renderer.add_string('<'); - renderer.add_expression(node.dynamic_tag_expr.node as ESExpression); - - const class_expression_list = node.classes.map(class_directive => { - const { expression, name } = class_directive; - const snippet = expression ? expression.node : x`#ctx.${name}`; // TODO is this right? - return x`${snippet} ? "${name}" : ""`; - }); - if (node.needs_manual_style_scoping) { - class_expression_list.push(x`"${node.component.stylesheet.id}"`); - } - const class_expression = - class_expression_list.length > 0 && - class_expression_list.reduce((lhs, rhs) => x`${lhs} + ' ' + ${rhs}`); - - if (node.attributes.some(attr => attr.is_spread)) { - // TODO dry this out - const args = []; - node.attributes.forEach(attribute => { - if (attribute.is_spread) { - args.push(x`@escape_object(${attribute.expression.node})`); - } else { - const attr_name = node.namespace === namespaces.foreign ? attribute.name : fix_attribute_casing(attribute.name); - const name = attribute.name.toLowerCase(); - if (name === 'value' && node.name.toLowerCase() === 'textarea') { - node_contents = get_attribute_value(attribute); - } else if (attribute.is_true) { - args.push(x`{ ${attr_name}: true }`); - } else if ( - boolean_attributes.has(name) && - attribute.chunks.length === 1 && - attribute.chunks[0].type !== 'Text' - ) { - // a boolean attribute with one non-Text chunk - args.push(x`{ ${attr_name}: ${(attribute.chunks[0] as Expression).node} || null }`); - } else if (attribute.chunks.length === 1 && attribute.chunks[0].type !== 'Text') { - const snippet = (attribute.chunks[0] as Expression).node; - args.push(x`{ ${attr_name}: @escape_attribute_value(${snippet}) }`); - } else { - args.push(x`{ ${attr_name}: ${get_attribute_value(attribute)} }`); - } - } - }); - - renderer.add_expression(x`@spread([${args}], ${class_expression})`); - } else { - let add_class_attribute = !!class_expression; - node.attributes.forEach(attribute => { - const name = attribute.name.toLowerCase(); - const attr_name = node.namespace === namespaces.foreign ? attribute.name : fix_attribute_casing(attribute.name); - if (name === 'value' && node.name.toLowerCase() === 'textarea') { - node_contents = get_attribute_value(attribute); - } else if (attribute.is_true) { - renderer.add_string(` ${attr_name}`); - } else if ( - boolean_attributes.has(name) && - attribute.chunks.length === 1 && - attribute.chunks[0].type !== 'Text' - ) { - // a boolean attribute with one non-Text chunk - renderer.add_string(' '); - renderer.add_expression(x`${(attribute.chunks[0] as Expression).node} ? "${attr_name}" : ""`); - } else if (name === 'class' && class_expression) { - add_class_attribute = false; - renderer.add_string(` ${attr_name}="`); - renderer.add_expression(x`[${get_class_attribute_value(attribute)}, ${class_expression}].join(' ').trim()`); - renderer.add_string('"'); - } else if (attribute.chunks.length === 1 && attribute.chunks[0].type !== 'Text') { - const snippet = (attribute.chunks[0] as Expression).node; - renderer.add_expression(x`@add_attribute("${attr_name}", ${snippet}, ${boolean_attributes.has(name) ? 1 : 0})`); - } else { - renderer.add_string(` ${attr_name}="`); - renderer.add_expression((name === 'class' ? get_class_attribute_value : get_attribute_value)(attribute)); - renderer.add_string('"'); - } - }); - if (add_class_attribute) { - renderer.add_expression(x`@add_classes([${class_expression}].join(' ').trim())`); - } - } - - node.bindings.forEach(binding => { - const { name, expression } = binding; - - if (binding.is_readonly) { - return; - } - - if (name === 'group') { - const value_attribute = node.attributes.find(({ name }) => name === 'value'); - if (value_attribute) { - const value = get_attribute_expression(value_attribute); - const type = node.get_static_attribute_value('type'); - const bound = expression.node; - const condition = type === 'checkbox' ? x`~${bound}.indexOf(${value})` : x`${value} === ${bound}`; - renderer.add_expression(x`${condition} ? @add_attribute("checked", true, 1) : ""`); - } - } else if (contenteditable && (name === 'textContent' || name === 'innerHTML')) { - node_contents = expression.node; - - // TODO where was this used? - // value = name === 'textContent' ? x`@escape($$value)` : x`$$value`; - } else if (binding.name === 'value' && node.name === 'textarea') { - const snippet = expression.node; - node_contents = x`${snippet} || ""`; - } else if (binding.name === 'value' && node.name === 'select') { - // NOTE: do not add "value" attribute on