-
Notifications
You must be signed in to change notification settings - Fork 2
/
htmlangElement.ts
81 lines (66 loc) · 2 KB
/
htmlangElement.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import { v4 as uuidv4 } from 'uuid';
import { globalScope } from '../main';
import { Scope } from '../scope';
import { scopeRegistry } from '../scopeRegistry';
export abstract class HtmlangElement extends HTMLElement {
private _scopeId = uuidv4();
private _parentScope: Scope | null = null;
private _originalSetAttribute = this.setAttribute;
constructor() {
super();
this.setAttribute = this._setAttribute;
}
disconnectedCallback(): void {
scopeRegistry.remove(this._scopeId);
}
get scope(): Scope {
if (!scopeRegistry.has(this._scopeId)) {
return this._registerScope().current;
}
return scopeRegistry.get(this._scopeId);
}
get parentScope(): Scope {
if (!this._parentScope) {
return this._registerScope().parent;
}
return this._parentScope;
}
abstract execute(): void;
private _getParentScope = (): Scope => {
let parent = this.parentElement;
while (parent !== null) {
if (parent instanceof HtmlangElement) {
return scopeRegistry.get(parent.scope.id);
} else {
parent = parent.parentElement;
}
}
return globalScope;
};
protected _registerScope = (): { current: Scope; parent: Scope } => {
this._parentScope = this._getParentScope();
return {
current: scopeRegistry.createAndAdd(this._scopeId, this._parentScope),
parent: this._parentScope,
};
};
private _setAttribute = (qualifiedName: string, value: string): void => {
try {
this._originalSetAttribute(qualifiedName, value);
} catch {
const parser = document.createElement('div');
parser.innerHTML = `<br ${qualifiedName} />`;
const attr = parser.firstElementChild!.attributes.removeNamedItem(qualifiedName);
attr.value = value;
this.attributes.setNamedItem(attr);
}
};
}
export class BaseHtmlangElement extends HtmlangElement {
static getTagName(): string {
throw new Error('Tag name not set');
}
execute(): void {
throw new Error('Method not implemented.');
}
}