blob: e92ec8e7edcae21929e19dea9390c588748920fe [file] [log] [blame]
/// This library contains token types used by the html5 tokenizer.
library token;
import 'dart:collection';
import 'package:source_span/source_span.dart';
/// An html5 token.
abstract class Token {
FileSpan span;
int get kind;
}
abstract class TagToken extends Token {
String name;
bool selfClosing;
TagToken(this.name, this.selfClosing);
}
class StartTagToken extends TagToken {
/// The tag's attributes. A map from the name to the value, where the name
/// can be a [String] or [AttributeName].
LinkedHashMap<dynamic, String> data;
/// The attribute spans if requested. Otherwise null.
List<TagAttribute> attributeSpans;
bool selfClosingAcknowledged;
/// The namespace. This is filled in later during tree building.
String namespace;
StartTagToken(String name,
{this.data,
bool selfClosing = false,
this.selfClosingAcknowledged = false,
this.namespace})
: super(name, selfClosing);
@override
int get kind => TokenKind.startTag;
}
class EndTagToken extends TagToken {
EndTagToken(String name, {bool selfClosing = false})
: super(name, selfClosing);
@override
int get kind => TokenKind.endTag;
}
abstract class StringToken extends Token {
StringBuffer _buffer;
String _string;
String get data {
if (_string == null) {
_string = _buffer.toString();
_buffer = null;
}
return _string;
}
StringToken(string)
: _string = string,
_buffer = string == null ? StringBuffer() : null;
StringToken add(String data) {
_buffer.write(data);
return this;
}
}
class ParseErrorToken extends StringToken {
/// Extra information that goes along with the error message.
Map messageParams;
ParseErrorToken(String data, {this.messageParams}) : super(data);
@override
int get kind => TokenKind.parseError;
}
class CharactersToken extends StringToken {
CharactersToken([String data]) : super(data);
@override
int get kind => TokenKind.characters;
/// Replaces the token's [data]. This should only be used to wholly replace
/// data, not to append data.
void replaceData(String newData) {
_string = newData;
_buffer = null;
}
}
class SpaceCharactersToken extends StringToken {
SpaceCharactersToken([String data]) : super(data);
@override
int get kind => TokenKind.spaceCharacters;
}
class CommentToken extends StringToken {
CommentToken([String data]) : super(data);
@override
int get kind => TokenKind.comment;
}
class DoctypeToken extends Token {
String publicId;
String systemId;
String name = '';
bool correct;
DoctypeToken({this.publicId, this.systemId, this.correct = false});
@override
int get kind => TokenKind.doctype;
}
/// These are used by the tokenizer to build up the attribute map.
/// They're also used by [StartTagToken.attributeSpans] if attribute spans are
/// requested.
class TagAttribute {
String name;
String value;
// The spans of the attribute. This is not used unless we are computing an
// attribute span on demand.
int start;
int end;
int startValue;
int endValue;
TagAttribute();
}
class TokenKind {
static const int spaceCharacters = 0;
static const int characters = 1;
static const int startTag = 2;
static const int endTag = 3;
static const int comment = 4;
static const int doctype = 5;
static const int parseError = 6;
}