apply CSS scoping classes directly to AST (WIP)

pull/1228/head
Conduitry 7 years ago
parent eae98f952d
commit e4032ea543

@ -31,7 +31,7 @@ export default class Selector {
if (toEncapsulate.length > 0) { if (toEncapsulate.length > 0) {
toEncapsulate.filter((_, i) => i === 0 || i === toEncapsulate.length - 1).forEach(({ node, block }) => { toEncapsulate.filter((_, i) => i === 0 || i === toEncapsulate.length - 1).forEach(({ node, block }) => {
node._needsCssAttribute = true; node.addCssClass();
block.shouldEncapsulate = true; block.shouldEncapsulate = true;
}); });

@ -353,7 +353,7 @@ export default class Stylesheet {
} }
if (this.cascade) { if (this.cascade) {
if (stack.length === 0) node._needsCssAttribute = true; if (stack.length === 0) node.addCssClass();
return; return;
} }

@ -141,10 +141,6 @@ export default class Attribute {
shouldCache = true; shouldCache = true;
} }
if (node._needsCssAttribute && name === 'class') {
value = `(${value}) + " ${this.generator.stylesheet.id}"`;
}
const isSelectValueAttribute = const isSelectValueAttribute =
name === 'value' && node.name === 'select'; name === 'value' && node.name === 'select';
@ -227,21 +223,10 @@ export default class Attribute {
); );
} }
} else { } else {
const isScopedClassAttribute = ( const value =
name === 'class' && this.value === true
this.parent._needsCssAttribute && ? 'true'
!this.generator.customElement : this.value.length === 0 ? `''` : stringify(this.value[0].data);
);
const value = isScopedClassAttribute && this.value !== true
? this.value.length === 0
? `'${this.generator.stylesheet.id}'`
: stringify(this.value[0].data.concat(` ${this.generator.stylesheet.id}`))
: this.value === true
? 'true'
: this.value.length === 0
? `''`
: stringify(this.value[0].data);
const statement = ( const statement = (
isLegacyInputType isLegacyInputType

@ -212,22 +212,11 @@ export default class Element extends Node {
block.builders.unmount.addLine(`@detachNode(${name});`); block.builders.unmount.addLine(`@detachNode(${name});`);
} }
// add CSS encapsulation attribute // TODO move this into a class as well?
if (this._needsCssAttribute && !this.generator.customElement) { if (this._cssRefAttribute) {
if (!this.attributes.find(a => a.type === 'Attribute' && a.name === 'class')) { block.builders.hydrate.addLine(
block.builders.hydrate.addLine( `@setAttribute(${name}, "svelte-ref-${this._cssRefAttribute}", "");`
this.namespace )
? `@setAttribute(${name}, "class", "${this.generator.stylesheet.id}");`
: `${name}.className = "${this.generator.stylesheet.id}";`
);
}
// TODO move this into a class as well?
if (this._cssRefAttribute) {
block.builders.hydrate.addLine(
`@setAttribute(${name}, "svelte-ref-${this._cssRefAttribute}", "");`
)
}
} }
// insert static children with textContent or innerHTML // insert static children with textContent or innerHTML
@ -438,17 +427,9 @@ export default class Element extends Node {
} }
node.attributes.forEach((attr: Node) => { node.attributes.forEach((attr: Node) => {
const value = (node._needsCssAttribute && attr.name === 'class') open += ` ${fixAttributeCasing(attr.name)}${stringifyAttributeValue(attr.value)}`
? [{ type: 'Text', data: `${attr.value[0].data} ${generator.stylesheet.id}` }]
: attr.value;
open += ` ${fixAttributeCasing(attr.name)}${stringifyAttributeValue(value)}`
}); });
if (node._needsCssAttribute && !node.attributes.find(a => a.name === 'class')) {
open += ` class="${generator.stylesheet.id}"`;
}
if (isVoidElementName(node.name)) return open + '>'; if (isVoidElementName(node.name)) return open + '>';
return `${open}>${node.children.map(toHTML).join('')}</${node.name}>`; return `${open}>${node.children.map(toHTML).join('')}</${node.name}>`;
@ -688,6 +669,30 @@ export default class Element extends Node {
return `@appendNode(${this.var}, ${name}._slotted${this.generator.legacy ? `["default"]` : `.default`});`; return `@appendNode(${this.var}, ${name}._slotted${this.generator.legacy ? `["default"]` : `.default`});`;
} }
addCssClass() {
if (this._addedCssClass || this.generator.customElement) return;
this._addedCssClass = true;
const classAttribute = this.attributes.find(a => a.name === 'class');
if (classAttribute && classAttribute.value !== true) {
if (classAttribute.value.length === 1 && classAttribute.value[0].type === 'Text') {
classAttribute.value[0].data += ` ${this.generator.stylesheet.id}`;
} else {
(<Node[]>classAttribute.value).push(
new Node({ type: 'Text', data: ` ${this.generator.stylesheet.id}` })
);
}
} else {
this.attributes.push(
new Attribute({
generator: this.generator,
name: 'class',
value: [new Node({ type: 'Text', data: `${this.generator.stylesheet.id}` })],
parent: this,
})
);
}
}
} }
function getRenderStatement( function getRenderStatement(

@ -50,25 +50,12 @@ export default function visitElement(
block.contextualise(attribute.value[0].expression); block.contextualise(attribute.value[0].expression);
openingTag += '${' + attribute.value[0].metadata.snippet + ' ? " ' + attribute.name + '" : "" }'; openingTag += '${' + attribute.value[0].metadata.snippet + ' ? " ' + attribute.name + '" : "" }';
} else { } else {
const value = attribute.name === 'class' && node._needsCssAttribute openingTag += ` ${attribute.name}="${stringifyAttributeValue(block, attribute.value)}"`;
? attribute.value.concat({
type: 'Text',
data: ` ${generator.stylesheet.id}`
})
: attribute.value;
openingTag += ` ${attribute.name}="${stringifyAttributeValue(block, value)}"`;
} }
}); });
if (node._needsCssAttribute && !node.attributes.find(a => a.type === 'Attribute' && a.name === 'class')) { if (node._cssRefAttribute) {
openingTag += ` class="${generator.stylesheet.id}"`; openingTag += ` svelte-ref-${node._cssRefAttribute}`;
}
if (node._needsCssAttribute) {
if (node._cssRefAttribute) {
openingTag += ` svelte-ref-${node._cssRefAttribute}`;
}
} }
openingTag += '>'; openingTag += '>';

Loading…
Cancel
Save