@nfrasser/simple-html-tokenizer
Version:
Simple HTML Tokenizer is a lightweight JavaScript library that can be used to tokenize the kind of HTML normally found in templates.
1 lines • 81.1 kB
Source Map (JSON)
{"version":3,"sources":["../../tests/tokenizer-tests.ts","src/entity-parser.lint-test.js","src/evented-tokenizer.lint-test.js","src/generated/html5-named-char-refs.lint-test.js","src/generated/tokenizer-states.lint-test.js","src/index.lint-test.js","entity-parser.ts","evented-tokenizer.ts","html5-named-char-refs.ts","index.ts","tokenize.ts","tokenizer.ts","utils.ts","src/tokenize.lint-test.js","src/tokenizer.lint-test.js","src/types.lint-test.js","src/utils.lint-test.js","tests/tokenizer-tests.lint-test.js"],"sourcesContent":["import {\n tokenize,\n EventedTokenizer,\n TokenizerDelegate,\n EntityParser,\n Doctype,\n StartTag,\n EndTag,\n Comment,\n Chars,\n Token,\n TokenType,\n Attribute\n} from 'simple-html-tokenizer';\n\nQUnit.module('simple-html-tokenizer - tokenizer');\n\nQUnit.test('does not fail if delegate does not include doctype methods', function(assert) {\n let steps: Array<string[]> = [];\n\n class MissingDoctypeTokenizerDelegate implements TokenizerDelegate {\n reset() {\n steps.push(['reset']);\n }\n finishData() {\n steps.push(['finishData']);\n }\n tagOpen() {\n steps.push(['tagOpen']);\n }\n\n beginData() {\n steps.push(['beginData']);\n }\n\n appendToData(char: string) {\n steps.push(['appendToData', char]);\n }\n\n beginStartTag() {\n steps.push(['beginStartTag']);\n }\n appendToTagName(char: string) {\n steps.push(['appendToTagName', char]);\n }\n\n beginAttribute() {\n steps.push(['beginAttribute']);\n }\n appendToAttributeName(char: string) {\n steps.push(['appendToAttributeName', char]);\n }\n beginAttributeValue(quoted: boolean) {\n steps.push(['beginAttributeValue', `${quoted}`]);\n }\n\n appendToAttributeValue(char: string) {\n steps.push(['appendToAttributeValue', char]);\n }\n finishAttributeValue() {\n steps.push(['finishAttributeValue']);\n }\n\n markTagAsSelfClosing() {\n steps.push(['markTagAsSelfClosing']);\n }\n\n beginEndTag() {\n steps.push(['beginEndTag']);\n }\n finishTag() {\n steps.push(['finishTag']);\n }\n\n beginComment() {\n steps.push(['beginComment']);\n }\n appendToCommentData(char: string) {\n steps.push(['appendToCommentData', char]);\n }\n finishComment() {\n steps.push(['finishComment']);\n }\n\n reportSyntaxError(error: string) {\n steps.push(['reportSyntaxError', error]);\n }\n }\n\n let delegate = new MissingDoctypeTokenizerDelegate();\n let tokenizer = new EventedTokenizer(delegate, new EntityParser({}));\n\n tokenizer.tokenize('\\n<!-- comment here --><!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\\n<!-- comment here -->');\n\n assert.deepEqual(steps, [\n [ \"reset\" ],\n [ \"reset\" ],\n [ \"beginData\" ],\n [ \"appendToData\", \"\\n\" ],\n [ \"finishData\" ],\n [ \"tagOpen\" ],\n [ \"beginComment\" ],\n [ \"appendToCommentData\", \" \" ],\n [ \"appendToCommentData\", \"c\" ],\n [ \"appendToCommentData\", \"o\" ],\n [ \"appendToCommentData\", \"m\" ],\n [ \"appendToCommentData\", \"m\" ],\n [ \"appendToCommentData\", \"e\" ],\n [ \"appendToCommentData\", \"n\" ],\n [ \"appendToCommentData\", \"t\" ],\n [ \"appendToCommentData\", \" \" ],\n [ \"appendToCommentData\", \"h\" ],\n [ \"appendToCommentData\", \"e\" ],\n [ \"appendToCommentData\", \"r\" ],\n [ \"appendToCommentData\", \"e\" ],\n [ \"appendToCommentData\", \" \" ],\n [ \"finishComment\" ],\n [ \"tagOpen\" ],\n [ \"beginData\" ],\n [ \"appendToData\", \"\\n\" ],\n [ \"finishData\" ],\n [ \"tagOpen\" ],\n [ \"beginComment\" ],\n [ \"appendToCommentData\", \" \" ],\n [ \"appendToCommentData\", \"c\" ],\n [ \"appendToCommentData\", \"o\" ],\n [ \"appendToCommentData\", \"m\" ],\n [ \"appendToCommentData\", \"m\" ],\n [ \"appendToCommentData\", \"e\" ],\n [ \"appendToCommentData\", \"n\" ],\n [ \"appendToCommentData\", \"t\" ],\n [ \"appendToCommentData\", \" \" ],\n [ \"appendToCommentData\", \"h\" ],\n [ \"appendToCommentData\", \"e\" ],\n [ \"appendToCommentData\", \"r\" ],\n [ \"appendToCommentData\", \"e\" ],\n [ \"appendToCommentData\", \" \" ],\n [ \"finishComment\" ]\n ]);\n});\n\nQUnit.test('Doctype', function(assert) {\n let tokens = tokenize('<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">');\n assert.deepEqual(tokens, [ doctype('-//W3C//DTD HTML 4.01//EN', 'http://www.w3.org/TR/html4/strict.dtd') ], 'Standard HTML 4.01 Strict doctype');\n\n tokens = tokenize('<!DOCTYPE html><html><body></body></html>');\n assert.deepEqual(tokens, [\n doctype(),\n startTag('html'),\n startTag('body'),\n endTag('body'),\n endTag('html'),\n ], 'DOCTYPE is included in tokens');\n\n tokens = tokenize('<!-- comment --><!DOCTYPE html>');\n assert.deepEqual(tokens, [comment(' comment '), doctype()], 'DOCTYPE after comments is valid');\n\n tokens = tokenize('<!-- comment --><!DOCTYPE html PUBLIC >');\n assert.deepEqual(tokens, [comment(' comment '), doctype()], 'DOCTYPE after comments is valid');\n});\n\nQUnit.test('Simple content', function(assert) {\n let tokens = tokenize('hello');\n assert.deepEqual(tokens, [chars('hello')]);\n});\n\nQUnit.test('A simple tag', function(assert) {\n let tokens = tokenize('<div>');\n assert.deepEqual(tokens, [startTag('div')]);\n});\n\nQUnit.test('A simple tag with trailing spaces', function(assert) {\n let tokens = tokenize('<div \\t\\n>');\n assert.deepEqual(tokens, [startTag('div')]);\n});\n\nQUnit.test('A simple closing tag', function(assert) {\n let tokens = tokenize('</div>');\n assert.deepEqual(tokens, [endTag('div')]);\n});\n\nQUnit.test('A simple closing tag with trailing spaces', function(assert) {\n let tokens = tokenize('</div \\t\\n>');\n assert.deepEqual(tokens, [endTag('div')]);\n});\n\nQUnit.test('A pair of hyphenated tags', function(assert) {\n let tokens = tokenize('<x-foo></x-foo>');\n assert.deepEqual(tokens, [startTag('x-foo'), endTag('x-foo')]);\n});\n\nQUnit.test('A tag with a single-quoted attribute', function(assert) {\n let tokens = tokenize(\"<div id='foo'>\");\n assert.deepEqual(tokens, [startTag('div', [['id', 'foo', true]])]);\n});\n\nQUnit.test('A tag with a double-quoted attribute', function(assert) {\n let tokens = tokenize('<div id=\"foo\">');\n assert.deepEqual(tokens, [startTag('div', [['id', 'foo', true]])]);\n});\n\nQUnit.test('A tag with a double-quoted empty', function(assert) {\n let tokens = tokenize('<div id=\"\">');\n assert.deepEqual(tokens, [startTag('div', [['id', '', true]])]);\n});\n\nQUnit.test('A tag with unquoted attribute', function(assert) {\n let tokens = tokenize('<div id=foo>');\n assert.deepEqual(tokens, [startTag('div', [['id', 'foo', false]])]);\n});\n\nQUnit.test('A tag with valueless attributes', function(assert) {\n let tokens = tokenize('<div foo bar>');\n assert.deepEqual(tokens, [\n startTag('div', [['foo', '', false], ['bar', '', false]])\n ]);\n});\n\nQUnit.test('Missing attribute name', function(assert) {\n let tokens = tokenize('<div =foo>');\n assert.deepEqual(tokens, [\n withSyntaxError(\n 'attribute name cannot start with equals sign',\n startTag('div', [['=foo', '', false]])\n )\n ]);\n});\n\nQUnit.test('Invalid character in attribute name', function(assert) {\n let tokens = tokenize('<div \">');\n assert.deepEqual(tokens, [\n withSyntaxError(\n '\" is not a valid character within attribute names',\n startTag('div', [['\"', '', false]])\n )\n ]);\n});\n\nQUnit.test('A tag with multiple attributes', function(assert) {\n let tokens = tokenize('<div id=foo class=\"bar baz\" href=\\'bat\\'>');\n assert.deepEqual(tokens, [\n startTag('div', [\n ['id', 'foo', false],\n ['class', 'bar baz', true],\n ['href', 'bat', true]\n ])\n ]);\n});\n\nQUnit.test('A tag with capitalization in attributes', function(assert) {\n let tokens = tokenize('<svg viewBox=\"0 0 0 0\">');\n assert.deepEqual(tokens, [startTag('svg', [['viewBox', '0 0 0 0', true]])]);\n});\n\nQUnit.test('A tag with capitalization in the tag', function(assert) {\n let tokens = tokenize('<linearGradient>');\n assert.deepEqual(tokens, [startTag('linearGradient', [])]);\n});\n\nQUnit.test('A self-closing tag', function(assert) {\n let tokens = tokenize('<img />');\n assert.deepEqual(tokens, [startTag('img', [], true)]);\n});\n\nQUnit.test(\n 'A self-closing tag with valueless attributes (regression)',\n function(assert) {\n let tokens = tokenize('<input disabled />');\n assert.deepEqual(tokens, [\n startTag('input', [['disabled', '', false]], true)\n ]);\n }\n);\n\nQUnit.test(\n 'A self-closing tag with valueless attributes without space before closing (regression)',\n function(assert) {\n let tokens = tokenize('<input disabled/>');\n assert.deepEqual(tokens, [\n startTag('input', [['disabled', '', false]], true)\n ]);\n }\n);\n\nQUnit.test(\n 'A self-closing tag with an attribute with unquoted value without space before closing (regression)',\n function(assert) {\n let tokens = tokenize('<input data-foo=bar/>');\n assert.deepEqual(tokens, [\n startTag('input', [['data-foo', 'bar', false]], true)\n ]);\n }\n);\n\nQUnit.test('A tag with a / in the middle', function(assert) {\n let tokens = tokenize('<img / src=\"foo.png\">');\n assert.deepEqual(tokens, [startTag('img', [['src', 'foo.png', true]])]);\n});\n\nQUnit.test('An opening and closing tag with some content', function(assert) {\n let tokens = tokenize(\"<div id='foo' class='{{bar}} baz'>Some content</div>\");\n assert.deepEqual(tokens, [\n startTag('div', [['id', 'foo', true], ['class', '{{bar}} baz', true]]),\n chars('Some content'),\n endTag('div')\n ]);\n});\n\nQUnit.test('A comment', function(assert) {\n let tokens = tokenize('<!-- hello -->');\n assert.deepEqual(tokens, [comment(' hello ')]);\n});\n\nQUnit.test('A (buggy) comment with no ending --', function(assert) {\n let tokens = tokenize('<!-->');\n assert.deepEqual(tokens, [comment()]);\n});\n\nQUnit.test('A comment that immediately closes', function(assert) {\n let tokens = tokenize('<!---->');\n assert.deepEqual(tokens, [comment()]);\n});\n\nQUnit.test('A comment that contains a -', function(assert) {\n let tokens = tokenize('<!-- A perfectly legal - appears -->');\n assert.deepEqual(tokens, [comment(' A perfectly legal - appears ')]);\n\n tokens = tokenize('<!-- A perfectly legal - -->');\n assert.deepEqual(tokens, [comment(' A perfectly legal - ')]);\n\n tokens = tokenize('<!-- A perfectly legal- -->');\n assert.deepEqual(tokens, [comment(' A perfectly legal- ')]);\n});\n\nQUnit.test('A (buggy) comment that contains two --', function(assert) {\n let tokens = tokenize('<!-- A questionable -- appears -->');\n assert.deepEqual(tokens, [comment(' A questionable -- appears ')]);\n\n tokens = tokenize('<!-- A questionable -- -->');\n assert.deepEqual(tokens, [comment(' A questionable -- ')]);\n\n tokens = tokenize('<!-- A questionable-- -->');\n assert.deepEqual(tokens, [comment(' A questionable-- ')]);\n});\n\nQUnit.test('A (buggy) comment ending with more than two --', function(assert) {\n let tokens = tokenize('<!-- A questionable but legal comment --->');\n assert.deepEqual(tokens, [comment(' A questionable but legal comment -')]);\n\n tokens = tokenize('<!-- A questionable but legal comment--->');\n assert.deepEqual(tokens, [comment(' A questionable but legal comment-')]);\n\n tokens = tokenize('<!-- A questionable but legal comment - --->');\n assert.deepEqual(tokens, [comment(' A questionable but legal comment - -')]);\n\n tokens = tokenize('<!-- A questionable but legal comment -- --->');\n assert.deepEqual(tokens, [comment(' A questionable but legal comment -- -')]);\n\n tokens = tokenize('<!-- A questionable but legal comment ------>');\n assert.deepEqual(tokens, [comment(' A questionable but legal comment ----')]);\n});\n\nQUnit.test('A (buggy) comment starting with more than two --', function(assert) {\n let tokens = tokenize('<!--- Questionable but legal -->');\n assert.deepEqual(tokens, [comment('- Questionable but legal ')]);\n\n tokens = tokenize('<!---Questionable but legal -->');\n assert.deepEqual(tokens, [comment('-Questionable but legal ')]);\n});\n\nQUnit.skip('Character references are expanded', function(assert) {\n let tokens = tokenize(\n '"Foo & Bar" < << < < ≧̸ &Borksnorlax; ≦̸'\n );\n assert.deepEqual(tokens, [chars('\"Foo & Bar\" < << < < ≧̸ &Borksnorlax; ≦̸')]);\n\n tokens = tokenize(\n \"<div title='"Foo & Bar" ▒ < << < < ≧̸ &Borksnorlax; ≦̸'>\"\n );\n assert.deepEqual(tokens, [\n startTag('div', [\n ['title', '\"Foo & Bar\" ▒ < << < < ≧̸ &Borksnorlax; ≦̸', true]\n ])\n ]);\n});\n\n// https://html.spec.whatwg.org/multipage/syntax.html#element-restrictions\nQUnit.test('A newline immediately following a <pre> tag is stripped', function(assert) {\n let tokens = tokenize(\"<pre>\\nhello</pre>\");\n assert.deepEqual(tokens, [startTag('pre'), chars('hello'), endTag('pre')]);\n});\n\nQUnit.test('A newline immediately following a closing </pre> tag is not stripped', function(assert) {\n let tokens = tokenize(\"\\n<pre>\\nhello</pre>\\n\");\n assert.deepEqual(tokens, [chars('\\n'), startTag('pre'), chars('hello'), endTag('pre'), chars('\\n')]);\n});\n\n// https://html.spec.whatwg.org/multipage/syntax.html#element-restrictions\nQUnit.test('A newline immediately following a <PRE> tag is stripped', function(assert) {\n let tokens = tokenize(\"<PRE>\\nhello</PRE>\");\n assert.deepEqual(tokens, [startTag('PRE'), chars('hello'), endTag('PRE')]);\n});\n\n// https://html.spec.whatwg.org/multipage/syntax.html#element-restrictions\nQUnit.test('A newline immediately following a <textarea> tag is stripped', function(assert) {\n let tokens = tokenize(\"<textarea>\\nhello</textarea>\");\n assert.deepEqual(tokens, [startTag('textarea'), chars('hello'), endTag('textarea')]);\n});\n\n// https://html.spec.whatwg.org/multipage/syntax.html#element-restrictions\nQUnit.test('codemod: A newline immediately following a <pre> tag is stripped', function(assert) {\n let tokens = tokenize(\"<pre>\\nhello</pre>\", { mode: 'codemod' });\n assert.deepEqual(tokens, [startTag('pre'), chars('\\nhello'), endTag('pre')]);\n});\n\nQUnit.test('codemod: A newline immediately following a closing </pre> tag is not stripped', function(assert) {\n let tokens = tokenize(\"\\n<pre>\\nhello</pre>\\n\", { mode: 'codemod' });\n assert.deepEqual(tokens, [chars('\\n'), startTag('pre'), chars('\\nhello'), endTag('pre'), chars('\\n')]);\n});\n\n// https://html.spec.whatwg.org/multipage/syntax.html#element-restrictions\nQUnit.test('codemod: A newline immediately following a <PRE> tag is stripped', function(assert) {\n let tokens = tokenize(\"<PRE>\\nhello</PRE>\", { mode: 'codemod' });\n assert.deepEqual(tokens, [startTag('PRE'), chars('\\nhello'), endTag('PRE')]);\n});\n\n// https://html.spec.whatwg.org/multipage/syntax.html#element-restrictions\nQUnit.test('codemod: A newline immediately following a <textarea> tag is stripped', function(assert) {\n let tokens = tokenize(\"<textarea>\\nhello</textarea>\", { mode: 'codemod' });\n assert.deepEqual(tokens, [startTag('textarea'), chars('\\nhello'), endTag('textarea')]);\n});\n\n// https://html.spec.whatwg.org/multipage/semantics.html#the-title-element\nQUnit.test('The title element content is always text', function(assert) {\n let tokens = tokenize(\"<title>"hey <b>there</b><!-- comment --></title>\");\n assert.deepEqual(tokens, [startTag('title'), chars('\"hey <b>there</b><!-- comment -->'), endTag('title')]);\n});\n\n// https://github.com/emberjs/ember.js/issues/18530\nQUnit.test('Title element content is not text', function(assert) {\n let tokens = tokenize(\"<Title><!-- hello --></Title>\");\n assert.deepEqual(tokens, [startTag('Title'), comment(' hello '), endTag('Title')]);\n});\n\n// https://html.spec.whatwg.org/multipage/semantics.html#the-style-element\nQUnit.test('The style element content is always text', function(assert) {\n let tokens = tokenize(\"<style>"hey <b>there</b><!-- comment --></style>\");\n assert.deepEqual(tokens, [startTag('style'), chars('"hey <b>there</b><!-- comment -->'), endTag('style')]);\n});\n\n// https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements\nQUnit.test('The script element content restrictions', function(assert) {\n let tokens = tokenize(\"<script>"hey <b>there</b><!-- comment --></script>\");\n assert.deepEqual(tokens, [startTag('script'), chars('"hey <b>there</b><!-- comment -->'), endTag('script')]);\n});\n\nQUnit.test('Two following script tags', function(assert) {\n let tokens = tokenize(\"<script><!-- comment --></script> <script>second</script>\");\n\n assert.deepEqual(tokens, [\n startTag('script'),\n chars('<!-- comment -->'),\n endTag('script'),\n chars(' '),\n startTag('script'),\n chars('second'),\n endTag('script')\n ]);\n});\n\n// https://github.com/emberjs/rfcs/blob/master/text/0311-angle-bracket-invocation.md#dynamic-invocations\nQUnit.test('An Emberish named arg invocation', function(assert) {\n let tokens = tokenize('<@foo></@foo>');\n assert.deepEqual(tokens, [startTag('@foo'), endTag('@foo')]);\n});\n\nQUnit.test('Parsing <script>s out of a complext HTML document [stefanpenner/find-scripts-srcs-in-document#1]', function(assert) {\n let input = `<!DOCTYPE html><html><head><script src=\"/foo.js\"></script><script src=\"/bar.js\"></script><script src=\"/baz.js\"></script></head></html>`;\n\n let tokens = tokenize(input);\n assert.deepEqual(tokens, [\n doctype(),\n startTag('html'),\n startTag('head'),\n startTag('script', [['src','/foo.js', true]]),\n endTag('script'),\n startTag('script', [['src','/bar.js', true]]),\n endTag('script'),\n startTag('script', [['src','/baz.js', true]]),\n endTag('script'),\n endTag('head'),\n endTag('html'),\n ]);\n});\n\nQUnit.module('simple-html-tokenizer - preprocessing');\n\nQUnit.test('Carriage returns are replaced with line feeds', function(assert) {\n let tokens = tokenize('\\r\\r\\n\\r\\r\\n\\n');\n assert.deepEqual(tokens, [chars('\\n\\n\\n\\n\\n')]);\n});\n\nQUnit.module('simple-html-tokenizer - location info');\n\nQUnit.test('lines are counted correctly', function(assert) {\n let tokens = tokenize('\\r\\r\\n\\r\\r\\n\\n', { loc: true });\n assert.deepEqual(tokens, [locInfo(chars('\\n\\n\\n\\n\\n'), 1, 0, 6, 0)]);\n});\n\nQUnit.test('tokens: Chars', function(assert) {\n let tokens = tokenize('Chars', { loc: true });\n assert.deepEqual(tokens, [locInfo(chars('Chars'), 1, 0, 1, 5)]);\n});\n\nQUnit.test('tokens: Chars start-tag Chars', function(assert) {\n let tokens = tokenize('Chars<div>Chars', { loc: true });\n assert.deepEqual(tokens, [\n locInfo(chars('Chars'), 1, 0, 1, 5),\n locInfo(startTag('div'), 1, 5, 1, 10),\n locInfo(chars('Chars'), 1, 10, 1, 15)\n ]);\n});\n\nQUnit.test('tokens: start-tag start-tag', function(assert) {\n let tokens = tokenize('<div><div>', { loc: true });\n assert.deepEqual(tokens, [\n locInfo(startTag('div'), 1, 0, 1, 5),\n locInfo(startTag('div'), 1, 5, 1, 10)\n ]);\n});\n\nQUnit.test('tokens: html char ref start-tag', function(assert) {\n let tokens = tokenize('><div>', { loc: true });\n assert.deepEqual(tokens, [\n locInfo(chars('>'), 1, 0, 1, 4),\n locInfo(startTag('div'), 1, 4, 1, 9)\n ]);\n});\n\nQUnit.test('tokens: Chars start-tag Chars start-tag', function(assert) {\n let tokens = tokenize('Chars\\n<div>Chars\\n<div>', {\n loc: true\n });\n assert.deepEqual(tokens, [\n locInfo(chars('Chars\\n'), 1, 0, 2, 0),\n locInfo(startTag('div'), 2, 0, 2, 5),\n locInfo(chars('Chars\\n'), 2, 5, 3, 0),\n locInfo(startTag('div'), 3, 0, 3, 5)\n ]);\n});\n\nQUnit.test('tokens: comment start-tag Chars end-tag', function(assert) {\n let tokens = tokenize(\n '<!-- multline\\ncomment --><div foo=bar>Chars\\n</div>',\n { loc: true }\n );\n assert.deepEqual(tokens, [\n locInfo(comment(' multline\\ncomment '), 1, 0, 2, 11),\n locInfo(startTag('div', [['foo', 'bar', false]]), 2, 11, 2, 24),\n locInfo(chars('Chars\\n'), 2, 24, 3, 0),\n locInfo(endTag('div'), 3, 0, 3, 6)\n ]);\n});\n\nfunction chars(s?: string): Chars {\n return {\n type: TokenType.Chars,\n chars: s === undefined ? '' : s\n };\n}\n\nfunction comment(s?: string): Comment {\n return {\n type: TokenType.Comment,\n chars: s === undefined ? '' : s\n };\n}\n\nfunction startTag(\n tagName: string,\n attributes?: Attribute[],\n selfClosing?: boolean\n): StartTag {\n return {\n type: TokenType.StartTag,\n tagName: tagName,\n attributes: attributes === undefined ? [] : attributes,\n selfClosing: selfClosing === undefined ? false : selfClosing\n };\n}\n\nfunction endTag(tagName: string): EndTag {\n return {\n type: TokenType.EndTag,\n tagName: tagName\n };\n}\n\nfunction doctype(publicIdentifier?: string, systemIdentifier?: string): Doctype {\n let doctype: Doctype = {\n type: TokenType.Doctype,\n name: 'html',\n };\n\n if (publicIdentifier) {\n doctype.publicIdentifier = publicIdentifier;\n }\n\n if (systemIdentifier) {\n doctype.systemIdentifier = systemIdentifier;\n }\n\n return doctype;\n}\n\nfunction locInfo(\n token: Token,\n startLine: number,\n startColumn: number,\n endLine: number,\n endColumn: number\n) {\n token.loc = {\n start: {\n line: startLine,\n column: startColumn\n },\n end: {\n line: endLine,\n column: endColumn\n }\n };\n\n return token;\n}\n\nfunction withSyntaxError(message: string, result: Token) {\n result.syntaxError = message;\n return result;\n}\n","QUnit.module('TSLint - src');\nQUnit.test('src/entity-parser.ts should pass tslint', function(assert) {\n assert.expect(1);\n assert.ok(true, 'src/entity-parser.ts should pass tslint.');\n});\n","QUnit.module('TSLint - src');\nQUnit.test('src/evented-tokenizer.ts should pass tslint', function(assert) {\n assert.expect(1);\n assert.ok(true, 'src/evented-tokenizer.ts should pass tslint.');\n});\n","QUnit.module('TSLint - src/generated');\nQUnit.test('src/generated/html5-named-char-refs.ts should pass tslint', function(assert) {\n assert.expect(1);\n assert.ok(true, 'src/generated/html5-named-char-refs.ts should pass tslint.');\n});\n","QUnit.module('TSLint - src/generated');\nQUnit.test('src/generated/tokenizer-states.ts should pass tslint', function(assert) {\n assert.expect(1);\n assert.ok(true, 'src/generated/tokenizer-states.ts should pass tslint.');\n});\n","QUnit.module('TSLint - src');\nQUnit.test('src/index.ts should pass tslint', function(assert) {\n assert.expect(1);\n assert.ok(true, 'src/index.ts should pass tslint.');\n});\n","const HEXCHARCODE = /^#[xX]([A-Fa-f0-9]+)$/;\nconst CHARCODE = /^#([0-9]+)$/;\nconst NAMED = /^([A-Za-z0-9]+)$/;\n\nexport default class EntityParser {\n constructor(private named) {\n }\n\n parse(entity) {\n if (!entity) {\n return;\n }\n let matches = entity.match(HEXCHARCODE);\n if (matches) {\n return `&#x${matches[1]};`;\n }\n matches = entity.match(CHARCODE);\n if (matches) {\n return `&#${matches[1]};`;\n }\n matches = entity.match(NAMED);\n if (matches) {\n return this.named[matches[1]] || `&${matches[1]};`;\n }\n }\n}\n","import { preprocessInput, isAlpha, isSpace } from './utils';\n\nexport default class EventedTokenizer {\n private state: any = null;\n private input: any = null;\n private index: number = -1;\n private tagLine: number = -1;\n private tagColumn: number = -1;\n\n public line: number = -1;\n public column: number = -1;\n\n constructor(private delegate, private entityParser) {\n this.reset();\n }\n\n reset() {\n this.state = 'beforeData';\n this.input = '';\n\n this.index = 0;\n this.line = 1;\n this.column = 0;\n\n this.tagLine = -1;\n this.tagColumn = -1;\n\n this.delegate.reset();\n }\n\n tokenize(input) {\n this.reset();\n this.tokenizePart(input);\n this.tokenizeEOF();\n }\n\n tokenizePart(input) {\n this.input += preprocessInput(input);\n\n while (this.index < this.input.length) {\n this.states[this.state].call(this);\n }\n }\n\n tokenizeEOF() {\n this.flushData();\n }\n\n flushData() {\n if (this.state === 'data') {\n this.delegate.finishData();\n this.state = 'beforeData';\n }\n }\n\n peek() {\n return this.input.charAt(this.index);\n }\n\n consume() {\n let char = this.peek();\n\n this.index++;\n\n if (char === \"\\n\") {\n this.line++;\n this.column = 0;\n } else {\n this.column++;\n }\n\n return char;\n }\n\n consumeCharRef() {\n let endIndex = this.input.indexOf(';', this.index);\n if (endIndex === -1) {\n return;\n }\n let entity = this.input.slice(this.index, endIndex);\n let chars = this.entityParser.parse(entity);\n if (chars) {\n let count = entity.length;\n // consume the entity chars\n while (count) {\n this.consume();\n count--;\n }\n // consume the `;`\n this.consume();\n\n return chars;\n }\n }\n\n markTagStart() {\n // these properties to be removed in next major bump\n this.tagLine = this.line;\n this.tagColumn = this.column;\n\n if (this.delegate.tagOpen) {\n this.delegate.tagOpen();\n }\n }\n\n states = {\n beforeData() {\n let char = this.peek();\n\n if (char === \"<\") {\n this.state = 'tagOpen';\n this.markTagStart();\n this.consume();\n } else {\n this.state = 'data';\n this.delegate.beginData();\n }\n },\n\n data() {\n let char = this.peek();\n\n if (char === \"<\") {\n this.delegate.finishData();\n this.state = 'tagOpen';\n this.markTagStart();\n this.consume(); \n } else if (char === \"&\") {\n this.consume();\n this.delegate.appendToData(this.consumeCharRef() || \"&\");\n } else {\n this.consume();\n this.delegate.appendToData(char);\n }\n },\n\n tagOpen() {\n let char = this.consume();\n\n if (char === \"!\") {\n this.state = 'markupDeclaration';\n } else if (char === \"/\") {\n this.state = 'endTagOpen';\n } else if (isAlpha(char)) {\n this.state = 'tagName';\n this.delegate.beginStartTag();\n this.delegate.appendToTagName(char.toLowerCase());\n }\n },\n\n markupDeclaration() {\n let char = this.consume();\n\n if (char === \"-\" && this.input.charAt(this.index) === \"-\") {\n this.consume();\n this.state = 'commentStart';\n this.delegate.beginComment();\n }\n },\n\n commentStart() {\n let char = this.consume();\n\n if (char === \"-\") {\n this.state = 'commentStartDash';\n } else if (char === \">\") {\n this.delegate.finishComment();\n this.state = 'beforeData';\n } else {\n this.delegate.appendToCommentData(char);\n this.state = 'comment';\n }\n },\n\n commentStartDash() {\n let char = this.consume();\n\n if (char === \"-\") {\n this.state = 'commentEnd';\n } else if (char === \">\") {\n this.delegate.finishComment();\n this.state = 'beforeData';\n } else {\n this.delegate.appendToCommentData(\"-\");\n this.state = 'comment';\n }\n },\n\n comment() {\n let char = this.consume();\n\n if (char === \"-\") {\n this.state = 'commentEndDash';\n } else {\n this.delegate.appendToCommentData(char);\n }\n },\n\n commentEndDash() {\n let char = this.consume();\n\n if (char === \"-\") {\n this.state = 'commentEnd';\n } else {\n this.delegate.appendToCommentData(\"-\" + char);\n this.state = 'comment';\n }\n },\n\n commentEnd() {\n let char = this.consume();\n\n if (char === \">\") {\n this.delegate.finishComment();\n this.state = 'beforeData';\n } else {\n this.delegate.appendToCommentData(\"--\" + char);\n this.state = 'comment';\n }\n },\n\n tagName() {\n let char = this.consume();\n\n if (isSpace(char)) {\n this.state = 'beforeAttributeName';\n } else if (char === \"/\") {\n this.state = 'selfClosingStartTag';\n } else if (char === \">\") {\n this.delegate.finishTag();\n this.state = 'beforeData';\n } else {\n this.delegate.appendToTagName(char);\n }\n },\n\n beforeAttributeName() {\n let char = this.peek();\n\n if (isSpace(char)) {\n this.consume();\n return;\n } else if (char === \"/\") {\n this.state = 'selfClosingStartTag';\n this.consume();\n } else if (char === \">\") {\n this.consume();\n this.delegate.finishTag();\n this.state = 'beforeData';\n } else if (char === '=') {\n this.delegate.reportSyntaxError(\"attribute name cannot start with equals sign\");\n this.state = 'attributeName';\n this.delegate.beginAttribute();\n this.consume();\n this.delegate.appendToAttributeName(char);\n } else {\n this.state = 'attributeName';\n this.delegate.beginAttribute();\n }\n },\n\n attributeName() {\n let char = this.peek();\n\n if (isSpace(char)) {\n this.state = 'afterAttributeName';\n this.consume();\n } else if (char === \"/\") {\n this.delegate.beginAttributeValue(false);\n this.delegate.finishAttributeValue();\n this.consume();\n this.state = 'selfClosingStartTag';\n } else if (char === \"=\") {\n this.state = 'beforeAttributeValue';\n this.consume();\n } else if (char === \">\") {\n this.delegate.beginAttributeValue(false);\n this.delegate.finishAttributeValue();\n this.consume();\n this.delegate.finishTag();\n this.state = 'beforeData';\n } else if (char === '\"' || char === \"'\" || char === '<') {\n this.delegate.reportSyntaxError(char + \" is not a valid character within attribute names\");\n this.consume();\n this.delegate.appendToAttributeName(char);\n } else {\n this.consume();\n this.delegate.appendToAttributeName(char);\n }\n },\n\n afterAttributeName() {\n let char = this.peek();\n\n if (isSpace(char)) {\n this.consume();\n return;\n } else if (char === \"/\") {\n this.delegate.beginAttributeValue(false);\n this.delegate.finishAttributeValue();\n this.consume();\n this.state = 'selfClosingStartTag';\n } else if (char === \"=\") {\n this.consume();\n this.state = 'beforeAttributeValue';\n } else if (char === \">\") {\n this.delegate.beginAttributeValue(false);\n this.delegate.finishAttributeValue();\n this.consume();\n this.delegate.finishTag();\n this.state = 'beforeData';\n } else {\n this.delegate.beginAttributeValue(false);\n this.delegate.finishAttributeValue();\n this.consume();\n this.state = 'attributeName';\n this.delegate.beginAttribute();\n this.delegate.appendToAttributeName(char);\n }\n },\n\n beforeAttributeValue() {\n let char = this.peek();\n\n if (isSpace(char)) {\n this.consume();\n } else if (char === '\"') {\n this.state = 'attributeValueDoubleQuoted';\n this.delegate.beginAttributeValue(true);\n this.consume();\n } else if (char === \"'\") {\n this.state = 'attributeValueSingleQuoted';\n this.delegate.beginAttributeValue(true);\n this.consume();\n } else if (char === \">\") {\n this.delegate.beginAttributeValue(false);\n this.delegate.finishAttributeValue();\n this.consume();\n this.delegate.finishTag();\n this.state = 'beforeData';\n } else {\n this.state = 'attributeValueUnquoted';\n this.delegate.beginAttributeValue(false);\n this.consume();\n this.delegate.appendToAttributeValue(char);\n }\n },\n\n attributeValueDoubleQuoted() {\n let char = this.consume();\n\n if (char === '\"') {\n this.delegate.finishAttributeValue();\n this.state = 'afterAttributeValueQuoted';\n } else if (char === \"&\") {\n this.delegate.appendToAttributeValue(this.consumeCharRef('\"') || \"&\");\n } else {\n this.delegate.appendToAttributeValue(char);\n }\n },\n\n attributeValueSingleQuoted() {\n let char = this.consume();\n\n if (char === \"'\") {\n this.delegate.finishAttributeValue();\n this.state = 'afterAttributeValueQuoted';\n } else if (char === \"&\") {\n this.delegate.appendToAttributeValue(this.consumeCharRef(\"'\") || \"&\");\n } else {\n this.delegate.appendToAttributeValue(char);\n }\n },\n\n attributeValueUnquoted() {\n let char = this.peek();\n\n if (isSpace(char)) {\n this.delegate.finishAttributeValue();\n this.consume();\n this.state = 'beforeAttributeName';\n } else if (char === \"&\") {\n this.consume();\n this.delegate.appendToAttributeValue(this.consumeCharRef(\">\") || \"&\");\n } else if (char === \">\") {\n this.delegate.finishAttributeValue();\n this.consume();\n this.delegate.finishTag();\n this.state = 'beforeData';\n } else {\n this.consume();\n this.delegate.appendToAttributeValue(char);\n }\n },\n\n afterAttributeValueQuoted() {\n let char = this.peek();\n\n if (isSpace(char)) {\n this.consume();\n this.state = 'beforeAttributeName';\n } else if (char === \"/\") {\n this.consume();\n this.state = 'selfClosingStartTag';\n } else if (char === \">\") {\n this.consume();\n this.delegate.finishTag();\n this.state = 'beforeData';\n } else {\n this.state = 'beforeAttributeName';\n }\n },\n\n selfClosingStartTag() {\n let char = this.peek();\n\n if (char === \">\") {\n this.consume();\n this.delegate.markTagAsSelfClosing();\n this.delegate.finishTag();\n this.state = 'beforeData';\n } else {\n this.state = 'beforeAttributeName';\n }\n },\n\n endTagOpen() {\n let char = this.consume();\n\n if (isAlpha(char)) {\n this.state = 'tagName';\n this.delegate.beginEndTag();\n this.delegate.appendToTagName(char.toLowerCase());\n }\n }\n };\n}\n","export default {\n // We don't need the complete named character reference because linkifyHtml\n // does not modify the escape sequences. We do need so that\n // whitespace is parsed properly. Other types of whitespace should already\n // be accounted for\n nbsp: \"\\u00a0\"\n};\n","export { default as HTML5NamedCharRefs } from './html5-named-char-refs';\nexport { default as EntityParser } from './entity-parser';\nexport { default as EventedTokenizer } from './evented-tokenizer';\nexport { default as Tokenizer } from './tokenizer';\nexport { default as tokenize } from './tokenize';\n","import Tokenizer, { Token } from './tokenizer';\nimport EntityParser from './entity-parser';\nimport namedCharRefs from './html5-named-char-refs';\n\nexport default function tokenize(input, options): Token[] {\n let tokenizer = new Tokenizer(new EntityParser(namedCharRefs), options);\n return tokenizer.tokenize(input);\n}\n","import EventedTokenizer from './evented-tokenizer';\n\nexport interface TokenizerOptions {\n loc?: any;\n};\n\nexport type Attribute = [string, string, boolean];\n\nexport interface Token {\n type: string;\n chars?: string;\n attributes?: Attribute[];\n tagName?: string;\n selfClosing?: boolean;\n loc?: {\n start: {\n line: number;\n column: number;\n },\n end: {\n line: number;\n column: number;\n }\n };\n syntaxError?: string;\n}\n\nexport default class Tokenizer {\n private token: Token = null;\n private startLine = 1;\n private startColumn = 0;\n private tokenizer: EventedTokenizer;\n private tokens: Token[] = [];\n private currentAttribute: Attribute = null;\n\n constructor(entityParser, private options: TokenizerOptions = {}) {\n this.tokenizer = new EventedTokenizer(this, entityParser);\n }\n\n tokenize(input) {\n this.tokens = [];\n this.tokenizer.tokenize(input);\n return this.tokens;\n }\n\n tokenizePart(input) {\n this.tokens = [];\n this.tokenizer.tokenizePart(input);\n return this.tokens;\n }\n\n tokenizeEOF() {\n this.tokens = [];\n this.tokenizer.tokenizeEOF();\n return this.tokens[0];\n }\n\n reset() {\n this.token = null;\n this.startLine = 1;\n this.startColumn = 0;\n }\n\n addLocInfo() {\n if (this.options.loc) {\n this.token.loc = {\n start: {\n line: this.startLine,\n column: this.startColumn\n },\n end: {\n line: this.tokenizer.line,\n column: this.tokenizer.column\n }\n };\n }\n this.startLine = this.tokenizer.line;\n this.startColumn = this.tokenizer.column;\n }\n\n // Data\n\n beginData() {\n this.token = {\n type: 'Chars',\n chars: ''\n };\n this.tokens.push(this.token);\n }\n\n appendToData(char) {\n this.token.chars += char;\n }\n\n finishData() {\n this.addLocInfo();\n }\n\n // Comment\n\n beginComment() {\n this.token = {\n type: 'Comment',\n chars: ''\n };\n this.tokens.push(this.token);\n }\n\n appendToCommentData(char) {\n this.token.chars += char;\n }\n\n finishComment() {\n this.addLocInfo();\n }\n\n // Tags - basic\n\n beginStartTag() {\n this.token = {\n type: 'StartTag',\n tagName: '',\n attributes: [],\n selfClosing: false\n };\n this.tokens.push(this.token);\n }\n\n beginEndTag() {\n this.token = {\n type: 'EndTag',\n tagName: ''\n };\n this.tokens.push(this.token);\n }\n\n finishTag() {\n this.addLocInfo();\n }\n\n markTagAsSelfClosing() {\n this.token.selfClosing = true;\n }\n\n // Tags - name\n\n appendToTagName(char) {\n this.token.tagName += char;\n }\n\n // Tags - attributes\n\n beginAttribute() {\n this.currentAttribute = [\"\", \"\", null];\n this.token.attributes.push(this.currentAttribute);\n }\n\n appendToAttributeName(char) {\n this.currentAttribute[0] += char;\n }\n\n beginAttributeValue(isQuoted) {\n this.currentAttribute[2] = isQuoted;\n }\n\n appendToAttributeValue(char) {\n this.currentAttribute[1] = this.currentAttribute[1] || \"\";\n this.currentAttribute[1] += char;\n }\n\n finishAttributeValue() {\n }\n\n reportSyntaxError(message: string) {\n this.token.syntaxError = message;\n }\n}\n","const WSP = /[\\t\\n\\f ]/;\nconst ALPHA = /[A-Za-z]/;\nconst CRLF = /\\r\\n?/g;\n\nexport function isSpace(char: string): boolean {\n return WSP.test(char);\n}\n\nexport function isAlpha(char: string): boolean {\n return ALPHA.test(char);\n}\n\nexport function preprocessInput(input: string): string {\n return input.replace(CRLF, \"\\n\");\n}\n","QUnit.module('TSLint - src');\nQUnit.test('src/tokenize.ts should pass tslint', function(assert) {\n assert.expect(1);\n assert.ok(true, 'src/tokenize.ts should pass tslint.');\n});\n","QUnit.module('TSLint - src');\nQUnit.test('src/tokenizer.ts should pass tslint', function(assert) {\n assert.expect(1);\n assert.ok(true, 'src/tokenizer.ts should pass tslint.');\n});\n","QUnit.module('TSLint - src');\nQUnit.test('src/types.ts should pass tslint', function(assert) {\n assert.expect(1);\n assert.ok(true, 'src/types.ts should pass tslint.');\n});\n","QUnit.module('TSLint - src');\nQUnit.test('src/utils.ts should pass tslint', function(assert) {\n assert.expect(1);\n assert.ok(true, 'src/utils.ts should pass tslint.');\n});\n","QUnit.module('TSLint - tests');\nQUnit.test('tests/tokenizer-tests.ts should pass tslint', function(assert) {\n assert.expect(1);\n assert.ok(true, 'tests/tokenizer-tests.ts should pass tslint.');\n});\n"],"names":["EventedTokenizer","EntityParser","tokenize"],"mappings":"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