diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index a3030f52a5..c5f7852750 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -702,16 +702,20 @@ export default class Element extends Node { return this.name === 'audio' || this.name === 'video'; } - add_css_class(class_name = this.component.stylesheet.id) { + add_css_class() { + const { id } = this.component.stylesheet; + const class_attribute = this.attributes.find(a => a.name === 'class'); + if (class_attribute && !class_attribute.is_true) { if (class_attribute.chunks.length === 1 && class_attribute.chunks[0].type === 'Text') { - (class_attribute.chunks[0] as Text).data += ` ${class_name}`; + (class_attribute.chunks[0] as Text).data += ` ${id}`; } else { (class_attribute.chunks as Node[]).push( new Text(this.component, this, this.scope, { type: 'Text', - data: ` ${class_name}` + data: ` ${id}`, + synthetic: true }) ); } @@ -720,7 +724,7 @@ export default class Element extends Node { new Attribute(this.component, this, this.scope, { type: 'Attribute', name: 'class', - value: [{ type: 'Text', data: class_name }] + value: [{ type: 'Text', data: id, synthetic: true }] }) ); } diff --git a/src/compiler/compile/nodes/Text.ts b/src/compiler/compile/nodes/Text.ts index eff3efe06e..bfd28a5073 100644 --- a/src/compiler/compile/nodes/Text.ts +++ b/src/compiler/compile/nodes/Text.ts @@ -6,9 +6,11 @@ import { INode } from './interfaces'; export default class Text extends Node { type: 'Text'; data: string; + synthetic: boolean; constructor(component: Component, parent: INode, scope: TemplateScope, info: any) { super(component, parent, scope, info); this.data = info.data; + this.synthetic = info.synthetic || false; } } diff --git a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts index eb242e994b..f83b1f2acf 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts @@ -85,13 +85,13 @@ export default class AttributeWrapper { value = (this.node.chunks[0] as Expression).render(block); } else { // '{foo} {bar}' — treat as string concatenation - const attrPrefix = this.node.chunks[0].type === 'Text' ? '' : `"" + `; + const prefix = this.node.chunks[0].type === 'Text' ? '' : `"" + `; - const attrText = this.node.name === 'class' + const text = this.node.name === 'class' ? this.get_class_name_text() - : this.get_attr_text(); + : this.render_chunks().join(' + '); - value = `${attrPrefix}${attrText}`; + value = `${prefix}${text}`; } const is_select_value_attribute = @@ -206,36 +206,27 @@ export default class AttributeWrapper { } get_class_name_text() { - const isStyled = this.node.chunks - .filter((chunk) => chunk.type === 'Text') - .some((chunk: Text) => !chunk.start && !chunk.end); + const scoped_css = this.node.chunks.some((chunk: Text) => chunk.synthetic); + const rendered = this.render_chunks(); - const classNameStringArray = this.render_attr(); - - if (!isStyled || classNameStringArray.length !== 2) { - return classNameStringArray.join(' + '); + if (scoped_css && rendered.length === 2) { + // we have a situation like class={possiblyUndefined} + rendered[0] = `@null_to_empty(${rendered[0]})`; } - const targetToken = 0; - return classNameStringArray - .map((token, index) => index === targetToken ? `@class_name_resolver(${token})` : token) - .join(' + '); - } - - get_attr_text() { - return this.render_attr().join(' + '); + return rendered.join(' + '); } - render_attr() { + render_chunks() { return this.node.chunks.map((chunk) => { if (chunk.type === 'Text') { return stringify(chunk.data); } - const renderedChunk = chunk.render(); + const rendered = chunk.render(); return chunk.get_precedence() <= 13 - ? `(${renderedChunk})` - : renderedChunk; + ? `(${rendered})` + : rendered; }); } diff --git a/src/runtime/internal/utils.ts b/src/runtime/internal/utils.ts index 3cef77e7be..47ada924ae 100644 --- a/src/runtime/internal/utils.ts +++ b/src/runtime/internal/utils.ts @@ -90,6 +90,6 @@ export function once(fn) { }; } -export function class_name_resolver(nextClassName) { - return nextClassName == undefined ? '' : nextClassName; +export function null_to_empty(value) { + return value == null ? '' : value; }