Skip to content

Commit cbd1a11

Browse files
committed
use classes instead of attributes - fixes #1118
1 parent 81743a2 commit cbd1a11

File tree

4 files changed

+56
-32
lines changed

4 files changed

+56
-32
lines changed

src/generators/dom/index.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,6 @@ export default function dom(
135135
builder.addBlock(generator.javascript);
136136
}
137137

138-
if (generator.needsEncapsulateHelper) {
139-
builder.addBlock(deindent`
140-
function @encapsulateStyles(node) {
141-
@setAttribute(node, "${generator.stylesheet.id}", "");
142-
}
143-
`);
144-
}
145-
146138
const { css, cssMap } = generator.stylesheet.render(options.filename, !generator.customElement);
147139
const styles = generator.stylesheet.hasStyles && stringify(options.dev ?
148140
`${css}\n/*# sourceMappingURL=${cssMap.toUrl()} */` :

src/generators/nodes/Attribute.ts

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ export default class Attribute {
141141
shouldCache = true;
142142
}
143143

144+
if (node._needsCssAttribute && propertyName === 'className') {
145+
value = `(${value}) + " ${this.generator.stylesheet.id}"`;
146+
}
147+
144148
const isSelectValueAttribute =
145149
name === 'value' && node.name === 'select';
146150

@@ -191,17 +195,17 @@ export default class Attribute {
191195
block.builders.hydrate.addLine(
192196
`${node.var}.${propertyName} = ${init};`
193197
);
194-
updater = `${node.var}.${propertyName} = ${shouldCache || isSelectValueAttribute ? last : value};`;
198+
updater = `${node.var}.${propertyName} = ${shouldCache ? last : value};`;
195199
} else if (isDataSet) {
196200
block.builders.hydrate.addLine(
197201
`${node.var}.dataset.${camelCaseName} = ${init};`
198202
);
199-
updater = `${node.var}.dataset.${camelCaseName} = ${shouldCache || isSelectValueAttribute ? last : value};`;
203+
updater = `${node.var}.dataset.${camelCaseName} = ${shouldCache ? last : value};`;
200204
} else {
201205
block.builders.hydrate.addLine(
202206
`${method}(${node.var}, "${name}", ${init});`
203207
);
204-
updater = `${method}(${node.var}, "${name}", ${shouldCache || isSelectValueAttribute ? last : value});`;
208+
updater = `${method}(${node.var}, "${name}", ${shouldCache ? last : value});`;
205209
}
206210

207211
if (allDependencies.size || hasChangeableIndex || isSelectValueAttribute) {
@@ -223,17 +227,30 @@ export default class Attribute {
223227
);
224228
}
225229
} else {
226-
const value = this.value === true
227-
? 'true'
228-
: this.value.length === 0
229-
? `''`
230-
: stringify(this.value[0].data);
230+
const isScopedClassAttribute = (
231+
propertyName === 'className' &&
232+
this.parent._needsCssAttribute &&
233+
!this.generator.customElement
234+
);
235+
236+
const value = isScopedClassAttribute && this.value !== true
237+
? this.value.length === 0
238+
? `'${this.generator.stylesheet.id}'`
239+
: stringify(this.value[0].data.concat(` ${this.generator.stylesheet.id}`))
240+
: this.value === true
241+
? 'true'
242+
: this.value.length === 0
243+
? `''`
244+
: stringify(this.value[0].data);
231245

232246
const statement = (
233-
isLegacyInputType ? `@setInputType(${node.var}, ${value});` :
234-
propertyName ? `${node.var}.${propertyName} = ${value};` :
235-
isDataSet ? `${node.var}.dataset.${camelCaseName} = ${value};` :
236-
`${method}(${node.var}, "${name}", ${value});`
247+
isLegacyInputType
248+
? `@setInputType(${node.var}, ${value});`
249+
: propertyName
250+
? `${node.var}.${propertyName} = ${value};`
251+
: isDataSet
252+
? `${node.var}.dataset.${camelCaseName} = ${value};`
253+
: `${method}(${node.var}, "${name}", ${value});`
237254
);
238255

239256
block.builders.hydrate.addLine(statement);

src/generators/nodes/Element.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,13 @@ export default class Element extends Node {
214214

215215
// add CSS encapsulation attribute
216216
if (this._needsCssAttribute && !this.generator.customElement) {
217-
this.generator.needsEncapsulateHelper = true;
218-
block.builders.hydrate.addLine(
219-
`@encapsulateStyles(${name});`
220-
);
217+
if (!this.attributes.find(a => a.type === 'Attribute' && a.name === 'class')) {
218+
block.builders.hydrate.addLine(
219+
`${name}.className = "${this.generator.stylesheet.id}";`
220+
);
221+
}
221222

223+
// TODO move this into a class as well?
222224
if (this._cssRefAttribute) {
223225
block.builders.hydrate.addLine(
224226
`@setAttribute(${name}, "svelte-ref-${this._cssRefAttribute}", "");`
@@ -429,18 +431,22 @@ export default class Element extends Node {
429431

430432
let open = `<${node.name}`;
431433

432-
if (node._needsCssAttribute) {
433-
open += ` ${generator.stylesheet.id}`;
434-
}
435-
436434
if (node._cssRefAttribute) {
437435
open += ` svelte-ref-${node._cssRefAttribute}`;
438436
}
439437

440438
node.attributes.forEach((attr: Node) => {
441-
open += ` ${fixAttributeCasing(attr.name)}${stringifyAttributeValue(attr.value)}`
439+
const value = node._needsCssAttribute && attr.name === 'class'
440+
? attr.value.concat({ type: 'Text', data: ` ${generator.stylesheet.id}` })
441+
: attr.value;
442+
443+
open += ` ${fixAttributeCasing(attr.name)}${stringifyAttributeValue(value)}`
442444
});
443445

446+
if (node._needsCssAttribute && !node.attributes.find(a => a.name === 'class')) {
447+
open += ` class="${generator.stylesheet.id}"`;
448+
}
449+
444450
if (isVoidElementName(node.name)) return open + '>';
445451

446452
return `${open}>${node.children.map(toHTML).join('')}</${node.name}>`;

src/generators/server-side-rendering/visitors/Element.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,22 @@ export default function visitElement(
5050
block.contextualise(attribute.value[0].expression);
5151
openingTag += '${' + attribute.value[0].metadata.snippet + ' ? " ' + attribute.name + '" : "" }';
5252
} else {
53-
openingTag += ` ${attribute.name}="${stringifyAttributeValue(block, attribute.value)}"`;
53+
const value = attribute.name === 'class' && node._needsCssAttribute
54+
? attribute.value.concat({
55+
type: 'Text',
56+
data: ` ${generator.stylesheet.id}`
57+
})
58+
: attribute.value;
59+
60+
openingTag += ` ${attribute.name}="${stringifyAttributeValue(block, value)}"`;
5461
}
5562
});
5663

57-
if (node._needsCssAttribute) {
58-
openingTag += ` ${generator.stylesheet.id}`;
64+
if (node._needsCssAttribute && !node.attributes.find(a => a.type === 'Attribute' && a.name === 'class')) {
65+
openingTag += ` class="${generator.stylesheet.id}"`;
66+
}
5967

68+
if (node._needsCssAttribute) {
6069
if (node._cssRefAttribute) {
6170
openingTag += ` svelte-ref-${node._cssRefAttribute}`;
6271
}

0 commit comments

Comments
 (0)