2023-12-13 11:23:54 +01:00
|
|
|
|
import { Options, tokenize as tokenize$1 } from 'linkifyjs';
|
2021-05-28 16:46:29 +02:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* generated from https://raw.githubusercontent.com/w3c/html/26b5126f96f736f796b9e29718138919dd513744/entities.json
|
|
|
|
|
|
* do not edit
|
|
|
|
|
|
*/
|
|
|
|
|
|
var HTML5NamedCharRefs = {
|
|
|
|
|
|
// We don't need the complete named character reference because linkifyHtml
|
|
|
|
|
|
// does not modify the escape sequences. We do need so that
|
|
|
|
|
|
// whitespace is parsed properly. Other types of whitespace should already
|
2023-12-13 11:23:54 +01:00
|
|
|
|
// be accounted for. > < and " are also frequently relevant ones
|
|
|
|
|
|
amp: "&",
|
|
|
|
|
|
gt: ">",
|
|
|
|
|
|
lt: "<",
|
|
|
|
|
|
nbsp: " ",
|
|
|
|
|
|
quot: "\""
|
2021-05-28 16:46:29 +02:00
|
|
|
|
};
|
|
|
|
|
|
var HEXCHARCODE = /^#[xX]([A-Fa-f0-9]+)$/;
|
|
|
|
|
|
var CHARCODE = /^#([0-9]+)$/;
|
|
|
|
|
|
var NAMED = /^([A-Za-z0-9]+)$/;
|
2023-12-13 11:23:54 +01:00
|
|
|
|
var EntityParser = /** @class */function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
function EntityParser(named) {
|
|
|
|
|
|
this.named = named;
|
|
|
|
|
|
}
|
|
|
|
|
|
EntityParser.prototype.parse = function (entity) {
|
|
|
|
|
|
if (!entity) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
var matches = entity.match(HEXCHARCODE);
|
|
|
|
|
|
if (matches) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
return String.fromCharCode(parseInt(matches[1], 16));
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
matches = entity.match(CHARCODE);
|
|
|
|
|
|
if (matches) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
return String.fromCharCode(parseInt(matches[1], 10));
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
matches = entity.match(NAMED);
|
|
|
|
|
|
if (matches) {
|
|
|
|
|
|
return this.named[matches[1]] || "&" + matches[1] + ";";
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
return EntityParser;
|
|
|
|
|
|
}();
|
|
|
|
|
|
var WSP = /[\t\n\f ]/;
|
|
|
|
|
|
var ALPHA = /[A-Za-z]/;
|
|
|
|
|
|
var CRLF = /\r\n?/g;
|
|
|
|
|
|
function isSpace(char) {
|
|
|
|
|
|
return WSP.test(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
function isAlpha(char) {
|
|
|
|
|
|
return ALPHA.test(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
function preprocessInput(input) {
|
|
|
|
|
|
return input.replace(CRLF, '\n');
|
|
|
|
|
|
}
|
2023-12-13 11:23:54 +01:00
|
|
|
|
var EventedTokenizer = /** @class */function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
function EventedTokenizer(delegate, entityParser, mode) {
|
|
|
|
|
|
if (mode === void 0) {
|
|
|
|
|
|
mode = 'precompile';
|
|
|
|
|
|
}
|
|
|
|
|
|
this.delegate = delegate;
|
|
|
|
|
|
this.entityParser = entityParser;
|
|
|
|
|
|
this.mode = mode;
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.state = "beforeData" /* beforeData */;
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.line = -1;
|
|
|
|
|
|
this.column = -1;
|
|
|
|
|
|
this.input = '';
|
|
|
|
|
|
this.index = -1;
|
|
|
|
|
|
this.tagNameBuffer = '';
|
|
|
|
|
|
this.states = {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
beforeData: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.peek();
|
|
|
|
|
|
if (char === '<' && !this.isIgnoredEndTag()) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("tagOpen" /* tagOpen */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.markTagStart();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (this.mode === 'precompile' && char === '\n') {
|
|
|
|
|
|
var tag = this.tagNameBuffer.toLowerCase();
|
|
|
|
|
|
if (tag === 'pre' || tag === 'textarea') {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("data" /* data */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.delegate.beginData();
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
data: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.peek();
|
|
|
|
|
|
var tag = this.tagNameBuffer;
|
|
|
|
|
|
if (char === '<' && !this.isIgnoredEndTag()) {
|
|
|
|
|
|
this.delegate.finishData();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("tagOpen" /* tagOpen */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.markTagStart();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
} else if (char === '&' && tag !== 'script' && tag !== 'style') {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.appendToData(this.consumeCharRef() || '&');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.appendToData(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
tagOpen: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.consume();
|
|
|
|
|
|
if (char === '!') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("markupDeclarationOpen" /* markupDeclarationOpen */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '/') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("endTagOpen" /* endTagOpen */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '@' || char === ':' || isAlpha(char)) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("tagName" /* tagName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.tagNameBuffer = '';
|
|
|
|
|
|
this.delegate.beginStartTag();
|
|
|
|
|
|
this.appendToTagName(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
markupDeclarationOpen: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.consume();
|
|
|
|
|
|
if (char === '-' && this.peek() === '-') {
|
|
|
|
|
|
this.consume();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("commentStart" /* commentStart */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.delegate.beginComment();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
var maybeDoctype = char.toUpperCase() + this.input.substring(this.index, this.index + 6).toUpperCase();
|
|
|
|
|
|
if (maybeDoctype === 'DOCTYPE') {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.consume();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("doctype" /* doctype */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (this.delegate.beginDoctype) this.delegate.beginDoctype();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
doctype: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.consume();
|
|
|
|
|
|
if (isSpace(char)) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeDoctypeName" /* beforeDoctypeName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
beforeDoctypeName: function () {
|
|
|
|
|
|
var char = this.consume();
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (isSpace(char)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
} else {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("doctypeName" /* doctypeName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (this.delegate.appendToDoctypeName) this.delegate.appendToDoctypeName(char.toLowerCase());
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
doctypeName: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.consume();
|
|
|
|
|
|
if (isSpace(char)) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("afterDoctypeName" /* afterDoctypeName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
if (this.delegate.endDoctype) this.delegate.endDoctype();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
if (this.delegate.appendToDoctypeName) this.delegate.appendToDoctypeName(char.toLowerCase());
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
afterDoctypeName: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.consume();
|
|
|
|
|
|
if (isSpace(char)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
if (this.delegate.endDoctype) this.delegate.endDoctype();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
var nextSixChars = char.toUpperCase() + this.input.substring(this.index, this.index + 5).toUpperCase();
|
|
|
|
|
|
var isPublic = nextSixChars.toUpperCase() === 'PUBLIC';
|
|
|
|
|
|
var isSystem = nextSixChars.toUpperCase() === 'SYSTEM';
|
|
|
|
|
|
if (isPublic || isSystem) {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (isPublic) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("afterDoctypePublicKeyword" /* afterDoctypePublicKeyword */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (isSystem) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("afterDoctypeSystemKeyword" /* afterDoctypeSystemKeyword */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
afterDoctypePublicKeyword: function () {
|
|
|
|
|
|
var char = this.peek();
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (isSpace(char)) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeDoctypePublicIdentifier" /* beforeDoctypePublicIdentifier */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.consume();
|
|
|
|
|
|
} else if (char === '"') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("doctypePublicIdentifierDoubleQuoted" /* doctypePublicIdentifierDoubleQuoted */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.consume();
|
|
|
|
|
|
} else if (char === "'") {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("doctypePublicIdentifierSingleQuoted" /* doctypePublicIdentifierSingleQuoted */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.consume();
|
|
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
if (this.delegate.endDoctype) this.delegate.endDoctype();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
doctypePublicIdentifierDoubleQuoted: function () {
|
|
|
|
|
|
var char = this.consume();
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (char === '"') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("afterDoctypePublicIdentifier" /* afterDoctypePublicIdentifier */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
if (this.delegate.endDoctype) this.delegate.endDoctype();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
if (this.delegate.appendToDoctypePublicIdentifier) this.delegate.appendToDoctypePublicIdentifier(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
doctypePublicIdentifierSingleQuoted: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.consume();
|
|
|
|
|
|
if (char === "'") {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("afterDoctypePublicIdentifier" /* afterDoctypePublicIdentifier */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
if (this.delegate.endDoctype) this.delegate.endDoctype();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
if (this.delegate.appendToDoctypePublicIdentifier) this.delegate.appendToDoctypePublicIdentifier(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
afterDoctypePublicIdentifier: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.consume();
|
|
|
|
|
|
if (isSpace(char)) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("betweenDoctypePublicAndSystemIdentifiers" /* betweenDoctypePublicAndSystemIdentifiers */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
if (this.delegate.endDoctype) this.delegate.endDoctype();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '"') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("doctypeSystemIdentifierDoubleQuoted" /* doctypeSystemIdentifierDoubleQuoted */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === "'") {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("doctypeSystemIdentifierSingleQuoted" /* doctypeSystemIdentifierSingleQuoted */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
betweenDoctypePublicAndSystemIdentifiers: function () {
|
|
|
|
|
|
var char = this.consume();
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (isSpace(char)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
if (this.delegate.endDoctype) this.delegate.endDoctype();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '"') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("doctypeSystemIdentifierDoubleQuoted" /* doctypeSystemIdentifierDoubleQuoted */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === "'") {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("doctypeSystemIdentifierSingleQuoted" /* doctypeSystemIdentifierSingleQuoted */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
doctypeSystemIdentifierDoubleQuoted: function () {
|
|
|
|
|
|
var char = this.consume();
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (char === '"') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("afterDoctypeSystemIdentifier" /* afterDoctypeSystemIdentifier */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
if (this.delegate.endDoctype) this.delegate.endDoctype();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
if (this.delegate.appendToDoctypeSystemIdentifier) this.delegate.appendToDoctypeSystemIdentifier(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
doctypeSystemIdentifierSingleQuoted: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.consume();
|
|
|
|
|
|
if (char === "'") {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("afterDoctypeSystemIdentifier" /* afterDoctypeSystemIdentifier */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
if (this.delegate.endDoctype) this.delegate.endDoctype();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
if (this.delegate.appendToDoctypeSystemIdentifier) this.delegate.appendToDoctypeSystemIdentifier(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
afterDoctypeSystemIdentifier: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.consume();
|
|
|
|
|
|
if (isSpace(char)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
if (this.delegate.endDoctype) this.delegate.endDoctype();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
commentStart: function () {
|
|
|
|
|
|
var char = this.consume();
|
2025-05-07 10:40:03 +02:00
|
|
|
|
if (char === '-' && this.peek() === '-') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("commentStartDash" /* commentStartDash */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
this.delegate.finishComment();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
this.delegate.appendToCommentData(char);
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("comment" /* comment */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
commentStartDash: function () {
|
|
|
|
|
|
var char = this.consume();
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (char === '-') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("commentEnd" /* commentEnd */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
this.delegate.finishComment();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
this.delegate.appendToCommentData('-');
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("comment" /* comment */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
comment: function () {
|
|
|
|
|
|
var char = this.consume();
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (char === '-') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("commentEndDash" /* commentEndDash */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
this.delegate.appendToCommentData(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
commentEndDash: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.consume();
|
2025-05-07 10:40:03 +02:00
|
|
|
|
if (char === '-' && this.peek() === '-') {
|
|
|
|
|
|
this.delegate.appendToCommentData(char);
|
|
|
|
|
|
} else if (char === '-') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("commentEnd" /* commentEnd */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
this.delegate.appendToCommentData('-' + char);
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("comment" /* comment */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
commentEnd: function () {
|
|
|
|
|
|
var char = this.consume();
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (char === '>') {
|
|
|
|
|
|
this.delegate.finishComment();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
this.delegate.appendToCommentData('--' + char);
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("comment" /* comment */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
tagName: function () {
|
|
|
|
|
|
var char = this.consume();
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (isSpace(char)) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '/') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
this.delegate.finishTag();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
this.appendToTagName(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
endTagName: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.consume();
|
|
|
|
|
|
if (isSpace(char)) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.tagNameBuffer = '';
|
|
|
|
|
|
} else if (char === '/') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.tagNameBuffer = '';
|
|
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
this.delegate.finishTag();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.tagNameBuffer = '';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.appendToTagName(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
beforeAttributeName: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.peek();
|
|
|
|
|
|
if (isSpace(char)) {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
return;
|
|
|
|
|
|
} else if (char === '/') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.consume();
|
|
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.finishTag();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '=') {
|
|
|
|
|
|
this.delegate.reportSyntaxError('attribute name cannot start with equals sign');
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("attributeName" /* attributeName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.delegate.beginAttribute();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.appendToAttributeName(char);
|
|
|
|
|
|
} else {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("attributeName" /* attributeName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.delegate.beginAttribute();
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
attributeName: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.peek();
|
|
|
|
|
|
if (isSpace(char)) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("afterAttributeName" /* afterAttributeName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.consume();
|
|
|
|
|
|
} else if (char === '/') {
|
|
|
|
|
|
this.delegate.beginAttributeValue(false);
|
|
|
|
|
|
this.delegate.finishAttributeValue();
|
|
|
|
|
|
this.consume();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '=') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeAttributeValue" /* beforeAttributeValue */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.consume();
|
|
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
this.delegate.beginAttributeValue(false);
|
|
|
|
|
|
this.delegate.finishAttributeValue();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.finishTag();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '"' || char === "'" || char === '<') {
|
|
|
|
|
|
this.delegate.reportSyntaxError(char + ' is not a valid character within attribute names');
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.appendToAttributeName(char);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.appendToAttributeName(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
afterAttributeName: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.peek();
|
|
|
|
|
|
if (isSpace(char)) {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
return;
|
|
|
|
|
|
} else if (char === '/') {
|
|
|
|
|
|
this.delegate.beginAttributeValue(false);
|
|
|
|
|
|
this.delegate.finishAttributeValue();
|
|
|
|
|
|
this.consume();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '=') {
|
|
|
|
|
|
this.consume();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeAttributeValue" /* beforeAttributeValue */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
this.delegate.beginAttributeValue(false);
|
|
|
|
|
|
this.delegate.finishAttributeValue();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.finishTag();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
this.delegate.beginAttributeValue(false);
|
|
|
|
|
|
this.delegate.finishAttributeValue();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("attributeName" /* attributeName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.delegate.beginAttribute();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.appendToAttributeName(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
beforeAttributeValue: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.peek();
|
|
|
|
|
|
if (isSpace(char)) {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
} else if (char === '"') {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("attributeValueDoubleQuoted" /* attributeValueDoubleQuoted */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.delegate.beginAttributeValue(true);
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
} else if (char === "'") {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("attributeValueSingleQuoted" /* attributeValueSingleQuoted */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.delegate.beginAttributeValue(true);
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
this.delegate.beginAttributeValue(false);
|
|
|
|
|
|
this.delegate.finishAttributeValue();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.finishTag();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("attributeValueUnquoted" /* attributeValueUnquoted */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.delegate.beginAttributeValue(false);
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.appendToAttributeValue(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
attributeValueDoubleQuoted: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.consume();
|
|
|
|
|
|
if (char === '"') {
|
|
|
|
|
|
this.delegate.finishAttributeValue();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("afterAttributeValueQuoted" /* afterAttributeValueQuoted */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '&') {
|
|
|
|
|
|
this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.delegate.appendToAttributeValue(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
attributeValueSingleQuoted: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.consume();
|
|
|
|
|
|
if (char === "'") {
|
|
|
|
|
|
this.delegate.finishAttributeValue();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("afterAttributeValueQuoted" /* afterAttributeValueQuoted */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '&') {
|
|
|
|
|
|
this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.delegate.appendToAttributeValue(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
attributeValueUnquoted: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.peek();
|
|
|
|
|
|
if (isSpace(char)) {
|
|
|
|
|
|
this.delegate.finishAttributeValue();
|
|
|
|
|
|
this.consume();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '/') {
|
|
|
|
|
|
this.delegate.finishAttributeValue();
|
|
|
|
|
|
this.consume();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '&') {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
|
|
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
this.delegate.finishAttributeValue();
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.finishTag();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.appendToAttributeValue(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
afterAttributeValueQuoted: function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
var char = this.peek();
|
|
|
|
|
|
if (isSpace(char)) {
|
|
|
|
|
|
this.consume();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '/') {
|
|
|
|
|
|
this.consume();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else if (char === '>') {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.finishTag();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
selfClosingStartTag: function () {
|
|
|
|
|
|
var char = this.peek();
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (char === '>') {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
this.delegate.markTagAsSelfClosing();
|
|
|
|
|
|
this.delegate.finishTag();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
} else {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2023-12-13 11:23:54 +01:00
|
|
|
|
endTagOpen: function () {
|
|
|
|
|
|
var char = this.consume();
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (char === '@' || char === ':' || isAlpha(char)) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("endTagName" /* endTagName */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.tagNameBuffer = '';
|
|
|
|
|
|
this.delegate.beginEndTag();
|
|
|
|
|
|
this.appendToTagName(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
this.reset();
|
|
|
|
|
|
}
|
|
|
|
|
|
EventedTokenizer.prototype.reset = function () {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.input = '';
|
|
|
|
|
|
this.tagNameBuffer = '';
|
|
|
|
|
|
this.index = 0;
|
|
|
|
|
|
this.line = 1;
|
|
|
|
|
|
this.column = 0;
|
|
|
|
|
|
this.delegate.reset();
|
|
|
|
|
|
};
|
|
|
|
|
|
EventedTokenizer.prototype.transitionTo = function (state) {
|
|
|
|
|
|
this.state = state;
|
|
|
|
|
|
};
|
|
|
|
|
|
EventedTokenizer.prototype.tokenize = function (input) {
|
|
|
|
|
|
this.reset();
|
|
|
|
|
|
this.tokenizePart(input);
|
|
|
|
|
|
this.tokenizeEOF();
|
|
|
|
|
|
};
|
|
|
|
|
|
EventedTokenizer.prototype.tokenizePart = function (input) {
|
|
|
|
|
|
this.input += preprocessInput(input);
|
|
|
|
|
|
while (this.index < this.input.length) {
|
|
|
|
|
|
var handler = this.states[this.state];
|
|
|
|
|
|
if (handler !== undefined) {
|
|
|
|
|
|
handler.call(this);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new Error("unhandled state " + this.state);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
EventedTokenizer.prototype.tokenizeEOF = function () {
|
|
|
|
|
|
this.flushData();
|
|
|
|
|
|
};
|
|
|
|
|
|
EventedTokenizer.prototype.flushData = function () {
|
|
|
|
|
|
if (this.state === 'data') {
|
|
|
|
|
|
this.delegate.finishData();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.transitionTo("beforeData" /* beforeData */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
EventedTokenizer.prototype.peek = function () {
|
|
|
|
|
|
return this.input.charAt(this.index);
|
|
|
|
|
|
};
|
|
|
|
|
|
EventedTokenizer.prototype.consume = function () {
|
|
|
|
|
|
var char = this.peek();
|
|
|
|
|
|
this.index++;
|
|
|
|
|
|
if (char === '\n') {
|
|
|
|
|
|
this.line++;
|
|
|
|
|
|
this.column = 0;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.column++;
|
|
|
|
|
|
}
|
|
|
|
|
|
return char;
|
|
|
|
|
|
};
|
|
|
|
|
|
EventedTokenizer.prototype.consumeCharRef = function () {
|
|
|
|
|
|
var endIndex = this.input.indexOf(';', this.index);
|
|
|
|
|
|
if (endIndex === -1) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
var entity = this.input.slice(this.index, endIndex);
|
|
|
|
|
|
var chars = this.entityParser.parse(entity);
|
|
|
|
|
|
if (chars) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
var count = entity.length;
|
|
|
|
|
|
// consume the entity chars
|
2021-05-28 16:46:29 +02:00
|
|
|
|
while (count) {
|
|
|
|
|
|
this.consume();
|
|
|
|
|
|
count--;
|
2023-12-13 11:23:54 +01:00
|
|
|
|
}
|
|
|
|
|
|
// consume the `;`
|
2021-05-28 16:46:29 +02:00
|
|
|
|
this.consume();
|
|
|
|
|
|
return chars;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
EventedTokenizer.prototype.markTagStart = function () {
|
|
|
|
|
|
this.delegate.tagOpen();
|
|
|
|
|
|
};
|
|
|
|
|
|
EventedTokenizer.prototype.appendToTagName = function (char) {
|
|
|
|
|
|
this.tagNameBuffer += char;
|
|
|
|
|
|
this.delegate.appendToTagName(char);
|
|
|
|
|
|
};
|
|
|
|
|
|
EventedTokenizer.prototype.isIgnoredEndTag = function () {
|
|
|
|
|
|
var tag = this.tagNameBuffer;
|
|
|
|
|
|
return tag === 'title' && this.input.substring(this.index, this.index + 8) !== '</title>' || tag === 'style' && this.input.substring(this.index, this.index + 8) !== '</style>' || tag === 'script' && this.input.substring(this.index, this.index + 9) !== '</script>';
|
|
|
|
|
|
};
|
|
|
|
|
|
return EventedTokenizer;
|
|
|
|
|
|
}();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
var Tokenizer = /** @class */function () {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
function Tokenizer(entityParser, options) {
|
|
|
|
|
|
if (options === void 0) {
|
|
|
|
|
|
options = {};
|
|
|
|
|
|
}
|
|
|
|
|
|
this.options = options;
|
|
|
|
|
|
this.token = null;
|
|
|
|
|
|
this.startLine = 1;
|
|
|
|
|
|
this.startColumn = 0;
|
|
|
|
|
|
this.tokens = [];
|
|
|
|
|
|
this.tokenizer = new EventedTokenizer(this, entityParser, options.mode);
|
|
|
|
|
|
this._currentAttribute = undefined;
|
|
|
|
|
|
}
|
|
|
|
|
|
Tokenizer.prototype.tokenize = function (input) {
|
|
|
|
|
|
this.tokens = [];
|
|
|
|
|
|
this.tokenizer.tokenize(input);
|
|
|
|
|
|
return this.tokens;
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.tokenizePart = function (input) {
|
|
|
|
|
|
this.tokens = [];
|
|
|
|
|
|
this.tokenizer.tokenizePart(input);
|
|
|
|
|
|
return this.tokens;
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.tokenizeEOF = function () {
|
|
|
|
|
|
this.tokens = [];
|
|
|
|
|
|
this.tokenizer.tokenizeEOF();
|
|
|
|
|
|
return this.tokens[0];
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.reset = function () {
|
|
|
|
|
|
this.token = null;
|
|
|
|
|
|
this.startLine = 1;
|
|
|
|
|
|
this.startColumn = 0;
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.current = function () {
|
|
|
|
|
|
var token = this.token;
|
|
|
|
|
|
if (token === null) {
|
|
|
|
|
|
throw new Error('token was unexpectedly null');
|
|
|
|
|
|
}
|
|
|
|
|
|
if (arguments.length === 0) {
|
|
|
|
|
|
return token;
|
|
|
|
|
|
}
|
|
|
|
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
|
|
|
|
if (token.type === arguments[i]) {
|
|
|
|
|
|
return token;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
throw new Error("token type was unexpectedly " + token.type);
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.push = function (token) {
|
|
|
|
|
|
this.token = token;
|
|
|
|
|
|
this.tokens.push(token);
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.currentAttribute = function () {
|
|
|
|
|
|
return this._currentAttribute;
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.addLocInfo = function () {
|
|
|
|
|
|
if (this.options.loc) {
|
|
|
|
|
|
this.current().loc = {
|
|
|
|
|
|
start: {
|
|
|
|
|
|
line: this.startLine,
|
|
|
|
|
|
column: this.startColumn
|
|
|
|
|
|
},
|
|
|
|
|
|
end: {
|
|
|
|
|
|
line: this.tokenizer.line,
|
|
|
|
|
|
column: this.tokenizer.column
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
this.startLine = this.tokenizer.line;
|
|
|
|
|
|
this.startColumn = this.tokenizer.column;
|
2023-12-13 11:23:54 +01:00
|
|
|
|
};
|
|
|
|
|
|
// Data
|
2021-05-28 16:46:29 +02:00
|
|
|
|
Tokenizer.prototype.beginDoctype = function () {
|
|
|
|
|
|
this.push({
|
2023-12-13 11:23:54 +01:00
|
|
|
|
type: "Doctype" /* Doctype */,
|
2021-05-28 16:46:29 +02:00
|
|
|
|
name: ''
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.appendToDoctypeName = function (char) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.current("Doctype" /* Doctype */).name += char;
|
2021-05-28 16:46:29 +02:00
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.appendToDoctypePublicIdentifier = function (char) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
var doctype = this.current("Doctype" /* Doctype */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (doctype.publicIdentifier === undefined) {
|
|
|
|
|
|
doctype.publicIdentifier = char;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
doctype.publicIdentifier += char;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.appendToDoctypeSystemIdentifier = function (char) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
var doctype = this.current("Doctype" /* Doctype */);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (doctype.systemIdentifier === undefined) {
|
|
|
|
|
|
doctype.systemIdentifier = char;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
doctype.systemIdentifier += char;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.endDoctype = function () {
|
|
|
|
|
|
this.addLocInfo();
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.beginData = function () {
|
|
|
|
|
|
this.push({
|
2023-12-13 11:23:54 +01:00
|
|
|
|
type: "Chars" /* Chars */,
|
2021-05-28 16:46:29 +02:00
|
|
|
|
chars: ''
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.appendToData = function (char) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.current("Chars" /* Chars */).chars += char;
|
2021-05-28 16:46:29 +02:00
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.finishData = function () {
|
|
|
|
|
|
this.addLocInfo();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
};
|
|
|
|
|
|
// Comment
|
2021-05-28 16:46:29 +02:00
|
|
|
|
Tokenizer.prototype.beginComment = function () {
|
|
|
|
|
|
this.push({
|
2023-12-13 11:23:54 +01:00
|
|
|
|
type: "Comment" /* Comment */,
|
2021-05-28 16:46:29 +02:00
|
|
|
|
chars: ''
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.appendToCommentData = function (char) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.current("Comment" /* Comment */).chars += char;
|
2021-05-28 16:46:29 +02:00
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.finishComment = function () {
|
|
|
|
|
|
this.addLocInfo();
|
2023-12-13 11:23:54 +01:00
|
|
|
|
};
|
|
|
|
|
|
// Tags - basic
|
2021-05-28 16:46:29 +02:00
|
|
|
|
Tokenizer.prototype.tagOpen = function () {};
|
|
|
|
|
|
Tokenizer.prototype.beginStartTag = function () {
|
|
|
|
|
|
this.push({
|
2023-12-13 11:23:54 +01:00
|
|
|
|
type: "StartTag" /* StartTag */,
|
2021-05-28 16:46:29 +02:00
|
|
|
|
tagName: '',
|
|
|
|
|
|
attributes: [],
|
|
|
|
|
|
selfClosing: false
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.beginEndTag = function () {
|
|
|
|
|
|
this.push({
|
2023-12-13 11:23:54 +01:00
|
|
|
|
type: "EndTag" /* EndTag */,
|
2021-05-28 16:46:29 +02:00
|
|
|
|
tagName: ''
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.finishTag = function () {
|
|
|
|
|
|
this.addLocInfo();
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.markTagAsSelfClosing = function () {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.current("StartTag" /* StartTag */).selfClosing = true;
|
|
|
|
|
|
};
|
|
|
|
|
|
// Tags - name
|
2021-05-28 16:46:29 +02:00
|
|
|
|
Tokenizer.prototype.appendToTagName = function (char) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.current("StartTag" /* StartTag */, "EndTag" /* EndTag */).tagName += char;
|
|
|
|
|
|
};
|
|
|
|
|
|
// Tags - attributes
|
2021-05-28 16:46:29 +02:00
|
|
|
|
Tokenizer.prototype.beginAttribute = function () {
|
|
|
|
|
|
this._currentAttribute = ['', '', false];
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.appendToAttributeName = function (char) {
|
|
|
|
|
|
this.currentAttribute()[0] += char;
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.beginAttributeValue = function (isQuoted) {
|
|
|
|
|
|
this.currentAttribute()[2] = isQuoted;
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.appendToAttributeValue = function (char) {
|
|
|
|
|
|
this.currentAttribute()[1] += char;
|
|
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.finishAttributeValue = function () {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
this.current("StartTag" /* StartTag */).attributes.push(this._currentAttribute);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
};
|
|
|
|
|
|
Tokenizer.prototype.reportSyntaxError = function (message) {
|
|
|
|
|
|
this.current().syntaxError = message;
|
|
|
|
|
|
};
|
|
|
|
|
|
return Tokenizer;
|
|
|
|
|
|
}();
|
|
|
|
|
|
function tokenize(input, options) {
|
|
|
|
|
|
var tokenizer = new Tokenizer(new EntityParser(HTML5NamedCharRefs), options);
|
|
|
|
|
|
return tokenizer.tokenize(input);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-13 11:23:54 +01:00
|
|
|
|
const LinkifyResult = 'LinkifyResult';
|
|
|
|
|
|
const StartTag = 'StartTag';
|
|
|
|
|
|
const EndTag = 'EndTag';
|
|
|
|
|
|
const Chars = 'Chars';
|
|
|
|
|
|
const Comment = 'Comment';
|
|
|
|
|
|
const Doctype = 'Doctype';
|
|
|
|
|
|
|
2021-05-28 16:46:29 +02:00
|
|
|
|
/**
|
|
|
|
|
|
* @param {string} str html string to link
|
2023-12-13 11:23:54 +01:00
|
|
|
|
* @param {import('linkifyjs').Opts} [opts] linkify options
|
2021-05-28 16:46:29 +02:00
|
|
|
|
* @returns {string} resulting string
|
|
|
|
|
|
*/
|
2025-05-07 10:40:03 +02:00
|
|
|
|
function linkifyHtml(str, opts = {}) {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
// `tokens` and `token` in this section refer to tokens generated by the
|
|
|
|
|
|
// HTML parser, not linkify's parser
|
2023-12-13 11:23:54 +01:00
|
|
|
|
const tokens = tokenize(str);
|
|
|
|
|
|
const linkifiedTokens = [];
|
|
|
|
|
|
const linkified = [];
|
|
|
|
|
|
const options = new Options(opts, defaultRender);
|
|
|
|
|
|
|
|
|
|
|
|
// Linkify the tokens given by the parser
|
|
|
|
|
|
for (let i = 0; i < tokens.length; i++) {
|
|
|
|
|
|
const token = tokens[i];
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (token.type === StartTag) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
linkifiedTokens.push(token);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
|
2023-12-13 11:23:54 +01:00
|
|
|
|
// Ignore all the contents of ignored tags
|
|
|
|
|
|
const tagName = token.tagName.toUpperCase();
|
|
|
|
|
|
const isIgnored = tagName === 'A' || options.ignoreTags.indexOf(tagName) >= 0;
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (!isIgnored) {
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
2023-12-13 11:23:54 +01:00
|
|
|
|
let preskipLen = linkifiedTokens.length;
|
2021-05-28 16:46:29 +02:00
|
|
|
|
skipTagTokens(tagName, tokens, ++i, linkifiedTokens);
|
|
|
|
|
|
i += linkifiedTokens.length - preskipLen - 1;
|
|
|
|
|
|
} else if (token.type !== Chars) {
|
|
|
|
|
|
// Skip this token, it's not important
|
|
|
|
|
|
linkifiedTokens.push(token);
|
2023-12-13 11:23:54 +01:00
|
|
|
|
} else {
|
|
|
|
|
|
// Valid text token, linkify it!
|
|
|
|
|
|
const linkifedChars = linkifyChars(token.chars, options);
|
|
|
|
|
|
linkifiedTokens.push.apply(linkifiedTokens, linkifedChars);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-05-28 16:46:29 +02:00
|
|
|
|
|
2023-12-13 11:23:54 +01:00
|
|
|
|
// Convert the tokens back into a string
|
|
|
|
|
|
for (let i = 0; i < linkifiedTokens.length; i++) {
|
|
|
|
|
|
const token = linkifiedTokens[i];
|
|
|
|
|
|
switch (token.type) {
|
|
|
|
|
|
case LinkifyResult:
|
|
|
|
|
|
linkified.push(token.rendered);
|
|
|
|
|
|
break;
|
2021-05-28 16:46:29 +02:00
|
|
|
|
case StartTag:
|
|
|
|
|
|
{
|
2023-12-13 11:23:54 +01:00
|
|
|
|
let link = '<' + token.tagName;
|
|
|
|
|
|
if (token.attributes.length > 0) {
|
|
|
|
|
|
link += ' ' + attributeArrayToStrings(token.attributes).join(' ');
|
|
|
|
|
|
}
|
|
|
|
|
|
if (token.selfClosing) {
|
|
|
|
|
|
link += ' /';
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
link += '>';
|
|
|
|
|
|
linkified.push(link);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case EndTag:
|
2023-12-13 11:23:54 +01:00
|
|
|
|
linkified.push(`</${token.tagName}>`);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
break;
|
|
|
|
|
|
case Chars:
|
2023-12-13 11:23:54 +01:00
|
|
|
|
linkified.push(escapeText(token.chars));
|
2021-05-28 16:46:29 +02:00
|
|
|
|
break;
|
|
|
|
|
|
case Comment:
|
2023-12-13 11:23:54 +01:00
|
|
|
|
linkified.push(`<!--${escapeText(token.chars)}-->`);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
break;
|
|
|
|
|
|
case Doctype:
|
|
|
|
|
|
{
|
2023-12-13 11:23:54 +01:00
|
|
|
|
let doctype = `<!DOCTYPE ${token.name}`;
|
|
|
|
|
|
if (token.publicIdentifier) {
|
|
|
|
|
|
doctype += ` PUBLIC "${token.publicIdentifier}"`;
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
2023-12-13 11:23:54 +01:00
|
|
|
|
if (token.systemIdentifier) {
|
|
|
|
|
|
doctype += ` "${token.systemIdentifier}"`;
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
doctype += '>';
|
|
|
|
|
|
linkified.push(doctype);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return linkified.join('');
|
|
|
|
|
|
}
|
2023-12-13 11:23:54 +01:00
|
|
|
|
|
2021-05-28 16:46:29 +02:00
|
|
|
|
/**
|
|
|
|
|
|
`tokens` and `token` in this section referes to tokens returned by
|
|
|
|
|
|
`linkify.tokenize`. `linkified` will contain HTML Parser-style tokens
|
2023-12-13 11:23:54 +01:00
|
|
|
|
@param {string}
|
|
|
|
|
|
@param {import('linkifyjs').Options}
|
2021-05-28 16:46:29 +02:00
|
|
|
|
*/
|
2023-12-13 11:23:54 +01:00
|
|
|
|
function linkifyChars(str, options) {
|
|
|
|
|
|
const tokens = tokenize$1(str);
|
|
|
|
|
|
const result = [];
|
|
|
|
|
|
for (let i = 0; i < tokens.length; i++) {
|
|
|
|
|
|
const token = tokens[i];
|
|
|
|
|
|
if (token.t === 'nl' && options.get('nl2br')) {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
result.push({
|
|
|
|
|
|
type: StartTag,
|
|
|
|
|
|
tagName: 'br',
|
|
|
|
|
|
attributes: [],
|
|
|
|
|
|
selfClosing: true
|
|
|
|
|
|
});
|
2023-12-13 11:23:54 +01:00
|
|
|
|
} else if (!token.isLink || !options.check(token)) {
|
2021-05-28 16:46:29 +02:00
|
|
|
|
result.push({
|
|
|
|
|
|
type: Chars,
|
|
|
|
|
|
chars: token.toString()
|
|
|
|
|
|
});
|
2023-12-13 11:23:54 +01:00
|
|
|
|
} else {
|
|
|
|
|
|
result.push({
|
|
|
|
|
|
type: LinkifyResult,
|
|
|
|
|
|
rendered: options.render(token)
|
|
|
|
|
|
});
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
2023-12-13 11:23:54 +01:00
|
|
|
|
|
2021-05-28 16:46:29 +02:00
|
|
|
|
/**
|
|
|
|
|
|
Returns a list of tokens skipped until the closing tag of tagName.
|
|
|
|
|
|
|
|
|
|
|
|
* `tagName` is the closing tag which will prompt us to stop skipping
|
|
|
|
|
|
* `tokens` is the array of tokens generated by HTML5Tokenizer which
|
|
|
|
|
|
* `i` is the index immediately after the opening tag to skip
|
|
|
|
|
|
* `skippedTokens` is an array which skipped tokens are being pushed into
|
|
|
|
|
|
|
|
|
|
|
|
Caveats
|
|
|
|
|
|
|
|
|
|
|
|
* Assumes that i is the first token after the given opening tagName
|
|
|
|
|
|
* The closing tag will be skipped, but nothing after it
|
|
|
|
|
|
* Will track whether there is a nested tag of the same type
|
|
|
|
|
|
*/
|
|
|
|
|
|
function skipTagTokens(tagName, tokens, i, skippedTokens) {
|
|
|
|
|
|
// number of tokens of this type on the [fictional] stack
|
2023-12-13 11:23:54 +01:00
|
|
|
|
let stackCount = 1;
|
2021-05-28 16:46:29 +02:00
|
|
|
|
while (i < tokens.length && stackCount > 0) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
let token = tokens[i];
|
2021-05-28 16:46:29 +02:00
|
|
|
|
if (token.type === StartTag && token.tagName.toUpperCase() === tagName) {
|
|
|
|
|
|
// Nested tag of the same type, "add to stack"
|
|
|
|
|
|
stackCount++;
|
|
|
|
|
|
} else if (token.type === EndTag && token.tagName.toUpperCase() === tagName) {
|
|
|
|
|
|
// Closing tag
|
|
|
|
|
|
stackCount--;
|
|
|
|
|
|
}
|
|
|
|
|
|
skippedTokens.push(token);
|
|
|
|
|
|
i++;
|
2023-12-13 11:23:54 +01:00
|
|
|
|
}
|
2021-05-28 16:46:29 +02:00
|
|
|
|
|
2023-12-13 11:23:54 +01:00
|
|
|
|
// Note that if stackCount > 0 here, the HTML is probably invalid
|
2021-05-28 16:46:29 +02:00
|
|
|
|
return skippedTokens;
|
|
|
|
|
|
}
|
2025-05-07 10:40:03 +02:00
|
|
|
|
function defaultRender({
|
|
|
|
|
|
tagName,
|
|
|
|
|
|
attributes,
|
|
|
|
|
|
content
|
|
|
|
|
|
}) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
return `<${tagName} ${attributesToString(attributes)}>${escapeText(content)}</${tagName}>`;
|
|
|
|
|
|
}
|
2021-05-28 16:46:29 +02:00
|
|
|
|
function escapeText(text) {
|
2023-12-13 11:23:54 +01:00
|
|
|
|
return text.replace(/</g, '<').replace(/>/g, '>');
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
function escapeAttr(attr) {
|
|
|
|
|
|
return attr.replace(/"/g, '"');
|
|
|
|
|
|
}
|
2023-12-13 11:23:54 +01:00
|
|
|
|
function attributesToString(attributes) {
|
|
|
|
|
|
const result = [];
|
|
|
|
|
|
for (const attr in attributes) {
|
|
|
|
|
|
const val = attributes[attr] + '';
|
|
|
|
|
|
result.push(`${attr}="${escapeAttr(val)}"`);
|
|
|
|
|
|
}
|
|
|
|
|
|
return result.join(' ');
|
|
|
|
|
|
}
|
|
|
|
|
|
function attributeArrayToStrings(attrs) {
|
|
|
|
|
|
const attrStrs = [];
|
|
|
|
|
|
for (let i = 0; i < attrs.length; i++) {
|
|
|
|
|
|
const name = attrs[i][0];
|
|
|
|
|
|
const value = attrs[i][1] + '';
|
|
|
|
|
|
attrStrs.push(`${name}="${escapeAttr(value)}"`);
|
2021-05-28 16:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
return attrStrs;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-01-19 15:17:38 +01:00
|
|
|
|
export { linkifyHtml as default };
|