From 7fe838e4b5030f3797da425a3786f2598712b448 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 22 Apr 2018 22:23:51 -0400 Subject: [PATCH] various --- src/generators/nodes/Action.ts | 15 +- src/generators/nodes/Attribute.ts | 33 +++- src/generators/nodes/Binding.ts | 24 +++ src/generators/nodes/Component.ts | 164 ++++++++++-------- src/generators/nodes/Element.ts | 37 ++-- src/generators/nodes/Window.ts | 9 +- src/generators/nodes/shared/Expression.ts | 7 +- .../server-side-rendering/visitors/Element.ts | 11 +- .../shared/stringifyAttributeValue.ts | 4 +- src/validate/html/index.ts | 23 ++- 10 files changed, 205 insertions(+), 122 deletions(-) diff --git a/src/generators/nodes/Action.ts b/src/generators/nodes/Action.ts index fa1320ffac..fc1958e88d 100644 --- a/src/generators/nodes/Action.ts +++ b/src/generators/nodes/Action.ts @@ -1,7 +1,18 @@ import Node from './shared/Node'; +import Expression from './shared/Expression'; export default class Action extends Node { + type: 'Action'; name: string; - value: Node[] - expression: Node + expression: Expression; + + constructor(compiler, parent, info) { + super(compiler, parent, info); + + this.name = info.name; + + this.expression = info.expression + ? new Expression(compiler, this, info.expression) + : null; + } } \ No newline at end of file diff --git a/src/generators/nodes/Attribute.ts b/src/generators/nodes/Attribute.ts index e44aad898c..b5bdf5de5e 100644 --- a/src/generators/nodes/Attribute.ts +++ b/src/generators/nodes/Attribute.ts @@ -47,7 +47,34 @@ export default class Attribute extends Node { return expression; }); - this.isDynamic = this.dependencies.size > 0; + this.isDynamic = this.chunks.length === 1 + ? this.chunks[0].type !== 'Text' + : this.chunks.length > 1; + + // TODO this would be better, but it breaks some stuff + // this.isDynamic = this.dependencies.size > 0; + } + + getValue() { + if (this.isTrue) return true; + if (this.chunks.length === 0) return `''`; + + if (this.chunks.length === 1) { + return this.chunks[0].type === 'Text' + ? stringify(this.chunks[0].data) + : this.chunks[0].snippet; + } + + return (this.chunks[0].type === 'Text' ? '' : `"" + `) + + this.chunks + .map((chunk: Node) => { + if (chunk.type === 'Text') { + return stringify(chunk.data); + } else { + return getExpressionPrecedence(chunk) <= 13 ? `(${chunk.snippet})` : snippet; + } + }) + .join(' + '); } render(block: Block) { @@ -287,7 +314,7 @@ export default class Attribute extends Node { allDependencies.add(d); }); - return getExpressionPrecedence(chunk.expression) <= 13 ? `( ${snippet} )` : snippet; + return getExpressionPrecedence(chunk) <= 13 ? `(${snippet})` : snippet; } }) .join(' + '); @@ -295,7 +322,7 @@ export default class Attribute extends Node { if (allDependencies.size || hasChangeableIndex) { const dependencies = Array.from(allDependencies); const condition = ( - ( block.hasOutroMethod ? `#outroing || ` : '' ) + + (block.hasOutroMethod ? `#outroing || ` : '') + dependencies.map(dependency => `changed.${dependency}`).join(' || ') ); diff --git a/src/generators/nodes/Binding.ts b/src/generators/nodes/Binding.ts index 4a452d6ee6..8d2d8f7950 100644 --- a/src/generators/nodes/Binding.ts +++ b/src/generators/nodes/Binding.ts @@ -17,12 +17,36 @@ const readOnlyMediaAttributes = new Set([ export default class Binding extends Node { name: string; value: Expression; + obj: string; + prop: string; constructor(compiler, parent, info) { super(compiler, parent, info); this.name = info.name; this.value = new Expression(compiler, this, info.value); + + // const contextual = block.contexts.has(name); + const contextual = false; // TODO + + let obj; + let prop; + + if (contextual) { + // TODO does this need to go later? + obj = `ctx.${block.listNames.get(name)}`; + prop = `${block.indexNames.get(name)}`; + } else if (this.value.node.type === 'MemberExpression') { + prop = `[✂${this.value.node.property.start}-${this.value.node.property.end}✂]`; + if (!this.value.node.computed) prop = `'${prop}'`; + obj = `[✂${this.value.node.object.start}-${this.value.node.object.end}✂]`; + } else { + obj = 'ctx'; + prop = `'${this.name}'`; + } + + this.obj = obj; + this.prop = prop; } munge( diff --git a/src/generators/nodes/Component.ts b/src/generators/nodes/Component.ts index d5512429a4..1c67672d45 100644 --- a/src/generators/nodes/Component.ts +++ b/src/generators/nodes/Component.ts @@ -12,12 +12,17 @@ import Block from '../dom/Block'; import Attribute from './Attribute'; import usesThisOrArguments from '../../validate/js/utils/usesThisOrArguments'; import mapChildren from './shared/mapChildren'; +import Binding from './Binding'; +import EventHandler from './EventHandler'; export default class Component extends Node { type: 'Component'; name: string; attributes: Attribute[]; + bindings: Binding[]; + handlers: EventHandler[]; children: Node[]; + ref: string; constructor(compiler, parent, info) { super(compiler, parent, info); @@ -27,7 +32,8 @@ export default class Component extends Node { this.name = info.name; this.attributes = []; - // TODO bindings etc + this.bindings = []; + this.handlers = []; info.attributes.forEach(node => { switch (node.type) { @@ -36,6 +42,22 @@ export default class Component extends Node { this.attributes.push(new Attribute(compiler, this, node)); break; + case 'Binding': + this.bindings.push(new Binding(compiler, this, node)); + break; + + case 'EventHandler': + this.handlers.push(new EventHandler(compiler, this, node)); + break; + + case 'Ref': + // TODO catch this in validation + if (this.ref) throw new Error(`Duplicate refs`); + + compiler.usesRefs = true + this.ref = node.name; + break; + default: throw new Error(`Not implemented: ${node.type}`); } @@ -51,23 +73,16 @@ export default class Component extends Node { ) { this.cannotUseInnerHTML(); - this.attributes.forEach((attribute: Node) => { - if (attribute.type === 'Attribute' && attribute.value !== true) { - attribute.value.forEach((chunk: Node) => { - if (chunk.type !== 'Text') { - const dependencies = chunk.metadata.dependencies; - block.addDependencies(dependencies); - } - }); - } else { - if (attribute.type === 'EventHandler' && attribute.expression) { - attribute.expression.arguments.forEach((arg: Node) => { - block.addDependencies(arg.metadata.dependencies); - }); - } else if (attribute.type === 'Binding' || attribute.type === 'Spread') { - block.addDependencies(attribute.metadata.dependencies); - } - } + this.attributes.forEach(attr => { + block.addDependencies(attr.dependencies); + }); + + this.bindings.forEach(binding => { + block.addDependencies(binding.value.dependencies); + }); + + this.handlers.forEach(handler => { + block.addDependencies(handler.dependencies); }); this.var = block.getUniqueName( @@ -115,60 +130,61 @@ export default class Component extends Node { let name_updating: string; let beforecreate: string = null; - const attributes = this.attributes - .filter(a => a.type === 'Attribute' || a.type === 'Spread') - .map(a => mungeAttribute(a, block)); + // const attributes = this.attributes + // .filter(a => a.type === 'Attribute' || a.type === 'Spread') + // .map(a => mungeAttribute(a, block)); - const bindings = this.attributes - .filter(a => a.type === 'Binding') - .map(a => mungeBinding(a, block)); + // const bindings = this.attributes + // .filter(a => a.type === 'Binding') + // .map(a => mungeBinding(a, block)); - const eventHandlers = this.attributes - .filter((a: Node) => a.type === 'EventHandler') - .map(a => mungeEventHandler(compiler, this, a, block, allContexts)); - - const ref = this.attributes.find((a: Node) => a.type === 'Ref'); - if (ref) compiler.usesRefs = true; + // const eventHandlers = this.attributes + // .filter((a: Node) => a.type === 'EventHandler') + // .map(a => mungeEventHandler(compiler, this, a, block, allContexts)); const updates: string[] = []; - const usesSpread = !!attributes.find(a => a.spread); + const usesSpread = !!this.attributes.find(a => a.spread); const attributeObject = usesSpread ? '{}' : stringifyProps( - attributes.map((attribute: Attribute) => `${attribute.name}: ${attribute.value}`) + // this.attributes.map(attr => `${attr.name}: ${attr.value}`) + this.attributes.map(attr => `${attr.name}: "TODO"`) ); - if (attributes.length || bindings.length) { + if (this.attributes.length || this.bindings.length) { componentInitProperties.push(`data: ${name_initial_data}`); } - if ((!usesSpread && attributes.filter(a => a.dynamic).length) || bindings.length) { + if ((!usesSpread && this.attributes.filter(a => a.isDynamic).length) || this.bindings.length) { updates.push(`var ${name_changes} = {};`); } - if (attributes.length) { + if (this.attributes.length) { if (usesSpread) { const levels = block.getUniqueName(`${this.var}_spread_levels`); const initialProps = []; const changes = []; - attributes - .forEach(munged => { - const { spread, name, dynamic, value, dependencies } = munged; + this.attributes + .forEach(attr => { + const { spread, name, dependencies } = attr; + const value = attr.getValue(); + + const condition = dependencies.size > 0 + ? [...dependencies].map(d => `changed.${d}`).join(' || ') + : null; if (spread) { initialProps.push(value); - const condition = dependencies && dependencies.map(d => `changed.${d}`).join(' || '); changes.push(condition ? `${condition} && ${value}` : value); } else { const obj = `{ ${quoteIfNecessary(name)}: ${value} }`; initialProps.push(obj); - const condition = dependencies && dependencies.map(d => `changed.${d}`).join(' || '); changes.push(condition ? `${condition} && ${obj}` : obj); } }); @@ -191,27 +207,27 @@ export default class Component extends Node { ]); `); } else { - attributes - .filter((attribute: Attribute) => attribute.dynamic) + this.attributes + .filter((attribute: Attribute) => attribute.isDynamic) .forEach((attribute: Attribute) => { - if (attribute.dependencies.length) { + if (attribute.dependencies.size > 0) { updates.push(deindent` - if (${attribute.dependencies + if (${[...attribute.dependencies] .map(dependency => `changed.${dependency}`) - .join(' || ')}) ${name_changes}.${attribute.name} = ${attribute.value}; + .join(' || ')}) ${name_changes}.${attribute.name} = ${attribute.getValue()}; `); } else { // TODO this is an odd situation to encounter – I *think* it should only happen with // each block indices, in which case it may be possible to optimise this - updates.push(`${name_changes}.${attribute.name} = ${attribute.value};`); + updates.push(`${name_changes}.${attribute.name} = ${attribute.getValue()};`); } }); } } - if (bindings.length) { + if (this.bindings.length) { compiler.hasComplexBindings = true; name_updating = block.alias(`${name}_updating`); @@ -222,18 +238,18 @@ export default class Component extends Node { const builder = new CodeBuilder(); - bindings.forEach((binding: Binding) => { - let { name: key } = getObject(binding.value); + this.bindings.forEach((binding: Binding) => { + let { name: key } = getObject(binding.value.node); - binding.contexts.forEach(context => { + binding.value.contexts.forEach(context => { allContexts.add(context); }); let setFromChild; if (block.contexts.has(key)) { - const computed = isComputed(binding.value); - const tail = binding.value.type === 'MemberExpression' ? getTailSnippet(binding.value) : ''; + const computed = isComputed(binding.value.node); + const tail = binding.value.node.type === 'MemberExpression' ? getTailSnippet(binding.value.node) : ''; const list = block.listNames.get(key); const index = block.indexNames.get(key); @@ -241,7 +257,7 @@ export default class Component extends Node { setFromChild = deindent` ${list}[${index}]${tail} = childState.${binding.name}; - ${binding.dependencies + ${[...binding.value.dependencies] .map((name: string) => { const isStoreProp = name[0] === '$'; const prop = isStoreProp ? name.slice(1) : name; @@ -263,9 +279,9 @@ export default class Component extends Node { if (isStoreProp) hasStoreBindings = true; else hasLocalBindings = true; - if (binding.value.type === 'MemberExpression') { + if (binding.value.node.type === 'MemberExpression') { setFromChild = deindent` - ${binding.snippet} = childState.${binding.name}; + ${binding.value.snippet} = childState.${binding.name}; ${newState}.${prop} = state.${key}; `; } @@ -277,7 +293,7 @@ export default class Component extends Node { statements.push(deindent` if (${binding.prop} in ${binding.obj}) { - ${name_initial_data}.${binding.name} = ${binding.snippet}; + ${name_initial_data}.${binding.name} = ${binding.value.snippet}; ${name_updating}.${binding.name} = true; }` ); @@ -288,8 +304,8 @@ export default class Component extends Node { ); updates.push(deindent` - if (!${name_updating}.${binding.name} && ${binding.dependencies.map((dependency: string) => `changed.${dependency}`).join(' || ')}) { - ${name_changes}.${binding.name} = ${binding.snippet}; + if (!${name_updating}.${binding.name} && ${[...binding.value.dependencies].map((dependency: string) => `changed.${dependency}`).join(' || ')}) { + ${name_changes}.${binding.name} = ${binding.value.snippet}; ${name_updating}.${binding.name} = true; } `); @@ -314,7 +330,7 @@ export default class Component extends Node { beforecreate = deindent` #component.root._beforecreate.push(function() { - ${name}._bind({ ${bindings.map(b => `${b.name}: 1`).join(', ')} }, ${name}.get()); + ${name}._bind({ ${this.bindings.map(b => `${b.name}: 1`).join(', ')} }, ${name}.get()); }); `; } @@ -323,8 +339,7 @@ export default class Component extends Node { const switch_value = block.getUniqueName('switch_value'); const switch_props = block.getUniqueName('switch_props'); - block.contextualise(this.expression); - const { dependencies, snippet } = this.metadata; + const { dependencies, snippet } = this.expression; const anchor = this.getOrCreateAnchor(block, parentNode, parentNodes); @@ -332,7 +347,7 @@ export default class Component extends Node { var ${switch_value} = ${snippet}; function ${switch_props}(state) { - ${(attributes.length || bindings.length) && deindent` + ${(this.attributes.length || this.bindings.length) && deindent` var ${name_initial_data} = ${attributeObject};`} ${statements} return { @@ -346,7 +361,7 @@ export default class Component extends Node { ${beforecreate} } - ${eventHandlers.map(handler => deindent` + ${this.handlers.map(handler => deindent` function ${handler.var}(event) { ${handler.body} } @@ -368,7 +383,7 @@ export default class Component extends Node { block.builders.mount.addBlock(deindent` if (${name}) { ${name}._mount(${parentNode || '#target'}, ${parentNode ? 'null' : 'anchor'}); - ${ref && `#component.refs.${ref.name} = ${name};`} + ${this.ref && `#component.refs.${this.ref} = ${name};`} } `); @@ -389,12 +404,12 @@ export default class Component extends Node { ${name}.on("${handler.name}", ${handler.var}); `)} - ${ref && `#component.refs.${ref.name} = ${name};`} + ${this.ref && `#component.refs.${this.ref} = ${name};`} } - ${ref && deindent` - else if (#component.refs.${ref.name} === ${name}) { - #component.refs.${ref.name} = null; + ${this.ref && deindent` + else if (#component.refs.${this.ref} === ${name}) { + #component.refs.${this.ref} = null; }`} } `); @@ -418,7 +433,7 @@ export default class Component extends Node { : `%components-${this.name}`; block.builders.init.addBlock(deindent` - ${(attributes.length || bindings.length) && deindent` + ${(this.attributes.length || this.bindings.length) && deindent` var ${name_initial_data} = ${attributeObject};`} ${statements} var ${name} = new ${expression}({ @@ -427,13 +442,13 @@ export default class Component extends Node { ${beforecreate} - ${eventHandlers.map(handler => deindent` + ${this.handlers.map(handler => deindent` ${name}.on("${handler.name}", function(event) { ${handler.body} }); `)} - ${ref && `#component.refs.${ref.name} = ${name};`} + ${this.ref && `#component.refs.${this.ref} = ${name};`} `); block.builders.create.addLine(`${name}._fragment.c();`); @@ -452,7 +467,7 @@ export default class Component extends Node { block.builders.update.addBlock(deindent` ${updates} ${name}._set(${name_changes}); - ${bindings.length && `${name_updating} = {};`} + ${this.bindings.length && `${name_updating} = {};`} `); } @@ -460,7 +475,7 @@ export default class Component extends Node { block.builders.destroy.addLine(deindent` ${name}.destroy(false); - ${ref && `if (#component.refs.${ref.name} === ${name}) #component.refs.${ref.name} = null;`} + ${this.ref && `if (#component.refs.${this.ref} === ${name}) #component.refs.${this.ref} = null;`} `); } } @@ -472,8 +487,7 @@ export default class Component extends Node { function mungeBinding(binding: Node, block: Block): Binding { const { name } = getObject(binding.value); - const { contexts } = block.contextualise(binding.value); - const { dependencies, snippet } = binding.metadata; + const { dependencies, snippet } = binding.expression; const contextual = block.contexts.has(name); diff --git a/src/generators/nodes/Element.ts b/src/generators/nodes/Element.ts index 7e848a4c1e..4c1e766c7b 100644 --- a/src/generators/nodes/Element.ts +++ b/src/generators/nodes/Element.ts @@ -23,6 +23,7 @@ export default class Element extends Node { type: 'Element'; name: string; attributes: Attribute[]; + actions: Action[]; bindings: Binding[]; handlers: EventHandler[]; intro: Transition; @@ -42,6 +43,7 @@ export default class Element extends Node { parentElement ? parentElement.namespace : this.compiler.namespace; this.attributes = []; + this.actions = []; this.bindings = []; this.handlers = []; @@ -50,6 +52,10 @@ export default class Element extends Node { info.attributes.forEach(node => { switch (node.type) { + case 'Action': + this.actions.push(new Action(compiler, this, node)); + break; + case 'Attribute': // special case if (node.name === 'xmlns') this.namespace = node.value[0].data; @@ -119,6 +125,13 @@ export default class Element extends Node { } }); + this.actions.forEach(action => { + this.cannotUseInnerHTML(); + if (action.expression) { + block.addDependencies(action.expression.dependencies); + } + }); + this.bindings.forEach(binding => { this.cannotUseInnerHTML(); block.addDependencies(binding.value.dependencies); @@ -144,9 +157,7 @@ export default class Element extends Node { } else { if (this.parent) this.parent.cannotUseInnerHTML(); - if (attribute.type === 'Action' && attribute.expression) { - block.addDependencies(attribute.metadata.dependencies); - } else if (attribute.type === 'Spread') { + if (attribute.type === 'Spread') { block.addDependencies(attribute.metadata.dependencies); } } @@ -739,31 +750,29 @@ export default class Element extends Node { } addActions(block: Block) { - this.attributes.filter((a: Action) => a.type === 'Action').forEach((attribute:Action) => { - const { expression } = attribute; + this.actions.forEach(action => { + const { expression } = action; let snippet, dependencies; if (expression) { - this.compiler.addSourcemapLocations(expression); - block.contextualise(expression); - snippet = attribute.metadata.snippet; - dependencies = attribute.metadata.dependencies; + snippet = action.expression.snippet; + dependencies = action.expression.dependencies; } const name = block.getUniqueName( - `${attribute.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_action` + `${action.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_action` ); block.addVariable(name); - const fn = `%actions-${attribute.name}`; + const fn = `%actions-${action.name}`; block.builders.hydrate.addLine( `${name} = ${fn}.call(#component, ${this.var}${snippet ? `, ${snippet}` : ''}) || {};` ); - if (dependencies && dependencies.length) { + if (dependencies && dependencies.size > 0) { let conditional = `typeof ${name}.update === 'function' && `; - const deps = dependencies.map(dependency => `changed.${dependency}`).join(' || '); - conditional += dependencies.length > 1 ? `(${deps})` : deps; + const deps = [...dependencies].map(dependency => `changed.${dependency}`).join(' || '); + conditional += dependencies.size > 1 ? `(${deps})` : deps; block.builders.update.addConditional( conditional, diff --git a/src/generators/nodes/Window.ts b/src/generators/nodes/Window.ts index ab532a0081..564ad1f47d 100644 --- a/src/generators/nodes/Window.ts +++ b/src/generators/nodes/Window.ts @@ -71,14 +71,7 @@ export default class Window extends Node { let usesState = handler.dependencies.size > 0; - // const flattened = flattenReference(handler.expression.callee); - // if (flattened.name !== 'event' && flattened.name !== 'this') { - // // allow event.stopPropagation(), this.select() etc - // compiler.code.prependRight( - // handler.expression.start, - // `${block.alias('component')}.` - // ); - // } + handler.render(compiler, block); const handlerName = block.getUniqueName(`onwindow${handler.name}`); const handlerBody = deindent` diff --git a/src/generators/nodes/shared/Expression.ts b/src/generators/nodes/shared/Expression.ts index 3e96677fa2..9358059b71 100644 --- a/src/generators/nodes/shared/Expression.ts +++ b/src/generators/nodes/shared/Expression.ts @@ -11,6 +11,8 @@ export default class Expression { references: Set; dependencies: Set; + contexts: Set; + indexes: Set; constructor(compiler, parent, info) { this.compiler = compiler; @@ -26,6 +28,7 @@ export default class Expression { const { code, helpers } = compiler; let { map, scope } = createScopes(info); + const isEventHandler = parent.type === 'EventHandler'; walk(info, { enter(node: any, parent: any) { @@ -38,11 +41,11 @@ export default class Expression { } if (isReference(node, parent)) { - code.prependRight(node.start, 'ctx.'); - const { name } = flattenReference(node); if (scope && scope.has(name) || helpers.has(name) || (name === 'event' && isEventHandler)) return; + code.prependRight(node.start, 'ctx.'); + if (contextDependencies.has(name)) { contextDependencies.get(name).forEach(dependency => { dependencies.add(dependency); diff --git a/src/generators/server-side-rendering/visitors/Element.ts b/src/generators/server-side-rendering/visitors/Element.ts index fe6bd97b12..0cd10cfbbe 100644 --- a/src/generators/server-side-rendering/visitors/Element.ts +++ b/src/generators/server-side-rendering/visitors/Element.ts @@ -68,18 +68,17 @@ export default function visitElement( if (attribute.name === 'value' && node.name === 'textarea') { textareaContents = stringifyAttributeValue(block, attribute.value); - } else if (attribute.value === true) { + } else if (attribute.isTrue) { openingTag += ` ${attribute.name}`; } else if ( booleanAttributes.has(attribute.name) && - attribute.value.length === 1 && - attribute.value[0].type !== 'Text' + attribute.chunks.length === 1 && + attribute.chunks[0].type !== 'Text' ) { // a boolean attribute with one non-Text chunk - block.contextualise(attribute.value[0].expression); - openingTag += '${' + attribute.value[0].metadata.snippet + ' ? " ' + attribute.name + '" : "" }'; + openingTag += '${' + attribute.chunks[0].snippet + ' ? " ' + attribute.name + '" : "" }'; } else { - openingTag += ` ${attribute.name}="${stringifyAttributeValue(block, attribute.value)}"`; + openingTag += ` ${attribute.name}="${stringifyAttributeValue(block, attribute.chunks)}"`; } }); } diff --git a/src/generators/server-side-rendering/visitors/shared/stringifyAttributeValue.ts b/src/generators/server-side-rendering/visitors/shared/stringifyAttributeValue.ts index a5399414cd..19088e976e 100644 --- a/src/generators/server-side-rendering/visitors/shared/stringifyAttributeValue.ts +++ b/src/generators/server-side-rendering/visitors/shared/stringifyAttributeValue.ts @@ -9,9 +9,7 @@ export default function stringifyAttributeValue(block: Block, chunks: Node[]) { return escapeTemplate(escape(chunk.data).replace(/"/g, '"')); } - block.contextualise(chunk.expression); - const { snippet } = chunk.metadata; - return '${__escape(' + snippet + ')}'; + return '${__escape(' + chunk.snippet + ')}'; }) .join(''); } \ No newline at end of file diff --git a/src/validate/html/index.ts b/src/validate/html/index.ts index e471ff6b41..26aa8e8e5b 100644 --- a/src/validate/html/index.ts +++ b/src/validate/html/index.ts @@ -29,12 +29,19 @@ export default function validateHtml(validator: Validator, html: Node) { validateHead(validator, node, refs, refCallees); } - else if (node.type === 'Element') { - const isComponent = - node.name === 'svelte:self' || - node.name === 'svelte:component' || - validator.components.has(node.name); + else if (node.type === 'Component' || node.name === 'svelte:self' || node.name === 'svelte:component') { + validateElement( + validator, + node, + refs, + refCallees, + stack, + elementStack, + true + ); + } + else if (node.type === 'Element') { validateElement( validator, node, @@ -42,12 +49,10 @@ export default function validateHtml(validator: Validator, html: Node) { refCallees, stack, elementStack, - isComponent + false ); - if (!isComponent) { - a11y(validator, node, elementStack); - } + a11y(validator, node, elementStack); } else if (node.type === 'EachBlock') {