61 lines
1.9 KiB
TypeScript
61 lines
1.9 KiB
TypeScript
|
export const enum Type {
|
||
|
DOCTYPE = 'DOCTYPE',
|
||
|
StartTag = 'start tag',
|
||
|
EndTag = 'end tag',
|
||
|
Comment = 'comment',
|
||
|
Character = 'character',
|
||
|
EndOfFile = 'end-of-file'
|
||
|
}
|
||
|
|
||
|
export type Attribute = { name: NonNullable<string>, value: NonNullable<string> };
|
||
|
|
||
|
export class AttributeList {
|
||
|
private attributes: Array<Attribute>;
|
||
|
|
||
|
public constructor() {
|
||
|
this.attributes = new Array<Attribute>();
|
||
|
}
|
||
|
|
||
|
public get current(): Attribute {
|
||
|
return this.attributes[this.attributes.length - 1];
|
||
|
}
|
||
|
|
||
|
public get list(): Array<Attribute> {
|
||
|
return this.attributes;
|
||
|
}
|
||
|
|
||
|
public nonEmpty(): boolean {
|
||
|
return this.list.length !== 0;
|
||
|
}
|
||
|
|
||
|
public append(attribute: Attribute): void {
|
||
|
this.attributes.push(attribute);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export type Token = { type: Type.DOCTYPE, name?: string, publicIdentifier?: string, systemIdentifier?: string, forceQuirks?: true } |
|
||
|
{ type: Type.StartTag, name: NonNullable<string>, selfClosing?: true, attributes: AttributeList } |
|
||
|
{ type: Type.EndTag, name: NonNullable<string>, selfClosing?: true, attributes: AttributeList } |
|
||
|
{ type: Type.Comment, data: NonNullable<string> } |
|
||
|
{ type: Type.Character, data: NonNullable<string> } |
|
||
|
{ type: Type.EndOfFile };
|
||
|
|
||
|
export function stringify(token: Token): string {
|
||
|
switch (token.type) {
|
||
|
case Type.Character: return token.data;
|
||
|
case Type.Comment: return `<!--${token.data}-->`;
|
||
|
case Type.DOCTYPE: return `<!DOCTYPE ${token.name}>`;
|
||
|
case Type.EndOfFile: return 'EOF';
|
||
|
case Type.EndTag: return `</${token.name}>`;
|
||
|
case Type.StartTag: {
|
||
|
let string = `<${token.name}`;
|
||
|
|
||
|
for (const attribute of token.attributes.list)
|
||
|
string += ` ${attribute.name}="${attribute.value}"`;
|
||
|
|
||
|
if (token.selfClosing) return `${string} />`;
|
||
|
|
||
|
return `${string}>`;
|
||
|
};
|
||
|
}
|
||
|
}
|