import type { TAG_ID } from './html.js';
export enum TokenType {
CHARACTER,
NULL_CHARACTER,
WHITESPACE_CHARACTER,
START_TAG,
END_TAG,
COMMENT,
DOCTYPE,
EOF,
HIBERNATION,
}
export interface Location {
startLine: number;
startCol: number;
startOffset: number;
endLine: number;
endCol: number;
endOffset: number;
}
export interface LocationWithAttributes extends Location {
attrs?: Record<string, Location>;
line?: number;
col?: number;
}
export interface ElementLocation extends LocationWithAttributes {
startTag?: Location;
* Element's end tag location info.
* This property is undefined, if the element has no closing tag.
*/
endTag?: Location;
}
interface TokenBase {
readonly type: TokenType;
location: Location | null;
}
export interface DoctypeToken extends TokenBase {
readonly type: TokenType.DOCTYPE;
name: string | null;
forceQuirks: boolean;
publicId: string | null;
systemId: string | null;
}
export interface Attribute {
name: string;
namespace?: string;
prefix?: string;
value: string;
}
export interface TagToken extends TokenBase {
readonly type: TokenType.START_TAG | TokenType.END_TAG;
tagName: string;
tagID: TAG_ID;
selfClosing: boolean;
ackSelfClosing: boolean;
attrs: Attribute[];
location: LocationWithAttributes | null;
}
export function getTokenAttr(token: TagToken, attrName: string): string | null {
for (let i = token.attrs.length - 1; i >= 0; i--) {
if (token.attrs[i].name === attrName) {
return token.attrs[i].value;
}
}
return null;
}
export interface CommentToken extends TokenBase {
readonly type: TokenType.COMMENT;
data: string;
}
export interface EOFToken extends TokenBase {
readonly type: TokenType.EOF;
}
export interface CharacterToken extends TokenBase {
type: TokenType.CHARACTER | TokenType.NULL_CHARACTER | TokenType.WHITESPACE_CHARACTER;
chars: string;
}
export type Token = DoctypeToken | TagToken | CommentToken | EOFToken | CharacterToken;