@panzer1119/bbcode-parser
Version:
BB code parser written in TypeScript.
164 lines • 6.41 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.Tokenizer = exports.asTextToken = exports.tagToken = exports.textToken = exports.Token = exports.TokenType = void 0;
var TokenType;
(function (TokenType) {
TokenType[TokenType["Text"] = 0] = "Text";
TokenType[TokenType["StartTag"] = 1] = "StartTag";
TokenType[TokenType["EndTag"] = 2] = "EndTag";
})(TokenType = exports.TokenType || (exports.TokenType = {}));
//Represents a token
var Token = /** @class */ (function () {
function Token(tokenType, content, tagAttributes, tagStr) {
this.tokenType = tokenType;
this.content = content;
this.tagAttributes = tagAttributes;
this.tagStr = tagStr;
}
//String representation of the token
Token.prototype.toString = function () {
return this.content + " (" + TokenType[this.tokenType] + ")";
};
//Check for equality
Token.prototype.equals = function (token) {
return this.tokenType == token.tokenType && this.content == token.content;
};
return Token;
}());
exports.Token = Token;
//Creates a new text token
function textToken(content) {
return new Token(TokenType.Text, content);
}
exports.textToken = textToken;
var attributeNameChars = "[a-zA-Z0-9\\.\\-_:;/]";
var attributeValueChars = "[a-zA-Z0-9\\.\\-_:;#/\\s]";
var tokenPattern = "\\[(\\/\\w*)\\]|\\[(\\w*)+(?:=(" + attributeValueChars + "*))?(?: (" + attributeNameChars + "+)=(" + attributeValueChars + "+))*\\]|\\[\\*\\] ?(['\\.,\\-:;#/\\w\\s]+)";
//Creates a new tag token
function tagToken(match) {
var _a;
if (match[1] == undefined) {
//Start tag
var tagName = match[2];
var attributes = {};
var attributePattern = new RegExp("(" + attributeNameChars + "+)?=(" + attributeValueChars + "+)", "g");
var attributeStr = match[0].substr(1 + tagName.length, match[0].length - 2 - tagName.length);
var attributeMatch = void 0;
while ((attributeMatch = attributePattern.exec(attributeStr))) {
var value = (_a = attributeMatch[2]) === null || _a === void 0 ? void 0 : _a.trim();
if (attributeMatch[1] == undefined) {
//The tag attribute
attributes[tagName] = value;
}
else {
//Normal attribute
attributes[attributeMatch[1]] = value;
}
}
return new Token(TokenType.StartTag, tagName, attributes, match[0]);
}
else {
//End tag
return new Token(TokenType.EndTag, match[1].substr(1, match[1].length - 1));
}
}
exports.tagToken = tagToken;
//Converts the given token to a text token
function asTextToken(token) {
var _a;
if (token.tokenType == TokenType.StartTag) {
token.content = (_a = token.tagStr) !== null && _a !== void 0 ? _a : "";
token.tokenType = TokenType.Text;
//delete token.attributes;
//delete token.tagStr;
}
if (token.tokenType == TokenType.EndTag) {
token.content = "[/" + token.content + "]";
token.tokenType = TokenType.Text;
}
}
exports.asTextToken = asTextToken;
//Represents a tokenizer
var Tokenizer = /** @class */ (function () {
//Creates a new tokenizer with the given tags
function Tokenizer(bbTags) {
this.bbTags = bbTags;
}
//Tokenizes the given string
Tokenizer.prototype.tokenizeString = function (str) {
var tokens = this.getTokens(str);
var newTokens = [];
var noNesting = false;
var noNestingTag = "";
var noNestedTagContent = "";
for (var i in tokens) {
var currentToken = tokens[i];
var bbTag = this.bbTags[currentToken.content];
var addTag = true;
//Replace invalid tags with text
if (bbTag === undefined && !noNesting) {
asTextToken(currentToken);
}
else {
//Check if current tag doesn't support nesting
if (noNesting) {
if (currentToken.tokenType == TokenType.EndTag && currentToken.content == noNestingTag) {
noNesting = false;
newTokens.push(textToken(noNestedTagContent));
}
else {
asTextToken(currentToken);
noNestedTagContent += currentToken.content;
addTag = false;
}
}
else {
if (bbTag.noNesting && currentToken.tokenType == TokenType.StartTag) {
noNesting = true;
noNestingTag = currentToken.content;
noNestedTagContent = "";
}
}
}
if (addTag) {
newTokens.push(currentToken);
}
}
return newTokens;
};
//Gets the tokens from the given string
Tokenizer.prototype.getTokens = function (str) {
var tagPattern = new RegExp(tokenPattern, "g");
var tokens = [];
var match;
var lastIndex = 0;
while ((match = tagPattern.exec(str))) {
var deltaInner = match.index - lastIndex;
if (deltaInner > 0) {
tokens.push(textToken(str.substr(lastIndex, deltaInner)));
}
if (match[6]) {
//Is [*] List Item
var tokenStart = new Token(TokenType.StartTag, "*", {}, "[*]");
var tokenText = textToken(match[6]);
var tokenEnd = new Token(TokenType.EndTag, "*");
tokens.push(tokenStart);
tokens.push(tokenText);
tokens.push(tokenEnd);
}
else {
var token = tagToken(match);
tokens.push(token);
}
lastIndex = tagPattern.lastIndex;
}
var delta = str.length - lastIndex;
if (delta > 0) {
tokens.push(textToken(str.substr(lastIndex, delta)));
}
return tokens;
};
return Tokenizer;
}());
exports.Tokenizer = Tokenizer;
//# sourceMappingURL=tokenizer.js.map
;