|
|
|
@ -5,25 +5,16 @@ import {
|
|
|
|
import { get_slot_scope } from './shared/get_slot_scope';
|
|
|
|
import { get_slot_scope } from './shared/get_slot_scope';
|
|
|
|
import { boolean_attributes } from './shared/boolean_attributes';
|
|
|
|
import { boolean_attributes } from './shared/boolean_attributes';
|
|
|
|
import Renderer, { RenderOptions } from '../Renderer';
|
|
|
|
import Renderer, { RenderOptions } from '../Renderer';
|
|
|
|
import ElementHandler from './Element';
|
|
|
|
|
|
|
|
import { x } from 'code-red';
|
|
|
|
import { x } from 'code-red';
|
|
|
|
import Expression from '../../nodes/shared/Expression';
|
|
|
|
import Expression from '../../nodes/shared/Expression';
|
|
|
|
import remove_whitespace_children from './utils/remove_whitespace_children';
|
|
|
|
import remove_whitespace_children from './utils/remove_whitespace_children';
|
|
|
|
import Element from '../../nodes/Element';
|
|
|
|
import Element from '../../nodes/Element';
|
|
|
|
import { Expression as ESExpression } from 'estree';
|
|
|
|
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 (
|
|
|
|
export default function (node: Element, renderer: Renderer, options: RenderOptions & { slot_scopes: Map<any, any>}) {
|
|
|
|
node: Element,
|
|
|
|
|
|
|
|
renderer: Renderer,
|
|
|
|
|
|
|
|
options: RenderOptions & {
|
|
|
|
|
|
|
|
slot_scopes: Map<any, any>;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
const dependencies = node.dynamic_tag_expr.dynamic_dependencies();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (dependencies.length === 0) {
|
|
|
|
|
|
|
|
ElementHandler(node, renderer, options);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
const children = remove_whitespace_children(node.children, node.next);
|
|
|
|
const children = remove_whitespace_children(node.children, node.next);
|
|
|
|
|
|
|
|
|
|
|
|
// awkward special case
|
|
|
|
// awkward special case
|
|
|
|
@ -43,7 +34,7 @@ export default function (
|
|
|
|
renderer.add_string('<');
|
|
|
|
renderer.add_string('<');
|
|
|
|
renderer.add_expression(node.dynamic_tag_expr.node as ESExpression);
|
|
|
|
renderer.add_expression(node.dynamic_tag_expr.node as ESExpression);
|
|
|
|
|
|
|
|
|
|
|
|
const class_expression_list = node.classes.map((class_directive) => {
|
|
|
|
const class_expression_list = node.classes.map(class_directive => {
|
|
|
|
const { expression, name } = class_directive;
|
|
|
|
const { expression, name } = class_directive;
|
|
|
|
const snippet = expression ? expression.node : x`#ctx.${name}`; // TODO is this right?
|
|
|
|
const snippet = expression ? expression.node : x`#ctx.${name}`; // TODO is this right?
|
|
|
|
return x`${snippet} ? "${name}" : ""`;
|
|
|
|
return x`${snippet} ? "${name}" : ""`;
|
|
|
|
@ -55,31 +46,26 @@ export default function (
|
|
|
|
class_expression_list.length > 0 &&
|
|
|
|
class_expression_list.length > 0 &&
|
|
|
|
class_expression_list.reduce((lhs, rhs) => x`${lhs} + ' ' + ${rhs}`);
|
|
|
|
class_expression_list.reduce((lhs, rhs) => x`${lhs} + ' ' + ${rhs}`);
|
|
|
|
|
|
|
|
|
|
|
|
if (node.attributes.some((attr) => attr.is_spread)) {
|
|
|
|
if (node.attributes.some(attr => attr.is_spread)) {
|
|
|
|
// TODO dry this out
|
|
|
|
// TODO dry this out
|
|
|
|
const args = [];
|
|
|
|
const args = [];
|
|
|
|
node.attributes.forEach((attribute) => {
|
|
|
|
node.attributes.forEach(attribute => {
|
|
|
|
if (attribute.is_spread) {
|
|
|
|
if (attribute.is_spread) {
|
|
|
|
args.push(attribute.expression.node);
|
|
|
|
args.push(x`@escape_object(${attribute.expression.node})`);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
|
|
|
|
const attr_name = node.namespace === namespaces.foreign ? attribute.name : fix_attribute_casing(attribute.name);
|
|
|
|
const name = attribute.name.toLowerCase();
|
|
|
|
const name = attribute.name.toLowerCase();
|
|
|
|
if (attribute.is_true) {
|
|
|
|
if (attribute.is_true) {
|
|
|
|
args.push(x`{ ${attribute.name}: true }`);
|
|
|
|
args.push(x`{ ${attr_name}: true }`);
|
|
|
|
} else if (
|
|
|
|
} else if (
|
|
|
|
boolean_attributes.has(name) &&
|
|
|
|
boolean_attributes.has(name) &&
|
|
|
|
attribute.chunks.length === 1 &&
|
|
|
|
attribute.chunks.length === 1 &&
|
|
|
|
attribute.chunks[0].type !== 'Text'
|
|
|
|
attribute.chunks[0].type !== 'Text'
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
// a boolean attribute with one non-Text chunk
|
|
|
|
// a boolean attribute with one non-Text chunk
|
|
|
|
args.push(
|
|
|
|
args.push(x`{ ${attr_name}: ${(attribute.chunks[0] as Expression).node} || null }`);
|
|
|
|
x`{ ${attribute.name}: ${
|
|
|
|
|
|
|
|
(attribute.chunks[0] as Expression).node
|
|
|
|
|
|
|
|
} || null }`
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
args.push(
|
|
|
|
args.push(x`{ ${attr_name}: ${get_attribute_value(attribute)} }`);
|
|
|
|
x`{ ${attribute.name}: ${get_attribute_value(attribute)} }`
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
@ -87,10 +73,11 @@ export default function (
|
|
|
|
renderer.add_expression(x`@spread([${args}], ${class_expression})`);
|
|
|
|
renderer.add_expression(x`@spread([${args}], ${class_expression})`);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
let add_class_attribute = !!class_expression;
|
|
|
|
let add_class_attribute = !!class_expression;
|
|
|
|
node.attributes.forEach((attribute) => {
|
|
|
|
node.attributes.forEach(attribute => {
|
|
|
|
const name = attribute.name.toLowerCase();
|
|
|
|
const name = attribute.name.toLowerCase();
|
|
|
|
|
|
|
|
const attr_name = node.namespace === namespaces.foreign ? attribute.name : fix_attribute_casing(attribute.name);
|
|
|
|
if (attribute.is_true) {
|
|
|
|
if (attribute.is_true) {
|
|
|
|
renderer.add_string(` ${attribute.name}`);
|
|
|
|
renderer.add_string(` ${attr_name}`);
|
|
|
|
} else if (
|
|
|
|
} else if (
|
|
|
|
boolean_attributes.has(name) &&
|
|
|
|
boolean_attributes.has(name) &&
|
|
|
|
attribute.chunks.length === 1 &&
|
|
|
|
attribute.chunks.length === 1 &&
|
|
|
|
@ -98,48 +85,27 @@ export default function (
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
// a boolean attribute with one non-Text chunk
|
|
|
|
// a boolean attribute with one non-Text chunk
|
|
|
|
renderer.add_string(' ');
|
|
|
|
renderer.add_string(' ');
|
|
|
|
renderer.add_expression(
|
|
|
|
renderer.add_expression(x`${(attribute.chunks[0] as Expression).node} ? "${attr_name}" : ""`);
|
|
|
|
x`${(attribute.chunks[0] as Expression).node} ? "${
|
|
|
|
|
|
|
|
attribute.name
|
|
|
|
|
|
|
|
}" : ""`
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
} else if (name === 'class' && class_expression) {
|
|
|
|
} else if (name === 'class' && class_expression) {
|
|
|
|
add_class_attribute = false;
|
|
|
|
add_class_attribute = false;
|
|
|
|
renderer.add_string(` ${attribute.name}="`);
|
|
|
|
renderer.add_string(` ${attr_name}="`);
|
|
|
|
renderer.add_expression(
|
|
|
|
renderer.add_expression(x`[${get_class_attribute_value(attribute)}, ${class_expression}].join(' ').trim()`);
|
|
|
|
x`[${get_class_attribute_value(
|
|
|
|
|
|
|
|
attribute
|
|
|
|
|
|
|
|
)}, ${class_expression}].join(' ').trim()`
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
renderer.add_string('"');
|
|
|
|
renderer.add_string('"');
|
|
|
|
} else if (
|
|
|
|
} else if (attribute.chunks.length === 1 && attribute.chunks[0].type !== 'Text') {
|
|
|
|
attribute.chunks.length === 1 &&
|
|
|
|
|
|
|
|
attribute.chunks[0].type !== 'Text'
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
const snippet = (attribute.chunks[0] as Expression).node;
|
|
|
|
const snippet = (attribute.chunks[0] as Expression).node;
|
|
|
|
renderer.add_expression(
|
|
|
|
renderer.add_expression(x`@add_attribute("${attr_name}", ${snippet}, ${boolean_attributes.has(name) ? 1 : 0})`);
|
|
|
|
x`@add_attribute("${attribute.name}", ${snippet}, ${
|
|
|
|
|
|
|
|
boolean_attributes.has(name) ? 1 : 0
|
|
|
|
|
|
|
|
})`
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
renderer.add_string(` ${attribute.name}="`);
|
|
|
|
renderer.add_string(` ${attr_name}="`);
|
|
|
|
renderer.add_expression(
|
|
|
|
renderer.add_expression((name === 'class' ? get_class_attribute_value : get_attribute_value)(attribute));
|
|
|
|
(name === 'class'
|
|
|
|
|
|
|
|
? get_class_attribute_value
|
|
|
|
|
|
|
|
: get_attribute_value)(attribute)
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
renderer.add_string('"');
|
|
|
|
renderer.add_string('"');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
if (add_class_attribute) {
|
|
|
|
if (add_class_attribute) {
|
|
|
|
renderer.add_expression(
|
|
|
|
renderer.add_expression(x`@add_classes([${class_expression}].join(' ').trim())`);
|
|
|
|
x`@add_classes([${class_expression}].join(' ').trim())`
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
node.bindings.forEach((binding) => {
|
|
|
|
node.bindings.forEach(binding => {
|
|
|
|
const { name, expression } = binding;
|
|
|
|
const { name, expression } = binding;
|
|
|
|
|
|
|
|
|
|
|
|
if (binding.is_readonly) {
|
|
|
|
if (binding.is_readonly) {
|
|
|
|
@ -148,10 +114,7 @@ export default function (
|
|
|
|
|
|
|
|
|
|
|
|
if (name === 'group') {
|
|
|
|
if (name === 'group') {
|
|
|
|
// TODO server-render group bindings
|
|
|
|
// TODO server-render group bindings
|
|
|
|
} else if (
|
|
|
|
} else if (contenteditable && (name === 'textContent' || name === 'innerHTML')) {
|
|
|
|
contenteditable &&
|
|
|
|
|
|
|
|
(name === 'textContent' || name === 'innerHTML')
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
node_contents = expression.node;
|
|
|
|
node_contents = expression.node;
|
|
|
|
|
|
|
|
|
|
|
|
// TODO where was this used?
|
|
|
|
// TODO where was this used?
|
|
|
|
@ -174,9 +137,7 @@ export default function (
|
|
|
|
renderer.render(children, options);
|
|
|
|
renderer.render(children, options);
|
|
|
|
const result = renderer.pop();
|
|
|
|
const result = renderer.pop();
|
|
|
|
|
|
|
|
|
|
|
|
renderer.add_expression(
|
|
|
|
renderer.add_expression(x`($$value => $$value === void 0 ? ${result} : $$value)(${node_contents})`);
|
|
|
|
x`($$value => $$value === void 0 ? ${result} : $$value)(${node_contents})`
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
renderer.add_expression(node_contents);
|
|
|
|
renderer.add_expression(node_contents);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -194,7 +155,7 @@ export default function (
|
|
|
|
const lets = node.lets;
|
|
|
|
const lets = node.lets;
|
|
|
|
const seen = new Set(lets.map((l) => l.name.name));
|
|
|
|
const seen = new Set(lets.map((l) => l.name.name));
|
|
|
|
|
|
|
|
|
|
|
|
nearest_inline_component.lets.forEach((l) => {
|
|
|
|
nearest_inline_component.lets.forEach(l => {
|
|
|
|
if (!seen.has(l.name.name)) lets.push(l);
|
|
|
|
if (!seen.has(l.name.name)) lets.push(l);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
@ -209,5 +170,4 @@ export default function (
|
|
|
|
renderer.add_expression(node.dynamic_tag_expr.node as ESExpression);
|
|
|
|
renderer.add_expression(node.dynamic_tag_expr.node as ESExpression);
|
|
|
|
renderer.add_string('>');
|
|
|
|
renderer.add_string('>');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|