Skip to content

Commit f25b9eb

Browse files
committed
fix(vdom): classes with consecutive spaces
1 parent 4f5093d commit f25b9eb

File tree

3 files changed

+77
-5
lines changed

3 files changed

+77
-5
lines changed

src/mock-doc/class-list.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ export class MockClassList {
33

44
constructor(private elm: HTMLElement) {}
55

6-
add(...className: string[]) {
6+
add(...classNames: string[]) {
77
const clsNames = getItems(this.elm);
88
let updated = false;
9-
className.forEach(className => {
9+
classNames.forEach(className => {
10+
className = String(className);
11+
validateClass(className);
1012
if (clsNames.includes(className) === false) {
1113
clsNames.push(className);
1214
updated = true;
@@ -17,10 +19,12 @@ export class MockClassList {
1719
}
1820
}
1921

20-
remove(...className: string[]) {
22+
remove(...classNames: string[]) {
2123
const clsNames = getItems(this.elm);
2224
let updated = false;
23-
className.forEach(className => {
25+
classNames.forEach(className => {
26+
className = String(className);
27+
validateClass(className);
2428
const index = clsNames.indexOf(className);
2529
if (index > -1) {
2630
clsNames.splice(index, 1);
@@ -33,10 +37,12 @@ export class MockClassList {
3337
}
3438

3539
contains(className: string) {
40+
className = String(className);
3641
return getItems(this.elm).includes(className);
3742
}
3843

3944
toggle(className: string) {
45+
className = String(className);
4046
if (this.contains(className) === true) {
4147
this.remove(className);
4248
} else {
@@ -59,6 +65,15 @@ export class MockClassList {
5965
}
6066

6167

68+
function validateClass(className: string) {
69+
if (className === '') {
70+
throw new Error('The token provided must not be empty.');
71+
}
72+
if (/\s/.test(className)) {
73+
throw new Error(`The token provided ('${className}') contains HTML space characters, which are not valid in tokens.`);
74+
}
75+
}
76+
6277
function getItems(elm: HTMLElement) {
6378
const className = elm.getAttribute('class');
6479
if (typeof className === 'string' && className.length > 0) {
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { MockDocument } from '../document';
2+
import { MockClassList } from '../class-list';
3+
import { MockElement } from '../node';
4+
5+
6+
describe('class-list', () => {
7+
let classList: MockClassList;
8+
beforeEach(() => {
9+
const doc = new MockDocument();
10+
const el = new MockElement(doc, 'div');
11+
classList = new MockClassList(el as any);
12+
});
13+
14+
it('add and remove classes', () => {
15+
classList.add('one');
16+
classList.add('two', 'three');
17+
classList.add(null);
18+
classList.add(undefined);
19+
classList.add(1 as any, 2 as any);
20+
expect(classList.toString()).toEqual('one two three null undefined 1 2');
21+
22+
expect(classList.contains('one')).toBe(true);
23+
expect(classList.contains('two')).toBe(true);
24+
expect(classList.contains('three')).toBe(true);
25+
expect(classList.contains('null')).toBe(true);
26+
expect(classList.contains(null)).toBe(true);
27+
expect(classList.contains('undefined')).toBe(true);
28+
expect(classList.contains('1')).toBe(true);
29+
expect(classList.contains(2 as any)).toBe(true);
30+
31+
classList.remove('one');
32+
classList.remove('two', 'three');
33+
classList.remove(null);
34+
classList.remove(undefined);
35+
classList.remove(1 as any, 2 as any);
36+
37+
expect(classList.toString()).toEqual('');
38+
});
39+
40+
it('should throw if empty', () => {
41+
expect(() => {
42+
classList.add('');
43+
}).toThrow();
44+
expect(() => {
45+
classList.remove('');
46+
}).toThrow();
47+
});
48+
49+
it('should throw if has spaces', () => {
50+
expect(() => {
51+
classList.add('');
52+
}).toThrow();
53+
expect(() => {
54+
classList.remove(' ');
55+
}).toThrow();
56+
});
57+
});

src/runtime/vdom/set-accessor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,4 @@ export const setAccessor = (elm: HTMLElement, memberName: string, oldValue: any,
122122
};
123123

124124
const parseClassList = (value: string | undefined | null): string[] =>
125-
(!value) ? [] : value.split(' ');
125+
(!value) ? [] : value.split(/ +/g);

0 commit comments

Comments
 (0)