bbcode-compiler 0.1.9 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/index.d.ts +1 -16
  2. package/dist/index.js +866 -1038
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.umd.cjs +914 -1063
  5. package/dist/index.umd.cjs.map +1 -1
  6. package/dist/src/generateHtml.d.ts +2 -0
  7. package/dist/src/generateHtml.d.ts.map +1 -0
  8. package/dist/{generator → src/generator}/Generator.d.ts +2 -3
  9. package/dist/src/generator/Generator.d.ts.map +1 -0
  10. package/dist/{generator → src/generator}/transforms/Transform.d.ts +1 -2
  11. package/dist/src/generator/transforms/Transform.d.ts.map +1 -0
  12. package/dist/src/generator/transforms/htmlTransforms.d.ts +3 -0
  13. package/dist/src/generator/transforms/htmlTransforms.d.ts.map +1 -0
  14. package/dist/{generator → src/generator}/utils/getTagImmediateAttrVal.d.ts +1 -2
  15. package/dist/src/generator/utils/getTagImmediateAttrVal.d.ts.map +1 -0
  16. package/dist/{generator → src/generator}/utils/getTagImmediateText.d.ts +1 -2
  17. package/dist/src/generator/utils/getTagImmediateText.d.ts.map +1 -0
  18. package/dist/{generator → src/generator}/utils/getWidthHeightAttr.d.ts +1 -2
  19. package/dist/src/generator/utils/getWidthHeightAttr.d.ts.map +1 -0
  20. package/dist/src/generator/utils/isDangerousUrl.d.ts.map +1 -0
  21. package/dist/{generator → src/generator}/utils/isOrderedList.d.ts +1 -2
  22. package/dist/src/generator/utils/isOrderedList.d.ts.map +1 -0
  23. package/dist/src/index.d.ts +16 -0
  24. package/dist/src/index.d.ts.map +1 -0
  25. package/dist/{lexer → src/lexer}/Lexer.d.ts +1 -2
  26. package/dist/src/lexer/Lexer.d.ts.map +1 -0
  27. package/dist/{lexer → src/lexer}/Token.d.ts +1 -2
  28. package/dist/src/lexer/Token.d.ts.map +1 -0
  29. package/dist/src/lexer/TokenType.d.ts +5 -0
  30. package/dist/src/lexer/TokenType.d.ts.map +1 -0
  31. package/dist/{parser → src/parser}/AstNode.d.ts +10 -18
  32. package/dist/src/parser/AstNode.d.ts.map +1 -0
  33. package/dist/{parser → src/parser}/Parser.d.ts +3 -4
  34. package/dist/src/parser/Parser.d.ts.map +1 -0
  35. package/dist/src/parser/nodeIsType.d.ts +13 -0
  36. package/dist/src/parser/nodeIsType.d.ts.map +1 -0
  37. package/package.json +81 -82
  38. package/src/generateHtml.ts +4 -4
  39. package/src/generator/Generator.ts +7 -7
  40. package/src/generator/transforms/Transform.ts +1 -1
  41. package/src/generator/transforms/htmlTransforms.ts +6 -6
  42. package/src/generator/utils/getTagImmediateAttrVal.ts +1 -1
  43. package/src/generator/utils/getTagImmediateText.ts +4 -4
  44. package/src/generator/utils/getWidthHeightAttr.ts +1 -1
  45. package/src/generator/utils/isOrderedList.ts +1 -1
  46. package/src/index.ts +15 -15
  47. package/src/lexer/Lexer.ts +9 -9
  48. package/src/lexer/Token.ts +12 -12
  49. package/src/lexer/TokenType.ts +39 -40
  50. package/src/parser/AstNode.ts +30 -29
  51. package/src/parser/Parser.ts +28 -28
  52. package/src/parser/nodeIsType.ts +8 -8
  53. package/dist/generateHtml.d.ts +0 -2
  54. package/dist/generateHtml.d.ts.map +0 -1
  55. package/dist/generator/Generator.d.ts.map +0 -1
  56. package/dist/generator/transforms/Transform.d.ts.map +0 -1
  57. package/dist/generator/transforms/htmlTransforms.d.ts +0 -4
  58. package/dist/generator/transforms/htmlTransforms.d.ts.map +0 -1
  59. package/dist/generator/utils/getTagImmediateAttrVal.d.ts.map +0 -1
  60. package/dist/generator/utils/getTagImmediateText.d.ts.map +0 -1
  61. package/dist/generator/utils/getWidthHeightAttr.d.ts.map +0 -1
  62. package/dist/generator/utils/isDangerousUrl.d.ts.map +0 -1
  63. package/dist/generator/utils/isOrderedList.d.ts.map +0 -1
  64. package/dist/index.d.ts.map +0 -1
  65. package/dist/lexer/Lexer.d.ts.map +0 -1
  66. package/dist/lexer/Token.d.ts.map +0 -1
  67. package/dist/lexer/TokenType.d.ts +0 -17
  68. package/dist/lexer/TokenType.d.ts.map +0 -1
  69. package/dist/parser/AstNode.d.ts.map +0 -1
  70. package/dist/parser/Parser.d.ts.map +0 -1
  71. package/dist/parser/nodeIsType.d.ts +0 -14
  72. package/dist/parser/nodeIsType.d.ts.map +0 -1
  73. /package/dist/{generator → src/generator}/utils/isDangerousUrl.d.ts +0 -0
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/parser/nodeIsType.ts","../src/parser/AstNode.ts","../src/generator/utils/getTagImmediateAttrVal.ts","../src/generator/utils/getTagImmediateText.ts","../src/generator/utils/getWidthHeightAttr.ts","../src/generator/utils/isDangerousUrl.ts","../src/generator/utils/isOrderedList.ts","../src/generator/transforms/htmlTransforms.ts","../src/generator/Generator.ts","../src/lexer/TokenType.ts","../src/lexer/Lexer.ts","../src/lexer/Token.ts","../src/parser/Parser.ts","../src/generateHtml.ts"],"sourcesContent":["import { AstNodeType, AstNode, AttrNode, RootNode, TagNode, TextNode, LinebreakNode, EndTagNode, StartTagNode } from './AstNode.js'\n\ntype AstMap = {\n [AstNodeType.RootNode]: RootNode\n [AstNodeType.LinebreakNode]: LinebreakNode\n [AstNodeType.TextNode]: TextNode\n [AstNodeType.TagNode]: TagNode\n [AstNodeType.StartTagNode]: StartTagNode\n [AstNodeType.EndTagNode]: EndTagNode\n [AstNodeType.AttrNode]: AttrNode\n}\n\nexport function nodeIsType<T extends keyof AstMap>(node: AstNode, nodeType: T): node is AstMap[T] {\n return node.nodeType === nodeType\n}\n","/**\n\nHaven't formally verified this grammar but it should be LL(2)\n\nThe root's intermediate state has StartTag/EndTag because it's easier to first parse them as independant nodes\nthan to parse a StartTag and find the matching EndTag since we can only lookahead by 1 token\n\nTrying to lookahead by 4 tokens after each advancement to determine the end of the sub-root will greatly affect performance\n 1 \"[\"\n 2 \"/\"\n 3 \"LABEL\"\n 4 \"]\"\n\n---\n\nRoot <- (Text | Linebreak | Tag)*\n\nText <-\n| {XSS Characters}.\n| STR.\n\nLinebreak <-\n| LINEBREAK.\n\nTag <- StartTag Root EndTag\nStartTag <- L_BRACKET Text Attr* R_BRACKET\nEndTag <- L_BRACKET BACKSLASH Text R_BRACKET\n\nAttr <-\n| STR EQUALS STR\n| EQUALS STR\n| STR\n\n*/\n\nimport { nodeIsType } from './nodeIsType.js'\n\n// ----------------------------------------------------------------------------\n// MARK: AstNode\n// ----------------------------------------------------------------------------\n\nexport const enum AstNodeType {\n RootNode = 'RootNode',\n TextNode = 'TextNode',\n LinebreakNode = 'LinebreakNode',\n TagNode = 'TagNode',\n StartTagNode = 'StartTagNode',\n EndTagNode = 'EndTagNode',\n AttrNode = 'AttrNode',\n}\n\nexport type AstNodeJson = {\n type: AstNodeType\n data?: Record<string, string | AstNodeJson>\n children?: Array<AstNodeJson>\n}\n\nexport abstract class AstNode {\n readonly abstract nodeType: AstNodeType\n\n constructor(\n readonly children: Array<AstNode> = [],\n ) {\n // nop\n }\n\n addChild(node: AstNode): void {\n this.children.push(node)\n }\n\n isValid(): boolean {\n for (const child of this.children) {\n if (!child.isValid()) {\n return false\n }\n }\n\n return true\n }\n\n toShortString(): string {\n return this.nodeType\n }\n\n // For debugging purposes only\n // Pretty-prints AST\n toString(depth = 0): string {\n let s = ' '.repeat(depth * 2) + this.toShortString()\n\n for (const child of this.children) {\n s += '\\n' + child.toString(depth + 1)\n }\n\n return s\n }\n\n toJSON(): AstNodeJson {\n const json: AstNodeJson = {\n type: this.nodeType,\n }\n\n if (this.children.length > 0) {\n json.children = this.children.map((child) => child.toJSON())\n }\n\n return json\n }\n}\n\n// ----------------------------------------------------------------------------\n// MARK: Root\n// ----------------------------------------------------------------------------\n\nexport class RootNode extends AstNode {\n readonly nodeType = AstNodeType.RootNode\n\n override isValid(): boolean {\n for (const child of this.children) {\n if (child.nodeType !== AstNodeType.TagNode &&\n child.nodeType !== AstNodeType.TextNode &&\n child.nodeType !== AstNodeType.LinebreakNode) {\n return false\n }\n }\n\n return super.isValid() && this.children.length > 0\n }\n}\n\n// ----------------------------------------------------------------------------\n// MARK: Text\n// ----------------------------------------------------------------------------\n\nexport class TextNode extends AstNode {\n readonly nodeType = AstNodeType.TextNode\n readonly str: string\n\n constructor(str: string) {\n super()\n this.str = str\n }\n\n override isValid(): boolean {\n return super.isValid() && this.children.length === 0\n }\n\n override toShortString(): string {\n return `${super.toShortString()} \"${this.str}\"`\n }\n\n override toJSON(): AstNodeJson {\n const json = super.toJSON()\n\n json.data = {\n str: this.str,\n }\n\n return json\n }\n}\n\nexport class LinebreakNode extends AstNode {\n readonly nodeType = AstNodeType.LinebreakNode\n\n override toShortString(): string {\n return `${super.toShortString()} \"\\\\n\"`\n }\n}\n\n// ----------------------------------------------------------------------------\n// MARK: Attr\n// ----------------------------------------------------------------------------\n\nexport class AttrNode extends AstNode {\n readonly nodeType = AstNodeType.AttrNode\n\n static readonly DEFAULT_KEY = 'default'\n\n get key(): string {\n switch (this.children.length) {\n case 1: {\n return AttrNode.DEFAULT_KEY\n }\n case 2: {\n if (!nodeIsType(this.children[0], AstNodeType.TextNode)) {\n throw new Error('Invalid TextNode')\n }\n\n return this.children[0].str.trim()\n }\n }\n\n throw new Error('Invalid AttrNode')\n }\n\n get val(): string {\n switch (this.children.length) {\n case 1: {\n if (!nodeIsType(this.children[0], AstNodeType.TextNode)) {\n throw new Error('Invalid TextNode')\n }\n\n return this.children[0].str.trim()\n }\n case 2: {\n if (!nodeIsType(this.children[1], AstNodeType.TextNode)) {\n throw new Error('Invalid TextNode')\n }\n\n return this.children[1].str.trim()\n }\n }\n\n throw new Error('Invalid AttrNode')\n }\n\n override isValid(): boolean {\n return super.isValid() && (this.children.length >= 1 && this.children.length <= 2)\n }\n\n override toShortString(): string {\n let s = super.toShortString()\n\n switch (this.children.length) {\n case 1: {\n s += ` VAL=\"${this.val}\"`\n break\n }\n case 2: {\n s += ` KEY=\"${this.key}\" VAL=\"${this.val}\"`\n break\n }\n }\n\n return s\n }\n\n override toJSON(): AstNodeJson {\n const json: AstNodeJson = {\n type: this.nodeType,\n }\n\n switch (this.children.length) {\n case 1: {\n json.data = {\n key: this.key,\n }\n break\n }\n case 2: {\n json.data = {\n key: this.key,\n val: this.val,\n }\n break\n }\n }\n\n return json\n }\n}\n\n// ----------------------------------------------------------------------------\n// MARK: Tag\n// ----------------------------------------------------------------------------\n\nexport class StartTagNode extends AstNode {\n readonly nodeType = AstNodeType.StartTagNode\n readonly tagName: string\n readonly ogTag: string\n\n constructor(tagName: string, ogTag: string, attrNodes: Array<AttrNode> = []) {\n super(attrNodes)\n this.tagName = tagName.toLowerCase()\n this.ogTag = ogTag\n }\n\n override isValid(): boolean {\n for (const child of this.children) {\n if (child.nodeType !== AstNodeType.AttrNode) {\n return false\n }\n }\n\n return super.isValid()\n }\n\n override toShortString(): string {\n return `${super.toShortString()} ${this.ogTag}`\n }\n\n override toJSON(): AstNodeJson {\n const json = super.toJSON()\n\n json.data = {\n tag: this.tagName,\n }\n\n return json\n }\n}\n\nexport class EndTagNode extends AstNode {\n readonly nodeType = AstNodeType.EndTagNode\n readonly tagName: string\n readonly ogTag: string\n\n constructor(tagName: string, ogTag: string) {\n super()\n this.tagName = tagName\n this.ogTag = ogTag\n }\n\n override isValid(): boolean {\n return super.isValid() && this.children.length === 0\n }\n\n override toShortString(): string {\n return `${super.toShortString()} ${this.ogTag}`\n }\n\n override toJSON(): AstNodeJson {\n const json = super.toJSON()\n\n json.data = {\n tag: this.tagName,\n }\n\n return json\n }\n}\n\nexport class TagNode extends AstNode {\n readonly nodeType = AstNodeType.TagNode\n private readonly _startTag: StartTagNode\n private readonly _endTag?: EndTagNode | LinebreakNode\n\n constructor(startTag: StartTagNode, endTag?: EndTagNode | LinebreakNode) {\n super()\n this._startTag = startTag\n this._endTag = endTag\n }\n\n get tagName(): string {\n return this._startTag.tagName\n }\n\n get attributes(): Array<AttrNode> {\n return this._startTag.children as Array<AttrNode>\n }\n\n get ogStartTag(): string {\n return this._startTag.ogTag\n }\n\n get ogEndTag(): string {\n if (!this._endTag) {\n return ''\n }\n\n if (nodeIsType(this._endTag, AstNodeType.LinebreakNode)) {\n return '\\n'\n } else {\n return this._endTag.ogTag\n }\n }\n\n override isValid(): boolean {\n if (this._endTag && nodeIsType(this._endTag, AstNodeType.EndTagNode) && this._startTag.tagName !== this._endTag.tagName) {\n return false\n }\n\n if (this.children.length === 1 && this.children[0].nodeType !== AstNodeType.RootNode) {\n return false\n }\n\n if (this.children.length > 2) {\n return false\n }\n\n return super.isValid() && this._startTag.isValid() && (this._endTag?.isValid() ?? true)\n }\n\n override toString(depth = 0): string {\n let s = ' '.repeat(depth * 2) + this.toShortString() + ` [${this.tagName}]`\n\n for (const attrNode of this._startTag.children) {\n s += '\\n' + attrNode.toString(depth + 1)\n }\n\n for (const child of this.children) {\n s += '\\n' + child.toString(depth + 1)\n }\n\n return s\n }\n\n override toJSON(): AstNodeJson {\n const json = super.toJSON()\n\n json.data = {\n startTag: this._startTag.toJSON(),\n }\n\n if (this._endTag) {\n json.data.endTag = this._endTag.toJSON()\n }\n\n return json\n }\n}\n","import type { TagNode } from '../../parser/AstNode.js'\n\n/**\n * Gets the text of the immediate attribute of the current TagNode\n *\n * [url=https://en.wikipedia.org]English Wikipedia[/url]\n *\n * TagNode [url]\n * AttrNode VAL=\"https://en.wikipedia.org\" (returns this string)\n * TextNode \"https://en.wikipedia.org\"\n * RootNode\n * TextNode \"English Wikipedia\"\n */\nexport function getTagImmediateAttrVal(tagNode: TagNode): string | undefined {\n if (tagNode.attributes.length !== 1) {\n return undefined\n }\n\n const attrNode = tagNode.attributes[0]\n return attrNode.val\n}\n","import { AstNodeType, TagNode } from '../../parser/AstNode.js'\nimport { nodeIsType } from '../../parser/nodeIsType.js'\n\n/**\n * Gets the text of the immediate descendant of the current TagNode\n *\n * [url]https://en.wikipedia.org[/url]\n *\n * TagNode [url]\n * RootNode\n * TextNode \"https://en.wikipedia.org\" (returns this string)\n */\nexport function getTagImmediateText(tagNode: TagNode): string | undefined {\n if (tagNode.children.length !== 1) {\n return undefined\n }\n\n const child = tagNode.children[0]\n if (!nodeIsType(child, AstNodeType.RootNode)) {\n return undefined\n }\n\n if (child.children.length !== 1) {\n return undefined\n }\n\n const textNode = child.children[0]\n if (!nodeIsType(textNode, AstNodeType.TextNode)) {\n return undefined\n }\n\n return textNode.str\n}\n","import type { TagNode } from '../../parser/AstNode.js'\n\n/**\n * Gets the width/height attributes of the TagNode if they exist\n *\n * [img 500x300]https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png[/img]\n *\n * RootNode\n * TagNode [img] (returns width:500, height:300)\n * AttrNode VAL=\"500x300\"\n * TextNode \" 500x300\"\n * RootNode\n * TextNode \"https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png\"\n *\n * [img width=500 height=300]https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png[/img]\n *\n * RootNode\n * TagNode [img] (returns width:500, height:300)\n * AttrNode KEY=\"width\" VAL=\"500\"\n * TextNode \" width\"\n * TextNode \"500\"\n * AttrNode KEY=\"height\" VAL=\"300\"\n * TextNode \" height\"\n * TextNode \"300\"\n * RootNode\n * TextNode \"https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png\n */\nexport function getWidthHeightAttr(tagNode: TagNode): { width?: string; height?: string } {\n let width: string | undefined\n let height: string | undefined\n\n for (const child of tagNode.attributes) {\n if (child.key === 'width') {\n width = child.val\n }\n if (child.key === 'height') {\n height = child.val\n }\n\n const matches = /(\\d+)x(\\d+)/.exec(child.val)\n if (matches) {\n width = matches[1]\n height = matches[2]\n }\n }\n\n return {\n width,\n height,\n }\n}\n","const dangerousUriRe = /^(vbscript|javascript|file|data):/\nconst safeDataUriRe = /^data:image\\/(gif|png|jpeg|webp);/\n\nexport function isDangerousUrl(url: string): boolean {\n const normalizedUrl = url.trim().toLowerCase()\n\n if (!dangerousUriRe.test(normalizedUrl)) {\n return false\n }\n\n // Only a subset of data uris are considered safe\n if (safeDataUriRe.test(normalizedUrl)) {\n return false\n }\n\n return true\n}\n","import type { TagNode } from '../../parser/AstNode.js'\n\n/**\n * Determines if the StartTag has an attribute of \"1\" to indicate that it's an ordered list\n *\n * [list=1]\n *\n * TagNode [list]\n * AttrNode VAL=\"1\"\n * TextNode \"1\"\n * RootNode\n * TagNode [*]\n * RootNode\n * TextNode \"Entry 1\"\n * TagNode [*]\n * RootNode\n * TextNode \"Entry 2\"\n */\nexport function isOrderedList(node: TagNode): boolean {\n for (const child of node.attributes) {\n const val = child.val\n if (val === '1') {\n return true\n }\n }\n\n return false\n}\n","import { getTagImmediateAttrVal } from '../utils/getTagImmediateAttrVal.js'\nimport { getTagImmediateText } from '../utils/getTagImmediateText.js'\nimport { getWidthHeightAttr } from '../utils/getWidthHeightAttr.js'\nimport { isDangerousUrl } from '../utils/isDangerousUrl.js'\nimport { isOrderedList } from '../utils/isOrderedList.js'\nimport type { Transform } from './Transform.js'\n\nexport const htmlTransforms: ReadonlyArray<Transform> = [\n {\n name: 'b',\n start: () => {\n return '<strong>'\n },\n end: () => {\n return '</strong>'\n },\n },\n {\n name: 'i',\n start: () => {\n return '<em>'\n },\n end: () => {\n return '</em>'\n },\n },\n {\n name: 'u',\n start: () => {\n return '<ins>'\n },\n end: () => {\n return '</ins>'\n },\n },\n {\n name: 's',\n start: () => {\n return '<del>'\n },\n end: () => {\n return '</del>'\n },\n },\n {\n name: 'style',\n start: (tagNode) => {\n let style = ''\n\n for (const child of tagNode.attributes) {\n switch (child.key) {\n case 'color': {\n style += `color:${child.val};`\n continue\n }\n case 'size': {\n if (/^\\d+$/.test(child.val)) {\n style += `font-size:${child.val}%;` // When no units provided (i.e. just a number), then assume %\n } else {\n style += `font-size:${child.val};`\n }\n continue\n }\n }\n }\n\n return `<span style=\"${style}\">`\n },\n end: () => {\n return '</span>'\n },\n },\n {\n name: 'color',\n start: (tagNode) => {\n const color = getTagImmediateAttrVal(tagNode)\n return `<span style=\"color:${color};\">`\n },\n end: () => {\n return '</span>'\n },\n },\n {\n name: 'hr',\n isStandalone: true,\n start: () => {\n return '<hr />'\n },\n },\n {\n name: 'br',\n isStandalone: true,\n start: () => {\n return '<br />'\n },\n },\n {\n name: 'list',\n start: (tagNode) => {\n return isOrderedList(tagNode)\n ? '<ol>'\n : '<ul>'\n },\n end: (tagNode) => {\n return isOrderedList(tagNode)\n ? '</ol>'\n : '</ul>'\n },\n },\n {\n name: '*',\n isLinebreakTerminated: true,\n start: () => {\n return '<li>'\n },\n end: () => {\n return '</li>'\n },\n },\n {\n name: 'img',\n skipChildren: true,\n start: (tagNode) => {\n const src = getTagImmediateText(tagNode)\n if (!src) {\n return false\n }\n\n if (isDangerousUrl(src)) {\n return false\n }\n\n const { width, height } = getWidthHeightAttr(tagNode)\n\n let str = `<img src=\"${src}\"`\n if (width) {\n str += ` width=\"${width}\"`\n }\n if (height) {\n str += ` height=\"${height}\"`\n }\n str += '>'\n return str\n },\n },\n {\n name: 'url',\n start: (tagNode) => {\n const href = getTagImmediateAttrVal(tagNode) ?? getTagImmediateText(tagNode)\n if (!href) {\n return false\n }\n\n if (isDangerousUrl(href)) {\n return false\n }\n\n return `<a href=\"${href}\">`\n },\n end: () => {\n return '</a>'\n },\n },\n {\n name: 'quote',\n start: (tagNode) => {\n const author = getTagImmediateAttrVal(tagNode)\n return author\n ? `<blockquote><strong>${author}</strong>`\n : '<blockquote>'\n },\n end: () => {\n return '</blockquote>'\n },\n },\n {\n name: 'table',\n start: () => {\n return '<table>'\n },\n end: () => {\n return '</table>'\n },\n },\n {\n name: 'tr',\n start: () => {\n return '<tr>'\n },\n end: () => {\n return '</tr>'\n },\n },\n {\n name: 'td',\n start: () => {\n return '<td>'\n },\n end: () => {\n return '</td>'\n },\n },\n {\n name: 'code',\n start: () => {\n return '<code>'\n },\n end: () => {\n return '</code>'\n },\n },\n]\n","import { AstNode, AstNodeType, RootNode } from '../parser/AstNode.js'\nimport { nodeIsType } from '../parser/nodeIsType.js'\nimport { htmlTransforms } from './transforms/htmlTransforms.js'\nimport type { Transform } from './transforms/Transform.js'\n\nexport class Generator {\n transforms: ReadonlyMap<string, Transform>\n\n constructor(transforms = htmlTransforms) {\n this.transforms = new Map(transforms.map((transform) => [transform.name, transform]))\n }\n\n generate(root: RootNode): string {\n const stringify = (node: AstNode): string => {\n let output = ''\n\n if (nodeIsType(node, AstNodeType.TagNode)) {\n const tagName = node.tagName\n const transform = this.transforms.get(tagName)\n if (!transform) {\n throw new Error(`Unrecognized bbcode ${node.tagName}`)\n }\n\n const renderedStartTag = transform.start(node)\n const renderedEndTag = transform.end?.(node) ?? ''\n const isInvalidTag = renderedStartTag === false\n\n if (isInvalidTag) {\n output += node.ogStartTag\n } else {\n output += renderedStartTag\n }\n\n if (!transform.skipChildren || isInvalidTag) {\n for (const child of node.children) {\n output += stringify(child)\n }\n }\n\n if (isInvalidTag) {\n output += node.ogEndTag\n } else {\n output += renderedEndTag\n }\n } else if (nodeIsType(node, AstNodeType.TextNode)) {\n output += node.str\n } else if (nodeIsType(node, AstNodeType.LinebreakNode)) {\n output += '\\n'\n } else {\n for (const child of node.children) {\n output += stringify(child)\n }\n }\n\n return output\n }\n\n return stringify(root)\n }\n}\n","export const enum TokenType {\n STR,\n LINEBREAK,\n\n // BBCode symbols\n L_BRACKET,\n R_BRACKET,\n BACKSLASH,\n EQUALS,\n\n // XSS symbols\n XSS_AMP,\n XSS_LT,\n XSS_GT,\n XSS_D_QUOTE,\n XSS_S_QUOTE,\n}\n\nexport function tokenTypeToString(tokenType: TokenType): string {\n switch (tokenType) {\n case TokenType.STR: return 'STR'\n case TokenType.LINEBREAK: return 'LINEBREAK'\n\n case TokenType.L_BRACKET: return 'L_BRACKET'\n case TokenType.R_BRACKET: return 'R_BRACKET'\n case TokenType.BACKSLASH: return 'BACKSLASH'\n case TokenType.EQUALS: return 'EQUALS'\n\n case TokenType.XSS_AMP: return 'XSS_AMP'\n case TokenType.XSS_LT: return 'XSS_LT'\n case TokenType.XSS_GT: return 'XSS_GT'\n case TokenType.XSS_D_QUOTE: return 'XSS_D_QUOTE'\n case TokenType.XSS_S_QUOTE: return 'XSS_S_QUOTE'\n }\n}\n\nexport function isStringToken(tokenType: TokenType): boolean {\n switch (tokenType) {\n case TokenType.XSS_AMP:\n case TokenType.XSS_LT:\n case TokenType.XSS_GT:\n case TokenType.XSS_D_QUOTE:\n case TokenType.XSS_S_QUOTE:\n case TokenType.STR: {\n return true\n }\n }\n\n return false\n}\n\nexport const symbolTable: Record<string, TokenType | undefined> = {\n '\\n': TokenType.LINEBREAK,\n\n '[': TokenType.L_BRACKET,\n ']': TokenType.R_BRACKET,\n '/': TokenType.BACKSLASH,\n '=': TokenType.EQUALS,\n\n '&': TokenType.XSS_AMP,\n '<': TokenType.XSS_LT,\n '>': TokenType.XSS_GT,\n '\"': TokenType.XSS_D_QUOTE,\n \"'\": TokenType.XSS_S_QUOTE,\n}\n","import { symbolTable, TokenType } from './TokenType.js'\nimport type { Token } from './Token.js'\n\nexport class Lexer {\n tokenize(input: Readonly<string>): Array<Token> {\n const tokens = new Array<Token>()\n\n const re = /\\n|\\[\\/|\\[(\\w+|\\*)|\\]|=|&|<|>|'|\"/g\n let offset = 0\n\n while (true) {\n // Match until next symbol\n const match = re.exec(input)\n if (!match) {\n break\n }\n\n // Everything between previous symbol and current symbol is treated as plaintext\n //\n // [...]plaintext[/...]\n // | |\n // offset match.index\n // (new) offset\n //\n const length = match.index - offset\n if (length > 0) {\n tokens.push({\n type: TokenType.STR,\n offset,\n length,\n })\n }\n\n offset = match.index\n\n // Only add BACKSLASH token if it's preceded by L_BRACKET\n // In the regex '[/' takes precedence over '['\n if (match[0] === '[/') {\n tokens.push({\n type: TokenType.L_BRACKET,\n offset,\n length: 1,\n })\n offset += 1\n\n tokens.push({\n type: TokenType.BACKSLASH,\n offset,\n length: 1,\n })\n offset += 1\n } else if (match[0].startsWith('[')) {\n tokens.push({\n type: TokenType.L_BRACKET,\n offset,\n length: 1,\n })\n offset += 1\n\n const length = match[0].length - 1\n tokens.push({\n type: TokenType.STR,\n offset,\n length,\n })\n offset += length\n } else {\n tokens.push({\n type: symbolTable[match[0]] ?? TokenType.STR,\n offset,\n length: 1,\n })\n offset += 1\n }\n }\n\n // Add any leftover non-symbol text\n const length = input.length - offset\n if (length > 0) {\n tokens.push({\n type: TokenType.STR,\n offset,\n length,\n })\n }\n\n return tokens\n }\n}\n","import { TokenType } from './TokenType.js'\n\nexport type Token = {\n type: TokenType\n offset: number\n length: number\n}\n\nexport function stringifyTokens(ogText: string, tokens: ReadonlyArray<Token>): string {\n let s = ''\n\n for (const token of tokens) {\n switch (token.type) {\n case TokenType.STR: {\n s += ogText.substring(token.offset, token.offset + token.length)\n break\n }\n case TokenType.LINEBREAK: {\n s += '\\n'\n break\n }\n\n case TokenType.L_BRACKET: {\n s += '['\n break\n }\n case TokenType.R_BRACKET: {\n s += ']'\n break\n }\n case TokenType.BACKSLASH: {\n s += '/'\n break\n }\n case TokenType.EQUALS: {\n s += '='\n break\n }\n\n case TokenType.XSS_AMP: {\n s += '&amp;'\n break\n }\n case TokenType.XSS_LT: {\n s += '&lt;'\n break\n }\n case TokenType.XSS_GT: {\n s += '&gt;'\n break\n }\n case TokenType.XSS_D_QUOTE: {\n s += '&quot;'\n break\n }\n case TokenType.XSS_S_QUOTE: {\n s += '&#x27;'\n break\n }\n }\n }\n\n return s\n}\n","import { htmlTransforms } from '../generator/transforms/htmlTransforms.js'\nimport { stringifyTokens, Token } from '../lexer/Token.js'\nimport { isStringToken, TokenType } from '../lexer/TokenType.js'\nimport { RootNode, AttrNode, TextNode, LinebreakNode, StartTagNode, EndTagNode, AstNodeType, TagNode, AstNode } from './AstNode.js'\nimport { nodeIsType } from './nodeIsType.js'\n\nexport class Parser {\n readonly tags: Set<string>\n readonly linebreakTerminatedTags: Set<string>\n readonly standaloneTags: Set<string>\n\n constructor(transforms = htmlTransforms) {\n this.tags = new Set(transforms.map((transform) => transform.name))\n this.linebreakTerminatedTags = new Set(transforms.filter((transform) => transform.isLinebreakTerminated).map((transform) => transform.name.toLowerCase()))\n this.standaloneTags = new Set(transforms.filter((transform) => transform.isStandalone).map((transform) => transform.name.toLowerCase()))\n }\n\n parse(ogText: string, tokens: Array<Token>): RootNode {\n let idx = 0\n\n const parseLabel = (): string => {\n const slice = tokens.slice(idx, idx + 1)\n const label = stringifyTokens(ogText, slice)\n idx += 1 // Consume LABEL\n return label.toLowerCase()\n }\n\n const parseText = (endOnQuotes = false, endOnSpace = false): TextNode => {\n const startIdx = idx\n\n while (idx < tokens.length) {\n if (!isStringToken(tokens[idx].type)) {\n break\n }\n\n if (endOnQuotes && (tokens[idx].type === TokenType.XSS_S_QUOTE || tokens[idx].type === TokenType.XSS_D_QUOTE)) {\n break\n }\n\n /**\n * SPECIAL CASE:\n * If we encounter a space, then we must split the current token into 2 tokens and only consume the first part\n *\n * a b -> a b\n * | | |\n * | | idx (new)\n * | |\n * idx consumed\n *\n * Note: We only handle endOnSpace special case when we don't expect the current text to endOnQuotes\n * If it endOnQuotes, then it implies that it opened with quotes (and thus we need an enclosing/matching quote)\n */\n if (endOnSpace && !endOnQuotes) {\n const origStr = stringifyTokens(ogText, [tokens[idx]])\n const spaceIdx = origStr.indexOf(' ')\n\n if (spaceIdx >= 0) {\n const oldToken: Token = {\n type: TokenType.STR,\n offset: tokens[idx].offset,\n length: spaceIdx,\n }\n\n const newToken: Token = {\n type: TokenType.STR,\n offset: tokens[idx].offset + spaceIdx,\n length: tokens[idx].length - spaceIdx,\n }\n\n tokens.splice(idx + 0, 1, oldToken)\n tokens.splice(idx + 1, 0, newToken)\n idx += 1\n break\n }\n }\n\n idx += 1\n }\n\n const slice = tokens.slice(startIdx, idx)\n const str = stringifyTokens(ogText, slice)\n\n return new TextNode(str)\n }\n\n const parseAttr = (): AttrNode | null => {\n if (idx + 1 >= tokens.length) {\n return null\n }\n\n const attrNode = new AttrNode()\n\n if (tokens[idx].type === TokenType.EQUALS && isStringToken(tokens[idx + 1].type)) { // [Tag = VAL ...] or [Tag = \"VAL\"]\n idx += 1 // Consume EQUALS\n\n const openedWithQuotes = tokens[idx].type === TokenType.XSS_S_QUOTE || tokens[idx].type === TokenType.XSS_D_QUOTE\n if (openedWithQuotes) {\n idx += 1\n }\n\n const valNode = parseText(openedWithQuotes, true)\n attrNode.addChild(valNode)\n\n if (openedWithQuotes) {\n if (tokens[idx].type !== TokenType.XSS_S_QUOTE && tokens[idx].type !== TokenType.XSS_D_QUOTE) {\n return null\n }\n\n idx += 1\n }\n } else if (isStringToken(tokens[idx].type) && tokens[idx + 1].type === TokenType.EQUALS && (idx + 2 < tokens.length && isStringToken(tokens[idx + 2].type))) { // [Tag KEY = VAL ...] or [Tag KEY = \"VAL\" ...]\n const keyNode = parseText()\n attrNode.addChild(keyNode)\n\n idx += 1 // Consume EQUALS\n\n const openedWithQuotes = tokens[idx].type === TokenType.XSS_S_QUOTE || tokens[idx].type === TokenType.XSS_D_QUOTE\n if (openedWithQuotes) {\n idx += 1\n }\n\n const valNode = parseText(openedWithQuotes, true)\n\n if (openedWithQuotes) {\n if (tokens[idx].type !== TokenType.XSS_S_QUOTE && tokens[idx].type !== TokenType.XSS_D_QUOTE) {\n return null\n }\n\n idx += 1\n }\n\n attrNode.addChild(valNode)\n } else if (isStringToken(tokens[idx].type) && tokens[idx + 1].type !== TokenType.EQUALS) { // [Tag VAL ...]\n const valNode = parseText()\n attrNode.addChild(valNode)\n } else {\n return null\n }\n\n return attrNode\n }\n\n const parseTag = (): StartTagNode | EndTagNode | null => {\n if (idx + 1 >= tokens.length) {\n return null\n }\n\n if (tokens[idx].type !== TokenType.L_BRACKET) {\n return null\n }\n\n // If L_BRACKET is followed by text, then it must be StartTag or is invalid\n if (isStringToken(tokens[idx + 1].type)) {\n const startIdx = idx\n idx += 1 // Consume L_BRACKET\n\n const labelText = parseLabel()\n if (!this.tags.has(labelText)) {\n return null\n }\n\n const attrNodes = new Array<AttrNode>()\n while (true) {\n const attrNode = parseAttr()\n if (attrNode === null) {\n break\n }\n\n attrNodes.push(attrNode)\n }\n\n if (tokens[idx].type !== TokenType.R_BRACKET) {\n return null\n }\n\n idx += 1 // Consume R_BRACKET\n\n const slice = tokens.slice(startIdx, idx)\n const ogTag = stringifyTokens(ogText, slice)\n const startTagNode = new StartTagNode(labelText, ogTag, attrNodes)\n return startTagNode\n }\n\n // If L_BRACKET is followed by BACKSLASH, then it must be EndTag or is invalid\n if (tokens[idx + 1].type === TokenType.BACKSLASH) {\n const startIdx = idx\n idx += 1 // Consume L_BRACKET\n idx += 1 // Consume BACKSLASH\n\n const labelText = parseLabel()\n if (!this.tags.has(labelText)) {\n return null\n }\n\n if (tokens[idx].type !== TokenType.R_BRACKET) {\n return null\n }\n\n idx += 1 // Consume R_BRACKET\n\n const slice = tokens.slice(startIdx, idx)\n const ogTag = stringifyTokens(ogText, slice)\n const endTagNode = new EndTagNode(labelText, ogTag)\n return endTagNode\n }\n\n return null\n }\n\n const parseRoot = (): RootNode => {\n const root = new RootNode()\n\n while (idx < tokens.length) {\n if (tokens[idx].type === TokenType.L_BRACKET) {\n const startIdx = idx\n const tagNode = parseTag()\n\n if (tagNode !== null) {\n root.addChild(tagNode)\n } else {\n const invalidTokens = tokens.slice(startIdx, idx)\n const str = stringifyTokens(ogText, invalidTokens)\n const textNode = new TextNode(str)\n root.addChild(textNode)\n }\n } else if (tokens[idx].type === TokenType.LINEBREAK) {\n idx += 1 // Consume LINEBREAK\n root.addChild(new LinebreakNode())\n } else {\n const startIdx = idx\n\n // Advance until we see the start of another RootNode's child (TagNode or LinebreakNode)\n while (idx < tokens.length && tokens[idx].type !== TokenType.L_BRACKET && tokens[idx].type !== TokenType.LINEBREAK) {\n idx += 1\n }\n\n const slice = tokens.slice(startIdx, idx)\n const str = stringifyTokens(ogText, slice)\n root.addChild(new TextNode(str))\n }\n }\n\n return root\n }\n\n let root = parseRoot()\n root = this.matchTagNodes(root)\n return root\n }\n\n // ------------------------------------------------------------------------\n // Post Parsing Transforms\n // ------------------------------------------------------------------------\n\n private matchTagNodes(rootNode: RootNode): RootNode {\n const transformedRoot = new RootNode()\n\n for (let i = 0; i < rootNode.children.length; i++) {\n const child = rootNode.children[i]\n\n if (nodeIsType(child, AstNodeType.StartTagNode)) {\n const endTag = this.findMatchingEndTag(rootNode.children, i, child.tagName)\n const isStandalone = this.standaloneTags.has(child.tagName)\n\n if (endTag || isStandalone) {\n const tagNode = new TagNode(child, endTag?.node)\n transformedRoot.addChild(tagNode)\n\n // If matching end tag exists, consume all nodes between start/end (exclusive) as a subtree\n if (endTag) {\n const subRoot = new RootNode(rootNode.children.slice(i + 1, endTag.idx))\n i = endTag.idx\n\n const transformedSubRoot = this.matchTagNodes(subRoot)\n tagNode.addChild(transformedSubRoot)\n }\n } else {\n // If no end tag exists, then treat tag as string literal\n transformedRoot.addChild(new TextNode(child.ogTag))\n }\n } else if (nodeIsType(child, AstNodeType.EndTagNode)) {\n // Encountered end tag when we're not expecting an end tag so we treat it as a string literal\n transformedRoot.addChild(new TextNode(child.ogTag))\n } else if (nodeIsType(child, AstNodeType.TextNode)) {\n // Normal text nodes get copied\n transformedRoot.addChild(child)\n } else if (nodeIsType(child, AstNodeType.LinebreakNode)) {\n // Linebreak nodes get copied\n transformedRoot.addChild(child)\n } else {\n throw new Error('Unexpected child of RootNode')\n }\n }\n\n return transformedRoot\n }\n\n private findMatchingEndTag(siblings: Array<AstNode>, startIdx: number, tagName: string): { idx: number; node: EndTagNode | LinebreakNode } | null {\n if (this.standaloneTags.has(tagName)) {\n return null\n }\n\n for (let i = startIdx; i < siblings.length; i++) {\n const sibling = siblings[i]\n const isEndTag =\n (nodeIsType(sibling, AstNodeType.LinebreakNode) && this.linebreakTerminatedTags.has(tagName)) ||\n (nodeIsType(sibling, AstNodeType.EndTagNode) && sibling.tagName === tagName)\n\n if (isEndTag) {\n return {\n idx: i,\n node: sibling,\n }\n }\n }\n\n return null\n }\n}\n","import { Generator } from './generator/Generator.js'\nimport { htmlTransforms } from './generator/transforms/htmlTransforms.js'\nimport { Lexer } from './lexer/Lexer.js'\nimport { Parser } from './parser/Parser.js'\n\nexport function generateHtml(input: string, transforms = htmlTransforms): string {\n const lexer = new Lexer()\n const tokens = lexer.tokenize(input)\n\n const parser = new Parser(transforms)\n const root = parser.parse(input, tokens)\n\n const generator = new Generator(transforms)\n return generator.generate(root)\n}\n"],"names":["AstNodeType","TokenType","length","root"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/parser/nodeIsType.ts","../src/parser/AstNode.ts","../src/generator/utils/getTagImmediateAttrVal.ts","../src/generator/utils/getTagImmediateText.ts","../src/generator/utils/getWidthHeightAttr.ts","../src/generator/utils/isDangerousUrl.ts","../src/generator/utils/isOrderedList.ts","../src/generator/transforms/htmlTransforms.ts","../src/generator/Generator.ts","../src/lexer/TokenType.ts","../src/lexer/Lexer.ts","../src/lexer/Token.ts","../src/parser/Parser.ts","../src/generateHtml.ts"],"sourcesContent":["import type { AstNode, AttrNode, RootNode, TagNode, TextNode, LinebreakNode, EndTagNode, StartTagNode } from './AstNode.ts'\n\ntype AstMap = {\n ['RootNode']: RootNode\n ['LinebreakNode']: LinebreakNode\n ['TextNode']: TextNode\n ['TagNode']: TagNode\n ['StartTagNode']: StartTagNode\n ['EndTagNode']: EndTagNode\n ['AttrNode']: AttrNode\n}\n\nexport function nodeIsType<T extends keyof AstMap>(node: AstNode, nodeType: T): node is AstMap[T] {\n return node.nodeType === nodeType\n}\n","/**\n\nHaven't formally verified this grammar but it should be LL(2)\n\nThe root's intermediate state has StartTag/EndTag because it's easier to first parse them as independant nodes\nthan to parse a StartTag and find the matching EndTag since we can only lookahead by 1 token\n\nTrying to lookahead by 4 tokens after each advancement to determine the end of the sub-root will greatly affect performance\n 1 \"[\"\n 2 \"/\"\n 3 \"LABEL\"\n 4 \"]\"\n\n---\n\nRoot <- (Text | Linebreak | Tag)*\n\nText <-\n| {XSS Characters}.\n| STR.\n\nLinebreak <-\n| LINEBREAK.\n\nTag <- StartTag Root EndTag\nStartTag <- L_BRACKET Text Attr* R_BRACKET\nEndTag <- L_BRACKET BACKSLASH Text R_BRACKET\n\nAttr <-\n| STR EQUALS STR\n| EQUALS STR\n| STR\n\n*/\n\nimport { nodeIsType } from './nodeIsType.ts'\n\n// ----------------------------------------------------------------------------\n// MARK: AstNode\n// ----------------------------------------------------------------------------\n\nexport type AstNodeType =\n | 'RootNode'\n | 'TextNode'\n | 'LinebreakNode'\n | 'TagNode'\n | 'StartTagNode'\n | 'EndTagNode'\n | 'AttrNode'\n\nexport type AstNodeJson = {\n type: AstNodeType\n data?: Record<string, string | AstNodeJson>\n children?: Array<AstNodeJson>\n}\n\nexport abstract class AstNode {\n readonly abstract nodeType: AstNodeType\n\n readonly children: Array<AstNode>\n\n constructor(\n children = new Array<AstNode>(),\n ) {\n this.children = children\n }\n\n addChild(node: AstNode): void {\n this.children.push(node)\n }\n\n isValid(): boolean {\n for (const child of this.children) {\n if (!child.isValid()) {\n return false\n }\n }\n\n return true\n }\n\n toShortString(): string {\n return this.nodeType\n }\n\n // For debugging purposes only\n // Pretty-prints AST\n toString(depth = 0): string {\n let s = ' '.repeat(depth * 2) + this.toShortString()\n\n for (const child of this.children) {\n s += '\\n' + child.toString(depth + 1)\n }\n\n return s\n }\n\n toJSON(): AstNodeJson {\n const json: AstNodeJson = {\n type: this.nodeType,\n }\n\n if (this.children.length > 0) {\n json.children = this.children.map((child) => child.toJSON())\n }\n\n return json\n }\n}\n\n// ----------------------------------------------------------------------------\n// MARK: Root\n// ----------------------------------------------------------------------------\n\nexport class RootNode extends AstNode {\n readonly nodeType = 'RootNode'\n\n override isValid(): boolean {\n for (const child of this.children) {\n if (child.nodeType !== 'TagNode' &&\n child.nodeType !== 'TextNode' &&\n child.nodeType !== 'LinebreakNode') {\n return false\n }\n }\n\n return super.isValid() && this.children.length > 0\n }\n}\n\n// ----------------------------------------------------------------------------\n// MARK: Text\n// ----------------------------------------------------------------------------\n\nexport class TextNode extends AstNode {\n readonly nodeType = 'TextNode'\n readonly str: string\n\n constructor(str: string) {\n super()\n this.str = str\n }\n\n override isValid(): boolean {\n return super.isValid() && this.children.length === 0\n }\n\n override toShortString(): string {\n return `${super.toShortString()} \"${this.str}\"`\n }\n\n override toJSON(): AstNodeJson {\n const json = super.toJSON()\n\n json.data = {\n str: this.str,\n }\n\n return json\n }\n}\n\nexport class LinebreakNode extends AstNode {\n readonly nodeType = 'LinebreakNode'\n\n override toShortString(): string {\n return `${super.toShortString()} \"\\\\n\"`\n }\n}\n\n// ----------------------------------------------------------------------------\n// MARK: Attr\n// ----------------------------------------------------------------------------\n\nexport class AttrNode extends AstNode {\n readonly nodeType = 'AttrNode'\n\n static readonly DEFAULT_KEY = 'default'\n\n get key(): string {\n switch (this.children.length) {\n case 1: {\n return AttrNode.DEFAULT_KEY\n }\n case 2: {\n if (!nodeIsType(this.children[0], 'TextNode')) {\n throw new Error('Invalid TextNode')\n }\n\n return this.children[0].str.trim()\n }\n }\n\n throw new Error('Invalid AttrNode')\n }\n\n get val(): string {\n switch (this.children.length) {\n case 1: {\n if (!nodeIsType(this.children[0], 'TextNode')) {\n throw new Error('Invalid TextNode')\n }\n\n return this.children[0].str.trim()\n }\n case 2: {\n if (!nodeIsType(this.children[1], 'TextNode')) {\n throw new Error('Invalid TextNode')\n }\n\n return this.children[1].str.trim()\n }\n }\n\n throw new Error('Invalid AttrNode')\n }\n\n override isValid(): boolean {\n return super.isValid() && (this.children.length >= 1 && this.children.length <= 2)\n }\n\n override toShortString(): string {\n let s = super.toShortString()\n\n switch (this.children.length) {\n case 1: {\n s += ` VAL=\"${this.val}\"`\n break\n }\n case 2: {\n s += ` KEY=\"${this.key}\" VAL=\"${this.val}\"`\n break\n }\n }\n\n return s\n }\n\n override toJSON(): AstNodeJson {\n const json: AstNodeJson = {\n type: this.nodeType,\n }\n\n switch (this.children.length) {\n case 1: {\n json.data = {\n key: this.key,\n }\n break\n }\n case 2: {\n json.data = {\n key: this.key,\n val: this.val,\n }\n break\n }\n }\n\n return json\n }\n}\n\n// ----------------------------------------------------------------------------\n// MARK: Tag\n// ----------------------------------------------------------------------------\n\nexport class StartTagNode extends AstNode {\n readonly nodeType = 'StartTagNode'\n readonly tagName: string\n readonly ogTag: string\n\n constructor(tagName: string, ogTag: string, attrNodes: Array<AttrNode> = []) {\n super(attrNodes)\n this.tagName = tagName.toLowerCase()\n this.ogTag = ogTag\n }\n\n override isValid(): boolean {\n for (const child of this.children) {\n if (child.nodeType !== 'AttrNode') {\n return false\n }\n }\n\n return super.isValid()\n }\n\n override toShortString(): string {\n return `${super.toShortString()} ${this.ogTag}`\n }\n\n override toJSON(): AstNodeJson {\n const json = super.toJSON()\n\n json.data = {\n tag: this.tagName,\n }\n\n return json\n }\n}\n\nexport class EndTagNode extends AstNode {\n readonly nodeType = 'EndTagNode'\n readonly tagName: string\n readonly ogTag: string\n\n constructor(tagName: string, ogTag: string) {\n super()\n this.tagName = tagName\n this.ogTag = ogTag\n }\n\n override isValid(): boolean {\n return super.isValid() && this.children.length === 0\n }\n\n override toShortString(): string {\n return `${super.toShortString()} ${this.ogTag}`\n }\n\n override toJSON(): AstNodeJson {\n const json = super.toJSON()\n\n json.data = {\n tag: this.tagName,\n }\n\n return json\n }\n}\n\nexport class TagNode extends AstNode {\n readonly nodeType = 'TagNode'\n private readonly _startTag: StartTagNode\n private readonly _endTag?: EndTagNode | LinebreakNode\n\n constructor(startTag: StartTagNode, endTag?: EndTagNode | LinebreakNode) {\n super()\n this._startTag = startTag\n this._endTag = endTag\n }\n\n get tagName(): string {\n return this._startTag.tagName\n }\n\n get attributes(): Array<AttrNode> {\n return this._startTag.children as Array<AttrNode>\n }\n\n get ogStartTag(): string {\n return this._startTag.ogTag\n }\n\n get ogEndTag(): string {\n if (!this._endTag) {\n return ''\n }\n\n if (nodeIsType(this._endTag, 'LinebreakNode')) {\n return '\\n'\n } else {\n return this._endTag.ogTag\n }\n }\n\n override isValid(): boolean {\n if (this._endTag && nodeIsType(this._endTag, 'EndTagNode') && this._startTag.tagName !== this._endTag.tagName) {\n return false\n }\n\n if (this.children.length === 1 && this.children[0].nodeType !== 'RootNode') {\n return false\n }\n\n if (this.children.length > 2) {\n return false\n }\n\n return super.isValid() && this._startTag.isValid() && (this._endTag?.isValid() ?? true)\n }\n\n override toString(depth = 0): string {\n let s = ' '.repeat(depth * 2) + this.toShortString() + ` [${this.tagName}]`\n\n for (const attrNode of this._startTag.children) {\n s += '\\n' + attrNode.toString(depth + 1)\n }\n\n for (const child of this.children) {\n s += '\\n' + child.toString(depth + 1)\n }\n\n return s\n }\n\n override toJSON(): AstNodeJson {\n const json = super.toJSON()\n\n json.data = {\n startTag: this._startTag.toJSON(),\n }\n\n if (this._endTag) {\n json.data.endTag = this._endTag.toJSON()\n }\n\n return json\n }\n}\n","import type { TagNode } from '../../parser/AstNode.ts'\n\n/**\n * Gets the text of the immediate attribute of the current TagNode\n *\n * [url=https://en.wikipedia.org]English Wikipedia[/url]\n *\n * TagNode [url]\n * AttrNode VAL=\"https://en.wikipedia.org\" (returns this string)\n * TextNode \"https://en.wikipedia.org\"\n * RootNode\n * TextNode \"English Wikipedia\"\n */\nexport function getTagImmediateAttrVal(tagNode: TagNode): string | undefined {\n if (tagNode.attributes.length !== 1) {\n return undefined\n }\n\n const attrNode = tagNode.attributes[0]\n return attrNode.val\n}\n","import { TagNode } from '../../parser/AstNode.ts'\nimport { nodeIsType } from '../../parser/nodeIsType.ts'\n\n/**\n * Gets the text of the immediate descendant of the current TagNode\n *\n * [url]https://en.wikipedia.org[/url]\n *\n * TagNode [url]\n * RootNode\n * TextNode \"https://en.wikipedia.org\" (returns this string)\n */\nexport function getTagImmediateText(tagNode: TagNode): string | undefined {\n if (tagNode.children.length !== 1) {\n return undefined\n }\n\n const child = tagNode.children[0]\n if (!nodeIsType(child, 'RootNode')) {\n return undefined\n }\n\n if (child.children.length !== 1) {\n return undefined\n }\n\n const textNode = child.children[0]\n if (!nodeIsType(textNode, 'TextNode')) {\n return undefined\n }\n\n return textNode.str\n}\n","import type { TagNode } from '../../parser/AstNode.ts'\n\n/**\n * Gets the width/height attributes of the TagNode if they exist\n *\n * [img 500x300]https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png[/img]\n *\n * RootNode\n * TagNode [img] (returns width:500, height:300)\n * AttrNode VAL=\"500x300\"\n * TextNode \" 500x300\"\n * RootNode\n * TextNode \"https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png\"\n *\n * [img width=500 height=300]https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png[/img]\n *\n * RootNode\n * TagNode [img] (returns width:500, height:300)\n * AttrNode KEY=\"width\" VAL=\"500\"\n * TextNode \" width\"\n * TextNode \"500\"\n * AttrNode KEY=\"height\" VAL=\"300\"\n * TextNode \" height\"\n * TextNode \"300\"\n * RootNode\n * TextNode \"https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png\n */\nexport function getWidthHeightAttr(tagNode: TagNode): { width?: string; height?: string } {\n let width: string | undefined\n let height: string | undefined\n\n for (const child of tagNode.attributes) {\n if (child.key === 'width') {\n width = child.val\n }\n if (child.key === 'height') {\n height = child.val\n }\n\n const matches = /(\\d+)x(\\d+)/.exec(child.val)\n if (matches) {\n width = matches[1]\n height = matches[2]\n }\n }\n\n return {\n width,\n height,\n }\n}\n","const dangerousUriRe = /^(vbscript|javascript|file|data):/\nconst safeDataUriRe = /^data:image\\/(gif|png|jpeg|webp);/\n\nexport function isDangerousUrl(url: string): boolean {\n const normalizedUrl = url.trim().toLowerCase()\n\n if (!dangerousUriRe.test(normalizedUrl)) {\n return false\n }\n\n // Only a subset of data uris are considered safe\n if (safeDataUriRe.test(normalizedUrl)) {\n return false\n }\n\n return true\n}\n","import type { TagNode } from '../../parser/AstNode.ts'\n\n/**\n * Determines if the StartTag has an attribute of \"1\" to indicate that it's an ordered list\n *\n * [list=1]\n *\n * TagNode [list]\n * AttrNode VAL=\"1\"\n * TextNode \"1\"\n * RootNode\n * TagNode [*]\n * RootNode\n * TextNode \"Entry 1\"\n * TagNode [*]\n * RootNode\n * TextNode \"Entry 2\"\n */\nexport function isOrderedList(node: TagNode): boolean {\n for (const child of node.attributes) {\n const val = child.val\n if (val === '1') {\n return true\n }\n }\n\n return false\n}\n","import { getTagImmediateAttrVal } from '../utils/getTagImmediateAttrVal.ts'\nimport { getTagImmediateText } from '../utils/getTagImmediateText.ts'\nimport { getWidthHeightAttr } from '../utils/getWidthHeightAttr.ts'\nimport { isDangerousUrl } from '../utils/isDangerousUrl.ts'\nimport { isOrderedList } from '../utils/isOrderedList.ts'\nimport type { Transform } from './Transform.ts'\n\nexport const htmlTransforms: ReadonlyArray<Transform> = [\n {\n name: 'b',\n start: () => {\n return '<strong>'\n },\n end: () => {\n return '</strong>'\n },\n },\n {\n name: 'i',\n start: () => {\n return '<em>'\n },\n end: () => {\n return '</em>'\n },\n },\n {\n name: 'u',\n start: () => {\n return '<ins>'\n },\n end: () => {\n return '</ins>'\n },\n },\n {\n name: 's',\n start: () => {\n return '<del>'\n },\n end: () => {\n return '</del>'\n },\n },\n {\n name: 'style',\n start: (tagNode) => {\n let style = ''\n\n for (const child of tagNode.attributes) {\n switch (child.key) {\n case 'color': {\n style += `color:${child.val};`\n continue\n }\n case 'size': {\n if (/^\\d+$/.test(child.val)) {\n style += `font-size:${child.val}%;` // When no units provided (i.e. just a number), then assume %\n } else {\n style += `font-size:${child.val};`\n }\n continue\n }\n }\n }\n\n return `<span style=\"${style}\">`\n },\n end: () => {\n return '</span>'\n },\n },\n {\n name: 'color',\n start: (tagNode) => {\n const color = getTagImmediateAttrVal(tagNode)\n return `<span style=\"color:${color};\">`\n },\n end: () => {\n return '</span>'\n },\n },\n {\n name: 'hr',\n isStandalone: true,\n start: () => {\n return '<hr />'\n },\n },\n {\n name: 'br',\n isStandalone: true,\n start: () => {\n return '<br />'\n },\n },\n {\n name: 'list',\n start: (tagNode) => {\n return isOrderedList(tagNode)\n ? '<ol>'\n : '<ul>'\n },\n end: (tagNode) => {\n return isOrderedList(tagNode)\n ? '</ol>'\n : '</ul>'\n },\n },\n {\n name: '*',\n isLinebreakTerminated: true,\n start: () => {\n return '<li>'\n },\n end: () => {\n return '</li>'\n },\n },\n {\n name: 'img',\n skipChildren: true,\n start: (tagNode) => {\n const src = getTagImmediateText(tagNode)\n if (!src) {\n return false\n }\n\n if (isDangerousUrl(src)) {\n return false\n }\n\n const { width, height } = getWidthHeightAttr(tagNode)\n\n let str = `<img src=\"${src}\"`\n if (width) {\n str += ` width=\"${width}\"`\n }\n if (height) {\n str += ` height=\"${height}\"`\n }\n str += '>'\n return str\n },\n },\n {\n name: 'url',\n start: (tagNode) => {\n const href = getTagImmediateAttrVal(tagNode) ?? getTagImmediateText(tagNode)\n if (!href) {\n return false\n }\n\n if (isDangerousUrl(href)) {\n return false\n }\n\n return `<a href=\"${href}\">`\n },\n end: () => {\n return '</a>'\n },\n },\n {\n name: 'quote',\n start: (tagNode) => {\n const author = getTagImmediateAttrVal(tagNode)\n return author\n ? `<blockquote><strong>${author}</strong>`\n : '<blockquote>'\n },\n end: () => {\n return '</blockquote>'\n },\n },\n {\n name: 'table',\n start: () => {\n return '<table>'\n },\n end: () => {\n return '</table>'\n },\n },\n {\n name: 'tr',\n start: () => {\n return '<tr>'\n },\n end: () => {\n return '</tr>'\n },\n },\n {\n name: 'td',\n start: () => {\n return '<td>'\n },\n end: () => {\n return '</td>'\n },\n },\n {\n name: 'code',\n start: () => {\n return '<code>'\n },\n end: () => {\n return '</code>'\n },\n },\n]\n","import { AstNode, RootNode } from '../parser/AstNode.ts'\nimport { nodeIsType } from '../parser/nodeIsType.ts'\nimport { htmlTransforms } from './transforms/htmlTransforms.ts'\nimport type { Transform } from './transforms/Transform.ts'\n\nexport class Generator {\n transforms: ReadonlyMap<string, Transform>\n\n constructor(transforms = htmlTransforms) {\n this.transforms = new Map(transforms.map((transform) => [transform.name, transform]))\n }\n\n generate(root: RootNode): string {\n const stringify = (node: AstNode): string => {\n let output = ''\n\n if (nodeIsType(node, 'TagNode')) {\n const tagName = node.tagName\n const transform = this.transforms.get(tagName)\n if (!transform) {\n throw new Error(`Unrecognized bbcode ${node.tagName}`)\n }\n\n const renderedStartTag = transform.start(node)\n const renderedEndTag = transform.end?.(node) ?? ''\n const isInvalidTag = renderedStartTag === false\n\n if (isInvalidTag) {\n output += node.ogStartTag\n } else {\n output += renderedStartTag\n }\n\n if (!transform.skipChildren || isInvalidTag) {\n for (const child of node.children) {\n output += stringify(child)\n }\n }\n\n if (isInvalidTag) {\n output += node.ogEndTag\n } else {\n output += renderedEndTag\n }\n } else if (nodeIsType(node, 'TextNode')) {\n output += node.str\n } else if (nodeIsType(node, 'LinebreakNode')) {\n output += '\\n'\n } else {\n for (const child of node.children) {\n output += stringify(child)\n }\n }\n\n return output\n }\n\n return stringify(root)\n }\n}\n","export type TokenType =\n | 'STR'\n | 'LINEBREAK'\n\n // BBCode symbols\n | 'L_BRACKET'\n | 'R_BRACKET'\n | 'BACKSLASH'\n | 'EQUALS'\n\n // XSS symbols\n | 'XSS_AMP'\n | 'XSS_LT'\n | 'XSS_GT'\n | 'XSS_D_QUOTE'\n | 'XSS_S_QUOTE'\n\nexport function tokenTypeToString(tokenType: TokenType): string {\n switch (tokenType) {\n case 'STR': return 'STR'\n case 'LINEBREAK': return 'LINEBREAK'\n\n case 'L_BRACKET': return 'L_BRACKET'\n case 'R_BRACKET': return 'R_BRACKET'\n case 'BACKSLASH': return 'BACKSLASH'\n case 'EQUALS': return 'EQUALS'\n\n case 'XSS_AMP': return 'XSS_AMP'\n case 'XSS_LT': return 'XSS_LT'\n case 'XSS_GT': return 'XSS_GT'\n case 'XSS_D_QUOTE': return 'XSS_D_QUOTE'\n case 'XSS_S_QUOTE': return 'XSS_S_QUOTE'\n }\n}\n\nexport function isStringToken(tokenType: TokenType): boolean {\n switch (tokenType) {\n case 'XSS_AMP':\n case 'XSS_LT':\n case 'XSS_GT':\n case 'XSS_D_QUOTE':\n case 'XSS_S_QUOTE':\n case 'STR': {\n return true\n }\n }\n\n return false\n}\n\nexport const symbolTable: Record<string, TokenType | undefined> = {\n '\\n': 'LINEBREAK',\n\n '[': 'L_BRACKET',\n ']': 'R_BRACKET',\n '/': 'BACKSLASH',\n '=': 'EQUALS',\n\n '&': 'XSS_AMP',\n '<': 'XSS_LT',\n '>': 'XSS_GT',\n '\"': 'XSS_D_QUOTE',\n \"'\": 'XSS_S_QUOTE',\n}\n","import { symbolTable } from './TokenType.ts'\nimport type { Token } from './Token.ts'\n\nexport class Lexer {\n tokenize(input: Readonly<string>): Array<Token> {\n const tokens = new Array<Token>()\n\n const re = /\\n|\\[\\/|\\[(\\w+|\\*)|\\]|=|&|<|>|'|\"/g\n let offset = 0\n\n while (true) {\n // Match until next symbol\n const match = re.exec(input)\n if (!match) {\n break\n }\n\n // Everything between previous symbol and current symbol is treated as plaintext\n //\n // [...]plaintext[/...]\n // | |\n // offset match.index\n // (new) offset\n //\n const length = match.index - offset\n if (length > 0) {\n tokens.push({\n type: 'STR',\n offset,\n length,\n })\n }\n\n offset = match.index\n\n // Only add BACKSLASH token if it's preceded by L_BRACKET\n // In the regex '[/' takes precedence over '['\n if (match[0] === '[/') {\n tokens.push({\n type: 'L_BRACKET',\n offset,\n length: 1,\n })\n offset += 1\n\n tokens.push({\n type: 'BACKSLASH',\n offset,\n length: 1,\n })\n offset += 1\n } else if (match[0].startsWith('[')) {\n tokens.push({\n type: 'L_BRACKET',\n offset,\n length: 1,\n })\n offset += 1\n\n const length = match[0].length - 1\n tokens.push({\n type: 'STR',\n offset,\n length,\n })\n offset += length\n } else {\n tokens.push({\n type: symbolTable[match[0]] ?? 'STR',\n offset,\n length: 1,\n })\n offset += 1\n }\n }\n\n // Add any leftover non-symbol text\n const length = input.length - offset\n if (length > 0) {\n tokens.push({\n type: 'STR',\n offset,\n length,\n })\n }\n\n return tokens\n }\n}\n","import type { TokenType } from './TokenType.ts'\n\nexport type Token = {\n type: TokenType\n offset: number\n length: number\n}\n\nexport function stringifyTokens(ogText: string, tokens: ReadonlyArray<Token>): string {\n let s = ''\n\n for (const token of tokens) {\n switch (token.type) {\n case 'STR': {\n s += ogText.substring(token.offset, token.offset + token.length)\n break\n }\n case 'LINEBREAK': {\n s += '\\n'\n break\n }\n\n case 'L_BRACKET': {\n s += '['\n break\n }\n case 'R_BRACKET': {\n s += ']'\n break\n }\n case 'BACKSLASH': {\n s += '/'\n break\n }\n case 'EQUALS': {\n s += '='\n break\n }\n\n case 'XSS_AMP': {\n s += '&amp;'\n break\n }\n case 'XSS_LT': {\n s += '&lt;'\n break\n }\n case 'XSS_GT': {\n s += '&gt;'\n break\n }\n case 'XSS_D_QUOTE': {\n s += '&quot;'\n break\n }\n case 'XSS_S_QUOTE': {\n s += '&#x27;'\n break\n }\n }\n }\n\n return s\n}\n","import { htmlTransforms } from '../generator/transforms/htmlTransforms.ts'\nimport { stringifyTokens, type Token } from '../lexer/Token.ts'\nimport { isStringToken } from '../lexer/TokenType.ts'\nimport { RootNode, AttrNode, TextNode, LinebreakNode, StartTagNode, EndTagNode, TagNode, AstNode } from './AstNode.ts'\nimport { nodeIsType } from './nodeIsType.ts'\n\nexport class Parser {\n readonly tags: Set<string>\n readonly linebreakTerminatedTags: Set<string>\n readonly standaloneTags: Set<string>\n\n constructor(transforms = htmlTransforms) {\n this.tags = new Set(transforms.map((transform) => transform.name))\n this.linebreakTerminatedTags = new Set(transforms.filter((transform) => transform.isLinebreakTerminated).map((transform) => transform.name.toLowerCase()))\n this.standaloneTags = new Set(transforms.filter((transform) => transform.isStandalone).map((transform) => transform.name.toLowerCase()))\n }\n\n parse(ogText: string, tokens: Array<Token>): RootNode {\n let idx = 0\n\n const parseLabel = (): string => {\n const slice = tokens.slice(idx, idx + 1)\n const label = stringifyTokens(ogText, slice)\n idx += 1 // Consume LABEL\n return label.toLowerCase()\n }\n\n const parseText = (endOnQuotes = false, endOnSpace = false): TextNode => {\n const startIdx = idx\n\n while (idx < tokens.length) {\n if (!isStringToken(tokens[idx].type)) {\n break\n }\n\n if (endOnQuotes && (tokens[idx].type === 'XSS_S_QUOTE' || tokens[idx].type === 'XSS_D_QUOTE')) {\n break\n }\n\n /**\n * SPECIAL CASE:\n * If we encounter a space, then we must split the current token into 2 tokens and only consume the first part\n *\n * a b -> a b\n * | | |\n * | | idx (new)\n * | |\n * idx consumed\n *\n * Note: We only handle endOnSpace special case when we don't expect the current text to endOnQuotes\n * If it endOnQuotes, then it implies that it opened with quotes (and thus we need an enclosing/matching quote)\n */\n if (endOnSpace && !endOnQuotes) {\n const origStr = stringifyTokens(ogText, [tokens[idx]])\n const spaceIdx = origStr.indexOf(' ')\n\n if (spaceIdx >= 0) {\n const oldToken: Token = {\n type: 'STR',\n offset: tokens[idx].offset,\n length: spaceIdx,\n }\n\n const newToken: Token = {\n type: 'STR',\n offset: tokens[idx].offset + spaceIdx,\n length: tokens[idx].length - spaceIdx,\n }\n\n tokens.splice(idx + 0, 1, oldToken)\n tokens.splice(idx + 1, 0, newToken)\n idx += 1\n break\n }\n }\n\n idx += 1\n }\n\n const slice = tokens.slice(startIdx, idx)\n const str = stringifyTokens(ogText, slice)\n\n return new TextNode(str)\n }\n\n const parseAttr = (): AttrNode | null => {\n if (idx + 1 >= tokens.length) {\n return null\n }\n\n const attrNode = new AttrNode()\n\n if (tokens[idx].type === 'EQUALS' && isStringToken(tokens[idx + 1].type)) { // [Tag = VAL ...] or [Tag = \"VAL\"]\n idx += 1 // Consume EQUALS\n\n const openedWithQuotes = tokens[idx].type === 'XSS_S_QUOTE' || tokens[idx].type === 'XSS_D_QUOTE'\n if (openedWithQuotes) {\n idx += 1\n }\n\n const valNode = parseText(openedWithQuotes, true)\n attrNode.addChild(valNode)\n\n if (openedWithQuotes) {\n if (tokens[idx].type !== 'XSS_S_QUOTE' && tokens[idx].type !== 'XSS_D_QUOTE') {\n return null\n }\n\n idx += 1\n }\n } else if (isStringToken(tokens[idx].type) && tokens[idx + 1].type === 'EQUALS' && (idx + 2 < tokens.length && isStringToken(tokens[idx + 2].type))) { // [Tag KEY = VAL ...] or [Tag KEY = \"VAL\" ...]\n const keyNode = parseText()\n attrNode.addChild(keyNode)\n\n idx += 1 // Consume EQUALS\n\n const openedWithQuotes = tokens[idx].type === 'XSS_S_QUOTE' || tokens[idx].type === 'XSS_D_QUOTE'\n if (openedWithQuotes) {\n idx += 1\n }\n\n const valNode = parseText(openedWithQuotes, true)\n\n if (openedWithQuotes) {\n if (tokens[idx].type !== 'XSS_S_QUOTE' && tokens[idx].type !== 'XSS_D_QUOTE') {\n return null\n }\n\n idx += 1\n }\n\n attrNode.addChild(valNode)\n } else if (isStringToken(tokens[idx].type) && tokens[idx + 1].type !== 'EQUALS') { // [Tag VAL ...]\n const valNode = parseText()\n attrNode.addChild(valNode)\n } else {\n return null\n }\n\n return attrNode\n }\n\n const parseTag = (): StartTagNode | EndTagNode | null => {\n if (idx + 1 >= tokens.length) {\n return null\n }\n\n if (tokens[idx].type !== 'L_BRACKET') {\n return null\n }\n\n // If L_BRACKET is followed by text, then it must be StartTag or is invalid\n if (isStringToken(tokens[idx + 1].type)) {\n const startIdx = idx\n idx += 1 // Consume L_BRACKET\n\n const labelText = parseLabel()\n if (!this.tags.has(labelText)) {\n return null\n }\n\n const attrNodes = new Array<AttrNode>()\n while (true) {\n const attrNode = parseAttr()\n if (attrNode === null) {\n break\n }\n\n attrNodes.push(attrNode)\n }\n\n if (tokens[idx].type !== 'R_BRACKET') {\n return null\n }\n\n idx += 1 // Consume R_BRACKET\n\n const slice = tokens.slice(startIdx, idx)\n const ogTag = stringifyTokens(ogText, slice)\n const startTagNode = new StartTagNode(labelText, ogTag, attrNodes)\n return startTagNode\n }\n\n // If L_BRACKET is followed by BACKSLASH, then it must be EndTag or is invalid\n if (tokens[idx + 1].type === 'BACKSLASH') {\n const startIdx = idx\n idx += 1 // Consume L_BRACKET\n idx += 1 // Consume BACKSLASH\n\n const labelText = parseLabel()\n if (!this.tags.has(labelText)) {\n return null\n }\n\n if (tokens[idx].type !== 'R_BRACKET') {\n return null\n }\n\n idx += 1 // Consume R_BRACKET\n\n const slice = tokens.slice(startIdx, idx)\n const ogTag = stringifyTokens(ogText, slice)\n const endTagNode = new EndTagNode(labelText, ogTag)\n return endTagNode\n }\n\n return null\n }\n\n const parseRoot = (): RootNode => {\n const root = new RootNode()\n\n while (idx < tokens.length) {\n if (tokens[idx].type === 'L_BRACKET') {\n const startIdx = idx\n const tagNode = parseTag()\n\n if (tagNode !== null) {\n root.addChild(tagNode)\n } else {\n const invalidTokens = tokens.slice(startIdx, idx)\n const str = stringifyTokens(ogText, invalidTokens)\n const textNode = new TextNode(str)\n root.addChild(textNode)\n }\n } else if (tokens[idx].type === 'LINEBREAK') {\n idx += 1 // Consume LINEBREAK\n root.addChild(new LinebreakNode())\n } else {\n const startIdx = idx\n\n // Advance until we see the start of another RootNode's child (TagNode or LinebreakNode)\n while (idx < tokens.length && tokens[idx].type !== 'L_BRACKET' && tokens[idx].type !== 'LINEBREAK') {\n idx += 1\n }\n\n const slice = tokens.slice(startIdx, idx)\n const str = stringifyTokens(ogText, slice)\n root.addChild(new TextNode(str))\n }\n }\n\n return root\n }\n\n let root = parseRoot()\n root = this.matchTagNodes(root)\n return root\n }\n\n // ------------------------------------------------------------------------\n // Post Parsing Transforms\n // ------------------------------------------------------------------------\n\n private matchTagNodes(rootNode: RootNode): RootNode {\n const transformedRoot = new RootNode()\n\n for (let i = 0; i < rootNode.children.length; i++) {\n const child = rootNode.children[i]\n\n if (nodeIsType(child, 'StartTagNode')) {\n const endTag = this.findMatchingEndTag(rootNode.children, i, child.tagName)\n const isStandalone = this.standaloneTags.has(child.tagName)\n\n if (endTag || isStandalone) {\n const tagNode = new TagNode(child, endTag?.node)\n transformedRoot.addChild(tagNode)\n\n // If matching end tag exists, consume all nodes between start/end (exclusive) as a subtree\n if (endTag) {\n const subRoot = new RootNode(rootNode.children.slice(i + 1, endTag.idx))\n i = endTag.idx\n\n const transformedSubRoot = this.matchTagNodes(subRoot)\n tagNode.addChild(transformedSubRoot)\n }\n } else {\n // If no end tag exists, then treat tag as string literal\n transformedRoot.addChild(new TextNode(child.ogTag))\n }\n } else if (nodeIsType(child, 'EndTagNode')) {\n // Encountered end tag when we're not expecting an end tag so we treat it as a string literal\n transformedRoot.addChild(new TextNode(child.ogTag))\n } else if (nodeIsType(child, 'TextNode')) {\n // Normal text nodes get copied\n transformedRoot.addChild(child)\n } else if (nodeIsType(child, 'LinebreakNode')) {\n // Linebreak nodes get copied\n transformedRoot.addChild(child)\n } else {\n throw new Error('Unexpected child of RootNode')\n }\n }\n\n return transformedRoot\n }\n\n private findMatchingEndTag(siblings: Array<AstNode>, startIdx: number, tagName: string): { idx: number; node: EndTagNode | LinebreakNode } | null {\n if (this.standaloneTags.has(tagName)) {\n return null\n }\n\n for (let i = startIdx; i < siblings.length; i++) {\n const sibling = siblings[i]\n const isEndTag =\n (nodeIsType(sibling, 'LinebreakNode') && this.linebreakTerminatedTags.has(tagName)) ||\n (nodeIsType(sibling, 'EndTagNode') && sibling.tagName === tagName)\n\n if (isEndTag) {\n return {\n idx: i,\n node: sibling,\n }\n }\n }\n\n return null\n }\n}\n","import { Generator } from './generator/Generator.ts'\nimport { htmlTransforms } from './generator/transforms/htmlTransforms.ts'\nimport { Lexer } from './lexer/Lexer.ts'\nimport { Parser } from './parser/Parser.ts'\n\nexport function generateHtml(input: string, transforms = htmlTransforms): string {\n const lexer = new Lexer()\n const tokens = lexer.tokenize(input)\n\n const parser = new Parser(transforms)\n const root = parser.parse(input, tokens)\n\n const generator = new Generator(transforms)\n return generator.generate(root)\n}\n"],"mappings":"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"}