mirror of
https://github.com/nodejs/node.git
synced 2026-10-14 10:26:26 -04:00
tools: update: eslint-plugin-markdown@1.0.0-beta.7
* Remove pinning of eslint-plugin-markdown An issue affecting Node.js source has been fixed in eslint-plugin-markdown so we don't need to pin it to beta-4 anymore. Refs: https://github.com/eslint/eslint-plugin-markdown/issues/69 * Update eslint-plugin-markdown up to 1.0.0-beta.7 * Fix docs for eslint-plugin-markdown@1.0.0-beta.7 PR-URL: https://github.com/nodejs/node/pull/14047 Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Yuta Hiroto <hello@about-hiroppy.com> Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
1 parent
5100cc6851
commit
15599cbc97
169 files changed
+8853
-22442
No files matched your search
-11
@@ -1,11 +0,0 @@
|
||||
<!--remark setext-->
|
||||
|
||||
<!--lint disable no-multiple-toplevel-headings-->
|
||||
|
||||
1.0.1 / 2016-07-23
|
||||
==================
|
||||
|
||||
* Rewrite module ([`c3cd494`](https://github.com/wooorm/ccount/commit/c3cd494))
|
||||
|
||||
1.0.0 / 2015-07-12
|
||||
==================
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module ccount
|
||||
* @fileoverview Count characters.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* Expose. */
|
||||
module.exports = ccount;
|
||||
|
||||
/**
|
||||
* Count how many characters `character` occur in `value`.
|
||||
*
|
||||
* @example
|
||||
* ccount('foo(bar(baz)', '(') // 2
|
||||
* ccount('foo(bar(baz)', ')') // 1
|
||||
*
|
||||
* @param {string} value - Content, coerced to string.
|
||||
* @param {string} character - Single character to look
|
||||
* for.
|
||||
* @return {number} - Count.
|
||||
* @throws {Error} - when `character` is not a single
|
||||
* character.
|
||||
*/
|
||||
function ccount(value, character) {
|
||||
var count = 0;
|
||||
var index;
|
||||
|
||||
value = String(value);
|
||||
|
||||
if (typeof character !== 'string' || character.length !== 1) {
|
||||
throw new Error('Expected character');
|
||||
}
|
||||
|
||||
index = value.indexOf(character);
|
||||
|
||||
while (index !== -1) {
|
||||
count++;
|
||||
index = value.indexOf(character, index + 1);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
-57
@@ -1,57 +0,0 @@
|
||||
# ccount [![Build Status][travis-badge]][travis] [![Coverage Status][codecov-badge]][codecov]
|
||||
|
||||
<!--lint disable heading-increment list-item-spacing-->
|
||||
|
||||
Count characters.
|
||||
|
||||
## Installation
|
||||
|
||||
[npm][npm-install]:
|
||||
|
||||
```bash
|
||||
npm install ccount
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
var ccount = require('ccount');
|
||||
|
||||
ccount('foo(bar(baz)', '(') // 2
|
||||
ccount('foo(bar(baz)', ')') // 1
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### `ccount(value, character)`
|
||||
|
||||
Get the total count of `character` in `value`.
|
||||
|
||||
###### Parameters
|
||||
|
||||
* `value` (`string`) — Content, coerced to string.
|
||||
* `character` (`string`) — Single character to look for.
|
||||
|
||||
###### Returns
|
||||
|
||||
`number` — Number of times `character` occurred in `value`.
|
||||
|
||||
## License
|
||||
|
||||
[MIT][license] © [Titus Wormer][author]
|
||||
|
||||
<!-- Definitions -->
|
||||
|
||||
[travis-badge]: https://img.shields.io/travis/wooorm/ccount.svg
|
||||
|
||||
[travis]: https://travis-ci.org/wooorm/ccount
|
||||
|
||||
[codecov-badge]: https://img.shields.io/codecov/c/github/wooorm/ccount.svg
|
||||
|
||||
[codecov]: https://codecov.io/github/wooorm/ccount
|
||||
|
||||
[npm-install]: https://docs.npmjs.com/cli/install
|
||||
|
||||
[license]: LICENSE
|
||||
|
||||
[author]: http://wooorm.com
|
||||
-254
@@ -1,254 +0,0 @@
|
||||
{
|
||||
"nbsp": " ",
|
||||
"iexcl": "¡",
|
||||
"cent": "¢",
|
||||
"pound": "£",
|
||||
"curren": "¤",
|
||||
"yen": "¥",
|
||||
"brvbar": "¦",
|
||||
"sect": "§",
|
||||
"uml": "¨",
|
||||
"copy": "©",
|
||||
"ordf": "ª",
|
||||
"laquo": "«",
|
||||
"not": "¬",
|
||||
"shy": "",
|
||||
"reg": "®",
|
||||
"macr": "¯",
|
||||
"deg": "°",
|
||||
"plusmn": "±",
|
||||
"sup2": "²",
|
||||
"sup3": "³",
|
||||
"acute": "´",
|
||||
"micro": "µ",
|
||||
"para": "¶",
|
||||
"middot": "·",
|
||||
"cedil": "¸",
|
||||
"sup1": "¹",
|
||||
"ordm": "º",
|
||||
"raquo": "»",
|
||||
"frac14": "¼",
|
||||
"frac12": "½",
|
||||
"frac34": "¾",
|
||||
"iquest": "¿",
|
||||
"Agrave": "À",
|
||||
"Aacute": "Á",
|
||||
"Acirc": "Â",
|
||||
"Atilde": "Ã",
|
||||
"Auml": "Ä",
|
||||
"Aring": "Å",
|
||||
"AElig": "Æ",
|
||||
"Ccedil": "Ç",
|
||||
"Egrave": "È",
|
||||
"Eacute": "É",
|
||||
"Ecirc": "Ê",
|
||||
"Euml": "Ë",
|
||||
"Igrave": "Ì",
|
||||
"Iacute": "Í",
|
||||
"Icirc": "Î",
|
||||
"Iuml": "Ï",
|
||||
"ETH": "Ð",
|
||||
"Ntilde": "Ñ",
|
||||
"Ograve": "Ò",
|
||||
"Oacute": "Ó",
|
||||
"Ocirc": "Ô",
|
||||
"Otilde": "Õ",
|
||||
"Ouml": "Ö",
|
||||
"times": "×",
|
||||
"Oslash": "Ø",
|
||||
"Ugrave": "Ù",
|
||||
"Uacute": "Ú",
|
||||
"Ucirc": "Û",
|
||||
"Uuml": "Ü",
|
||||
"Yacute": "Ý",
|
||||
"THORN": "Þ",
|
||||
"szlig": "ß",
|
||||
"agrave": "à",
|
||||
"aacute": "á",
|
||||
"acirc": "â",
|
||||
"atilde": "ã",
|
||||
"auml": "ä",
|
||||
"aring": "å",
|
||||
"aelig": "æ",
|
||||
"ccedil": "ç",
|
||||
"egrave": "è",
|
||||
"eacute": "é",
|
||||
"ecirc": "ê",
|
||||
"euml": "ë",
|
||||
"igrave": "ì",
|
||||
"iacute": "í",
|
||||
"icirc": "î",
|
||||
"iuml": "ï",
|
||||
"eth": "ð",
|
||||
"ntilde": "ñ",
|
||||
"ograve": "ò",
|
||||
"oacute": "ó",
|
||||
"ocirc": "ô",
|
||||
"otilde": "õ",
|
||||
"ouml": "ö",
|
||||
"divide": "÷",
|
||||
"oslash": "ø",
|
||||
"ugrave": "ù",
|
||||
"uacute": "ú",
|
||||
"ucirc": "û",
|
||||
"uuml": "ü",
|
||||
"yacute": "ý",
|
||||
"thorn": "þ",
|
||||
"yuml": "ÿ",
|
||||
"fnof": "ƒ",
|
||||
"Alpha": "Α",
|
||||
"Beta": "Β",
|
||||
"Gamma": "Γ",
|
||||
"Delta": "Δ",
|
||||
"Epsilon": "Ε",
|
||||
"Zeta": "Ζ",
|
||||
"Eta": "Η",
|
||||
"Theta": "Θ",
|
||||
"Iota": "Ι",
|
||||
"Kappa": "Κ",
|
||||
"Lambda": "Λ",
|
||||
"Mu": "Μ",
|
||||
"Nu": "Ν",
|
||||
"Xi": "Ξ",
|
||||
"Omicron": "Ο",
|
||||
"Pi": "Π",
|
||||
"Rho": "Ρ",
|
||||
"Sigma": "Σ",
|
||||
"Tau": "Τ",
|
||||
"Upsilon": "Υ",
|
||||
"Phi": "Φ",
|
||||
"Chi": "Χ",
|
||||
"Psi": "Ψ",
|
||||
"Omega": "Ω",
|
||||
"alpha": "α",
|
||||
"beta": "β",
|
||||
"gamma": "γ",
|
||||
"delta": "δ",
|
||||
"epsilon": "ε",
|
||||
"zeta": "ζ",
|
||||
"eta": "η",
|
||||
"theta": "θ",
|
||||
"iota": "ι",
|
||||
"kappa": "κ",
|
||||
"lambda": "λ",
|
||||
"mu": "μ",
|
||||
"nu": "ν",
|
||||
"xi": "ξ",
|
||||
"omicron": "ο",
|
||||
"pi": "π",
|
||||
"rho": "ρ",
|
||||
"sigmaf": "ς",
|
||||
"sigma": "σ",
|
||||
"tau": "τ",
|
||||
"upsilon": "υ",
|
||||
"phi": "φ",
|
||||
"chi": "χ",
|
||||
"psi": "ψ",
|
||||
"omega": "ω",
|
||||
"thetasym": "ϑ",
|
||||
"upsih": "ϒ",
|
||||
"piv": "ϖ",
|
||||
"bull": "•",
|
||||
"hellip": "…",
|
||||
"prime": "′",
|
||||
"Prime": "″",
|
||||
"oline": "‾",
|
||||
"frasl": "⁄",
|
||||
"weierp": "℘",
|
||||
"image": "ℑ",
|
||||
"real": "ℜ",
|
||||
"trade": "™",
|
||||
"alefsym": "ℵ",
|
||||
"larr": "←",
|
||||
"uarr": "↑",
|
||||
"rarr": "→",
|
||||
"darr": "↓",
|
||||
"harr": "↔",
|
||||
"crarr": "↵",
|
||||
"lArr": "⇐",
|
||||
"uArr": "⇑",
|
||||
"rArr": "⇒",
|
||||
"dArr": "⇓",
|
||||
"hArr": "⇔",
|
||||
"forall": "∀",
|
||||
"part": "∂",
|
||||
"exist": "∃",
|
||||
"empty": "∅",
|
||||
"nabla": "∇",
|
||||
"isin": "∈",
|
||||
"notin": "∉",
|
||||
"ni": "∋",
|
||||
"prod": "∏",
|
||||
"sum": "∑",
|
||||
"minus": "−",
|
||||
"lowast": "∗",
|
||||
"radic": "√",
|
||||
"prop": "∝",
|
||||
"infin": "∞",
|
||||
"ang": "∠",
|
||||
"and": "∧",
|
||||
"or": "∨",
|
||||
"cap": "∩",
|
||||
"cup": "∪",
|
||||
"int": "∫",
|
||||
"there4": "∴",
|
||||
"sim": "∼",
|
||||
"cong": "≅",
|
||||
"asymp": "≈",
|
||||
"ne": "≠",
|
||||
"equiv": "≡",
|
||||
"le": "≤",
|
||||
"ge": "≥",
|
||||
"sub": "⊂",
|
||||
"sup": "⊃",
|
||||
"nsub": "⊄",
|
||||
"sube": "⊆",
|
||||
"supe": "⊇",
|
||||
"oplus": "⊕",
|
||||
"otimes": "⊗",
|
||||
"perp": "⊥",
|
||||
"sdot": "⋅",
|
||||
"lceil": "⌈",
|
||||
"rceil": "⌉",
|
||||
"lfloor": "⌊",
|
||||
"rfloor": "⌋",
|
||||
"lang": "〈",
|
||||
"rang": "〉",
|
||||
"loz": "◊",
|
||||
"spades": "♠",
|
||||
"clubs": "♣",
|
||||
"hearts": "♥",
|
||||
"diams": "♦",
|
||||
"quot": "\"",
|
||||
"amp": "&",
|
||||
"lt": "<",
|
||||
"gt": ">",
|
||||
"OElig": "Œ",
|
||||
"oelig": "œ",
|
||||
"Scaron": "Š",
|
||||
"scaron": "š",
|
||||
"Yuml": "Ÿ",
|
||||
"circ": "ˆ",
|
||||
"tilde": "˜",
|
||||
"ensp": " ",
|
||||
"emsp": " ",
|
||||
"thinsp": " ",
|
||||
"zwnj": "",
|
||||
"zwj": "",
|
||||
"lrm": "",
|
||||
"rlm": "",
|
||||
"ndash": "–",
|
||||
"mdash": "—",
|
||||
"lsquo": "‘",
|
||||
"rsquo": "’",
|
||||
"sbquo": "‚",
|
||||
"ldquo": "“",
|
||||
"rdquo": "”",
|
||||
"bdquo": "„",
|
||||
"dagger": "†",
|
||||
"Dagger": "‡",
|
||||
"permil": "‰",
|
||||
"lsaquo": "‹",
|
||||
"rsaquo": "›",
|
||||
"euro": "€"
|
||||
}
|
||||
-98
@@ -1,98 +0,0 @@
|
||||
{
|
||||
"_from": "character-entities-html4@^1.0.0",
|
||||
"_id": "character-entities-html4@1.1.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-GrCFUdPOH6HfCNAPucod77FHoGw=",
|
||||
"_location": "/character-entities-html4",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "character-entities-html4@^1.0.0",
|
||||
"name": "character-entities-html4",
|
||||
"escapedName": "character-entities-html4",
|
||||
"rawSpec": "^1.0.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^1.0.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/stringify-entities"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.0.tgz",
|
||||
"_shasum": "1ab08551d3ce1fa1df08d00fb9ca1defb147a06c",
|
||||
"_spec": "character-entities-html4@^1.0.0",
|
||||
"_where": "/Users/trott/io.js/tools/eslint-tmp/node_modules/eslint/node_modules/stringify-entities",
|
||||
"author": {
|
||||
"name": "Titus Wormer",
|
||||
"email": "tituswormer@gmail.com",
|
||||
"url": "http://wooorm.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/wooorm/character-entities-html4/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Titus Wormer",
|
||||
"email": "tituswormer@gmail.com",
|
||||
"url": "http://wooorm.com"
|
||||
}
|
||||
],
|
||||
"dependencies": {},
|
||||
"deprecated": false,
|
||||
"description": "HTML4 character entity information",
|
||||
"devDependencies": {
|
||||
"bail": "^1.0.1",
|
||||
"browserify": "^13.0.1",
|
||||
"concat-stream": "^1.5.2",
|
||||
"esmangle": "^1.0.1",
|
||||
"nyc": "^8.0.0",
|
||||
"remark-cli": "^2.0.0",
|
||||
"remark-preset-wooorm": "^1.0.0",
|
||||
"tape": "^4.0.0",
|
||||
"xo": "^0.17.0"
|
||||
},
|
||||
"files": [
|
||||
"index.json"
|
||||
],
|
||||
"homepage": "https://github.com/wooorm/character-entities-html4#readme",
|
||||
"keywords": [
|
||||
"html",
|
||||
"html4",
|
||||
"entity",
|
||||
"entities",
|
||||
"character",
|
||||
"reference",
|
||||
"name",
|
||||
"replacement"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "index.json",
|
||||
"name": "character-entities-html4",
|
||||
"remarkConfig": {
|
||||
"output": true,
|
||||
"presets": "wooorm"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/wooorm/character-entities-html4.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run build-md && npm run build-generate && npm run build-bundle && npm run build-mangle",
|
||||
"build-bundle": "browserify index.json --bare -s characterEntitiesHTML4 > character-entities-html4.js",
|
||||
"build-generate": "node build",
|
||||
"build-mangle": "esmangle character-entities-html4.js > character-entities-html4.min.js",
|
||||
"build-md": "remark . --quiet --frail",
|
||||
"lint": "xo",
|
||||
"test": "npm run build && npm run lint && npm run test-coverage",
|
||||
"test-api": "node test",
|
||||
"test-coverage": "nyc --reporter lcov tape test.js"
|
||||
},
|
||||
"version": "1.1.0",
|
||||
"xo": {
|
||||
"space": true,
|
||||
"ignores": [
|
||||
"character-entities-html4.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
# character-entities-html4 [![Build Status][travis-badge]][travis] [![Coverage Status][codecov-badge]][codecov]
|
||||
|
||||
HTML4 character entity information.
|
||||
|
||||
## Installation
|
||||
|
||||
[npm][npm-install]:
|
||||
|
||||
```bash
|
||||
npm install character-entities-html4
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
console.log(characterEntities.AElig); // Æ
|
||||
console.log(characterEntities.aelig); // æ
|
||||
console.log(characterEntities.amp); // &
|
||||
console.log(characterEntities.apos); // undefined
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### `characterEntitiesHTML4`
|
||||
|
||||
Mapping between (case-sensitive) character entity names to replacements.
|
||||
|
||||
## Support
|
||||
|
||||
See [w3.org][html].
|
||||
|
||||
## License
|
||||
|
||||
[MIT][license] © [Titus Wormer][author]
|
||||
|
||||
<!-- Definitions -->
|
||||
|
||||
[travis-badge]: https://img.shields.io/travis/wooorm/character-entities-html4.svg
|
||||
|
||||
[travis]: https://travis-ci.org/wooorm/character-entities-html4
|
||||
|
||||
[codecov-badge]: https://img.shields.io/codecov/c/github/wooorm/character-entities-html4.svg
|
||||
|
||||
[codecov]: https://codecov.io/github/wooorm/character-entities-html4
|
||||
|
||||
[npm-install]: https://docs.npmjs.com/cli/install
|
||||
|
||||
[license]: LICENSE
|
||||
|
||||
[author]: http://wooorm.com
|
||||
|
||||
[html]: http://www.w3.org/TR/html4/sgml/entities.html
|
||||
+21
-2
@@ -102,6 +102,26 @@ Each code block in a file is linted separately, so configuration comments apply
|
||||
alert("Hello, world!");
|
||||
```
|
||||
|
||||
## Skipping Blocks
|
||||
|
||||
Sometimes it can be useful to have code blocks marked with `js` even though they don't contain valid JavaScript syntax, such as commented JSON blobs that need `js` syntax highlighting. Standard `eslint-disable` comments only silence rule reporting, but ESLint still reports any syntax errors it finds. In cases where a code block should not even be parsed, insert a non-standard `<!-- eslint-skip -->` comment before the block, and this plugin will hide the following block from ESLint. Neither rule nor syntax errors will be reported.
|
||||
|
||||
There are comments in this JSON, so we use `js` syntax for better
|
||||
highlighting. Skip the block to prevent warnings about invalid syntax.
|
||||
|
||||
<!-- eslint-skip -->
|
||||
|
||||
```js
|
||||
{
|
||||
// This code block is hidden from ESLint.
|
||||
"hello": "world"
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
console.log("This code block is linted normally.");
|
||||
```
|
||||
|
||||
## Unsatisfiable Rules
|
||||
|
||||
Since code blocks are not files themselves but embedded inside a Markdown document, some rules do not apply to Markdown code blocks, and messages from these rules are automatically suppressed:
|
||||
@@ -113,8 +133,7 @@ Since code blocks are not files themselves but embedded inside a Markdown docume
|
||||
```sh
|
||||
$ git clone https://github.com/eslint/eslint-plugin-markdown.git
|
||||
$ cd eslint-plugin-markdown
|
||||
$ npm link
|
||||
$ npm link eslint-plugin-markdown
|
||||
$ npm install
|
||||
$ npm test
|
||||
```
|
||||
|
||||
|
||||
+38
-25
@@ -6,14 +6,16 @@
|
||||
"use strict";
|
||||
|
||||
var assign = require("object-assign");
|
||||
var parse5 = require("parse5");
|
||||
var remark = require("remark");
|
||||
var unified = require("unified");
|
||||
var remarkParse = require("remark-parse");
|
||||
|
||||
var SUPPORTED_SYNTAXES = ["js", "javascript", "node", "jsx"];
|
||||
var UNSATISFIABLE_RULES = [
|
||||
"eol-last" // The Markdown parser strips trailing newlines in code fences
|
||||
];
|
||||
|
||||
var markdown = unified().use(remarkParse);
|
||||
|
||||
var blocks = [];
|
||||
|
||||
/**
|
||||
@@ -42,26 +44,25 @@ function traverse(node, callbacks, parent) {
|
||||
* @param {string} html The text content of an HTML AST node.
|
||||
* @returns {string[]} An array of JS block comments.
|
||||
*/
|
||||
function getComments(html) {
|
||||
var ast = parse5.parse(html, { locationInfo: true });
|
||||
var nodes = ast.childNodes.filter(function(node) {
|
||||
return node.__location; // eslint-disable-line no-underscore-dangle
|
||||
});
|
||||
var comments = [];
|
||||
var index;
|
||||
function getComment(html) {
|
||||
var commentStart = "<!--";
|
||||
var commentEnd = "-->";
|
||||
var prefix = "eslint";
|
||||
|
||||
for (index = nodes.length - 1; index >= 0; index--) {
|
||||
if (
|
||||
nodes[index].nodeName === "#comment"
|
||||
&& nodes[index].data.trim().slice(0, "eslint".length) === "eslint"
|
||||
) {
|
||||
comments.unshift("/*" + nodes[index].data + "*/");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (
|
||||
html.slice(0, commentStart.length) !== commentStart ||
|
||||
html.slice(-commentEnd.length) !== commentEnd
|
||||
) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return comments;
|
||||
html = html.slice(commentStart.length, -commentEnd.length);
|
||||
|
||||
if (html.trim().slice(0, prefix.length) !== prefix) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,19 +71,31 @@ function getComments(html) {
|
||||
* @returns {string[]} Source code strings to lint.
|
||||
*/
|
||||
function preprocess(text) {
|
||||
var ast = remark().parse(text);
|
||||
var ast = markdown.parse(text);
|
||||
|
||||
blocks = [];
|
||||
traverse(ast, {
|
||||
"code": function(node, parent) {
|
||||
var comments = [];
|
||||
var index, previousNode;
|
||||
var index, previousNode, comment;
|
||||
|
||||
if (node.lang && SUPPORTED_SYNTAXES.indexOf(node.lang.toLowerCase()) >= 0) {
|
||||
index = parent.children.indexOf(node);
|
||||
previousNode = parent.children[index - 1];
|
||||
if (previousNode && previousNode.type === "html") {
|
||||
comments = getComments(previousNode.value) || [];
|
||||
index = parent.children.indexOf(node) - 1;
|
||||
previousNode = parent.children[index];
|
||||
while (previousNode && previousNode.type === "html") {
|
||||
comment = getComment(previousNode.value);
|
||||
|
||||
if (!comment) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (comment.trim() === "eslint-skip") {
|
||||
return;
|
||||
}
|
||||
|
||||
comments.unshift("/*" + comment + "*/");
|
||||
index--;
|
||||
previousNode = parent.children[index];
|
||||
}
|
||||
|
||||
blocks.push(assign({}, node, { comments: comments }));
|
||||
|
||||
+25
-17
@@ -1,28 +1,28 @@
|
||||
{
|
||||
"_from": "eslint-plugin-markdown@1.0.0-beta.4",
|
||||
"_id": "eslint-plugin-markdown@1.0.0-beta.4",
|
||||
"_from": "eslint-plugin-markdown@1.0.0-beta.7",
|
||||
"_id": "eslint-plugin-markdown@1.0.0-beta.7",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-gqGZcTmeSxti99SsZCRofCwH7no=",
|
||||
"_integrity": "sha1-Euc6QSfEpLedlm+fR1hR3Q949+c=",
|
||||
"_location": "/eslint-plugin-markdown",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "eslint-plugin-markdown@1.0.0-beta.4",
|
||||
"raw": "eslint-plugin-markdown@1.0.0-beta.7",
|
||||
"name": "eslint-plugin-markdown",
|
||||
"escapedName": "eslint-plugin-markdown",
|
||||
"rawSpec": "1.0.0-beta.4",
|
||||
"rawSpec": "1.0.0-beta.7",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "1.0.0-beta.4"
|
||||
"fetchSpec": "1.0.0-beta.7"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER",
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-1.0.0-beta.4.tgz",
|
||||
"_shasum": "82a19971399e4b1b62f7d4ac6424687c2c07ee7a",
|
||||
"_spec": "eslint-plugin-markdown@1.0.0-beta.4",
|
||||
"_where": "/Users/trott/io.js/tools/eslint-tmp/node_modules/eslint",
|
||||
"_resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-1.0.0-beta.7.tgz",
|
||||
"_shasum": "12e73a4127c4a4b79d966f9f475851dd0f78f7e7",
|
||||
"_spec": "eslint-plugin-markdown@1.0.0-beta.7",
|
||||
"_where": "j:\\temp\\_git\\node-fork\\tools\\eslint",
|
||||
"author": {
|
||||
"name": "Brandon Mills",
|
||||
"url": "https://github.com/btmills"
|
||||
@@ -33,8 +33,8 @@
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"object-assign": "^4.0.1",
|
||||
"parse5": "^2.2.2",
|
||||
"remark": "^5.0.0"
|
||||
"remark-parse": "^3.0.0",
|
||||
"unified": "^6.1.2"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "An ESLint plugin to lint JavaScript in Markdown code fences.",
|
||||
@@ -42,13 +42,14 @@
|
||||
"chai": "^3.0.0",
|
||||
"eslint": "^2.2.0",
|
||||
"eslint-config-eslint": "^3.0.0",
|
||||
"eslint-release": "^0.10.2",
|
||||
"istanbul": "^0.4.5",
|
||||
"mocha": "^2.2.5"
|
||||
},
|
||||
"files": [
|
||||
"lib/*.js",
|
||||
"index.js",
|
||||
"LICENSE",
|
||||
"README.md"
|
||||
"lib/index.js",
|
||||
"lib/processor.js"
|
||||
],
|
||||
"homepage": "https://github.com/eslint/eslint-plugin-markdown#readme",
|
||||
"keywords": [
|
||||
@@ -66,7 +67,14 @@
|
||||
"url": "git+https://github.com/eslint/eslint-plugin-markdown.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "eslint --ext .js --ext .md . && mocha tests"
|
||||
"alpharelease": "eslint-prerelease alpha",
|
||||
"betarelease": "eslint-prerelease beta",
|
||||
"ci-release": "eslint-ci-release",
|
||||
"gh-release": "eslint-gh-release",
|
||||
"lint": "eslint Makefile.js lib/**/*.js tests/lib/plugin.js",
|
||||
"release": "eslint-release",
|
||||
"test": "npm run lint && npm run test-cov",
|
||||
"test-cov": "istanbul cover _mocha -- -c tests/lib/**/*.js"
|
||||
},
|
||||
"version": "1.0.0-beta.4"
|
||||
"version": "1.0.0-beta.7"
|
||||
}
|
||||
Generated
Vendored
+3
-1
@@ -1,4 +1,6 @@
|
||||
Copyright (c) 2013-2016 Ivan Nikulin (ifaaan@gmail.com, https://github.com/inikulin)
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Feross Aboukhadijeh
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
# is-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][npm-url]
|
||||
|
||||
#### Determine if an object is a [`Buffer`](http://nodejs.org/api/buffer.html) (including the [browserify Buffer](https://github.com/feross/buffer))
|
||||
|
||||
[![saucelabs][saucelabs-image]][saucelabs-url]
|
||||
|
||||
[travis-image]: https://img.shields.io/travis/feross/is-buffer/master.svg
|
||||
[travis-url]: https://travis-ci.org/feross/is-buffer
|
||||
[npm-image]: https://img.shields.io/npm/v/is-buffer.svg
|
||||
[npm-url]: https://npmjs.org/package/is-buffer
|
||||
[downloads-image]: https://img.shields.io/npm/dm/is-buffer.svg
|
||||
[saucelabs-image]: https://saucelabs.com/browser-matrix/is-buffer.svg
|
||||
[saucelabs-url]: https://saucelabs.com/u/is-buffer
|
||||
|
||||
## Why not use `Buffer.isBuffer`?
|
||||
|
||||
This module lets you check if an object is a `Buffer` without using `Buffer.isBuffer` (which includes the whole [buffer](https://github.com/feross/buffer) module in [browserify](http://browserify.org/)).
|
||||
|
||||
It's future-proof and works in node too!
|
||||
|
||||
## install
|
||||
|
||||
```bash
|
||||
npm install is-buffer
|
||||
```
|
||||
|
||||
## usage
|
||||
|
||||
```js
|
||||
var isBuffer = require('is-buffer')
|
||||
|
||||
isBuffer(new Buffer(4)) // true
|
||||
|
||||
isBuffer(undefined) // false
|
||||
isBuffer(null) // false
|
||||
isBuffer('') // false
|
||||
isBuffer(true) // false
|
||||
isBuffer(false) // false
|
||||
isBuffer(0) // false
|
||||
isBuffer(1) // false
|
||||
isBuffer(1.0) // false
|
||||
isBuffer('string') // false
|
||||
isBuffer({}) // false
|
||||
isBuffer(function foo () {}) // false
|
||||
```
|
||||
|
||||
## license
|
||||
|
||||
MIT. Copyright (C) [Feross Aboukhadijeh](http://feross.org).
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*!
|
||||
* Determine if an object is a Buffer
|
||||
*
|
||||
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
// The _isBuffer check is for Safari 5-7 support, because it's missing
|
||||
// Object.prototype.constructor. Remove this eventually
|
||||
module.exports = function (obj) {
|
||||
return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
|
||||
}
|
||||
|
||||
function isBuffer (obj) {
|
||||
return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
|
||||
}
|
||||
|
||||
// For Node v0.10 support. Remove this eventually.
|
||||
function isSlowBuffer (obj) {
|
||||
return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"_from": "is-buffer@^1.1.4",
|
||||
"_id": "is-buffer@1.1.5",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=",
|
||||
"_location": "/is-buffer",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "is-buffer@^1.1.4",
|
||||
"name": "is-buffer",
|
||||
"escapedName": "is-buffer",
|
||||
"rawSpec": "^1.1.4",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^1.1.4"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/eslint-plugin-markdown/vfile"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz",
|
||||
"_shasum": "1f3b26ef613b214b88cbca23cc6c01d87961eecc",
|
||||
"_spec": "is-buffer@^1.1.4",
|
||||
"_where": "j:\\temp\\_git\\node-fork\\tools\\eslint\\node_modules\\eslint-plugin-markdown\\node_modules\\vfile",
|
||||
"author": {
|
||||
"name": "Feross Aboukhadijeh",
|
||||
"email": "feross@feross.org",
|
||||
"url": "http://feross.org/"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/feross/is-buffer/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {},
|
||||
"deprecated": false,
|
||||
"description": "Determine if an object is a Buffer",
|
||||
"devDependencies": {
|
||||
"standard": "*",
|
||||
"tape": "^4.0.0",
|
||||
"zuul": "^3.0.0"
|
||||
},
|
||||
"homepage": "https://github.com/feross/is-buffer#readme",
|
||||
"keywords": [
|
||||
"buffer",
|
||||
"buffers",
|
||||
"type",
|
||||
"core buffer",
|
||||
"browser buffer",
|
||||
"browserify",
|
||||
"typed array",
|
||||
"uint32array",
|
||||
"int16array",
|
||||
"int32array",
|
||||
"float32array",
|
||||
"float64array",
|
||||
"browser",
|
||||
"arraybuffer",
|
||||
"dataview"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"name": "is-buffer",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/feross/is-buffer.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "standard && npm run test-node && npm run test-browser",
|
||||
"test-browser": "zuul -- test/*.js",
|
||||
"test-browser-local": "zuul --local -- test/*.js",
|
||||
"test-node": "tape test/*.js"
|
||||
},
|
||||
"testling": {
|
||||
"files": "test/*.js"
|
||||
},
|
||||
"version": "1.1.5"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
module.exports = function (x) {
|
||||
var prototype;
|
||||
return toString.call(x) === '[object Object]' && (prototype = Object.getPrototypeOf(x), prototype === null || prototype === Object.getPrototypeOf({}));
|
||||
};
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"_from": "is-plain-obj@^1.1.0",
|
||||
"_id": "is-plain-obj@1.1.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
|
||||
"_location": "/is-plain-obj",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "is-plain-obj@^1.1.0",
|
||||
"name": "is-plain-obj",
|
||||
"escapedName": "is-plain-obj",
|
||||
"rawSpec": "^1.1.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^1.1.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/eslint-plugin-markdown/unified"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
|
||||
"_shasum": "71a50c8429dfca773c92a390a4a03b39fcd51d3e",
|
||||
"_spec": "is-plain-obj@^1.1.0",
|
||||
"_where": "j:\\temp\\_git\\node-fork\\tools\\eslint\\node_modules\\eslint-plugin-markdown\\node_modules\\unified",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/sindresorhus/is-plain-obj/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"deprecated": false,
|
||||
"description": "Check if a value is a plain object",
|
||||
"devDependencies": {
|
||||
"ava": "0.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"homepage": "https://github.com/sindresorhus/is-plain-obj#readme",
|
||||
"keywords": [
|
||||
"obj",
|
||||
"object",
|
||||
"is",
|
||||
"check",
|
||||
"test",
|
||||
"type",
|
||||
"plain",
|
||||
"vanilla",
|
||||
"pure",
|
||||
"simple"
|
||||
],
|
||||
"license": "MIT",
|
||||
"name": "is-plain-obj",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sindresorhus/is-plain-obj.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node test.js"
|
||||
},
|
||||
"version": "1.1.0"
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
# is-plain-obj [](https://travis-ci.org/sindresorhus/is-plain-obj)
|
||||
|
||||
> Check if a value is a plain object
|
||||
|
||||
An object is plain if it's created by either `{}`, `new Object()` or `Object.create(null)`.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save is-plain-obj
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var isPlainObj = require('is-plain-obj');
|
||||
|
||||
isPlainObj({foo: 'bar'});
|
||||
//=> true
|
||||
|
||||
isPlainObj([1, 2, 3]);
|
||||
//=> false
|
||||
```
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [is-obj](https://github.com/sindresorhus/is-obj) - Check if a value is an object
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](http://sindresorhus.com)
|
||||
tools/eslint/node_modules/ccount/LICENSE → tools/eslint/node_modules/is-whitespace-character/LICENSE
Generated
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2015 Titus Wormer <tituswormer@gmail.com>
|
||||
Copyright (c) 2016 Titus Wormer <tituswormer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
Generated
Vendored
+2
-5
@@ -1,9 +1,6 @@
|
||||
---
|
||||
mdast:
|
||||
setext: true
|
||||
---
|
||||
<!--remark setext-->
|
||||
|
||||
<!--lint disable no-multiple-toplevel-headings -->
|
||||
|
||||
1.0.0 / 2015-07-12
|
||||
1.0.0 / 2016-07-12
|
||||
==================
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2016 Titus Wormer
|
||||
* @license MIT
|
||||
* @module is-whitespace-character
|
||||
* @fileoverview Check if a character is a whitespace character.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* eslint-env commonjs */
|
||||
|
||||
/* Expose. */
|
||||
module.exports = whitespace;
|
||||
|
||||
/* Methods. */
|
||||
var fromCode = String.fromCharCode;
|
||||
|
||||
/* Constants. */
|
||||
var re = /\s/;
|
||||
|
||||
/**
|
||||
* Check whether the given character code, or the character
|
||||
* code at the first character, is a whitespace character.
|
||||
*
|
||||
* @param {string|number} character
|
||||
* @return {boolean} - Whether `character` is a whitespaces character.
|
||||
*/
|
||||
function whitespace(character) {
|
||||
return re.test(
|
||||
typeof character === 'number' ? fromCode(character) : character.charAt(0)
|
||||
);
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"_from": "is-whitespace-character@^1.0.0",
|
||||
"_id": "is-whitespace-character@1.0.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-u/SoN2Tq0NRRvsKlUhjpGWGtwnU=",
|
||||
"_location": "/is-whitespace-character",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "is-whitespace-character@^1.0.0",
|
||||
"name": "is-whitespace-character",
|
||||
"escapedName": "is-whitespace-character",
|
||||
"rawSpec": "^1.0.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^1.0.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/eslint-plugin-markdown/remark-parse"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.0.tgz",
|
||||
"_shasum": "bbf4a83764ead0d451bec2a55218e91961adc275",
|
||||
"_spec": "is-whitespace-character@^1.0.0",
|
||||
"_where": "j:\\temp\\_git\\node-fork\\tools\\eslint\\node_modules\\eslint-plugin-markdown\\node_modules\\remark-parse",
|
||||
"author": {
|
||||
"name": "Titus Wormer",
|
||||
"email": "tituswormer@gmail.com",
|
||||
"url": "http://wooorm.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/wooorm/is-whitespace-character/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Titus Wormer",
|
||||
"email": "tituswormer@gmail.com",
|
||||
"url": "http://wooorm.com"
|
||||
}
|
||||
],
|
||||
"dependencies": {},
|
||||
"deprecated": false,
|
||||
"description": "Check if a character is a whitespace character",
|
||||
"devDependencies": {
|
||||
"browserify": "^13.0.1",
|
||||
"esmangle": "^1.0.1",
|
||||
"nyc": "^7.0.0",
|
||||
"remark-cli": "^1.0.0",
|
||||
"remark-comment-config": "^4.0.0",
|
||||
"remark-github": "^5.0.0",
|
||||
"remark-lint": "^4.0.0",
|
||||
"remark-validate-links": "^4.0.0",
|
||||
"tape": "^4.0.0",
|
||||
"xo": "^0.16.0"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"homepage": "https://github.com/wooorm/is-whitespace-character#readme",
|
||||
"keywords": [
|
||||
"string",
|
||||
"character",
|
||||
"char",
|
||||
"code",
|
||||
"whitespace",
|
||||
"white",
|
||||
"space"
|
||||
],
|
||||
"license": "MIT",
|
||||
"name": "is-whitespace-character",
|
||||
"nyc": {
|
||||
"check-coverage": true,
|
||||
"lines": 100,
|
||||
"functions": 100,
|
||||
"branches": 100
|
||||
},
|
||||
"remarkConfig": {
|
||||
"output": true,
|
||||
"plugins": [
|
||||
"comment-config",
|
||||
"github",
|
||||
"lint",
|
||||
"validate-links"
|
||||
],
|
||||
"settings": {
|
||||
"bullet": "*"
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/wooorm/is-whitespace-character.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run build-md && npm run build-bundle && npm run build-mangle",
|
||||
"build-bundle": "browserify index.js --bare -s isWhitespaceCharacter > is-whitespace-character.js",
|
||||
"build-mangle": "esmangle < is-whitespace-character.js > is-whitespace-character.min.js",
|
||||
"build-md": "remark . --quiet --frail",
|
||||
"lint": "xo",
|
||||
"test": "npm run build && npm run lint && npm run test-coverage",
|
||||
"test-api": "node test",
|
||||
"test-coverage": "nyc --reporter lcov tape test.js"
|
||||
},
|
||||
"version": "1.0.0",
|
||||
"xo": {
|
||||
"space": true,
|
||||
"ignores": [
|
||||
"is-whitespace-character.js",
|
||||
"is-whitespace-character.min.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
# is-whitespace-character [![Build Status][travis-badge]][travis] [![Coverage Status][codecov-badge]][codecov]
|
||||
|
||||
<!--lint disable heading-increment list-item-spacing-->
|
||||
|
||||
Check if a character is a whitespace character: `\s`, which equals
|
||||
all Unicode Space Separators (including `[ \t\v\f]`), the BOM
|
||||
(`\uFEFF`), and line terminator (`[\n\r\u2028\u2029]`).
|
||||
|
||||
## Installation
|
||||
|
||||
[npm][npm-install]:
|
||||
|
||||
```bash
|
||||
npm install is-whitespace-character
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
var whitespace = require('is-whitespace-character');
|
||||
|
||||
whitespace(' '); // true
|
||||
whitespace('\n'); // true
|
||||
whitespace('\ufeff'); // true
|
||||
whitespace('_'); // false
|
||||
whitespace('a'); // true
|
||||
whitespace('💩'); // false
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### `whitespaceCharacter(character)`
|
||||
|
||||
Check whether the given character code (`number`), or the character
|
||||
code at the first position (`string`), is a whitespace character.
|
||||
|
||||
## Related
|
||||
|
||||
* [`is-alphabetical`](https://github.com/wooorm/is-alphabetical)
|
||||
* [`is-alphanumerical`](https://github.com/wooorm/is-alphanumerical)
|
||||
* [`is-decimal`](https://github.com/wooorm/is-decimal)
|
||||
* [`is-hexadecimal`](https://github.com/wooorm/is-hexadecimal)
|
||||
* [`is-word-character`](https://github.com/wooorm/is-word-character)
|
||||
|
||||
## License
|
||||
|
||||
[MIT][license] © [Titus Wormer][author]
|
||||
|
||||
<!-- Definitions -->
|
||||
|
||||
[travis-badge]: https://img.shields.io/travis/wooorm/is-whitespace-character.svg
|
||||
|
||||
[travis]: https://travis-ci.org/wooorm/is-whitespace-character
|
||||
|
||||
[codecov-badge]: https://img.shields.io/codecov/c/github/wooorm/is-whitespace-character.svg
|
||||
|
||||
[codecov]: https://codecov.io/github/wooorm/is-whitespace-character
|
||||
|
||||
[npm-install]: https://docs.npmjs.com/cli/install
|
||||
|
||||
[license]: LICENSE
|
||||
|
||||
[author]: http://wooorm.com
|
||||
Generated
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2015 Titus Wormer <tituswormer@gmail.com>
|
||||
Copyright (c) 2016 Titus Wormer <tituswormer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<!--remark setext-->
|
||||
|
||||
<!--lint disable no-multiple-toplevel-headings -->
|
||||
|
||||
1.0.0 / 2016-07-12
|
||||
==================
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2016 Titus Wormer
|
||||
* @license MIT
|
||||
* @module is-word-character
|
||||
* @fileoverview Check if a character is a word character.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* eslint-env commonjs */
|
||||
|
||||
/* Expose. */
|
||||
module.exports = wordCharacter;
|
||||
|
||||
/* Methods. */
|
||||
var fromCode = String.fromCharCode;
|
||||
|
||||
/* Constants. */
|
||||
var re = /\w/;
|
||||
|
||||
/**
|
||||
* Check whether the given character code, or the character
|
||||
* code at the first character, is a word character.
|
||||
*
|
||||
* @param {string|number} character
|
||||
* @return {boolean} - Whether `character` is a word character.
|
||||
*/
|
||||
function wordCharacter(character) {
|
||||
return re.test(
|
||||
typeof character === 'number' ? fromCode(character) : character.charAt(0)
|
||||
);
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
{
|
||||
"_from": "is-word-character@^1.0.0",
|
||||
"_id": "is-word-character@1.0.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-o6nl3a1wxcLuNvSpz8mlP0RTUkc=",
|
||||
"_location": "/is-word-character",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "is-word-character@^1.0.0",
|
||||
"name": "is-word-character",
|
||||
"escapedName": "is-word-character",
|
||||
"rawSpec": "^1.0.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^1.0.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/eslint-plugin-markdown/remark-parse"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.0.tgz",
|
||||
"_shasum": "a3a9e5ddad70c5c2ee36f4a9cfc9a53f44535247",
|
||||
"_spec": "is-word-character@^1.0.0",
|
||||
"_where": "j:\\temp\\_git\\node-fork\\tools\\eslint\\node_modules\\eslint-plugin-markdown\\node_modules\\remark-parse",
|
||||
"author": {
|
||||
"name": "Titus Wormer",
|
||||
"email": "tituswormer@gmail.com",
|
||||
"url": "http://wooorm.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/wooorm/is-word-character/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Titus Wormer",
|
||||
"email": "tituswormer@gmail.com",
|
||||
"url": "http://wooorm.com"
|
||||
}
|
||||
],
|
||||
"dependencies": {},
|
||||
"deprecated": false,
|
||||
"description": "Check if a character is a word character",
|
||||
"devDependencies": {
|
||||
"browserify": "^13.0.1",
|
||||
"esmangle": "^1.0.1",
|
||||
"nyc": "^7.0.0",
|
||||
"remark-cli": "^1.0.0",
|
||||
"remark-comment-config": "^4.0.0",
|
||||
"remark-github": "^5.0.0",
|
||||
"remark-lint": "^4.0.0",
|
||||
"remark-validate-links": "^4.0.0",
|
||||
"tape": "^4.0.0",
|
||||
"xo": "^0.16.0"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"homepage": "https://github.com/wooorm/is-word-character#readme",
|
||||
"keywords": [
|
||||
"string",
|
||||
"character",
|
||||
"char",
|
||||
"code",
|
||||
"word"
|
||||
],
|
||||
"license": "MIT",
|
||||
"name": "is-word-character",
|
||||
"nyc": {
|
||||
"check-coverage": true,
|
||||
"lines": 100,
|
||||
"functions": 100,
|
||||
"branches": 100
|
||||
},
|
||||
"remarkConfig": {
|
||||
"output": true,
|
||||
"plugins": [
|
||||
"comment-config",
|
||||
"github",
|
||||
"lint",
|
||||
"validate-links"
|
||||
],
|
||||
"settings": {
|
||||
"bullet": "*"
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/wooorm/is-word-character.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run build-md && npm run build-bundle && npm run build-mangle",
|
||||
"build-bundle": "browserify index.js --bare -s isWordCharacter > is-word-character.js",
|
||||
"build-mangle": "esmangle < is-word-character.js > is-word-character.min.js",
|
||||
"build-md": "remark . --quiet --frail",
|
||||
"lint": "xo",
|
||||
"test": "npm run build && npm run lint && npm run test-coverage",
|
||||
"test-api": "node test",
|
||||
"test-coverage": "nyc --reporter lcov tape test.js"
|
||||
},
|
||||
"version": "1.0.0",
|
||||
"xo": {
|
||||
"space": true,
|
||||
"ignores": [
|
||||
"is-word-character.js",
|
||||
"is-word-character.min.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
# is-word-character [![Build Status][travis-badge]][travis] [![Coverage Status][codecov-badge]][codecov]
|
||||
|
||||
<!--lint disable heading-increment list-item-spacing-->
|
||||
|
||||
Check if a character is a word character (`\w`, which equals
|
||||
`[a-zA-Z0-9_]`).
|
||||
|
||||
## Installation
|
||||
|
||||
[npm][npm-install]:
|
||||
|
||||
```bash
|
||||
npm install is-word-character
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
var wordCharacter = require('is-word-character');
|
||||
|
||||
wordCharacter('a'); // true
|
||||
wordCharacter('Z'); // true
|
||||
wordCharacter('0'); // true
|
||||
wordCharacter('_'); // true
|
||||
wordCharacter(' '); // false
|
||||
wordCharacter('💩'); // false
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### `wordCharacter(character)`
|
||||
|
||||
Check whether the given character code (`number`), or the character
|
||||
code at the first position (`string`), is a word character.
|
||||
|
||||
## Related
|
||||
|
||||
* [`is-alphabetical`](https://github.com/wooorm/is-alphabetical)
|
||||
* [`is-alphanumerical`](https://github.com/wooorm/is-alphanumerical)
|
||||
* [`is-decimal`](https://github.com/wooorm/is-decimal)
|
||||
* [`is-hexadecimal`](https://github.com/wooorm/is-hexadecimal)
|
||||
* [`is-whitespace-character`](https://github.com/wooorm/is-whitespace-character)
|
||||
|
||||
## License
|
||||
|
||||
[MIT][license] © [Titus Wormer][author]
|
||||
|
||||
<!-- Definitions -->
|
||||
|
||||
[travis-badge]: https://img.shields.io/travis/wooorm/is-word-character.svg
|
||||
|
||||
[travis]: https://travis-ci.org/wooorm/is-word-character
|
||||
|
||||
[codecov-badge]: https://img.shields.io/codecov/c/github/wooorm/is-word-character.svg
|
||||
|
||||
[codecov]: https://codecov.io/github/wooorm/is-word-character
|
||||
|
||||
[npm-install]: https://docs.npmjs.com/cli/install
|
||||
|
||||
[license]: LICENSE
|
||||
|
||||
[author]: http://wooorm.com
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Get the count of the longest repeating streak of
|
||||
* `character` in `value`.
|
||||
*
|
||||
* @example
|
||||
* longestStreak('` foo `` bar `', '`') // 2
|
||||
*
|
||||
* @param {string} value - Content, coerced to string.
|
||||
* @param {string} character - Single character to look
|
||||
* for.
|
||||
* @return {number} - Number of characters at the place
|
||||
* where `character` occurs in its longest streak in
|
||||
* `value`.
|
||||
* @throws {Error} - when `character` is not a single
|
||||
* character.
|
||||
*/
|
||||
function longestStreak(value, character) {
|
||||
var count = 0;
|
||||
var maximum = 0;
|
||||
var index = -1;
|
||||
var length;
|
||||
|
||||
value = String(value);
|
||||
length = value.length;
|
||||
|
||||
if (typeof character !== 'string' || character.length !== 1) {
|
||||
throw new Error('Expected character');
|
||||
}
|
||||
|
||||
while (++index < length) {
|
||||
if (value.charAt(index) === character) {
|
||||
count++;
|
||||
|
||||
if (count > maximum) {
|
||||
maximum = count;
|
||||
}
|
||||
} else {
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return maximum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose.
|
||||
*/
|
||||
|
||||
module.exports = longestStreak;
|
||||
-83
@@ -1,83 +0,0 @@
|
||||
{
|
||||
"_from": "longest-streak@^1.0.0",
|
||||
"_id": "longest-streak@1.0.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-0GWXxNTDG1LMsfXY+P5xSOr9aWU=",
|
||||
"_location": "/longest-streak",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "longest-streak@^1.0.0",
|
||||
"name": "longest-streak",
|
||||
"escapedName": "longest-streak",
|
||||
"rawSpec": "^1.0.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^1.0.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/remark-stringify"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-1.0.0.tgz",
|
||||
"_shasum": "d06597c4d4c31b52ccb1f5d8f8fe7148eafd6965",
|
||||
"_spec": "longest-streak@^1.0.0",
|
||||
"_where": "/Users/trott/io.js/tools/eslint-tmp/node_modules/eslint/node_modules/remark-stringify",
|
||||
"author": {
|
||||
"name": "Titus Wormer",
|
||||
"email": "tituswormer@gmail.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/wooorm/longest-streak/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"deprecated": false,
|
||||
"description": "Count the longest repeating streak of a character",
|
||||
"devDependencies": {
|
||||
"browserify": "^10.0.0",
|
||||
"eslint": "^0.24.0",
|
||||
"esmangle": "^1.0.0",
|
||||
"istanbul": "^0.3.0",
|
||||
"jscs": "^1.0.0",
|
||||
"jscs-jsdoc": "^1.0.0",
|
||||
"mdast": "^0.26.0",
|
||||
"mdast-github": "^0.3.1",
|
||||
"mdast-lint": "^0.4.1",
|
||||
"mdast-yaml-config": "^0.2.0",
|
||||
"mocha": "^2.0.0"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"LICENSE"
|
||||
],
|
||||
"homepage": "https://github.com/wooorm/longest-streak#readme",
|
||||
"keywords": [
|
||||
"count",
|
||||
"length",
|
||||
"longest",
|
||||
"repeating",
|
||||
"streak",
|
||||
"character"
|
||||
],
|
||||
"license": "MIT",
|
||||
"name": "longest-streak",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/wooorm/longest-streak.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run build-md && npm run build-bundle",
|
||||
"build-bundle": "browserify index.js --bare -s longestStreak > longest-streak.js",
|
||||
"build-md": "mdast . LICENSE --output --quiet",
|
||||
"lint": "npm run lint-api && npm run lint-style",
|
||||
"lint-api": "eslint .",
|
||||
"lint-style": "jscs --reporter inline .",
|
||||
"make": "npm run lint && npm run test-coverage",
|
||||
"postbuild-bundle": "esmangle longest-streak.js > longest-streak.min.js",
|
||||
"test": "npm run test-api",
|
||||
"test-api": "mocha --check-leaks test.js",
|
||||
"test-coverage": "istanbul cover _mocha -- --check-leaks test.js",
|
||||
"test-coveralls": "istanbul cover _mocha --report lcovonly -- --check-leaks test.js",
|
||||
"test-travis": "npm run test-coveralls"
|
||||
},
|
||||
"version": "1.0.0"
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
# longest-streak [](https://travis-ci.org/wooorm/longest-streak) [](https://coveralls.io/r/wooorm/longest-streak?branch=master)
|
||||
|
||||
Count the longest repeating streak of a character.
|
||||
|
||||
## Installation
|
||||
|
||||
[npm](https://docs.npmjs.com/cli/install):
|
||||
|
||||
```bash
|
||||
npm install longest-streak
|
||||
```
|
||||
|
||||
**longest-streak** is also available for [bower](http://bower.io/#install-packages),
|
||||
[component](https://github.com/componentjs/component), [duo](http://duojs.org/#getting-started),
|
||||
and for AMD, CommonJS, and globals ([uncompressed](longest-streak.js) and
|
||||
[compressed](longest-streak.min.js)).
|
||||
|
||||
## Usage
|
||||
|
||||
Dependencies.
|
||||
|
||||
```javascript
|
||||
var longestStreak = require('longest-streak');
|
||||
```
|
||||
|
||||
Process:
|
||||
|
||||
```javascript
|
||||
longestStreak('` foo `` bar `', '`') // 2
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### longestStreak(value, character)
|
||||
|
||||
Get the count of the longest repeating streak of `character` in `value`.
|
||||
|
||||
Parameters:
|
||||
|
||||
* `value` (`string`) — Content, coerced to string.
|
||||
* `character` (`string`) — Single character to look for.
|
||||
|
||||
Returns: `number` — Number of characters at the place where `character`
|
||||
occurs in its longest streak in `value`.
|
||||
|
||||
Throws:
|
||||
|
||||
* `Error` — when `character` is not a single character string.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE) @ [Titus Wormer](http://wooorm.com)
|
||||
Generated
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014-2015 Titus Wormer <tituswormer@gmail.com>
|
||||
Copyright (c) 2016 Titus Wormer <tituswormer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<!--remark setext-->
|
||||
|
||||
<!--lint disable no-multiple-toplevel-headings -->
|
||||
|
||||
1.0.0 / 2016-07-16
|
||||
==================
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2016 Titus Wormer
|
||||
* @license MIT
|
||||
* @module markdown-escapes
|
||||
* @fileoverview List of escapable characters in markdown.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* eslint-env commonjs */
|
||||
|
||||
/* Expose. */
|
||||
module.exports = escapes;
|
||||
|
||||
/* Characters. */
|
||||
var defaults = [
|
||||
'\\',
|
||||
'`',
|
||||
'*',
|
||||
'{',
|
||||
'}',
|
||||
'[',
|
||||
']',
|
||||
'(',
|
||||
')',
|
||||
'#',
|
||||
'+',
|
||||
'-',
|
||||
'.',
|
||||
'!',
|
||||
'_',
|
||||
'>'
|
||||
];
|
||||
|
||||
var gfm = defaults.concat(['~', '|']);
|
||||
|
||||
var commonmark = gfm.concat([
|
||||
'\n',
|
||||
'"',
|
||||
'$',
|
||||
'%',
|
||||
'&',
|
||||
'\'',
|
||||
',',
|
||||
'/',
|
||||
':',
|
||||
';',
|
||||
'<',
|
||||
'=',
|
||||
'?',
|
||||
'@',
|
||||
'^'
|
||||
]);
|
||||
|
||||
/* Expose characters. */
|
||||
escapes.default = defaults;
|
||||
escapes.gfm = gfm;
|
||||
escapes.commonmark = commonmark;
|
||||
|
||||
/**
|
||||
* Get markdown escapes.
|
||||
*
|
||||
* @param {Object?} [options] - Configuration.
|
||||
* @return {Array.<string>} - Escapes.
|
||||
*/
|
||||
function escapes(options) {
|
||||
var settings = options || {};
|
||||
|
||||
if (settings.commonmark) {
|
||||
return commonmark;
|
||||
}
|
||||
|
||||
return settings.gfm ? gfm : defaults;
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
{
|
||||
"_from": "markdown-escapes@^1.0.0",
|
||||
"_id": "markdown-escapes@1.0.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-yMoZ8dlNaCRZ4Kk8htsnp+9xayM=",
|
||||
"_location": "/markdown-escapes",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "markdown-escapes@^1.0.0",
|
||||
"name": "markdown-escapes",
|
||||
"escapedName": "markdown-escapes",
|
||||
"rawSpec": "^1.0.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^1.0.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/eslint-plugin-markdown/remark-parse"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.0.tgz",
|
||||
"_shasum": "c8ca19f1d94d682459e0a93c86db27a7ef716b23",
|
||||
"_spec": "markdown-escapes@^1.0.0",
|
||||
"_where": "j:\\temp\\_git\\node-fork\\tools\\eslint\\node_modules\\eslint-plugin-markdown\\node_modules\\remark-parse",
|
||||
"author": {
|
||||
"name": "Titus Wormer",
|
||||
"email": "tituswormer@gmail.com",
|
||||
"url": "http://wooorm.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/wooorm/markdown-escapes/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Titus Wormer",
|
||||
"email": "tituswormer@gmail.com",
|
||||
"url": "http://wooorm.com"
|
||||
}
|
||||
],
|
||||
"dependencies": {},
|
||||
"deprecated": false,
|
||||
"description": "List of escapable characters in markdown",
|
||||
"devDependencies": {
|
||||
"browserify": "^13.0.1",
|
||||
"esmangle": "^1.0.1",
|
||||
"nyc": "^7.0.0",
|
||||
"remark-cli": "^1.0.0",
|
||||
"remark-comment-config": "^4.0.0",
|
||||
"remark-github": "^5.0.0",
|
||||
"remark-lint": "^4.0.0",
|
||||
"remark-validate-links": "^4.0.0",
|
||||
"tape": "^4.0.0",
|
||||
"xo": "^0.16.0"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"homepage": "https://github.com/wooorm/markdown-escapes#readme",
|
||||
"keywords": [
|
||||
"markdown",
|
||||
"escape",
|
||||
"pedantic",
|
||||
"gfm",
|
||||
"commonmark"
|
||||
],
|
||||
"license": "MIT",
|
||||
"name": "markdown-escapes",
|
||||
"nyc": {
|
||||
"check-coverage": true,
|
||||
"lines": 100,
|
||||
"functions": 100,
|
||||
"branches": 100
|
||||
},
|
||||
"remarkConfig": {
|
||||
"output": true,
|
||||
"plugins": [
|
||||
"comment-config",
|
||||
"github",
|
||||
"lint",
|
||||
"validate-links"
|
||||
],
|
||||
"settings": {
|
||||
"bullet": "*"
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/wooorm/markdown-escapes.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run build-md && npm run build-bundle && npm run build-mangle",
|
||||
"build-bundle": "browserify index.js --bare -s markdownEscapes > markdown-escapes.js",
|
||||
"build-mangle": "esmangle < markdown-escapes.js > markdown-escapes.min.js",
|
||||
"build-md": "remark . --quiet --frail",
|
||||
"lint": "xo",
|
||||
"test": "npm run build && npm run lint && npm run test-coverage",
|
||||
"test-api": "node test",
|
||||
"test-coverage": "nyc --reporter lcov tape test.js"
|
||||
},
|
||||
"version": "1.0.0",
|
||||
"xo": {
|
||||
"space": true,
|
||||
"ignores": [
|
||||
"markdown-escapes.js",
|
||||
"markdown-escapes.min.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
# markdown-escapes [![Build Status][travis-badge]][travis] [![Coverage Status][codecov-badge]][codecov]
|
||||
|
||||
<!--lint disable heading-increment no-duplicate-headings-->
|
||||
|
||||
List of escapable characters in markdown.
|
||||
|
||||
## Installation
|
||||
|
||||
[npm][npm-install]:
|
||||
|
||||
```bash
|
||||
npm install markdown-escapes
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
var escapes = require('markdown-escapes');
|
||||
|
||||
// Access by property:
|
||||
escapes.commonmark;
|
||||
// ['\\', '`', ..., '@', '^']
|
||||
|
||||
// Access by options object:
|
||||
escapes({gfm: true});
|
||||
// ['\\', '`', ..., '~', '|']
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### `escapes([options])`
|
||||
|
||||
Get escapes. Supports `options.commonmark` and `options.gfm`, which
|
||||
when `true` returns the extra escape characters supported by those
|
||||
flavours.
|
||||
|
||||
###### Returns
|
||||
|
||||
`Array.<string>`.
|
||||
|
||||
### `escapes.default`
|
||||
|
||||
List of default escapable characters.
|
||||
|
||||
### `escapes.gfm`
|
||||
|
||||
List of escapable characters in GFM (which includes all `default`s).
|
||||
|
||||
### `escapes.commonmark`
|
||||
|
||||
List of escapable characters in CommonMark (which includes all `gfm`s).
|
||||
|
||||
## License
|
||||
|
||||
[MIT][license] © [Titus Wormer][author]
|
||||
|
||||
<!-- Definitions -->
|
||||
|
||||
[travis-badge]: https://img.shields.io/travis/wooorm/markdown-escapes.svg
|
||||
|
||||
[travis]: https://travis-ci.org/wooorm/markdown-escapes
|
||||
|
||||
[codecov-badge]: https://img.shields.io/codecov/c/github/wooorm/markdown-escapes.svg
|
||||
|
||||
[codecov]: https://codecov.io/github/wooorm/markdown-escapes
|
||||
|
||||
[npm-install]: https://docs.npmjs.com/cli/install
|
||||
|
||||
[license]: LICENSE
|
||||
|
||||
[author]: http://wooorm.com
|
||||
-132
@@ -1,132 +0,0 @@
|
||||
# markdown-table [](https://travis-ci.org/wooorm/markdown-table) [](https://coveralls.io/r/wooorm/markdown-table?branch=master)
|
||||
|
||||
Generate fancy [Markdown](https://help.github.com/articles/github-flavored-markdown/#tables)/ASCII tables.
|
||||
|
||||
## Installation
|
||||
|
||||
[npm](https://docs.npmjs.com/cli/install):
|
||||
|
||||
```bash
|
||||
$ npm install markdown-table
|
||||
```
|
||||
|
||||
[Component.js](https://github.com/componentjs/component):
|
||||
|
||||
```bash
|
||||
$ component install wooorm/markdown-table
|
||||
```
|
||||
|
||||
[Bower](http://bower.io/#install-packages):
|
||||
|
||||
```bash
|
||||
$ bower install markdown-table
|
||||
```
|
||||
|
||||
[Duo](http://duojs.org/#getting-started):
|
||||
|
||||
```javascript
|
||||
var table = require('wooorm/markdown-table');
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
var table = require('markdown-table');
|
||||
|
||||
/**
|
||||
* Normal usage (defaults to left-alignment):
|
||||
*/
|
||||
|
||||
table([
|
||||
['Branch', 'Commit'],
|
||||
['master', '0123456789abcdef'],
|
||||
['staging', 'fedcba9876543210']
|
||||
]);
|
||||
/*
|
||||
* | Branch | Commit |
|
||||
* | ------- | ---------------- |
|
||||
* | master | 0123456789abcdef |
|
||||
* | staging | fedcba9876543210 |
|
||||
*/
|
||||
|
||||
/**
|
||||
* With alignment:
|
||||
*/
|
||||
|
||||
table([
|
||||
['Beep', 'No.', 'Boop'],
|
||||
['beep', '1024', 'xyz'],
|
||||
['boop', '3388450', 'tuv'],
|
||||
['foo', '10106', 'qrstuv'],
|
||||
['bar', '45', 'lmno']
|
||||
], {
|
||||
'align': ['l', 'c', 'r']
|
||||
});
|
||||
/*
|
||||
* | Beep | No. | Boop |
|
||||
* | :--- | :-----: | -----: |
|
||||
* | beep | 1024 | xyz |
|
||||
* | boop | 3388450 | tuv |
|
||||
* | foo | 10106 | qrstuv |
|
||||
* | bar | 45 | lmno |
|
||||
*/
|
||||
|
||||
/**
|
||||
* Alignment on dots:
|
||||
*/
|
||||
|
||||
table([
|
||||
['No.'],
|
||||
['0.1.2'],
|
||||
['11.22.33'],
|
||||
['5.6.'],
|
||||
['1.22222'],
|
||||
], {
|
||||
'align': '.'
|
||||
});
|
||||
/*
|
||||
* | No. |
|
||||
* | :---------: |
|
||||
* | 0.1.2 |
|
||||
* | 11.22.33 |
|
||||
* | 5.6. |
|
||||
* | 1.22222 |
|
||||
*/
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### markdownTable(table, options?)
|
||||
|
||||
Turns a given matrix of strings (an array of arrays of strings) into a table.
|
||||
|
||||
The following options are available:
|
||||
|
||||
- `options.align` — String or array of strings, the strings being either `"l"` (left), `"r"` (right), `c` (center), or `.` (dot). Other values are treated as `""`, which doesn’t place the colon but does left align. _Only the lowercased first character is used, so `Right` is fine_;
|
||||
- `options.delimiter` — Value to insert between cells. Carefull, non-pipe values will break GitHub Flavored Markdown;
|
||||
- `options.start` — Value to insert at the beginning of every row.
|
||||
- `options.end` — Value to insert at the end of every row.
|
||||
- `options.rule` — Whether to display a rule between the header and the body of the table. Carefull, will break GitHub Flavored Markdown when `false`;
|
||||
- `options.stringLength` — The method to detect the length of a cell (see below).
|
||||
|
||||
### options.stringLength(cell)
|
||||
|
||||
ANSI-sequences mess up tables on terminals. To fix this, you have to pass in a `stringLength` option to detect the “visible” length of a cell.
|
||||
|
||||
```javascript
|
||||
var chalk = require('chalk');
|
||||
|
||||
function stringLength(cell) {
|
||||
return chalk.stripColor(cell).length;
|
||||
}
|
||||
```
|
||||
|
||||
See the [tests for an example](test.js#L368-L375).
|
||||
|
||||
## Inspiration
|
||||
|
||||
The original idea and basic implementation was inspired by James Halliday's [text-table](https://github.com/substack/text-table) library.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE) © [Titus Wormer](http://wooorm.com)
|
||||
-284
@@ -1,284 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
* Useful expressions.
|
||||
*/
|
||||
|
||||
var EXPRESSION_DOT = /\./;
|
||||
var EXPRESSION_LAST_DOT = /\.[^.]*$/;
|
||||
|
||||
/*
|
||||
* Allowed alignment values.
|
||||
*/
|
||||
|
||||
var LEFT = 'l';
|
||||
var RIGHT = 'r';
|
||||
var CENTER = 'c';
|
||||
var DOT = '.';
|
||||
var NULL = '';
|
||||
|
||||
var ALLIGNMENT = [LEFT, RIGHT, CENTER, DOT, NULL];
|
||||
|
||||
/*
|
||||
* Characters.
|
||||
*/
|
||||
|
||||
var COLON = ':';
|
||||
var DASH = '-';
|
||||
var PIPE = '|';
|
||||
var SPACE = ' ';
|
||||
var NEW_LINE = '\n';
|
||||
|
||||
/**
|
||||
* Get the length of `value`.
|
||||
*
|
||||
* @param {string} value
|
||||
* @return {number}
|
||||
*/
|
||||
function lengthNoop(value) {
|
||||
return String(value).length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string consisting of `length` `character`s.
|
||||
*
|
||||
* @param {number} length
|
||||
* @param {string} [character=' ']
|
||||
* @return {string}
|
||||
*/
|
||||
function pad(length, character) {
|
||||
return Array(length + 1).join(character || SPACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position of the last dot in `value`.
|
||||
*
|
||||
* @param {string} value
|
||||
* @return {number}
|
||||
*/
|
||||
function dotindex(value) {
|
||||
var match = EXPRESSION_LAST_DOT.exec(value);
|
||||
|
||||
return match ? match.index + 1 : value.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a table from a matrix of strings.
|
||||
*
|
||||
* @param {Array.<Array.<string>>} table
|
||||
* @param {Object?} options
|
||||
* @param {boolean?} [options.rule=true]
|
||||
* @param {string?} [options.delimiter=" | "]
|
||||
* @param {string?} [options.start="| "]
|
||||
* @param {string?} [options.end=" |"]
|
||||
* @param {Array.<string>?} options.align
|
||||
* @param {function(string)?} options.stringLength
|
||||
* @return {string} Pretty table
|
||||
*/
|
||||
function markdownTable(table, options) {
|
||||
var settings = options || {};
|
||||
var delimiter = settings.delimiter;
|
||||
var start = settings.start;
|
||||
var end = settings.end;
|
||||
var alignment = settings.align;
|
||||
var calculateStringLength = settings.stringLength || lengthNoop;
|
||||
var cellCount = 0;
|
||||
var rowIndex = -1;
|
||||
var rowLength = table.length;
|
||||
var sizes = [];
|
||||
var align;
|
||||
var rule;
|
||||
var rows;
|
||||
var row;
|
||||
var cells;
|
||||
var index;
|
||||
var position;
|
||||
var size;
|
||||
var value;
|
||||
var spacing;
|
||||
var before;
|
||||
var after;
|
||||
|
||||
alignment = alignment ? alignment.concat() : [];
|
||||
|
||||
if (delimiter === null || delimiter === undefined) {
|
||||
delimiter = SPACE + PIPE + SPACE;
|
||||
}
|
||||
|
||||
if (start === null || start === undefined) {
|
||||
start = PIPE + SPACE;
|
||||
}
|
||||
|
||||
if (end === null || end === undefined) {
|
||||
end = SPACE + PIPE;
|
||||
}
|
||||
|
||||
while (++rowIndex < rowLength) {
|
||||
row = table[rowIndex];
|
||||
|
||||
index = -1;
|
||||
|
||||
if (row.length > cellCount) {
|
||||
cellCount = row.length;
|
||||
}
|
||||
|
||||
while (++index < cellCount) {
|
||||
position = row[index] ? dotindex(row[index]) : null;
|
||||
|
||||
if (!sizes[index]) {
|
||||
sizes[index] = 3;
|
||||
}
|
||||
|
||||
if (position > sizes[index]) {
|
||||
sizes[index] = position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof alignment === 'string') {
|
||||
alignment = pad(cellCount, alignment).split('');
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure only valid alignments are used.
|
||||
*/
|
||||
|
||||
index = -1;
|
||||
|
||||
while (++index < cellCount) {
|
||||
align = alignment[index];
|
||||
|
||||
if (typeof align === 'string') {
|
||||
align = align.charAt(0).toLowerCase();
|
||||
}
|
||||
|
||||
if (ALLIGNMENT.indexOf(align) === -1) {
|
||||
align = NULL;
|
||||
}
|
||||
|
||||
alignment[index] = align;
|
||||
}
|
||||
|
||||
rowIndex = -1;
|
||||
rows = [];
|
||||
|
||||
while (++rowIndex < rowLength) {
|
||||
row = table[rowIndex];
|
||||
|
||||
index = -1;
|
||||
cells = [];
|
||||
|
||||
while (++index < cellCount) {
|
||||
value = row[index];
|
||||
|
||||
if (value === null || value === undefined) {
|
||||
value = '';
|
||||
} else {
|
||||
value = String(value);
|
||||
}
|
||||
|
||||
if (alignment[index] !== DOT) {
|
||||
cells[index] = value;
|
||||
} else {
|
||||
position = dotindex(value);
|
||||
|
||||
size = sizes[index] +
|
||||
(EXPRESSION_DOT.test(value) ? 0 : 1) -
|
||||
(calculateStringLength(value) - position);
|
||||
|
||||
cells[index] = value + pad(size - 1);
|
||||
}
|
||||
}
|
||||
|
||||
rows[rowIndex] = cells;
|
||||
}
|
||||
|
||||
sizes = [];
|
||||
rowIndex = -1;
|
||||
|
||||
while (++rowIndex < rowLength) {
|
||||
cells = rows[rowIndex];
|
||||
|
||||
index = -1;
|
||||
|
||||
while (++index < cellCount) {
|
||||
value = cells[index];
|
||||
|
||||
if (!sizes[index]) {
|
||||
sizes[index] = 3;
|
||||
}
|
||||
|
||||
size = calculateStringLength(value);
|
||||
|
||||
if (size > sizes[index]) {
|
||||
sizes[index] = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rowIndex = -1;
|
||||
|
||||
while (++rowIndex < rowLength) {
|
||||
cells = rows[rowIndex];
|
||||
|
||||
index = -1;
|
||||
|
||||
while (++index < cellCount) {
|
||||
value = cells[index];
|
||||
|
||||
position = sizes[index] - (calculateStringLength(value) || 0);
|
||||
spacing = pad(position);
|
||||
|
||||
if (alignment[index] === RIGHT || alignment[index] === DOT) {
|
||||
value = spacing + value;
|
||||
} else if (alignment[index] !== CENTER) {
|
||||
value = value + spacing;
|
||||
} else {
|
||||
position = position / 2;
|
||||
|
||||
if (position % 1 === 0) {
|
||||
before = position;
|
||||
after = position;
|
||||
} else {
|
||||
before = position + 0.5;
|
||||
after = position - 0.5;
|
||||
}
|
||||
|
||||
value = pad(before) + value + pad(after);
|
||||
}
|
||||
|
||||
cells[index] = value;
|
||||
}
|
||||
|
||||
rows[rowIndex] = cells.join(delimiter);
|
||||
}
|
||||
|
||||
if (settings.rule !== false) {
|
||||
index = -1;
|
||||
rule = [];
|
||||
|
||||
while (++index < cellCount) {
|
||||
align = alignment[index];
|
||||
|
||||
/*
|
||||
* When `align` is left, don't add colons.
|
||||
*/
|
||||
|
||||
value = align === RIGHT || align === NULL ? DASH : COLON;
|
||||
value += pad(sizes[index] - 2, DASH);
|
||||
value += align !== LEFT && align !== NULL ? COLON : DASH;
|
||||
|
||||
rule[index] = value;
|
||||
}
|
||||
|
||||
rows.splice(1, 0, rule.join(delimiter));
|
||||
}
|
||||
|
||||
return start + rows.join(end + NEW_LINE + start) + end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose `markdownTable`.
|
||||
*/
|
||||
|
||||
module.exports = markdownTable;
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
{
|
||||
"_from": "markdown-table@^0.4.0",
|
||||
"_id": "markdown-table@0.4.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-iQwsGzv+g/sA5BKbjkz+ZFJw+dE=",
|
||||
"_location": "/markdown-table",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "markdown-table@^0.4.0",
|
||||
"name": "markdown-table",
|
||||
"escapedName": "markdown-table",
|
||||
"rawSpec": "^0.4.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^0.4.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/remark-stringify"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-0.4.0.tgz",
|
||||
"_shasum": "890c2c1b3bfe83fb00e4129b8e4cfe645270f9d1",
|
||||
"_spec": "markdown-table@^0.4.0",
|
||||
"_where": "/Users/trott/io.js/tools/eslint-tmp/node_modules/eslint/node_modules/remark-stringify",
|
||||
"author": {
|
||||
"name": "Titus Wormer",
|
||||
"email": "tituswormer@gmail.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/wooorm/markdown-table/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"deprecated": false,
|
||||
"description": "Markdown/ASCII tables",
|
||||
"devDependencies": {
|
||||
"chalk": "^1.0.0",
|
||||
"eslint": "^0.18.0",
|
||||
"istanbul": "^0.3.0",
|
||||
"jscs": "^1.0.0",
|
||||
"jscs-jsdoc": "^0.4.0",
|
||||
"mocha": "^2.0.0"
|
||||
},
|
||||
"homepage": "https://github.com/wooorm/markdown-table#readme",
|
||||
"keywords": [
|
||||
"text",
|
||||
"markdown",
|
||||
"table",
|
||||
"align",
|
||||
"ascii",
|
||||
"rows",
|
||||
"tabular"
|
||||
],
|
||||
"license": "MIT",
|
||||
"name": "markdown-table",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/wooorm/markdown-table.git"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "npm run lint-api && npm run lint-test && npm run lint-style",
|
||||
"lint-api": "eslint index.js",
|
||||
"lint-style": "jscs --reporter inline index.js test.js",
|
||||
"lint-test": "eslint --env mocha test.js",
|
||||
"make": "npm run lint && npm run test-coverage",
|
||||
"test": "npm run test-api",
|
||||
"test-api": "_mocha --check-leaks test.js",
|
||||
"test-coverage": "istanbul cover _mocha -- -- test.js",
|
||||
"test-coveralls": "istanbul cover _mocha --report lcovonly -- --check-leaks test.js",
|
||||
"test-travis": "npm run test-coveralls"
|
||||
},
|
||||
"version": "0.4.0"
|
||||
}
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
<p align="center">
|
||||
<a href="https://github.com/inikulin/parse5">
|
||||
<img src="https://raw.github.com/inikulin/parse5/master/docs/logo.png" alt="parse5" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<i>WHATWG HTML5 specification-compliant, fast and ready for production HTML parsing/serialization toolset for Node.js</i>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.org/inikulin/parse5"><img alt="Build Status" src="https://api.travis-ci.org/inikulin/parse5.svg"></a>
|
||||
<a href="https://www.npmjs.com/package/parse5"><img alt="NPM Version" src="https://img.shields.io/npm/v/parse5.svg"></a>
|
||||
<a href="https://npmjs.org/package/parse5"><img alt="Downloads" src="http://img.shields.io/npm/dm/parse5.svg"></a>
|
||||
<a href="https://npmjs.org/package/parse5"><img alt="Downloads total" src="http://img.shields.io/npm/dt/parse5.svg"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b><i>parse5</i></b> provides nearly everything you may need when dealing with HTML. It's the fastest spec-compliant HTML parser
|
||||
for Node to date. It parses HTML the way the latest version of your browser does. It has proven itself reliable in such projects
|
||||
as <a href="https://github.com/tmpvar/jsdom">jsdom</a>, <a href="https://github.com/angular/angular">Angular2</a>, <a href="https://www.polymer-project.org">Polymer</a> and many more.
|
||||
</p>
|
||||
|
||||
----
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/inikulin/parse5/wiki/Documentation">Documentation</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/inikulin/parse5/wiki/Documentation#version-history">Version history</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="http://astexplorer.net/#/1CHlCXc4n4">Online playground</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/inikulin/parse5/issues">Issue tracker</a>
|
||||
</p>
|
||||
-137
@@ -1,137 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
//Const
|
||||
var VALID_DOCTYPE_NAME = 'html',
|
||||
QUIRKS_MODE_SYSTEM_ID = 'http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd',
|
||||
QUIRKS_MODE_PUBLIC_ID_PREFIXES = [
|
||||
'+//silmaril//dtd html pro v0r11 19970101//en',
|
||||
'-//advasoft ltd//dtd html 3.0 aswedit + extensions//en',
|
||||
'-//as//dtd html 3.0 aswedit + extensions//en',
|
||||
'-//ietf//dtd html 2.0 level 1//en',
|
||||
'-//ietf//dtd html 2.0 level 2//en',
|
||||
'-//ietf//dtd html 2.0 strict level 1//en',
|
||||
'-//ietf//dtd html 2.0 strict level 2//en',
|
||||
'-//ietf//dtd html 2.0 strict//en',
|
||||
'-//ietf//dtd html 2.0//en',
|
||||
'-//ietf//dtd html 2.1e//en',
|
||||
'-//ietf//dtd html 3.0//en',
|
||||
'-//ietf//dtd html 3.0//en//',
|
||||
'-//ietf//dtd html 3.2 final//en',
|
||||
'-//ietf//dtd html 3.2//en',
|
||||
'-//ietf//dtd html 3//en',
|
||||
'-//ietf//dtd html level 0//en',
|
||||
'-//ietf//dtd html level 0//en//2.0',
|
||||
'-//ietf//dtd html level 1//en',
|
||||
'-//ietf//dtd html level 1//en//2.0',
|
||||
'-//ietf//dtd html level 2//en',
|
||||
'-//ietf//dtd html level 2//en//2.0',
|
||||
'-//ietf//dtd html level 3//en',
|
||||
'-//ietf//dtd html level 3//en//3.0',
|
||||
'-//ietf//dtd html strict level 0//en',
|
||||
'-//ietf//dtd html strict level 0//en//2.0',
|
||||
'-//ietf//dtd html strict level 1//en',
|
||||
'-//ietf//dtd html strict level 1//en//2.0',
|
||||
'-//ietf//dtd html strict level 2//en',
|
||||
'-//ietf//dtd html strict level 2//en//2.0',
|
||||
'-//ietf//dtd html strict level 3//en',
|
||||
'-//ietf//dtd html strict level 3//en//3.0',
|
||||
'-//ietf//dtd html strict//en',
|
||||
'-//ietf//dtd html strict//en//2.0',
|
||||
'-//ietf//dtd html strict//en//3.0',
|
||||
'-//ietf//dtd html//en',
|
||||
'-//ietf//dtd html//en//2.0',
|
||||
'-//ietf//dtd html//en//3.0',
|
||||
'-//metrius//dtd metrius presentational//en',
|
||||
'-//microsoft//dtd internet explorer 2.0 html strict//en',
|
||||
'-//microsoft//dtd internet explorer 2.0 html//en',
|
||||
'-//microsoft//dtd internet explorer 2.0 tables//en',
|
||||
'-//microsoft//dtd internet explorer 3.0 html strict//en',
|
||||
'-//microsoft//dtd internet explorer 3.0 html//en',
|
||||
'-//microsoft//dtd internet explorer 3.0 tables//en',
|
||||
'-//netscape comm. corp.//dtd html//en',
|
||||
'-//netscape comm. corp.//dtd strict html//en',
|
||||
'-//o\'reilly and associates//dtd html 2.0//en',
|
||||
'-//o\'reilly and associates//dtd html extended 1.0//en',
|
||||
'-//spyglass//dtd html 2.0 extended//en',
|
||||
'-//sq//dtd html 2.0 hotmetal + extensions//en',
|
||||
'-//sun microsystems corp.//dtd hotjava html//en',
|
||||
'-//sun microsystems corp.//dtd hotjava strict html//en',
|
||||
'-//w3c//dtd html 3 1995-03-24//en',
|
||||
'-//w3c//dtd html 3.2 draft//en',
|
||||
'-//w3c//dtd html 3.2 final//en',
|
||||
'-//w3c//dtd html 3.2//en',
|
||||
'-//w3c//dtd html 3.2s draft//en',
|
||||
'-//w3c//dtd html 4.0 frameset//en',
|
||||
'-//w3c//dtd html 4.0 transitional//en',
|
||||
'-//w3c//dtd html experimental 19960712//en',
|
||||
'-//w3c//dtd html experimental 970421//en',
|
||||
'-//w3c//dtd w3 html//en',
|
||||
'-//w3o//dtd w3 html 3.0//en',
|
||||
'-//w3o//dtd w3 html 3.0//en//',
|
||||
'-//webtechs//dtd mozilla html 2.0//en',
|
||||
'-//webtechs//dtd mozilla html//en'
|
||||
],
|
||||
QUIRKS_MODE_NO_SYSTEM_ID_PUBLIC_ID_PREFIXES = [
|
||||
'-//w3c//dtd html 4.01 frameset//',
|
||||
'-//w3c//dtd html 4.01 transitional//'
|
||||
],
|
||||
QUIRKS_MODE_PUBLIC_IDS = [
|
||||
'-//w3o//dtd w3 html strict 3.0//en//',
|
||||
'-/w3c/dtd html 4.0 transitional/en',
|
||||
'html'
|
||||
];
|
||||
|
||||
|
||||
//Utils
|
||||
function enquoteDoctypeId(id) {
|
||||
var quote = id.indexOf('"') !== -1 ? '\'' : '"';
|
||||
|
||||
return quote + id + quote;
|
||||
}
|
||||
|
||||
|
||||
//API
|
||||
exports.isQuirks = function (name, publicId, systemId) {
|
||||
if (name !== VALID_DOCTYPE_NAME)
|
||||
return true;
|
||||
|
||||
if (systemId && systemId.toLowerCase() === QUIRKS_MODE_SYSTEM_ID)
|
||||
return true;
|
||||
|
||||
if (publicId !== null) {
|
||||
publicId = publicId.toLowerCase();
|
||||
|
||||
if (QUIRKS_MODE_PUBLIC_IDS.indexOf(publicId) > -1)
|
||||
return true;
|
||||
|
||||
var prefixes = QUIRKS_MODE_PUBLIC_ID_PREFIXES;
|
||||
|
||||
if (systemId === null)
|
||||
prefixes = prefixes.concat(QUIRKS_MODE_NO_SYSTEM_ID_PUBLIC_ID_PREFIXES);
|
||||
|
||||
for (var i = 0; i < prefixes.length; i++) {
|
||||
if (publicId.indexOf(prefixes[i]) === 0)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
exports.serializeContent = function (name, publicId, systemId) {
|
||||
var str = '!DOCTYPE ';
|
||||
|
||||
if (name)
|
||||
str += name;
|
||||
|
||||
if (publicId !== null)
|
||||
str += ' PUBLIC ' + enquoteDoctypeId(publicId);
|
||||
|
||||
else if (systemId !== null)
|
||||
str += ' SYSTEM';
|
||||
|
||||
if (systemId !== null)
|
||||
str += ' ' + enquoteDoctypeId(systemId);
|
||||
|
||||
return str;
|
||||
};
|
||||
-260
@@ -1,260 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var Tokenizer = require('../tokenizer'),
|
||||
HTML = require('./html');
|
||||
|
||||
//Aliases
|
||||
var $ = HTML.TAG_NAMES,
|
||||
NS = HTML.NAMESPACES,
|
||||
ATTRS = HTML.ATTRS;
|
||||
|
||||
|
||||
//MIME types
|
||||
var MIME_TYPES = {
|
||||
TEXT_HTML: 'text/html',
|
||||
APPLICATION_XML: 'application/xhtml+xml'
|
||||
};
|
||||
|
||||
//Attributes
|
||||
var DEFINITION_URL_ATTR = 'definitionurl',
|
||||
ADJUSTED_DEFINITION_URL_ATTR = 'definitionURL',
|
||||
SVG_ATTRS_ADJUSTMENT_MAP = {
|
||||
'attributename': 'attributeName',
|
||||
'attributetype': 'attributeType',
|
||||
'basefrequency': 'baseFrequency',
|
||||
'baseprofile': 'baseProfile',
|
||||
'calcmode': 'calcMode',
|
||||
'clippathunits': 'clipPathUnits',
|
||||
'diffuseconstant': 'diffuseConstant',
|
||||
'edgemode': 'edgeMode',
|
||||
'filterunits': 'filterUnits',
|
||||
'glyphref': 'glyphRef',
|
||||
'gradienttransform': 'gradientTransform',
|
||||
'gradientunits': 'gradientUnits',
|
||||
'kernelmatrix': 'kernelMatrix',
|
||||
'kernelunitlength': 'kernelUnitLength',
|
||||
'keypoints': 'keyPoints',
|
||||
'keysplines': 'keySplines',
|
||||
'keytimes': 'keyTimes',
|
||||
'lengthadjust': 'lengthAdjust',
|
||||
'limitingconeangle': 'limitingConeAngle',
|
||||
'markerheight': 'markerHeight',
|
||||
'markerunits': 'markerUnits',
|
||||
'markerwidth': 'markerWidth',
|
||||
'maskcontentunits': 'maskContentUnits',
|
||||
'maskunits': 'maskUnits',
|
||||
'numoctaves': 'numOctaves',
|
||||
'pathlength': 'pathLength',
|
||||
'patterncontentunits': 'patternContentUnits',
|
||||
'patterntransform': 'patternTransform',
|
||||
'patternunits': 'patternUnits',
|
||||
'pointsatx': 'pointsAtX',
|
||||
'pointsaty': 'pointsAtY',
|
||||
'pointsatz': 'pointsAtZ',
|
||||
'preservealpha': 'preserveAlpha',
|
||||
'preserveaspectratio': 'preserveAspectRatio',
|
||||
'primitiveunits': 'primitiveUnits',
|
||||
'refx': 'refX',
|
||||
'refy': 'refY',
|
||||
'repeatcount': 'repeatCount',
|
||||
'repeatdur': 'repeatDur',
|
||||
'requiredextensions': 'requiredExtensions',
|
||||
'requiredfeatures': 'requiredFeatures',
|
||||
'specularconstant': 'specularConstant',
|
||||
'specularexponent': 'specularExponent',
|
||||
'spreadmethod': 'spreadMethod',
|
||||
'startoffset': 'startOffset',
|
||||
'stddeviation': 'stdDeviation',
|
||||
'stitchtiles': 'stitchTiles',
|
||||
'surfacescale': 'surfaceScale',
|
||||
'systemlanguage': 'systemLanguage',
|
||||
'tablevalues': 'tableValues',
|
||||
'targetx': 'targetX',
|
||||
'targety': 'targetY',
|
||||
'textlength': 'textLength',
|
||||
'viewbox': 'viewBox',
|
||||
'viewtarget': 'viewTarget',
|
||||
'xchannelselector': 'xChannelSelector',
|
||||
'ychannelselector': 'yChannelSelector',
|
||||
'zoomandpan': 'zoomAndPan'
|
||||
},
|
||||
XML_ATTRS_ADJUSTMENT_MAP = {
|
||||
'xlink:actuate': {prefix: 'xlink', name: 'actuate', namespace: NS.XLINK},
|
||||
'xlink:arcrole': {prefix: 'xlink', name: 'arcrole', namespace: NS.XLINK},
|
||||
'xlink:href': {prefix: 'xlink', name: 'href', namespace: NS.XLINK},
|
||||
'xlink:role': {prefix: 'xlink', name: 'role', namespace: NS.XLINK},
|
||||
'xlink:show': {prefix: 'xlink', name: 'show', namespace: NS.XLINK},
|
||||
'xlink:title': {prefix: 'xlink', name: 'title', namespace: NS.XLINK},
|
||||
'xlink:type': {prefix: 'xlink', name: 'type', namespace: NS.XLINK},
|
||||
'xml:base': {prefix: 'xml', name: 'base', namespace: NS.XML},
|
||||
'xml:lang': {prefix: 'xml', name: 'lang', namespace: NS.XML},
|
||||
'xml:space': {prefix: 'xml', name: 'space', namespace: NS.XML},
|
||||
'xmlns': {prefix: '', name: 'xmlns', namespace: NS.XMLNS},
|
||||
'xmlns:xlink': {prefix: 'xmlns', name: 'xlink', namespace: NS.XMLNS}
|
||||
|
||||
};
|
||||
|
||||
//SVG tag names adjustment map
|
||||
var SVG_TAG_NAMES_ADJUSTMENT_MAP = exports.SVG_TAG_NAMES_ADJUSTMENT_MAP = {
|
||||
'altglyph': 'altGlyph',
|
||||
'altglyphdef': 'altGlyphDef',
|
||||
'altglyphitem': 'altGlyphItem',
|
||||
'animatecolor': 'animateColor',
|
||||
'animatemotion': 'animateMotion',
|
||||
'animatetransform': 'animateTransform',
|
||||
'clippath': 'clipPath',
|
||||
'feblend': 'feBlend',
|
||||
'fecolormatrix': 'feColorMatrix',
|
||||
'fecomponenttransfer': 'feComponentTransfer',
|
||||
'fecomposite': 'feComposite',
|
||||
'feconvolvematrix': 'feConvolveMatrix',
|
||||
'fediffuselighting': 'feDiffuseLighting',
|
||||
'fedisplacementmap': 'feDisplacementMap',
|
||||
'fedistantlight': 'feDistantLight',
|
||||
'feflood': 'feFlood',
|
||||
'fefunca': 'feFuncA',
|
||||
'fefuncb': 'feFuncB',
|
||||
'fefuncg': 'feFuncG',
|
||||
'fefuncr': 'feFuncR',
|
||||
'fegaussianblur': 'feGaussianBlur',
|
||||
'feimage': 'feImage',
|
||||
'femerge': 'feMerge',
|
||||
'femergenode': 'feMergeNode',
|
||||
'femorphology': 'feMorphology',
|
||||
'feoffset': 'feOffset',
|
||||
'fepointlight': 'fePointLight',
|
||||
'fespecularlighting': 'feSpecularLighting',
|
||||
'fespotlight': 'feSpotLight',
|
||||
'fetile': 'feTile',
|
||||
'feturbulence': 'feTurbulence',
|
||||
'foreignobject': 'foreignObject',
|
||||
'glyphref': 'glyphRef',
|
||||
'lineargradient': 'linearGradient',
|
||||
'radialgradient': 'radialGradient',
|
||||
'textpath': 'textPath'
|
||||
};
|
||||
|
||||
//Tags that causes exit from foreign content
|
||||
var EXITS_FOREIGN_CONTENT = {};
|
||||
|
||||
EXITS_FOREIGN_CONTENT[$.B] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.BIG] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.BLOCKQUOTE] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.BODY] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.BR] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.CENTER] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.CODE] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.DD] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.DIV] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.DL] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.DT] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.EM] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.EMBED] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.H1] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.H2] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.H3] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.H4] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.H5] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.H6] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.HEAD] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.HR] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.I] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.IMG] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.LI] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.LISTING] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.MENU] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.META] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.NOBR] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.OL] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.P] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.PRE] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.RUBY] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.S] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.SMALL] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.SPAN] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.STRONG] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.STRIKE] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.SUB] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.SUP] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.TABLE] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.TT] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.U] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.UL] = true;
|
||||
EXITS_FOREIGN_CONTENT[$.VAR] = true;
|
||||
|
||||
//Check exit from foreign content
|
||||
exports.causesExit = function (startTagToken) {
|
||||
var tn = startTagToken.tagName;
|
||||
var isFontWithAttrs = tn === $.FONT && (Tokenizer.getTokenAttr(startTagToken, ATTRS.COLOR) !== null ||
|
||||
Tokenizer.getTokenAttr(startTagToken, ATTRS.SIZE) !== null ||
|
||||
Tokenizer.getTokenAttr(startTagToken, ATTRS.FACE) !== null);
|
||||
|
||||
return isFontWithAttrs ? true : EXITS_FOREIGN_CONTENT[tn];
|
||||
};
|
||||
|
||||
//Token adjustments
|
||||
exports.adjustTokenMathMLAttrs = function (token) {
|
||||
for (var i = 0; i < token.attrs.length; i++) {
|
||||
if (token.attrs[i].name === DEFINITION_URL_ATTR) {
|
||||
token.attrs[i].name = ADJUSTED_DEFINITION_URL_ATTR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.adjustTokenSVGAttrs = function (token) {
|
||||
for (var i = 0; i < token.attrs.length; i++) {
|
||||
var adjustedAttrName = SVG_ATTRS_ADJUSTMENT_MAP[token.attrs[i].name];
|
||||
|
||||
if (adjustedAttrName)
|
||||
token.attrs[i].name = adjustedAttrName;
|
||||
}
|
||||
};
|
||||
|
||||
exports.adjustTokenXMLAttrs = function (token) {
|
||||
for (var i = 0; i < token.attrs.length; i++) {
|
||||
var adjustedAttrEntry = XML_ATTRS_ADJUSTMENT_MAP[token.attrs[i].name];
|
||||
|
||||
if (adjustedAttrEntry) {
|
||||
token.attrs[i].prefix = adjustedAttrEntry.prefix;
|
||||
token.attrs[i].name = adjustedAttrEntry.name;
|
||||
token.attrs[i].namespace = adjustedAttrEntry.namespace;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.adjustTokenSVGTagName = function (token) {
|
||||
var adjustedTagName = SVG_TAG_NAMES_ADJUSTMENT_MAP[token.tagName];
|
||||
|
||||
if (adjustedTagName)
|
||||
token.tagName = adjustedTagName;
|
||||
};
|
||||
|
||||
//Integration points
|
||||
function isMathMLTextIntegrationPoint(tn, ns) {
|
||||
return ns === NS.MATHML && (tn === $.MI || tn === $.MO || tn === $.MN || tn === $.MS || tn === $.MTEXT);
|
||||
}
|
||||
|
||||
function isHtmlIntegrationPoint(tn, ns, attrs) {
|
||||
if (ns === NS.MATHML && tn === $.ANNOTATION_XML) {
|
||||
for (var i = 0; i < attrs.length; i++) {
|
||||
if (attrs[i].name === ATTRS.ENCODING) {
|
||||
var value = attrs[i].value.toLowerCase();
|
||||
|
||||
return value === MIME_TYPES.TEXT_HTML || value === MIME_TYPES.APPLICATION_XML;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ns === NS.SVG && (tn === $.FOREIGN_OBJECT || tn === $.DESC || tn === $.TITLE);
|
||||
}
|
||||
|
||||
exports.isIntegrationPoint = function (tn, ns, attrs, foreignNS) {
|
||||
if ((!foreignNS || foreignNS === NS.HTML) && isHtmlIntegrationPoint(tn, ns, attrs))
|
||||
return true;
|
||||
|
||||
if ((!foreignNS || foreignNS === NS.MATHML) && isMathMLTextIntegrationPoint(tn, ns))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
-266
@@ -1,266 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var NS = exports.NAMESPACES = {
|
||||
HTML: 'http://www.w3.org/1999/xhtml',
|
||||
MATHML: 'http://www.w3.org/1998/Math/MathML',
|
||||
SVG: 'http://www.w3.org/2000/svg',
|
||||
XLINK: 'http://www.w3.org/1999/xlink',
|
||||
XML: 'http://www.w3.org/XML/1998/namespace',
|
||||
XMLNS: 'http://www.w3.org/2000/xmlns/'
|
||||
};
|
||||
|
||||
exports.ATTRS = {
|
||||
TYPE: 'type',
|
||||
ACTION: 'action',
|
||||
ENCODING: 'encoding',
|
||||
PROMPT: 'prompt',
|
||||
NAME: 'name',
|
||||
COLOR: 'color',
|
||||
FACE: 'face',
|
||||
SIZE: 'size'
|
||||
};
|
||||
|
||||
var $ = exports.TAG_NAMES = {
|
||||
A: 'a',
|
||||
ADDRESS: 'address',
|
||||
ANNOTATION_XML: 'annotation-xml',
|
||||
APPLET: 'applet',
|
||||
AREA: 'area',
|
||||
ARTICLE: 'article',
|
||||
ASIDE: 'aside',
|
||||
|
||||
B: 'b',
|
||||
BASE: 'base',
|
||||
BASEFONT: 'basefont',
|
||||
BGSOUND: 'bgsound',
|
||||
BIG: 'big',
|
||||
BLOCKQUOTE: 'blockquote',
|
||||
BODY: 'body',
|
||||
BR: 'br',
|
||||
BUTTON: 'button',
|
||||
|
||||
CAPTION: 'caption',
|
||||
CENTER: 'center',
|
||||
CODE: 'code',
|
||||
COL: 'col',
|
||||
COLGROUP: 'colgroup',
|
||||
|
||||
DD: 'dd',
|
||||
DESC: 'desc',
|
||||
DETAILS: 'details',
|
||||
DIALOG: 'dialog',
|
||||
DIR: 'dir',
|
||||
DIV: 'div',
|
||||
DL: 'dl',
|
||||
DT: 'dt',
|
||||
|
||||
EM: 'em',
|
||||
EMBED: 'embed',
|
||||
|
||||
FIELDSET: 'fieldset',
|
||||
FIGCAPTION: 'figcaption',
|
||||
FIGURE: 'figure',
|
||||
FONT: 'font',
|
||||
FOOTER: 'footer',
|
||||
FOREIGN_OBJECT: 'foreignObject',
|
||||
FORM: 'form',
|
||||
FRAME: 'frame',
|
||||
FRAMESET: 'frameset',
|
||||
|
||||
H1: 'h1',
|
||||
H2: 'h2',
|
||||
H3: 'h3',
|
||||
H4: 'h4',
|
||||
H5: 'h5',
|
||||
H6: 'h6',
|
||||
HEAD: 'head',
|
||||
HEADER: 'header',
|
||||
HGROUP: 'hgroup',
|
||||
HR: 'hr',
|
||||
HTML: 'html',
|
||||
|
||||
I: 'i',
|
||||
IMG: 'img',
|
||||
IMAGE: 'image',
|
||||
INPUT: 'input',
|
||||
IFRAME: 'iframe',
|
||||
|
||||
KEYGEN: 'keygen',
|
||||
|
||||
LABEL: 'label',
|
||||
LI: 'li',
|
||||
LINK: 'link',
|
||||
LISTING: 'listing',
|
||||
|
||||
MAIN: 'main',
|
||||
MALIGNMARK: 'malignmark',
|
||||
MARQUEE: 'marquee',
|
||||
MATH: 'math',
|
||||
MENU: 'menu',
|
||||
MENUITEM: 'menuitem',
|
||||
META: 'meta',
|
||||
MGLYPH: 'mglyph',
|
||||
MI: 'mi',
|
||||
MO: 'mo',
|
||||
MN: 'mn',
|
||||
MS: 'ms',
|
||||
MTEXT: 'mtext',
|
||||
|
||||
NAV: 'nav',
|
||||
NOBR: 'nobr',
|
||||
NOFRAMES: 'noframes',
|
||||
NOEMBED: 'noembed',
|
||||
NOSCRIPT: 'noscript',
|
||||
|
||||
OBJECT: 'object',
|
||||
OL: 'ol',
|
||||
OPTGROUP: 'optgroup',
|
||||
OPTION: 'option',
|
||||
|
||||
P: 'p',
|
||||
PARAM: 'param',
|
||||
PLAINTEXT: 'plaintext',
|
||||
PRE: 'pre',
|
||||
|
||||
RB: 'rb',
|
||||
RP: 'rp',
|
||||
RT: 'rt',
|
||||
RTC: 'rtc',
|
||||
RUBY: 'ruby',
|
||||
|
||||
S: 's',
|
||||
SCRIPT: 'script',
|
||||
SECTION: 'section',
|
||||
SELECT: 'select',
|
||||
SOURCE: 'source',
|
||||
SMALL: 'small',
|
||||
SPAN: 'span',
|
||||
STRIKE: 'strike',
|
||||
STRONG: 'strong',
|
||||
STYLE: 'style',
|
||||
SUB: 'sub',
|
||||
SUMMARY: 'summary',
|
||||
SUP: 'sup',
|
||||
|
||||
TABLE: 'table',
|
||||
TBODY: 'tbody',
|
||||
TEMPLATE: 'template',
|
||||
TEXTAREA: 'textarea',
|
||||
TFOOT: 'tfoot',
|
||||
TD: 'td',
|
||||
TH: 'th',
|
||||
THEAD: 'thead',
|
||||
TITLE: 'title',
|
||||
TR: 'tr',
|
||||
TRACK: 'track',
|
||||
TT: 'tt',
|
||||
|
||||
U: 'u',
|
||||
UL: 'ul',
|
||||
|
||||
SVG: 'svg',
|
||||
|
||||
VAR: 'var',
|
||||
|
||||
WBR: 'wbr',
|
||||
|
||||
XMP: 'xmp'
|
||||
};
|
||||
|
||||
var SPECIAL_ELEMENTS = exports.SPECIAL_ELEMENTS = {};
|
||||
|
||||
SPECIAL_ELEMENTS[NS.HTML] = {};
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.ADDRESS] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.APPLET] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.AREA] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.ARTICLE] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.ASIDE] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.BASE] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.BASEFONT] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.BGSOUND] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.BLOCKQUOTE] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.BODY] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.BR] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.BUTTON] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.CAPTION] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.CENTER] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.COL] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.COLGROUP] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.DD] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.DETAILS] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.DIR] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.DIV] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.DL] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.DT] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.EMBED] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.FIELDSET] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.FIGCAPTION] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.FIGURE] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.FOOTER] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.FORM] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.FRAME] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.FRAMESET] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.H1] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.H2] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.H3] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.H4] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.H5] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.H6] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.HEAD] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.HEADER] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.HGROUP] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.HR] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.HTML] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.IFRAME] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.IMG] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.INPUT] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.LI] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.LINK] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.LISTING] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.MAIN] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.MARQUEE] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.MENU] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.META] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.NAV] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.NOEMBED] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.NOFRAMES] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.NOSCRIPT] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.OBJECT] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.OL] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.P] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.PARAM] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.PLAINTEXT] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.PRE] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.SCRIPT] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.SECTION] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.SELECT] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.SOURCE] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.STYLE] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.SUMMARY] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.TABLE] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.TBODY] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.TD] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.TEMPLATE] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.TEXTAREA] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.TFOOT] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.TH] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.THEAD] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.TITLE] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.TR] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.TRACK] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.UL] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.WBR] = true;
|
||||
SPECIAL_ELEMENTS[NS.HTML][$.XMP] = true;
|
||||
|
||||
SPECIAL_ELEMENTS[NS.MATHML] = {};
|
||||
SPECIAL_ELEMENTS[NS.MATHML][$.MI] = true;
|
||||
SPECIAL_ELEMENTS[NS.MATHML][$.MO] = true;
|
||||
SPECIAL_ELEMENTS[NS.MATHML][$.MN] = true;
|
||||
SPECIAL_ELEMENTS[NS.MATHML][$.MS] = true;
|
||||
SPECIAL_ELEMENTS[NS.MATHML][$.MTEXT] = true;
|
||||
SPECIAL_ELEMENTS[NS.MATHML][$.ANNOTATION_XML] = true;
|
||||
|
||||
SPECIAL_ELEMENTS[NS.SVG] = {};
|
||||
SPECIAL_ELEMENTS[NS.SVG][$.TITLE] = true;
|
||||
SPECIAL_ELEMENTS[NS.SVG][$.FOREIGN_OBJECT] = true;
|
||||
SPECIAL_ELEMENTS[NS.SVG][$.DESC] = true;
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function mergeOptions(defaults, options) {
|
||||
options = options || {};
|
||||
|
||||
return [defaults, options].reduce(function (merged, optObj) {
|
||||
Object.keys(optObj).forEach(function (key) {
|
||||
merged[key] = optObj[key];
|
||||
});
|
||||
|
||||
return merged;
|
||||
}, {});
|
||||
};
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
exports.REPLACEMENT_CHARACTER = '\uFFFD';
|
||||
|
||||
exports.CODE_POINTS = {
|
||||
EOF: -1,
|
||||
NULL: 0x00,
|
||||
TABULATION: 0x09,
|
||||
CARRIAGE_RETURN: 0x0D,
|
||||
LINE_FEED: 0x0A,
|
||||
FORM_FEED: 0x0C,
|
||||
SPACE: 0x20,
|
||||
EXCLAMATION_MARK: 0x21,
|
||||
QUOTATION_MARK: 0x22,
|
||||
NUMBER_SIGN: 0x23,
|
||||
AMPERSAND: 0x26,
|
||||
APOSTROPHE: 0x27,
|
||||
HYPHEN_MINUS: 0x2D,
|
||||
SOLIDUS: 0x2F,
|
||||
DIGIT_0: 0x30,
|
||||
DIGIT_9: 0x39,
|
||||
SEMICOLON: 0x3B,
|
||||
LESS_THAN_SIGN: 0x3C,
|
||||
EQUALS_SIGN: 0x3D,
|
||||
GREATER_THAN_SIGN: 0x3E,
|
||||
QUESTION_MARK: 0x3F,
|
||||
LATIN_CAPITAL_A: 0x41,
|
||||
LATIN_CAPITAL_F: 0x46,
|
||||
LATIN_CAPITAL_X: 0x58,
|
||||
LATIN_CAPITAL_Z: 0x5A,
|
||||
GRAVE_ACCENT: 0x60,
|
||||
LATIN_SMALL_A: 0x61,
|
||||
LATIN_SMALL_F: 0x66,
|
||||
LATIN_SMALL_X: 0x78,
|
||||
LATIN_SMALL_Z: 0x7A,
|
||||
REPLACEMENT_CHARACTER: 0xFFFD
|
||||
};
|
||||
|
||||
exports.CODE_POINT_SEQUENCES = {
|
||||
DASH_DASH_STRING: [0x2D, 0x2D], //--
|
||||
DOCTYPE_STRING: [0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45], //DOCTYPE
|
||||
CDATA_START_STRING: [0x5B, 0x43, 0x44, 0x41, 0x54, 0x41, 0x5B], //[CDATA[
|
||||
CDATA_END_STRING: [0x5D, 0x5D, 0x3E], //]]>
|
||||
SCRIPT_STRING: [0x73, 0x63, 0x72, 0x69, 0x70, 0x74], //script
|
||||
PUBLIC_STRING: [0x50, 0x55, 0x42, 0x4C, 0x49, 0x43], //PUBLIC
|
||||
SYSTEM_STRING: [0x53, 0x59, 0x53, 0x54, 0x45, 0x4D] //SYSTEM
|
||||
};
|
||||
-108
@@ -1,108 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var Parser = require('./parser'),
|
||||
Serializer = require('./serializer');
|
||||
|
||||
/** @namespace parse5 */
|
||||
|
||||
/**
|
||||
* Parses an HTML string.
|
||||
* @function parse
|
||||
* @memberof parse5
|
||||
* @instance
|
||||
* @param {string} html - Input HTML string.
|
||||
* @param {ParserOptions} [options] - Parsing options.
|
||||
* @returns {ASTNode<Document>} document
|
||||
* @example
|
||||
* var parse5 = require('parse5');
|
||||
*
|
||||
* var document = parse5.parse('<!DOCTYPE html><html><head></head><body>Hi there!</body></html>');
|
||||
*/
|
||||
exports.parse = function parse(html, options) {
|
||||
var parser = new Parser(options);
|
||||
|
||||
return parser.parse(html);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses an HTML fragment.
|
||||
* @function parseFragment
|
||||
* @memberof parse5
|
||||
* @instance
|
||||
* @param {ASTNode} [fragmentContext] - Parsing context element. If specified, given fragment
|
||||
* will be parsed as if it was set to the context element's `innerHTML` property.
|
||||
* @param {string} html - Input HTML fragment string.
|
||||
* @param {ParserOptions} [options] - Parsing options.
|
||||
* @returns {ASTNode<DocumentFragment>} documentFragment
|
||||
* @example
|
||||
* var parse5 = require('parse5');
|
||||
*
|
||||
* var documentFragment = parse5.parseFragment('<table></table>');
|
||||
*
|
||||
* // Parses the html fragment in the context of the parsed <table> element.
|
||||
* var trFragment = parser.parseFragment(documentFragment.childNodes[0], '<tr><td>Shake it, baby</td></tr>');
|
||||
*/
|
||||
exports.parseFragment = function parseFragment(fragmentContext, html, options) {
|
||||
if (typeof fragmentContext === 'string') {
|
||||
options = html;
|
||||
html = fragmentContext;
|
||||
fragmentContext = null;
|
||||
}
|
||||
|
||||
var parser = new Parser(options);
|
||||
|
||||
return parser.parseFragment(html, fragmentContext);
|
||||
};
|
||||
|
||||
/**
|
||||
* Serializes an AST node to an HTML string.
|
||||
* @function serialize
|
||||
* @memberof parse5
|
||||
* @instance
|
||||
* @param {ASTNode} node - Node to serialize.
|
||||
* @param {SerializerOptions} [options] - Serialization options.
|
||||
* @returns {String} html
|
||||
* @example
|
||||
* var parse5 = require('parse5');
|
||||
*
|
||||
* var document = parse5.parse('<!DOCTYPE html><html><head></head><body>Hi there!</body></html>');
|
||||
*
|
||||
* // Serializes a document.
|
||||
* var html = parse5.serialize(document);
|
||||
*
|
||||
* // Serializes the <body> element content.
|
||||
* var bodyInnerHtml = parse5.serialize(document.childNodes[0].childNodes[1]);
|
||||
*/
|
||||
exports.serialize = function (node, options) {
|
||||
var serializer = new Serializer(node, options);
|
||||
|
||||
return serializer.serialize();
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides built-in tree adapters that can be used for parsing and serialization.
|
||||
* @var treeAdapters
|
||||
* @memberof parse5
|
||||
* @instance
|
||||
* @property {TreeAdapter} default - Default tree format for parse5.
|
||||
* @property {TreeAdapter} htmlparser2 - Quite popular [htmlparser2](https://github.com/fb55/htmlparser2) tree format
|
||||
* (e.g. used by [cheerio](https://github.com/MatthewMueller/cheerio) and [jsdom](https://github.com/tmpvar/jsdom)).
|
||||
* @example
|
||||
* var parse5 = require('parse5');
|
||||
*
|
||||
* // Uses the default tree adapter for parsing.
|
||||
* var document = parse5.parse('<div></div>', { treeAdapter: parse5.treeAdapters.default });
|
||||
*
|
||||
* // Uses the htmlparser2 tree adapter with the SerializerStream.
|
||||
* var serializer = new parse5.SerializerStream(node, { treeAdapter: parse5.treeAdapters.htmlparser2 });
|
||||
*/
|
||||
exports.treeAdapters = {
|
||||
default: require('./tree_adapters/default'),
|
||||
htmlparser2: require('./tree_adapters/htmlparser2')
|
||||
};
|
||||
|
||||
|
||||
// Streaming
|
||||
exports.ParserStream = require('./parser/stream');
|
||||
exports.SerializerStream = require('./serializer/stream');
|
||||
exports.SAXParser = require('./sax');
|
||||
-217
@@ -1,217 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var OpenElementStack = require('../parser/open_element_stack'),
|
||||
Tokenizer = require('../tokenizer'),
|
||||
HTML = require('../common/html');
|
||||
|
||||
|
||||
//Aliases
|
||||
var $ = HTML.TAG_NAMES;
|
||||
|
||||
|
||||
function setEndLocation(element, closingToken, treeAdapter) {
|
||||
var loc = element.__location;
|
||||
|
||||
if (!loc)
|
||||
return;
|
||||
|
||||
/**
|
||||
* @typedef {Object} ElementLocationInfo
|
||||
* @extends StartTagLocationInfo
|
||||
*
|
||||
* @property {StartTagLocationInfo} startTag - Element's start tag location info.
|
||||
* @property {LocationInfo} endTag - Element's end tag location info.
|
||||
*/
|
||||
if (!loc.startTag) {
|
||||
loc.startTag = {
|
||||
line: loc.line,
|
||||
col: loc.col,
|
||||
startOffset: loc.startOffset,
|
||||
endOffset: loc.endOffset
|
||||
};
|
||||
if (loc.attrs)
|
||||
loc.startTag.attrs = loc.attrs;
|
||||
}
|
||||
|
||||
if (closingToken.location) {
|
||||
var ctLocation = closingToken.location,
|
||||
tn = treeAdapter.getTagName(element),
|
||||
// NOTE: For cases like <p> <p> </p> - First 'p' closes without a closing tag and
|
||||
// for cases like <td> <p> </td> - 'p' closes without a closing tag
|
||||
isClosingEndTag = closingToken.type === Tokenizer.END_TAG_TOKEN &&
|
||||
tn === closingToken.tagName;
|
||||
|
||||
if (isClosingEndTag) {
|
||||
loc.endTag = {
|
||||
line: ctLocation.line,
|
||||
col: ctLocation.col,
|
||||
startOffset: ctLocation.startOffset,
|
||||
endOffset: ctLocation.endOffset
|
||||
};
|
||||
}
|
||||
|
||||
if (isClosingEndTag)
|
||||
loc.endOffset = ctLocation.endOffset;
|
||||
else
|
||||
loc.endOffset = ctLocation.startOffset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
exports.assign = function (parser) {
|
||||
//NOTE: obtain Parser proto this way to avoid module circular references
|
||||
var parserProto = Object.getPrototypeOf(parser),
|
||||
treeAdapter = parser.treeAdapter,
|
||||
attachableElementLocation = null,
|
||||
lastFosterParentingLocation = null,
|
||||
currentToken = null;
|
||||
|
||||
|
||||
//NOTE: patch _bootstrap method
|
||||
parser._bootstrap = function (document, fragmentContext) {
|
||||
parserProto._bootstrap.call(this, document, fragmentContext);
|
||||
|
||||
attachableElementLocation = null;
|
||||
lastFosterParentingLocation = null;
|
||||
currentToken = null;
|
||||
|
||||
//OpenElementStack
|
||||
parser.openElements.pop = function () {
|
||||
setEndLocation(this.current, currentToken, treeAdapter);
|
||||
OpenElementStack.prototype.pop.call(this);
|
||||
};
|
||||
|
||||
parser.openElements.popAllUpToHtmlElement = function () {
|
||||
for (var i = this.stackTop; i > 0; i--)
|
||||
setEndLocation(this.items[i], currentToken, treeAdapter);
|
||||
|
||||
OpenElementStack.prototype.popAllUpToHtmlElement.call(this);
|
||||
};
|
||||
|
||||
parser.openElements.remove = function (element) {
|
||||
setEndLocation(element, currentToken, treeAdapter);
|
||||
OpenElementStack.prototype.remove.call(this, element);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//Token processing
|
||||
parser._processTokenInForeignContent = function (token) {
|
||||
currentToken = token;
|
||||
parserProto._processTokenInForeignContent.call(this, token);
|
||||
};
|
||||
|
||||
parser._processToken = function (token) {
|
||||
currentToken = token;
|
||||
parserProto._processToken.call(this, token);
|
||||
|
||||
//NOTE: <body> and <html> are never popped from the stack, so we need to updated
|
||||
//their end location explicitly.
|
||||
if (token.type === Tokenizer.END_TAG_TOKEN &&
|
||||
(token.tagName === $.HTML ||
|
||||
token.tagName === $.BODY && this.openElements.hasInScope($.BODY))) {
|
||||
for (var i = this.openElements.stackTop; i >= 0; i--) {
|
||||
var element = this.openElements.items[i];
|
||||
|
||||
if (this.treeAdapter.getTagName(element) === token.tagName) {
|
||||
setEndLocation(element, token, treeAdapter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//Doctype
|
||||
parser._setDocumentType = function (token) {
|
||||
parserProto._setDocumentType.call(this, token);
|
||||
|
||||
var documentChildren = this.treeAdapter.getChildNodes(this.document),
|
||||
cnLength = documentChildren.length;
|
||||
|
||||
for (var i = 0; i < cnLength; i++) {
|
||||
var node = documentChildren[i];
|
||||
|
||||
if (this.treeAdapter.isDocumentTypeNode(node)) {
|
||||
node.__location = token.location;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//Elements
|
||||
parser._attachElementToTree = function (element) {
|
||||
//NOTE: _attachElementToTree is called from _appendElement, _insertElement and _insertTemplate methods.
|
||||
//So we will use token location stored in this methods for the element.
|
||||
element.__location = attachableElementLocation || null;
|
||||
attachableElementLocation = null;
|
||||
parserProto._attachElementToTree.call(this, element);
|
||||
};
|
||||
|
||||
parser._appendElement = function (token, namespaceURI) {
|
||||
attachableElementLocation = token.location;
|
||||
parserProto._appendElement.call(this, token, namespaceURI);
|
||||
};
|
||||
|
||||
parser._insertElement = function (token, namespaceURI) {
|
||||
attachableElementLocation = token.location;
|
||||
parserProto._insertElement.call(this, token, namespaceURI);
|
||||
};
|
||||
|
||||
parser._insertTemplate = function (token) {
|
||||
attachableElementLocation = token.location;
|
||||
parserProto._insertTemplate.call(this, token);
|
||||
|
||||
var tmplContent = this.treeAdapter.getTemplateContent(this.openElements.current);
|
||||
|
||||
tmplContent.__location = null;
|
||||
};
|
||||
|
||||
parser._insertFakeRootElement = function () {
|
||||
parserProto._insertFakeRootElement.call(this);
|
||||
this.openElements.current.__location = null;
|
||||
};
|
||||
|
||||
|
||||
//Comments
|
||||
parser._appendCommentNode = function (token, parent) {
|
||||
parserProto._appendCommentNode.call(this, token, parent);
|
||||
|
||||
var children = this.treeAdapter.getChildNodes(parent),
|
||||
commentNode = children[children.length - 1];
|
||||
|
||||
commentNode.__location = token.location;
|
||||
};
|
||||
|
||||
|
||||
//Text
|
||||
parser._findFosterParentingLocation = function () {
|
||||
//NOTE: store last foster parenting location, so we will be able to find inserted text
|
||||
//in case of foster parenting
|
||||
lastFosterParentingLocation = parserProto._findFosterParentingLocation.call(this);
|
||||
return lastFosterParentingLocation;
|
||||
};
|
||||
|
||||
parser._insertCharacters = function (token) {
|
||||
parserProto._insertCharacters.call(this, token);
|
||||
|
||||
var hasFosterParent = this._shouldFosterParentOnInsertion(),
|
||||
parent = hasFosterParent && lastFosterParentingLocation.parent ||
|
||||
this.openElements.currentTmplContent ||
|
||||
this.openElements.current,
|
||||
siblings = this.treeAdapter.getChildNodes(parent),
|
||||
textNodeIdx = hasFosterParent && lastFosterParentingLocation.beforeElement ?
|
||||
siblings.indexOf(lastFosterParentingLocation.beforeElement) - 1 :
|
||||
siblings.length - 1,
|
||||
textNode = siblings[textNodeIdx];
|
||||
|
||||
//NOTE: if we have location assigned by another token, then just update end position
|
||||
if (textNode.__location)
|
||||
textNode.__location.endOffset = token.location.endOffset;
|
||||
|
||||
else
|
||||
textNode.__location = token.location;
|
||||
};
|
||||
};
|
||||
|
||||
-169
@@ -1,169 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var UNICODE = require('../common/unicode');
|
||||
|
||||
//Aliases
|
||||
var $ = UNICODE.CODE_POINTS;
|
||||
|
||||
|
||||
exports.assign = function (tokenizer) {
|
||||
//NOTE: obtain Tokenizer proto this way to avoid module circular references
|
||||
var tokenizerProto = Object.getPrototypeOf(tokenizer),
|
||||
tokenStartOffset = -1,
|
||||
tokenCol = -1,
|
||||
tokenLine = 1,
|
||||
isEol = false,
|
||||
lineStartPosStack = [0],
|
||||
lineStartPos = 0,
|
||||
col = -1,
|
||||
line = 1;
|
||||
|
||||
function attachLocationInfo(token) {
|
||||
/**
|
||||
* @typedef {Object} LocationInfo
|
||||
*
|
||||
* @property {Number} line - One-based line index
|
||||
* @property {Number} col - One-based column index
|
||||
* @property {Number} startOffset - Zero-based first character index
|
||||
* @property {Number} endOffset - Zero-based last character index
|
||||
*/
|
||||
token.location = {
|
||||
line: tokenLine,
|
||||
col: tokenCol,
|
||||
startOffset: tokenStartOffset,
|
||||
endOffset: -1
|
||||
};
|
||||
}
|
||||
|
||||
//NOTE: patch consumption method to track line/col information
|
||||
tokenizer._consume = function () {
|
||||
var cp = tokenizerProto._consume.call(this);
|
||||
|
||||
//NOTE: LF should be in the last column of the line
|
||||
if (isEol) {
|
||||
isEol = false;
|
||||
line++;
|
||||
lineStartPosStack.push(this.preprocessor.sourcePos);
|
||||
lineStartPos = this.preprocessor.sourcePos;
|
||||
}
|
||||
|
||||
if (cp === $.LINE_FEED)
|
||||
isEol = true;
|
||||
|
||||
col = this.preprocessor.sourcePos - lineStartPos + 1;
|
||||
|
||||
return cp;
|
||||
};
|
||||
|
||||
tokenizer._unconsume = function () {
|
||||
tokenizerProto._unconsume.call(this);
|
||||
isEol = false;
|
||||
|
||||
while (lineStartPos > this.preprocessor.sourcePos && lineStartPosStack.length > 1) {
|
||||
lineStartPos = lineStartPosStack.pop();
|
||||
line--;
|
||||
}
|
||||
|
||||
col = this.preprocessor.sourcePos - lineStartPos + 1;
|
||||
};
|
||||
|
||||
//NOTE: patch token creation methods and attach location objects
|
||||
tokenizer._createStartTagToken = function () {
|
||||
tokenizerProto._createStartTagToken.call(this);
|
||||
attachLocationInfo(this.currentToken);
|
||||
};
|
||||
|
||||
tokenizer._createEndTagToken = function () {
|
||||
tokenizerProto._createEndTagToken.call(this);
|
||||
attachLocationInfo(this.currentToken);
|
||||
};
|
||||
|
||||
tokenizer._createCommentToken = function () {
|
||||
tokenizerProto._createCommentToken.call(this);
|
||||
attachLocationInfo(this.currentToken);
|
||||
};
|
||||
|
||||
tokenizer._createDoctypeToken = function (initialName) {
|
||||
tokenizerProto._createDoctypeToken.call(this, initialName);
|
||||
attachLocationInfo(this.currentToken);
|
||||
};
|
||||
|
||||
tokenizer._createCharacterToken = function (type, ch) {
|
||||
tokenizerProto._createCharacterToken.call(this, type, ch);
|
||||
attachLocationInfo(this.currentCharacterToken);
|
||||
};
|
||||
|
||||
tokenizer._createAttr = function (attrNameFirstCh) {
|
||||
tokenizerProto._createAttr.call(this, attrNameFirstCh);
|
||||
this.currentAttrLocation = {
|
||||
line: line,
|
||||
col: col,
|
||||
startOffset: this.preprocessor.sourcePos,
|
||||
endOffset: -1
|
||||
};
|
||||
};
|
||||
|
||||
tokenizer._leaveAttrName = function (toState) {
|
||||
tokenizerProto._leaveAttrName.call(this, toState);
|
||||
this._attachCurrentAttrLocationInfo();
|
||||
};
|
||||
|
||||
tokenizer._leaveAttrValue = function (toState) {
|
||||
tokenizerProto._leaveAttrValue.call(this, toState);
|
||||
this._attachCurrentAttrLocationInfo();
|
||||
};
|
||||
|
||||
tokenizer._attachCurrentAttrLocationInfo = function () {
|
||||
this.currentAttrLocation.endOffset = this.preprocessor.sourcePos;
|
||||
|
||||
if (!this.currentToken.location.attrs)
|
||||
this.currentToken.location.attrs = {};
|
||||
|
||||
/**
|
||||
* @typedef {Object} StartTagLocationInfo
|
||||
* @extends LocationInfo
|
||||
*
|
||||
* @property {Dictionary<String, LocationInfo>} attrs - Start tag attributes' location info.
|
||||
*/
|
||||
this.currentToken.location.attrs[this.currentAttr.name] = this.currentAttrLocation;
|
||||
};
|
||||
|
||||
//NOTE: patch token emission methods to determine end location
|
||||
tokenizer._emitCurrentToken = function () {
|
||||
//NOTE: if we have pending character token make it's end location equal to the
|
||||
//current token's start location.
|
||||
if (this.currentCharacterToken)
|
||||
this.currentCharacterToken.location.endOffset = this.currentToken.location.startOffset;
|
||||
|
||||
this.currentToken.location.endOffset = this.preprocessor.sourcePos + 1;
|
||||
tokenizerProto._emitCurrentToken.call(this);
|
||||
};
|
||||
|
||||
tokenizer._emitCurrentCharacterToken = function () {
|
||||
//NOTE: if we have character token and it's location wasn't set in the _emitCurrentToken(),
|
||||
//then set it's location at the current preprocessor position.
|
||||
//We don't need to increment preprocessor position, since character token
|
||||
//emission is always forced by the start of the next character token here.
|
||||
//So, we already have advanced position.
|
||||
if (this.currentCharacterToken && this.currentCharacterToken.location.endOffset === -1)
|
||||
this.currentCharacterToken.location.endOffset = this.preprocessor.sourcePos;
|
||||
|
||||
tokenizerProto._emitCurrentCharacterToken.call(this);
|
||||
};
|
||||
|
||||
//NOTE: patch initial states for each mode to obtain token start position
|
||||
Object.keys(tokenizerProto.MODE)
|
||||
|
||||
.map(function (modeName) {
|
||||
return tokenizerProto.MODE[modeName];
|
||||
})
|
||||
|
||||
.forEach(function (state) {
|
||||
tokenizer[state] = function (cp) {
|
||||
tokenStartOffset = this.preprocessor.sourcePos;
|
||||
tokenLine = line;
|
||||
tokenCol = col;
|
||||
tokenizerProto[state].call(this, cp);
|
||||
};
|
||||
});
|
||||
};
|
||||
-167
@@ -1,167 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
//Const
|
||||
var NOAH_ARK_CAPACITY = 3;
|
||||
|
||||
//List of formatting elements
|
||||
var FormattingElementList = module.exports = function (treeAdapter) {
|
||||
this.length = 0;
|
||||
this.entries = [];
|
||||
this.treeAdapter = treeAdapter;
|
||||
this.bookmark = null;
|
||||
};
|
||||
|
||||
//Entry types
|
||||
FormattingElementList.MARKER_ENTRY = 'MARKER_ENTRY';
|
||||
FormattingElementList.ELEMENT_ENTRY = 'ELEMENT_ENTRY';
|
||||
|
||||
//Noah Ark's condition
|
||||
//OPTIMIZATION: at first we try to find possible candidates for exclusion using
|
||||
//lightweight heuristics without thorough attributes check.
|
||||
FormattingElementList.prototype._getNoahArkConditionCandidates = function (newElement) {
|
||||
var candidates = [];
|
||||
|
||||
if (this.length >= NOAH_ARK_CAPACITY) {
|
||||
var neAttrsLength = this.treeAdapter.getAttrList(newElement).length,
|
||||
neTagName = this.treeAdapter.getTagName(newElement),
|
||||
neNamespaceURI = this.treeAdapter.getNamespaceURI(newElement);
|
||||
|
||||
for (var i = this.length - 1; i >= 0; i--) {
|
||||
var entry = this.entries[i];
|
||||
|
||||
if (entry.type === FormattingElementList.MARKER_ENTRY)
|
||||
break;
|
||||
|
||||
var element = entry.element,
|
||||
elementAttrs = this.treeAdapter.getAttrList(element),
|
||||
isCandidate = this.treeAdapter.getTagName(element) === neTagName &&
|
||||
this.treeAdapter.getNamespaceURI(element) === neNamespaceURI &&
|
||||
elementAttrs.length === neAttrsLength;
|
||||
|
||||
if (isCandidate)
|
||||
candidates.push({idx: i, attrs: elementAttrs});
|
||||
}
|
||||
}
|
||||
|
||||
return candidates.length < NOAH_ARK_CAPACITY ? [] : candidates;
|
||||
};
|
||||
|
||||
FormattingElementList.prototype._ensureNoahArkCondition = function (newElement) {
|
||||
var candidates = this._getNoahArkConditionCandidates(newElement),
|
||||
cLength = candidates.length;
|
||||
|
||||
if (cLength) {
|
||||
var neAttrs = this.treeAdapter.getAttrList(newElement),
|
||||
neAttrsLength = neAttrs.length,
|
||||
neAttrsMap = {};
|
||||
|
||||
//NOTE: build attrs map for the new element so we can perform fast lookups
|
||||
for (var i = 0; i < neAttrsLength; i++) {
|
||||
var neAttr = neAttrs[i];
|
||||
|
||||
neAttrsMap[neAttr.name] = neAttr.value;
|
||||
}
|
||||
|
||||
for (i = 0; i < neAttrsLength; i++) {
|
||||
for (var j = 0; j < cLength; j++) {
|
||||
var cAttr = candidates[j].attrs[i];
|
||||
|
||||
if (neAttrsMap[cAttr.name] !== cAttr.value) {
|
||||
candidates.splice(j, 1);
|
||||
cLength--;
|
||||
}
|
||||
|
||||
if (candidates.length < NOAH_ARK_CAPACITY)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//NOTE: remove bottommost candidates until Noah's Ark condition will not be met
|
||||
for (i = cLength - 1; i >= NOAH_ARK_CAPACITY - 1; i--) {
|
||||
this.entries.splice(candidates[i].idx, 1);
|
||||
this.length--;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//Mutations
|
||||
FormattingElementList.prototype.insertMarker = function () {
|
||||
this.entries.push({type: FormattingElementList.MARKER_ENTRY});
|
||||
this.length++;
|
||||
};
|
||||
|
||||
FormattingElementList.prototype.pushElement = function (element, token) {
|
||||
this._ensureNoahArkCondition(element);
|
||||
|
||||
this.entries.push({
|
||||
type: FormattingElementList.ELEMENT_ENTRY,
|
||||
element: element,
|
||||
token: token
|
||||
});
|
||||
|
||||
this.length++;
|
||||
};
|
||||
|
||||
FormattingElementList.prototype.insertElementAfterBookmark = function (element, token) {
|
||||
var bookmarkIdx = this.length - 1;
|
||||
|
||||
for (; bookmarkIdx >= 0; bookmarkIdx--) {
|
||||
if (this.entries[bookmarkIdx] === this.bookmark)
|
||||
break;
|
||||
}
|
||||
|
||||
this.entries.splice(bookmarkIdx + 1, 0, {
|
||||
type: FormattingElementList.ELEMENT_ENTRY,
|
||||
element: element,
|
||||
token: token
|
||||
});
|
||||
|
||||
this.length++;
|
||||
};
|
||||
|
||||
FormattingElementList.prototype.removeEntry = function (entry) {
|
||||
for (var i = this.length - 1; i >= 0; i--) {
|
||||
if (this.entries[i] === entry) {
|
||||
this.entries.splice(i, 1);
|
||||
this.length--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
FormattingElementList.prototype.clearToLastMarker = function () {
|
||||
while (this.length) {
|
||||
var entry = this.entries.pop();
|
||||
|
||||
this.length--;
|
||||
|
||||
if (entry.type === FormattingElementList.MARKER_ENTRY)
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
//Search
|
||||
FormattingElementList.prototype.getElementEntryInScopeWithTagName = function (tagName) {
|
||||
for (var i = this.length - 1; i >= 0; i--) {
|
||||
var entry = this.entries[i];
|
||||
|
||||
if (entry.type === FormattingElementList.MARKER_ENTRY)
|
||||
return null;
|
||||
|
||||
if (this.treeAdapter.getTagName(entry.element) === tagName)
|
||||
return entry;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
FormattingElementList.prototype.getElementEntry = function (element) {
|
||||
for (var i = this.length - 1; i >= 0; i--) {
|
||||
var entry = this.entries[i];
|
||||
|
||||
if (entry.type === FormattingElementList.ELEMENT_ENTRY && entry.element === element)
|
||||
return entry;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
-2817
File diff suppressed because it is too large.
Load diff
-395
@@ -1,395 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var HTML = require('../common/html');
|
||||
|
||||
//Aliases
|
||||
var $ = HTML.TAG_NAMES,
|
||||
NS = HTML.NAMESPACES;
|
||||
|
||||
//Element utils
|
||||
|
||||
//OPTIMIZATION: Integer comparisons are low-cost, so we can use very fast tag name length filters here.
|
||||
//It's faster than using dictionary.
|
||||
function isImpliedEndTagRequired(tn) {
|
||||
switch (tn.length) {
|
||||
case 1:
|
||||
return tn === $.P;
|
||||
|
||||
case 2:
|
||||
return tn === $.RB || tn === $.RP || tn === $.RT || tn === $.DD || tn === $.DT || tn === $.LI;
|
||||
|
||||
case 3:
|
||||
return tn === $.RTC;
|
||||
|
||||
case 6:
|
||||
return tn === $.OPTION;
|
||||
|
||||
case 8:
|
||||
return tn === $.OPTGROUP || tn === $.MENUITEM;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function isScopingElement(tn, ns) {
|
||||
switch (tn.length) {
|
||||
case 2:
|
||||
if (tn === $.TD || tn === $.TH)
|
||||
return ns === NS.HTML;
|
||||
|
||||
else if (tn === $.MI || tn === $.MO || tn === $.MN || tn === $.MS)
|
||||
return ns === NS.MATHML;
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (tn === $.HTML)
|
||||
return ns === NS.HTML;
|
||||
|
||||
else if (tn === $.DESC)
|
||||
return ns === NS.SVG;
|
||||
|
||||
break;
|
||||
|
||||
case 5:
|
||||
if (tn === $.TABLE)
|
||||
return ns === NS.HTML;
|
||||
|
||||
else if (tn === $.MTEXT)
|
||||
return ns === NS.MATHML;
|
||||
|
||||
else if (tn === $.TITLE)
|
||||
return ns === NS.SVG;
|
||||
|
||||
break;
|
||||
|
||||
case 6:
|
||||
return (tn === $.APPLET || tn === $.OBJECT) && ns === NS.HTML;
|
||||
|
||||
case 7:
|
||||
return (tn === $.CAPTION || tn === $.MARQUEE) && ns === NS.HTML;
|
||||
|
||||
case 8:
|
||||
return tn === $.TEMPLATE && ns === NS.HTML;
|
||||
|
||||
case 13:
|
||||
return tn === $.FOREIGN_OBJECT && ns === NS.SVG;
|
||||
|
||||
case 14:
|
||||
return tn === $.ANNOTATION_XML && ns === NS.MATHML;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//Stack of open elements
|
||||
var OpenElementStack = module.exports = function (document, treeAdapter) {
|
||||
this.stackTop = -1;
|
||||
this.items = [];
|
||||
this.current = document;
|
||||
this.currentTagName = null;
|
||||
this.currentTmplContent = null;
|
||||
this.tmplCount = 0;
|
||||
this.treeAdapter = treeAdapter;
|
||||
};
|
||||
|
||||
//Index of element
|
||||
OpenElementStack.prototype._indexOf = function (element) {
|
||||
var idx = -1;
|
||||
|
||||
for (var i = this.stackTop; i >= 0; i--) {
|
||||
if (this.items[i] === element) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
};
|
||||
|
||||
//Update current element
|
||||
OpenElementStack.prototype._isInTemplate = function () {
|
||||
return this.currentTagName === $.TEMPLATE && this.treeAdapter.getNamespaceURI(this.current) === NS.HTML;
|
||||
};
|
||||
|
||||
OpenElementStack.prototype._updateCurrentElement = function () {
|
||||
this.current = this.items[this.stackTop];
|
||||
this.currentTagName = this.current && this.treeAdapter.getTagName(this.current);
|
||||
|
||||
this.currentTmplContent = this._isInTemplate() ? this.treeAdapter.getTemplateContent(this.current) : null;
|
||||
};
|
||||
|
||||
//Mutations
|
||||
OpenElementStack.prototype.push = function (element) {
|
||||
this.items[++this.stackTop] = element;
|
||||
this._updateCurrentElement();
|
||||
|
||||
if (this._isInTemplate())
|
||||
this.tmplCount++;
|
||||
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.pop = function () {
|
||||
this.stackTop--;
|
||||
|
||||
if (this.tmplCount > 0 && this._isInTemplate())
|
||||
this.tmplCount--;
|
||||
|
||||
this._updateCurrentElement();
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.replace = function (oldElement, newElement) {
|
||||
var idx = this._indexOf(oldElement);
|
||||
|
||||
this.items[idx] = newElement;
|
||||
|
||||
if (idx === this.stackTop)
|
||||
this._updateCurrentElement();
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.insertAfter = function (referenceElement, newElement) {
|
||||
var insertionIdx = this._indexOf(referenceElement) + 1;
|
||||
|
||||
this.items.splice(insertionIdx, 0, newElement);
|
||||
|
||||
if (insertionIdx === ++this.stackTop)
|
||||
this._updateCurrentElement();
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.popUntilTagNamePopped = function (tagName) {
|
||||
while (this.stackTop > -1) {
|
||||
var tn = this.currentTagName,
|
||||
ns = this.treeAdapter.getNamespaceURI(this.current);
|
||||
|
||||
this.pop();
|
||||
|
||||
if (tn === tagName && ns === NS.HTML)
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.popUntilElementPopped = function (element) {
|
||||
while (this.stackTop > -1) {
|
||||
var poppedElement = this.current;
|
||||
|
||||
this.pop();
|
||||
|
||||
if (poppedElement === element)
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.popUntilNumberedHeaderPopped = function () {
|
||||
while (this.stackTop > -1) {
|
||||
var tn = this.currentTagName,
|
||||
ns = this.treeAdapter.getNamespaceURI(this.current);
|
||||
|
||||
this.pop();
|
||||
|
||||
if (tn === $.H1 || tn === $.H2 || tn === $.H3 || tn === $.H4 || tn === $.H5 || tn === $.H6 && ns === NS.HTML)
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.popUntilTableCellPopped = function () {
|
||||
while (this.stackTop > -1) {
|
||||
var tn = this.currentTagName,
|
||||
ns = this.treeAdapter.getNamespaceURI(this.current);
|
||||
|
||||
this.pop();
|
||||
|
||||
if (tn === $.TD || tn === $.TH && ns === NS.HTML)
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.popAllUpToHtmlElement = function () {
|
||||
//NOTE: here we assume that root <html> element is always first in the open element stack, so
|
||||
//we perform this fast stack clean up.
|
||||
this.stackTop = 0;
|
||||
this._updateCurrentElement();
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.clearBackToTableContext = function () {
|
||||
while (this.currentTagName !== $.TABLE &&
|
||||
this.currentTagName !== $.TEMPLATE &&
|
||||
this.currentTagName !== $.HTML ||
|
||||
this.treeAdapter.getNamespaceURI(this.current) !== NS.HTML)
|
||||
this.pop();
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.clearBackToTableBodyContext = function () {
|
||||
while (this.currentTagName !== $.TBODY &&
|
||||
this.currentTagName !== $.TFOOT &&
|
||||
this.currentTagName !== $.THEAD &&
|
||||
this.currentTagName !== $.TEMPLATE &&
|
||||
this.currentTagName !== $.HTML ||
|
||||
this.treeAdapter.getNamespaceURI(this.current) !== NS.HTML)
|
||||
this.pop();
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.clearBackToTableRowContext = function () {
|
||||
while (this.currentTagName !== $.TR &&
|
||||
this.currentTagName !== $.TEMPLATE &&
|
||||
this.currentTagName !== $.HTML ||
|
||||
this.treeAdapter.getNamespaceURI(this.current) !== NS.HTML)
|
||||
this.pop();
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.remove = function (element) {
|
||||
for (var i = this.stackTop; i >= 0; i--) {
|
||||
if (this.items[i] === element) {
|
||||
this.items.splice(i, 1);
|
||||
this.stackTop--;
|
||||
this._updateCurrentElement();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//Search
|
||||
OpenElementStack.prototype.tryPeekProperlyNestedBodyElement = function () {
|
||||
//Properly nested <body> element (should be second element in stack).
|
||||
var element = this.items[1];
|
||||
|
||||
return element && this.treeAdapter.getTagName(element) === $.BODY ? element : null;
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.contains = function (element) {
|
||||
return this._indexOf(element) > -1;
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.getCommonAncestor = function (element) {
|
||||
var elementIdx = this._indexOf(element);
|
||||
|
||||
return --elementIdx >= 0 ? this.items[elementIdx] : null;
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.isRootHtmlElementCurrent = function () {
|
||||
return this.stackTop === 0 && this.currentTagName === $.HTML;
|
||||
};
|
||||
|
||||
//Element in scope
|
||||
OpenElementStack.prototype.hasInScope = function (tagName) {
|
||||
for (var i = this.stackTop; i >= 0; i--) {
|
||||
var tn = this.treeAdapter.getTagName(this.items[i]),
|
||||
ns = this.treeAdapter.getNamespaceURI(this.items[i]);
|
||||
|
||||
if (tn === tagName && ns === NS.HTML)
|
||||
return true;
|
||||
|
||||
if (isScopingElement(tn, ns))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.hasNumberedHeaderInScope = function () {
|
||||
for (var i = this.stackTop; i >= 0; i--) {
|
||||
var tn = this.treeAdapter.getTagName(this.items[i]),
|
||||
ns = this.treeAdapter.getNamespaceURI(this.items[i]);
|
||||
|
||||
if ((tn === $.H1 || tn === $.H2 || tn === $.H3 || tn === $.H4 || tn === $.H5 || tn === $.H6) && ns === NS.HTML)
|
||||
return true;
|
||||
|
||||
if (isScopingElement(tn, ns))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.hasInListItemScope = function (tagName) {
|
||||
for (var i = this.stackTop; i >= 0; i--) {
|
||||
var tn = this.treeAdapter.getTagName(this.items[i]),
|
||||
ns = this.treeAdapter.getNamespaceURI(this.items[i]);
|
||||
|
||||
if (tn === tagName && ns === NS.HTML)
|
||||
return true;
|
||||
|
||||
if ((tn === $.UL || tn === $.OL) && ns === NS.HTML || isScopingElement(tn, ns))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.hasInButtonScope = function (tagName) {
|
||||
for (var i = this.stackTop; i >= 0; i--) {
|
||||
var tn = this.treeAdapter.getTagName(this.items[i]),
|
||||
ns = this.treeAdapter.getNamespaceURI(this.items[i]);
|
||||
|
||||
if (tn === tagName && ns === NS.HTML)
|
||||
return true;
|
||||
|
||||
if (tn === $.BUTTON && ns === NS.HTML || isScopingElement(tn, ns))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.hasInTableScope = function (tagName) {
|
||||
for (var i = this.stackTop; i >= 0; i--) {
|
||||
var tn = this.treeAdapter.getTagName(this.items[i]),
|
||||
ns = this.treeAdapter.getNamespaceURI(this.items[i]);
|
||||
|
||||
if (ns !== NS.HTML)
|
||||
continue;
|
||||
|
||||
if (tn === tagName)
|
||||
return true;
|
||||
|
||||
if (tn === $.TABLE || tn === $.TEMPLATE || tn === $.HTML)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.hasTableBodyContextInTableScope = function () {
|
||||
for (var i = this.stackTop; i >= 0; i--) {
|
||||
var tn = this.treeAdapter.getTagName(this.items[i]),
|
||||
ns = this.treeAdapter.getNamespaceURI(this.items[i]);
|
||||
|
||||
if (ns !== NS.HTML)
|
||||
continue;
|
||||
|
||||
if (tn === $.TBODY || tn === $.THEAD || tn === $.TFOOT)
|
||||
return true;
|
||||
|
||||
if (tn === $.TABLE || tn === $.HTML)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.hasInSelectScope = function (tagName) {
|
||||
for (var i = this.stackTop; i >= 0; i--) {
|
||||
var tn = this.treeAdapter.getTagName(this.items[i]),
|
||||
ns = this.treeAdapter.getNamespaceURI(this.items[i]);
|
||||
|
||||
if (ns !== NS.HTML)
|
||||
continue;
|
||||
|
||||
if (tn === tagName)
|
||||
return true;
|
||||
|
||||
if (tn !== $.OPTION && tn !== $.OPTGROUP)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
//Implied end tags
|
||||
OpenElementStack.prototype.generateImpliedEndTags = function () {
|
||||
while (isImpliedEndTagRequired(this.currentTagName))
|
||||
this.pop();
|
||||
};
|
||||
|
||||
OpenElementStack.prototype.generateImpliedEndTagsWithExclusion = function (exclusionTagName) {
|
||||
while (isImpliedEndTagRequired(this.currentTagName) && this.currentTagName !== exclusionTagName)
|
||||
this.pop();
|
||||
};
|
||||
-140
@@ -1,140 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var WritableStream = require('stream').Writable,
|
||||
inherits = require('util').inherits,
|
||||
Parser = require('./index');
|
||||
|
||||
/**
|
||||
* Streaming HTML parser with scripting support.
|
||||
* A [writable stream]{@link https://nodejs.org/api/stream.html#stream_class_stream_writable}.
|
||||
* @class ParserStream
|
||||
* @memberof parse5
|
||||
* @instance
|
||||
* @extends stream.Writable
|
||||
* @param {ParserOptions} options - Parsing options.
|
||||
* @example
|
||||
* var parse5 = require('parse5');
|
||||
* var http = require('http');
|
||||
*
|
||||
* // Fetch the google.com content and obtain it's <body> node
|
||||
* http.get('http://google.com', function(res) {
|
||||
* var parser = new parse5.ParserStream();
|
||||
*
|
||||
* parser.on('finish', function() {
|
||||
* var body = parser.document.childNodes[0].childNodes[1];
|
||||
* });
|
||||
*
|
||||
* res.pipe(parser);
|
||||
* });
|
||||
*/
|
||||
var ParserStream = module.exports = function (options) {
|
||||
WritableStream.call(this);
|
||||
|
||||
this.parser = new Parser(options);
|
||||
|
||||
this.lastChunkWritten = false;
|
||||
this.writeCallback = null;
|
||||
this.pausedByScript = false;
|
||||
|
||||
/**
|
||||
* The resulting document node.
|
||||
* @member {ASTNode<document>} document
|
||||
* @memberof parse5#ParserStream
|
||||
* @instance
|
||||
*/
|
||||
this.document = this.parser.treeAdapter.createDocument();
|
||||
|
||||
this.pendingHtmlInsertions = [];
|
||||
|
||||
this._resume = this._resume.bind(this);
|
||||
this._documentWrite = this._documentWrite.bind(this);
|
||||
this._scriptHandler = this._scriptHandler.bind(this);
|
||||
|
||||
this.parser._bootstrap(this.document, null);
|
||||
};
|
||||
|
||||
inherits(ParserStream, WritableStream);
|
||||
|
||||
//WritableStream implementation
|
||||
ParserStream.prototype._write = function (chunk, encoding, callback) {
|
||||
this.writeCallback = callback;
|
||||
this.parser.tokenizer.write(chunk.toString('utf8'), this.lastChunkWritten);
|
||||
this._runParsingLoop();
|
||||
};
|
||||
|
||||
ParserStream.prototype.end = function (chunk, encoding, callback) {
|
||||
this.lastChunkWritten = true;
|
||||
WritableStream.prototype.end.call(this, chunk, encoding, callback);
|
||||
};
|
||||
|
||||
//Scriptable parser implementation
|
||||
ParserStream.prototype._runParsingLoop = function () {
|
||||
this.parser._runParsingLoop(this.writeCallback, this._scriptHandler);
|
||||
};
|
||||
|
||||
ParserStream.prototype._resume = function () {
|
||||
if (!this.pausedByScript)
|
||||
throw new Error('Parser was already resumed');
|
||||
|
||||
while (this.pendingHtmlInsertions.length) {
|
||||
var html = this.pendingHtmlInsertions.pop();
|
||||
|
||||
this.parser.tokenizer.insertHtmlAtCurrentPos(html);
|
||||
}
|
||||
|
||||
this.pausedByScript = false;
|
||||
|
||||
//NOTE: keep parsing if we don't wait for the next input chunk
|
||||
if (this.parser.tokenizer.active)
|
||||
this._runParsingLoop();
|
||||
};
|
||||
|
||||
ParserStream.prototype._documentWrite = function (html) {
|
||||
if (!this.parser.stopped)
|
||||
this.pendingHtmlInsertions.push(html);
|
||||
};
|
||||
|
||||
ParserStream.prototype._scriptHandler = function (scriptElement) {
|
||||
if (this.listeners('script').length) {
|
||||
this.pausedByScript = true;
|
||||
|
||||
/**
|
||||
* Raised then parser encounters a `<script>` element.
|
||||
* If this event has listeners, parsing will be suspended once it is emitted.
|
||||
* So, if `<script>` has the `src` attribute, you can fetch it, execute and then resume parsing just like browsers do.
|
||||
* @event script
|
||||
* @memberof parse5#ParserStream
|
||||
* @instance
|
||||
* @type {Function}
|
||||
* @param {ASTNode} scriptElement - The script element that caused the event.
|
||||
* @param {Function} documentWrite(html) - Write additional `html` at the current parsing position.
|
||||
* Suitable for implementing the DOM `document.write` and `document.writeln` methods.
|
||||
* @param {Function} resume - Resumes parsing.
|
||||
* @example
|
||||
* var parse = require('parse5');
|
||||
* var http = require('http');
|
||||
*
|
||||
* var parser = new parse5.ParserStream();
|
||||
*
|
||||
* parser.on('script', function(scriptElement, documentWrite, resume) {
|
||||
* var src = parse5.treeAdapters.default.getAttrList(scriptElement)[0].value;
|
||||
*
|
||||
* http.get(src, function(res) {
|
||||
* // Fetch the script content, execute it with DOM built around `parser.document` and
|
||||
* // `document.write` implemented using `documentWrite`.
|
||||
* ...
|
||||
* // Then resume parsing.
|
||||
* resume();
|
||||
* });
|
||||
* });
|
||||
*
|
||||
* parser.end('<script src="example.com/script.js"></script>');
|
||||
*/
|
||||
|
||||
|
||||
this.emit('script', scriptElement, this._documentWrite, this._resume);
|
||||
}
|
||||
else
|
||||
this._runParsingLoop();
|
||||
};
|
||||
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var WritableStream = require('stream').Writable,
|
||||
util = require('util');
|
||||
|
||||
var DevNullStream = module.exports = function () {
|
||||
WritableStream.call(this);
|
||||
};
|
||||
|
||||
util.inherits(DevNullStream, WritableStream);
|
||||
|
||||
DevNullStream.prototype._write = function (chunk, encoding, cb) {
|
||||
cb();
|
||||
};
|
||||
-230
@@ -1,230 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var TransformStream = require('stream').Transform,
|
||||
DevNullStream = require('./dev_null_stream'),
|
||||
inherits = require('util').inherits,
|
||||
Tokenizer = require('../tokenizer'),
|
||||
ParserFeedbackSimulator = require('./parser_feedback_simulator'),
|
||||
mergeOptions = require('../common/merge_options');
|
||||
|
||||
/**
|
||||
* @typedef {Object} SAXParserOptions
|
||||
*
|
||||
* @property {Boolean} [locationInfo=false] - Enables source code location information for the tokens.
|
||||
* When enabled, each token event handler will receive {@link LocationInfo} (or {@link StartTagLocationInfo})
|
||||
* object as its last argument.
|
||||
*/
|
||||
var DEFAULT_OPTIONS = {
|
||||
locationInfo: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Streaming [SAX]{@link https://en.wikipedia.org/wiki/Simple_API_for_XML}-style HTML parser.
|
||||
* A [transform stream](https://nodejs.org/api/stream.html#stream_class_stream_transform)
|
||||
* (which means you can pipe *through* it, see example).
|
||||
* @class SAXParser
|
||||
* @memberof parse5
|
||||
* @instance
|
||||
* @extends stream.Transform
|
||||
* @param {SAXParserOptions} options - Parsing options.
|
||||
* @example
|
||||
* var parse5 = require('parse5');
|
||||
* var http = require('http');
|
||||
* var fs = require('fs');
|
||||
*
|
||||
* var file = fs.createWriteStream('/home/google.com.html');
|
||||
* var parser = new parse5.SAXParser();
|
||||
*
|
||||
* parser.on('text', function(text) {
|
||||
* // Handle page text content
|
||||
* ...
|
||||
* });
|
||||
*
|
||||
* http.get('http://google.com', function(res) {
|
||||
* // SAXParser is the Transform stream, which means you can pipe
|
||||
* // through it. So, you can analyze page content and, e.g., save it
|
||||
* // to the file at the same time:
|
||||
* res.pipe(parser).pipe(file);
|
||||
* });
|
||||
*/
|
||||
var SAXParser = module.exports = function (options) {
|
||||
TransformStream.call(this);
|
||||
|
||||
this.options = mergeOptions(DEFAULT_OPTIONS, options);
|
||||
|
||||
this.tokenizer = new Tokenizer(options);
|
||||
this.parserFeedbackSimulator = new ParserFeedbackSimulator(this.tokenizer);
|
||||
|
||||
this.pendingText = null;
|
||||
this.currentTokenLocation = void 0;
|
||||
|
||||
this.lastChunkWritten = false;
|
||||
this.stopped = false;
|
||||
|
||||
// NOTE: always pipe stream to the /dev/null stream to avoid
|
||||
// `highWaterMark` hit even if we don't have consumers.
|
||||
// (see: https://github.com/inikulin/parse5/issues/97#issuecomment-171940774)
|
||||
this.pipe(new DevNullStream());
|
||||
};
|
||||
|
||||
inherits(SAXParser, TransformStream);
|
||||
|
||||
//TransformStream implementation
|
||||
SAXParser.prototype._transform = function (chunk, encoding, callback) {
|
||||
if (!this.stopped) {
|
||||
this.tokenizer.write(chunk.toString('utf8'), this.lastChunkWritten);
|
||||
this._runParsingLoop();
|
||||
}
|
||||
|
||||
this.push(chunk);
|
||||
|
||||
callback();
|
||||
};
|
||||
|
||||
SAXParser.prototype._flush = function (callback) {
|
||||
callback();
|
||||
};
|
||||
|
||||
SAXParser.prototype.end = function (chunk, encoding, callback) {
|
||||
this.lastChunkWritten = true;
|
||||
TransformStream.prototype.end.call(this, chunk, encoding, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Stops parsing. Useful if you want the parser to stop consuming CPU time once you've obtained the desired info
|
||||
* from the input stream. Doesn't prevent piping, so that data will flow through the parser as usual.
|
||||
*
|
||||
* @function stop
|
||||
* @memberof parse5#SAXParser
|
||||
* @instance
|
||||
* @example
|
||||
* var parse5 = require('parse5');
|
||||
* var http = require('http');
|
||||
* var fs = require('fs');
|
||||
*
|
||||
* var file = fs.createWriteStream('/home/google.com.html');
|
||||
* var parser = new parse5.SAXParser();
|
||||
*
|
||||
* parser.on('doctype', function(name, publicId, systemId) {
|
||||
* // Process doctype info ans stop parsing
|
||||
* ...
|
||||
* parser.stop();
|
||||
* });
|
||||
*
|
||||
* http.get('http://google.com', function(res) {
|
||||
* // Despite the fact that parser.stop() was called whole
|
||||
* // content of the page will be written to the file
|
||||
* res.pipe(parser).pipe(file);
|
||||
* });
|
||||
*/
|
||||
SAXParser.prototype.stop = function () {
|
||||
this.stopped = true;
|
||||
};
|
||||
|
||||
//Internals
|
||||
SAXParser.prototype._runParsingLoop = function () {
|
||||
do {
|
||||
var token = this.parserFeedbackSimulator.getNextToken();
|
||||
|
||||
if (token.type === Tokenizer.HIBERNATION_TOKEN)
|
||||
break;
|
||||
|
||||
if (token.type === Tokenizer.CHARACTER_TOKEN ||
|
||||
token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN ||
|
||||
token.type === Tokenizer.NULL_CHARACTER_TOKEN) {
|
||||
|
||||
if (this.options.locationInfo) {
|
||||
if (this.pendingText === null)
|
||||
this.currentTokenLocation = token.location;
|
||||
|
||||
else
|
||||
this.currentTokenLocation.endOffset = token.location.endOffset;
|
||||
}
|
||||
|
||||
this.pendingText = (this.pendingText || '') + token.chars;
|
||||
}
|
||||
|
||||
else {
|
||||
this._emitPendingText();
|
||||
this._handleToken(token);
|
||||
}
|
||||
} while (!this.stopped && token.type !== Tokenizer.EOF_TOKEN);
|
||||
};
|
||||
|
||||
SAXParser.prototype._handleToken = function (token) {
|
||||
if (this.options.locationInfo)
|
||||
this.currentTokenLocation = token.location;
|
||||
|
||||
if (token.type === Tokenizer.START_TAG_TOKEN)
|
||||
/**
|
||||
* Raised when the parser encounters a start tag.
|
||||
* @event startTag
|
||||
* @memberof parse5#SAXParser
|
||||
* @instance
|
||||
* @type {Function}
|
||||
* @param {String} name - Tag name.
|
||||
* @param {Array} attrs - List of attributes in the `{ name: String, value: String, prefix?: String }` form.
|
||||
* @param {Boolean} selfClosing - Indicates if the tag is self-closing.
|
||||
* @param {StartTagLocationInfo} [location] - Start tag source code location info.
|
||||
* Available if location info is enabled in {@link SAXParserOptions}.
|
||||
*/
|
||||
this.emit('startTag', token.tagName, token.attrs, token.selfClosing, this.currentTokenLocation);
|
||||
|
||||
else if (token.type === Tokenizer.END_TAG_TOKEN)
|
||||
/**
|
||||
* Raised then parser encounters an end tag.
|
||||
* @event endTag
|
||||
* @memberof parse5#SAXParser
|
||||
* @instance
|
||||
* @type {Function}
|
||||
* @param {String} name - Tag name.
|
||||
* @param {LocationInfo} [location] - End tag source code location info.
|
||||
* Available if location info is enabled in {@link SAXParserOptions}.
|
||||
*/
|
||||
this.emit('endTag', token.tagName, this.currentTokenLocation);
|
||||
|
||||
else if (token.type === Tokenizer.COMMENT_TOKEN)
|
||||
/**
|
||||
* Raised then parser encounters a comment.
|
||||
* @event comment
|
||||
* @memberof parse5#SAXParser
|
||||
* @instance
|
||||
* @type {Function}
|
||||
* @param {String} text - Comment text.
|
||||
* @param {LocationInfo} [location] - Comment source code location info.
|
||||
* Available if location info is enabled in {@link SAXParserOptions}.
|
||||
*/
|
||||
this.emit('comment', token.data, this.currentTokenLocation);
|
||||
|
||||
else if (token.type === Tokenizer.DOCTYPE_TOKEN)
|
||||
/**
|
||||
* Raised then parser encounters a [document type declaration]{@link https://en.wikipedia.org/wiki/Document_type_declaration}.
|
||||
* @event doctype
|
||||
* @memberof parse5#SAXParser
|
||||
* @instance
|
||||
* @type {Function}
|
||||
* @param {String} name - Document type name.
|
||||
* @param {String} publicId - Document type public identifier.
|
||||
* @param {String} systemId - Document type system identifier.
|
||||
* @param {LocationInfo} [location] - Document type declaration source code location info.
|
||||
* Available if location info is enabled in {@link SAXParserOptions}.
|
||||
*/
|
||||
this.emit('doctype', token.name, token.publicId, token.systemId, this.currentTokenLocation);
|
||||
};
|
||||
|
||||
SAXParser.prototype._emitPendingText = function () {
|
||||
if (this.pendingText !== null) {
|
||||
/**
|
||||
* Raised then parser encounters text content.
|
||||
* @event text
|
||||
* @memberof parse5#SAXParser
|
||||
* @instance
|
||||
* @type {Function}
|
||||
* @param {String} text - Text content.
|
||||
* @param {LocationInfo} [location] - Text content code location info.
|
||||
* Available if location info is enabled in {@link SAXParserOptions}.
|
||||
*/
|
||||
this.emit('text', this.pendingText, this.currentTokenLocation);
|
||||
this.pendingText = null;
|
||||
}
|
||||
};
|
||||
-153
@@ -1,153 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var Tokenizer = require('../tokenizer'),
|
||||
foreignContent = require('../common/foreign_content'),
|
||||
UNICODE = require('../common/unicode'),
|
||||
HTML = require('../common/html');
|
||||
|
||||
|
||||
//Aliases
|
||||
var $ = HTML.TAG_NAMES,
|
||||
NS = HTML.NAMESPACES;
|
||||
|
||||
|
||||
//ParserFeedbackSimulator
|
||||
//Simulates adjustment of the Tokenizer which performed by standard parser during tree construction.
|
||||
var ParserFeedbackSimulator = module.exports = function (tokenizer) {
|
||||
this.tokenizer = tokenizer;
|
||||
|
||||
this.namespaceStack = [];
|
||||
this.namespaceStackTop = -1;
|
||||
this._enterNamespace(NS.HTML);
|
||||
};
|
||||
|
||||
ParserFeedbackSimulator.prototype.getNextToken = function () {
|
||||
var token = this.tokenizer.getNextToken();
|
||||
|
||||
if (token.type === Tokenizer.START_TAG_TOKEN)
|
||||
this._handleStartTagToken(token);
|
||||
|
||||
else if (token.type === Tokenizer.END_TAG_TOKEN)
|
||||
this._handleEndTagToken(token);
|
||||
|
||||
else if (token.type === Tokenizer.NULL_CHARACTER_TOKEN && this.inForeignContent) {
|
||||
token.type = Tokenizer.CHARACTER_TOKEN;
|
||||
token.chars = UNICODE.REPLACEMENT_CHARACTER;
|
||||
}
|
||||
|
||||
else if (this.skipNextNewLine) {
|
||||
if (token.type !== Tokenizer.HIBERNATION_TOKEN)
|
||||
this.skipNextNewLine = false;
|
||||
|
||||
if (token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN && token.chars[0] === '\n') {
|
||||
if (token.chars.length === 1)
|
||||
return this.getNextToken();
|
||||
|
||||
token.chars = token.chars.substr(1);
|
||||
}
|
||||
}
|
||||
|
||||
return token;
|
||||
};
|
||||
|
||||
//Namespace stack mutations
|
||||
ParserFeedbackSimulator.prototype._enterNamespace = function (namespace) {
|
||||
this.namespaceStackTop++;
|
||||
this.namespaceStack.push(namespace);
|
||||
|
||||
this.inForeignContent = namespace !== NS.HTML;
|
||||
this.currentNamespace = namespace;
|
||||
this.tokenizer.allowCDATA = this.inForeignContent;
|
||||
};
|
||||
|
||||
ParserFeedbackSimulator.prototype._leaveCurrentNamespace = function () {
|
||||
this.namespaceStackTop--;
|
||||
this.namespaceStack.pop();
|
||||
|
||||
this.currentNamespace = this.namespaceStack[this.namespaceStackTop];
|
||||
this.inForeignContent = this.currentNamespace !== NS.HTML;
|
||||
this.tokenizer.allowCDATA = this.inForeignContent;
|
||||
};
|
||||
|
||||
//Token handlers
|
||||
ParserFeedbackSimulator.prototype._ensureTokenizerMode = function (tn) {
|
||||
if (tn === $.TEXTAREA || tn === $.TITLE)
|
||||
this.tokenizer.state = Tokenizer.MODE.RCDATA;
|
||||
|
||||
else if (tn === $.PLAINTEXT)
|
||||
this.tokenizer.state = Tokenizer.MODE.PLAINTEXT;
|
||||
|
||||
else if (tn === $.SCRIPT)
|
||||
this.tokenizer.state = Tokenizer.MODE.SCRIPT_DATA;
|
||||
|
||||
else if (tn === $.STYLE || tn === $.IFRAME || tn === $.XMP ||
|
||||
tn === $.NOEMBED || tn === $.NOFRAMES || tn === $.NOSCRIPT)
|
||||
this.tokenizer.state = Tokenizer.MODE.RAWTEXT;
|
||||
};
|
||||
|
||||
ParserFeedbackSimulator.prototype._handleStartTagToken = function (token) {
|
||||
var tn = token.tagName;
|
||||
|
||||
if (tn === $.SVG)
|
||||
this._enterNamespace(NS.SVG);
|
||||
|
||||
else if (tn === $.MATH)
|
||||
this._enterNamespace(NS.MATHML);
|
||||
|
||||
if (this.inForeignContent) {
|
||||
if (foreignContent.causesExit(token)) {
|
||||
this._leaveCurrentNamespace();
|
||||
return;
|
||||
}
|
||||
|
||||
var currentNs = this.currentNamespace;
|
||||
|
||||
if (currentNs === NS.MATHML)
|
||||
foreignContent.adjustTokenMathMLAttrs(token);
|
||||
|
||||
else if (currentNs === NS.SVG) {
|
||||
foreignContent.adjustTokenSVGTagName(token);
|
||||
foreignContent.adjustTokenSVGAttrs(token);
|
||||
}
|
||||
|
||||
foreignContent.adjustTokenXMLAttrs(token);
|
||||
|
||||
tn = token.tagName;
|
||||
|
||||
if (!token.selfClosing && foreignContent.isIntegrationPoint(tn, currentNs, token.attrs))
|
||||
this._enterNamespace(NS.HTML);
|
||||
}
|
||||
|
||||
else {
|
||||
if (tn === $.PRE || tn === $.TEXTAREA || tn === $.LISTING)
|
||||
this.skipNextNewLine = true;
|
||||
|
||||
else if (tn === $.IMAGE)
|
||||
token.tagName = $.IMG;
|
||||
|
||||
this._ensureTokenizerMode(tn);
|
||||
}
|
||||
};
|
||||
|
||||
ParserFeedbackSimulator.prototype._handleEndTagToken = function (token) {
|
||||
var tn = token.tagName;
|
||||
|
||||
if (!this.inForeignContent) {
|
||||
var previousNs = this.namespaceStack[this.namespaceStackTop - 1];
|
||||
|
||||
if (previousNs === NS.SVG && foreignContent.SVG_TAG_NAMES_ADJUSTMENT_MAP[tn])
|
||||
tn = foreignContent.SVG_TAG_NAMES_ADJUSTMENT_MAP[tn];
|
||||
|
||||
//NOTE: check for exit from integration point
|
||||
if (foreignContent.isIntegrationPoint(tn, previousNs, token.attrs))
|
||||
this._leaveCurrentNamespace();
|
||||
}
|
||||
|
||||
else if (tn === $.SVG && this.currentNamespace === NS.SVG ||
|
||||
tn === $.MATH && this.currentNamespace === NS.MATHML)
|
||||
this._leaveCurrentNamespace();
|
||||
|
||||
// NOTE: adjust end tag name as well for consistency
|
||||
if (this.currentNamespace === NS.SVG)
|
||||
foreignContent.adjustTokenSVGTagName(token);
|
||||
};
|
||||
-180
@@ -1,180 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var defaultTreeAdapter = require('../tree_adapters/default'),
|
||||
doctype = require('../common/doctype'),
|
||||
mergeOptions = require('../common/merge_options'),
|
||||
HTML = require('../common/html');
|
||||
|
||||
//Aliases
|
||||
var $ = HTML.TAG_NAMES,
|
||||
NS = HTML.NAMESPACES;
|
||||
|
||||
//Default serializer options
|
||||
/**
|
||||
* @typedef {Object} SerializerOptions
|
||||
*
|
||||
* @property {TreeAdapter} [treeAdapter=parse5.treeAdapters.default] - Specifies input tree format.
|
||||
*/
|
||||
var DEFAULT_OPTIONS = {
|
||||
treeAdapter: defaultTreeAdapter
|
||||
};
|
||||
|
||||
//Escaping regexes
|
||||
var AMP_REGEX = /&/g,
|
||||
NBSP_REGEX = /\u00a0/g,
|
||||
DOUBLE_QUOTE_REGEX = /"/g,
|
||||
LT_REGEX = /</g,
|
||||
GT_REGEX = />/g;
|
||||
|
||||
//Serializer
|
||||
var Serializer = module.exports = function (node, options) {
|
||||
this.options = mergeOptions(DEFAULT_OPTIONS, options);
|
||||
this.treeAdapter = this.options.treeAdapter;
|
||||
|
||||
this.html = '';
|
||||
this.startNode = node;
|
||||
};
|
||||
|
||||
// NOTE: exported as static method for the testing purposes
|
||||
Serializer.escapeString = function (str, attrMode) {
|
||||
str = str
|
||||
.replace(AMP_REGEX, '&')
|
||||
.replace(NBSP_REGEX, ' ');
|
||||
|
||||
if (attrMode)
|
||||
str = str.replace(DOUBLE_QUOTE_REGEX, '"');
|
||||
|
||||
else {
|
||||
str = str
|
||||
.replace(LT_REGEX, '<')
|
||||
.replace(GT_REGEX, '>');
|
||||
}
|
||||
|
||||
return str;
|
||||
};
|
||||
|
||||
|
||||
//API
|
||||
Serializer.prototype.serialize = function () {
|
||||
this._serializeChildNodes(this.startNode);
|
||||
|
||||
return this.html;
|
||||
};
|
||||
|
||||
|
||||
//Internals
|
||||
Serializer.prototype._serializeChildNodes = function (parentNode) {
|
||||
var childNodes = this.treeAdapter.getChildNodes(parentNode);
|
||||
|
||||
if (childNodes) {
|
||||
for (var i = 0, cnLength = childNodes.length; i < cnLength; i++) {
|
||||
var currentNode = childNodes[i];
|
||||
|
||||
if (this.treeAdapter.isElementNode(currentNode))
|
||||
this._serializeElement(currentNode);
|
||||
|
||||
else if (this.treeAdapter.isTextNode(currentNode))
|
||||
this._serializeTextNode(currentNode);
|
||||
|
||||
else if (this.treeAdapter.isCommentNode(currentNode))
|
||||
this._serializeCommentNode(currentNode);
|
||||
|
||||
else if (this.treeAdapter.isDocumentTypeNode(currentNode))
|
||||
this._serializeDocumentTypeNode(currentNode);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Serializer.prototype._serializeElement = function (node) {
|
||||
var tn = this.treeAdapter.getTagName(node),
|
||||
ns = this.treeAdapter.getNamespaceURI(node);
|
||||
|
||||
this.html += '<' + tn;
|
||||
this._serializeAttributes(node);
|
||||
this.html += '>';
|
||||
|
||||
if (tn !== $.AREA && tn !== $.BASE && tn !== $.BASEFONT && tn !== $.BGSOUND && tn !== $.BR && tn !== $.BR &&
|
||||
tn !== $.COL && tn !== $.EMBED && tn !== $.FRAME && tn !== $.HR && tn !== $.IMG && tn !== $.INPUT &&
|
||||
tn !== $.KEYGEN && tn !== $.LINK && tn !== $.MENUITEM && tn !== $.META && tn !== $.PARAM && tn !== $.SOURCE &&
|
||||
tn !== $.TRACK && tn !== $.WBR) {
|
||||
|
||||
if (tn === $.PRE || tn === $.TEXTAREA || tn === $.LISTING) {
|
||||
var firstChild = this.treeAdapter.getFirstChild(node);
|
||||
|
||||
if (firstChild && this.treeAdapter.isTextNode(firstChild)) {
|
||||
var content = this.treeAdapter.getTextNodeContent(firstChild);
|
||||
|
||||
if (content[0] === '\n')
|
||||
this.html += '\n';
|
||||
}
|
||||
}
|
||||
|
||||
var childNodesHolder = tn === $.TEMPLATE && ns === NS.HTML ?
|
||||
this.treeAdapter.getTemplateContent(node) :
|
||||
node;
|
||||
|
||||
this._serializeChildNodes(childNodesHolder);
|
||||
this.html += '</' + tn + '>';
|
||||
}
|
||||
};
|
||||
|
||||
Serializer.prototype._serializeAttributes = function (node) {
|
||||
var attrs = this.treeAdapter.getAttrList(node);
|
||||
|
||||
for (var i = 0, attrsLength = attrs.length; i < attrsLength; i++) {
|
||||
var attr = attrs[i],
|
||||
value = Serializer.escapeString(attr.value, true);
|
||||
|
||||
this.html += ' ';
|
||||
|
||||
if (!attr.namespace)
|
||||
this.html += attr.name;
|
||||
|
||||
else if (attr.namespace === NS.XML)
|
||||
this.html += 'xml:' + attr.name;
|
||||
|
||||
else if (attr.namespace === NS.XMLNS) {
|
||||
if (attr.name !== 'xmlns')
|
||||
this.html += 'xmlns:';
|
||||
|
||||
this.html += attr.name;
|
||||
}
|
||||
|
||||
else if (attr.namespace === NS.XLINK)
|
||||
this.html += 'xlink:' + attr.name;
|
||||
|
||||
else
|
||||
this.html += attr.namespace + ':' + attr.name;
|
||||
|
||||
this.html += '="' + value + '"';
|
||||
}
|
||||
};
|
||||
|
||||
Serializer.prototype._serializeTextNode = function (node) {
|
||||
var content = this.treeAdapter.getTextNodeContent(node),
|
||||
parent = this.treeAdapter.getParentNode(node),
|
||||
parentTn = void 0;
|
||||
|
||||
if (parent && this.treeAdapter.isElementNode(parent))
|
||||
parentTn = this.treeAdapter.getTagName(parent);
|
||||
|
||||
if (parentTn === $.STYLE || parentTn === $.SCRIPT || parentTn === $.XMP || parentTn === $.IFRAME ||
|
||||
parentTn === $.NOEMBED || parentTn === $.NOFRAMES || parentTn === $.PLAINTEXT || parentTn === $.NOSCRIPT)
|
||||
|
||||
this.html += content;
|
||||
|
||||
else
|
||||
this.html += Serializer.escapeString(content, false);
|
||||
};
|
||||
|
||||
Serializer.prototype._serializeCommentNode = function (node) {
|
||||
this.html += '<!--' + this.treeAdapter.getCommentNodeContent(node) + '-->';
|
||||
};
|
||||
|
||||
Serializer.prototype._serializeDocumentTypeNode = function (node) {
|
||||
var name = this.treeAdapter.getDocumentTypeNodeName(node),
|
||||
publicId = this.treeAdapter.getDocumentTypeNodePublicId(node),
|
||||
systemId = this.treeAdapter.getDocumentTypeNodeSystemId(node);
|
||||
|
||||
this.html += '<' + doctype.serializeContent(name, publicId, systemId) + '>';
|
||||
};
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var ReadableStream = require('stream').Readable,
|
||||
inherits = require('util').inherits,
|
||||
Serializer = require('./index');
|
||||
|
||||
/**
|
||||
* Streaming AST node to an HTML serializer.
|
||||
* A [readable stream]{@link https://nodejs.org/api/stream.html#stream_class_stream_readable}.
|
||||
* @class SerializerStream
|
||||
* @memberof parse5
|
||||
* @instance
|
||||
* @extends stream.Readable
|
||||
* @param {ASTNode} node - Node to serialize.
|
||||
* @param {SerializerOptions} [options] - Serialization options.
|
||||
* @example
|
||||
* var parse5 = require('parse5');
|
||||
* var fs = require('fs');
|
||||
*
|
||||
* var file = fs.createWriteStream('/home/index.html');
|
||||
*
|
||||
* // Serializes the parsed document to HTML and writes it to the file.
|
||||
* var document = parse5.parse('<body>Who is John Galt?</body>');
|
||||
* var serializer = new parse5.SerializerStream(document);
|
||||
*
|
||||
* serializer.pipe(file);
|
||||
*/
|
||||
var SerializerStream = module.exports = function (node, options) {
|
||||
ReadableStream.call(this);
|
||||
|
||||
this.serializer = new Serializer(node, options);
|
||||
|
||||
Object.defineProperty(this.serializer, 'html', {
|
||||
//NOTE: To make `+=` concat operator work properly we define
|
||||
//getter which always returns empty string
|
||||
get: function () {
|
||||
return '';
|
||||
},
|
||||
set: this.push.bind(this)
|
||||
});
|
||||
};
|
||||
|
||||
inherits(SerializerStream, ReadableStream);
|
||||
|
||||
//Readable stream implementation
|
||||
SerializerStream.prototype._read = function () {
|
||||
this.serializer.serialize();
|
||||
this.push(null);
|
||||
};
|
||||
-2101
File diff suppressed because it is too large.
Load diff
-6
@@ -1,6 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
//NOTE: this file contains auto-generated trie structure that is used for named entity references consumption
|
||||
//(see: http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#tokenizing-character-references and
|
||||
//http://www.whatwg.org/specs/web-apps/current-work/multipage/named-character-references.html#named-character-references)
|
||||
module.exports = {65:{l:{69:{l:{108:{l:{105:{l:{103:{l:{59:{c:[198]}},c:[198]}}}}}}},77:{l:{80:{l:{59:{c:[38]}},c:[38]}}},97:{l:{99:{l:{117:{l:{116:{l:{101:{l:{59:{c:[193]}},c:[193]}}}}}}}}},98:{l:{114:{l:{101:{l:{118:{l:{101:{l:{59:{c:[258]}}}}}}}}}}},99:{l:{105:{l:{114:{l:{99:{l:{59:{c:[194]}},c:[194]}}}}},121:{l:{59:{c:[1040]}}}}},102:{l:{114:{l:{59:{c:[120068]}}}}},103:{l:{114:{l:{97:{l:{118:{l:{101:{l:{59:{c:[192]}},c:[192]}}}}}}}}},108:{l:{112:{l:{104:{l:{97:{l:{59:{c:[913]}}}}}}}}},109:{l:{97:{l:{99:{l:{114:{l:{59:{c:[256]}}}}}}}}},110:{l:{100:{l:{59:{c:[10835]}}}}},111:{l:{103:{l:{111:{l:{110:{l:{59:{c:[260]}}}}}}},112:{l:{102:{l:{59:{c:[120120]}}}}}}},112:{l:{112:{l:{108:{l:{121:{l:{70:{l:{117:{l:{110:{l:{99:{l:{116:{l:{105:{l:{111:{l:{110:{l:{59:{c:[8289]}}}}}}}}}}}}}}}}}}}}}}}}},114:{l:{105:{l:{110:{l:{103:{l:{59:{c:[197]}},c:[197]}}}}}}},115:{l:{99:{l:{114:{l:{59:{c:[119964]}}}}},115:{l:{105:{l:{103:{l:{110:{l:{59:{c:[8788]}}}}}}}}}}},116:{l:{105:{l:{108:{l:{100:{l:{101:{l:{59:{c:[195]}},c:[195]}}}}}}}}},117:{l:{109:{l:{108:{l:{59:{c:[196]}},c:[196]}}}}}}},66:{l:{97:{l:{99:{l:{107:{l:{115:{l:{108:{l:{97:{l:{115:{l:{104:{l:{59:{c:[8726]}}}}}}}}}}}}}}},114:{l:{118:{l:{59:{c:[10983]}}},119:{l:{101:{l:{100:{l:{59:{c:[8966]}}}}}}}}}}},99:{l:{121:{l:{59:{c:[1041]}}}}},101:{l:{99:{l:{97:{l:{117:{l:{115:{l:{101:{l:{59:{c:[8757]}}}}}}}}}}},114:{l:{110:{l:{111:{l:{117:{l:{108:{l:{108:{l:{105:{l:{115:{l:{59:{c:[8492]}}}}}}}}}}}}}}}}},116:{l:{97:{l:{59:{c:[914]}}}}}}},102:{l:{114:{l:{59:{c:[120069]}}}}},111:{l:{112:{l:{102:{l:{59:{c:[120121]}}}}}}},114:{l:{101:{l:{118:{l:{101:{l:{59:{c:[728]}}}}}}}}},115:{l:{99:{l:{114:{l:{59:{c:[8492]}}}}}}},117:{l:{109:{l:{112:{l:{101:{l:{113:{l:{59:{c:[8782]}}}}}}}}}}}}},67:{l:{72:{l:{99:{l:{121:{l:{59:{c:[1063]}}}}}}},79:{l:{80:{l:{89:{l:{59:{c:[169]}},c:[169]}}}}},97:{l:{99:{l:{117:{l:{116:{l:{101:{l:{59:{c:[262]}}}}}}}}},112:{l:{59:{c:[8914]},105:{l:{116:{l:{97:{l:{108:{l:{68:{l:{105:{l:{102:{l:{102:{l:{101:{l:{114:{l:{101:{l:{110:{l:{116:{l:{105:{l:{97:{l:{108:{l:{68:{l:{59:{c:[8517]}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},121:{l:{108:{l:{101:{l:{121:{l:{115:{l:{59:{c:[8493]}}}}}}}}}}}}},99:{l:{97:{l:{114:{l:{111:{l:{110:{l:{59:{c:[268]}}}}}}}}},101:{l:{100:{l:{105:{l:{108:{l:{59:{c:[199]}},c:[199]}}}}}}},105:{l:{114:{l:{99:{l:{59:{c:[264]}}}}}}},111:{l:{110:{l:{105:{l:{110:{l:{116:{l:{59:{c:[8752]}}}}}}}}}}}}},100:{l:{111:{l:{116:{l:{59:{c:[266]}}}}}}},101:{l:{100:{l:{105:{l:{108:{l:{108:{l:{97:{l:{59:{c:[184]}}}}}}}}}}},110:{l:{116:{l:{101:{l:{114:{l:{68:{l:{111:{l:{116:{l:{59:{c:[183]}}}}}}}}}}}}}}}}},102:{l:{114:{l:{59:{c:[8493]}}}}},104:{l:{105:{l:{59:{c:[935]}}}}},105:{l:{114:{l:{99:{l:{108:{l:{101:{l:{68:{l:{111:{l:{116:{l:{59:{c:[8857]}}}}}}},77:{l:{105:{l:{110:{l:{117:{l:{115:{l:{59:{c:[8854]}}}}}}}}}}},80:{l:{108:{l:{117:{l:{115:{l:{59:{c:[8853]}}}}}}}}},84:{l:{105:{l:{109:{l:{101:{l:{115:{l:{59:{c:[8855]}}}}}}}}}}}}}}}}}}}}},108:{l:{111:{l:{99:{l:{107:{l:{119:{l:{105:{l:{115:{l:{101:{l:{67:{l:{111:{l:{110:{l:{116:{l:{111:{l:{117:{l:{114:{l:{73:{l:{110:{l:{116:{l:{101:{l:{103:{l:{114:{l:{97:{l:{108:{l:{59:{c:[8754]}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},115:{l:{101:{l:{67:{l:{117:{l:{114:{l:{108:{l:{121:{l:{68:{l:{111:{l:{117:{l:{98:{l:{108:{l:{101:{l:{81:{l:{117:{l:{111:{l:{116:{l:{101:{l:{59:{c:[8221]}}}}}}}}}}}}}}}}}}}}}}},81:{l:{117:{l:{111:{l:{116:{l:{101:{l:{59:{c:[8217]}}}}}}}}}}}}}}}}}}}}}}}}}}}}},111:{l:{108:{l:{111:{l:{110:{l:{59:{c:[8759]},101:{l:{59:{c:[10868]}}}}}}}}},110:{l:{103:{l:{114:{l:{117:{l:{101:{l:{110:{l:{116:{l:{59:{c:[8801]}}}}}}}}}}}}},105:{l:{110:{l:{116:{l:{59:{c:[8751]}}}}}}},116:{l:{111:{l:{117:{l:{114:{l:{73:{l:{110:{l:{116:{l:{101:{l:{103:{l:{114:{l:{97:{l:{108:{l:{59:{c:[8750]}}}}}}}}}}}}}}}}}}}}}}}}}}},112:{l:{102:{l:{59:{c:[8450]}}},114:{l:{111:{l:{100:{l:{117:{l:{99:{l:{116:{l:{59:{c:[8720]}}}}}}}}}}}}}}},117:{l:{110:{l:{116:{l:{101:{l:{114:{l:{67:{l:{108:{l:{111:{l:{99:{l:{107:{l:{119:{l:{105:{l:{115:{l:{101:{l:{67:{l:{111:{l:{110:{l:{116:{l:{111:{l:{117:{l:{114:{l:{73:{l:{110:{l:{116:{l:{101:{l:{103:{l:{114:{l:{97:{l:{108:{l:{59:{c:[8755]}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},114:{l:{111:{l:{115:{l:{115:{l:{59:{c:[10799]}}}}}}}}},115:{l:{99:{l:{114:{l:{59:{c:[119966]}}}}}}},117:{l:{112:{l:{59:{c:[8915]},67:{l:{97:{l:{112:{l:{59:{c:[8781]}}}}}}}}}}}}},68:{l:{68:{l:{59:{c:[8517]},111:{l:{116:{l:{114:{l:{97:{l:{104:{l:{100:{l:{59:{c:[10513]}}}}}}}}}}}}}}},74:{l:{99:{l:{121:{l:{59:{c:[1026]}}}}}}},83:{l:{99:{l:{121:{l:{59:{c:[1029]}}}}}}},90:{l:{99:{l:{121:{l:{59:{c:[1039]}}}}}}},97:{l:{103:{l:{103:{l:{101:{l:{114:{l:{59:{c:[8225]}}}}}}}}},114:{l:{114:{l:{59:{c:[8609]}}}}},115:{l:{104:{l:{118:{l:{59:{c:[10980]}}}}}}}}},99:{l:{97:{l:{114:{l:{111:{l:{110:{l:{59:{c:[270]}}}}}}}}},121:{l:{59:{c:[1044]}}}}},101:{l:{108:{l:{59:{c:[8711]},116:{l:{97:{l:{59:{c:[916]}}}}}}}}},102:{l:{114:{l:{59:{c:[120071]}}}}},105:{l:{97:{l:{99:{l:{114:{l:{105:{l:{116:{l:{105:{l:{99:{l:{97:{l:{108:{l:{65:{l:{99:{l:{117:{l:{Line truncated
|
||||
-155
@@ -1,155 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var UNICODE = require('../common/unicode');
|
||||
|
||||
//Aliases
|
||||
var $ = UNICODE.CODE_POINTS;
|
||||
|
||||
//Utils
|
||||
|
||||
//OPTIMIZATION: these utility functions should not be moved out of this module. V8 Crankshaft will not inline
|
||||
//this functions if they will be situated in another module due to context switch.
|
||||
//Always perform inlining check before modifying this functions ('node --trace-inlining').
|
||||
function isSurrogatePair(cp1, cp2) {
|
||||
return cp1 >= 0xD800 && cp1 <= 0xDBFF && cp2 >= 0xDC00 && cp2 <= 0xDFFF;
|
||||
}
|
||||
|
||||
function getSurrogatePairCodePoint(cp1, cp2) {
|
||||
return (cp1 - 0xD800) * 0x400 + 0x2400 + cp2;
|
||||
}
|
||||
|
||||
|
||||
//Const
|
||||
var DEFAULT_BUFFER_WATERLINE = 1 << 16;
|
||||
|
||||
|
||||
//Preprocessor
|
||||
//NOTE: HTML input preprocessing
|
||||
//(see: http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#preprocessing-the-input-stream)
|
||||
var Preprocessor = module.exports = function () {
|
||||
this.html = null;
|
||||
|
||||
this.pos = -1;
|
||||
this.lastGapPos = -1;
|
||||
this.lastCharPos = -1;
|
||||
this.droppedBufferSize = 0;
|
||||
|
||||
this.gapStack = [];
|
||||
|
||||
this.skipNextNewLine = false;
|
||||
|
||||
this.lastChunkWritten = false;
|
||||
this.endOfChunkHit = false;
|
||||
this.bufferWaterline = DEFAULT_BUFFER_WATERLINE;
|
||||
};
|
||||
|
||||
Object.defineProperty(Preprocessor.prototype, 'sourcePos', {
|
||||
get: function () {
|
||||
return this.droppedBufferSize + this.pos;
|
||||
}
|
||||
});
|
||||
|
||||
Preprocessor.prototype.dropParsedChunk = function () {
|
||||
if (this.pos > this.bufferWaterline) {
|
||||
this.lastCharPos -= this.pos;
|
||||
this.droppedBufferSize += this.pos;
|
||||
this.html = this.html.substring(this.pos);
|
||||
this.pos = 0;
|
||||
this.lastGapPos = -1;
|
||||
this.gapStack = [];
|
||||
}
|
||||
};
|
||||
|
||||
Preprocessor.prototype._addGap = function () {
|
||||
this.gapStack.push(this.lastGapPos);
|
||||
this.lastGapPos = this.pos;
|
||||
};
|
||||
|
||||
Preprocessor.prototype._processHighRangeCodePoint = function (cp) {
|
||||
//NOTE: try to peek a surrogate pair
|
||||
if (this.pos !== this.lastCharPos) {
|
||||
var nextCp = this.html.charCodeAt(this.pos + 1);
|
||||
|
||||
if (isSurrogatePair(cp, nextCp)) {
|
||||
//NOTE: we have a surrogate pair. Peek pair character and recalculate code point.
|
||||
this.pos++;
|
||||
cp = getSurrogatePairCodePoint(cp, nextCp);
|
||||
|
||||
//NOTE: add gap that should be avoided during retreat
|
||||
this._addGap();
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: we've hit the end of chunk, stop processing at this point
|
||||
else if (!this.lastChunkWritten) {
|
||||
this.endOfChunkHit = true;
|
||||
return $.EOF;
|
||||
}
|
||||
|
||||
return cp;
|
||||
};
|
||||
|
||||
Preprocessor.prototype.write = function (chunk, isLastChunk) {
|
||||
if (this.html)
|
||||
this.html += chunk;
|
||||
|
||||
else
|
||||
this.html = chunk;
|
||||
|
||||
this.lastCharPos = this.html.length - 1;
|
||||
this.endOfChunkHit = false;
|
||||
this.lastChunkWritten = isLastChunk;
|
||||
};
|
||||
|
||||
Preprocessor.prototype.insertHtmlAtCurrentPos = function (chunk) {
|
||||
this.html = this.html.substring(0, this.pos + 1) +
|
||||
chunk +
|
||||
this.html.substring(this.pos + 1, this.html.length);
|
||||
|
||||
this.lastCharPos = this.html.length - 1;
|
||||
this.endOfChunkHit = false;
|
||||
};
|
||||
|
||||
|
||||
Preprocessor.prototype.advance = function () {
|
||||
this.pos++;
|
||||
|
||||
if (this.pos > this.lastCharPos) {
|
||||
if (!this.lastChunkWritten)
|
||||
this.endOfChunkHit = true;
|
||||
|
||||
return $.EOF;
|
||||
}
|
||||
|
||||
var cp = this.html.charCodeAt(this.pos);
|
||||
|
||||
//NOTE: any U+000A LINE FEED (LF) characters that immediately follow a U+000D CARRIAGE RETURN (CR) character
|
||||
//must be ignored.
|
||||
if (this.skipNextNewLine && cp === $.LINE_FEED) {
|
||||
this.skipNextNewLine = false;
|
||||
this._addGap();
|
||||
return this.advance();
|
||||
}
|
||||
|
||||
//NOTE: all U+000D CARRIAGE RETURN (CR) characters must be converted to U+000A LINE FEED (LF) characters
|
||||
if (cp === $.CARRIAGE_RETURN) {
|
||||
this.skipNextNewLine = true;
|
||||
return $.LINE_FEED;
|
||||
}
|
||||
|
||||
this.skipNextNewLine = false;
|
||||
|
||||
//OPTIMIZATION: first perform check if the code point in the allowed range that covers most common
|
||||
//HTML input (e.g. ASCII codes) to avoid performance-cost operations for high-range code points.
|
||||
return cp >= 0xD800 ? this._processHighRangeCodePoint(cp) : cp;
|
||||
};
|
||||
|
||||
Preprocessor.prototype.retreat = function () {
|
||||
if (this.pos === this.lastGapPos) {
|
||||
this.lastGapPos = this.gapStack.pop();
|
||||
this.pos--;
|
||||
}
|
||||
|
||||
this.pos--;
|
||||
};
|
||||
|
||||
-578
@@ -1,578 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @typedef {Object} TreeAdapter
|
||||
*/
|
||||
|
||||
//Node construction
|
||||
|
||||
/**
|
||||
* Creates a document node.
|
||||
*
|
||||
* @function createDocument
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @returns {ASTNode<Document>} document
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L19|default implementation.}
|
||||
*/
|
||||
exports.createDocument = function () {
|
||||
return {
|
||||
nodeName: '#document',
|
||||
quirksMode: false,
|
||||
childNodes: []
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a document fragment node.
|
||||
*
|
||||
* @function createDocumentFragment
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @returns {ASTNode<DocumentFragment>} fragment
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L37|default implementation.}
|
||||
*/
|
||||
exports.createDocumentFragment = function () {
|
||||
return {
|
||||
nodeName: '#document-fragment',
|
||||
quirksMode: false,
|
||||
childNodes: []
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates an element node.
|
||||
*
|
||||
* @function createElement
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {String} tagName - Tag name of the element.
|
||||
* @param {String} namespaceURI - Namespace of the element.
|
||||
* @param {Array} attrs - Attribute name-value pair array.
|
||||
* Foreign attributes may contain `namespace` and `prefix` fields as well.
|
||||
*
|
||||
* @returns {ASTNode<Element>} element
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L61|default implementation.}
|
||||
*/
|
||||
exports.createElement = function (tagName, namespaceURI, attrs) {
|
||||
return {
|
||||
nodeName: tagName,
|
||||
tagName: tagName,
|
||||
attrs: attrs,
|
||||
namespaceURI: namespaceURI,
|
||||
childNodes: [],
|
||||
parentNode: null
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a comment node.
|
||||
*
|
||||
* @function createCommentNode
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {String} data - Comment text.
|
||||
*
|
||||
* @returns {ASTNode<CommentNode>} comment
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L85|default implementation.}
|
||||
*/
|
||||
exports.createCommentNode = function (data) {
|
||||
return {
|
||||
nodeName: '#comment',
|
||||
data: data,
|
||||
parentNode: null
|
||||
};
|
||||
};
|
||||
|
||||
var createTextNode = function (value) {
|
||||
return {
|
||||
nodeName: '#text',
|
||||
value: value,
|
||||
parentNode: null
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//Tree mutation
|
||||
/**
|
||||
* Appends a child node to the given parent node.
|
||||
*
|
||||
* @function appendChild
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode} parentNode - Parent node.
|
||||
* @param {ASTNode} newNode - Child node.
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L114|default implementation.}
|
||||
*/
|
||||
var appendChild = exports.appendChild = function (parentNode, newNode) {
|
||||
parentNode.childNodes.push(newNode);
|
||||
newNode.parentNode = parentNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inserts a child node to the given parent node before the given reference node.
|
||||
*
|
||||
* @function insertBefore
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode} parentNode - Parent node.
|
||||
* @param {ASTNode} newNode - Child node.
|
||||
* @param {ASTNode} referenceNode - Reference node.
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L131|default implementation.}
|
||||
*/
|
||||
var insertBefore = exports.insertBefore = function (parentNode, newNode, referenceNode) {
|
||||
var insertionIdx = parentNode.childNodes.indexOf(referenceNode);
|
||||
|
||||
parentNode.childNodes.splice(insertionIdx, 0, newNode);
|
||||
newNode.parentNode = parentNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the `<template>` element content element.
|
||||
*
|
||||
* @function setTemplateContent
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode<TemplateElement>} templateElement - `<template>` element.
|
||||
* @param {ASTNode<DocumentFragment>} contentTemplate - Content element.
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L149|default implementation.}
|
||||
*/
|
||||
exports.setTemplateContent = function (templateElement, contentElement) {
|
||||
templateElement.content = contentElement;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the `<template>` element content element.
|
||||
*
|
||||
* @function getTemplateContent
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode<TemplateElement>} templateElement - `<template>` element.
|
||||
|
||||
* @returns {ASTNode<DocumentFragment>}
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L166|default implementation.}
|
||||
*/
|
||||
exports.getTemplateContent = function (templateElement) {
|
||||
return templateElement.content;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the document type. If the `document` already contains a document type node, the `name`, `publicId` and `systemId`
|
||||
* properties of this node will be updated with the provided values. Otherwise, creates a new document type node
|
||||
* with the given properties and inserts it into the `document`.
|
||||
*
|
||||
* @function setDocumentType
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode<Document>} document - Document node.
|
||||
* @param {String} name - Document type name.
|
||||
* @param {String} publicId - Document type public identifier.
|
||||
* @param {String} systemId - Document type system identifier.
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L185|default implementation.}
|
||||
*/
|
||||
exports.setDocumentType = function (document, name, publicId, systemId) {
|
||||
var doctypeNode = null;
|
||||
|
||||
for (var i = 0; i < document.childNodes.length; i++) {
|
||||
if (document.childNodes[i].nodeName === '#documentType') {
|
||||
doctypeNode = document.childNodes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (doctypeNode) {
|
||||
doctypeNode.name = name;
|
||||
doctypeNode.publicId = publicId;
|
||||
doctypeNode.systemId = systemId;
|
||||
}
|
||||
|
||||
else {
|
||||
appendChild(document, {
|
||||
nodeName: '#documentType',
|
||||
name: name,
|
||||
publicId: publicId,
|
||||
systemId: systemId
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the document's quirks mode flag.
|
||||
*
|
||||
* @function setQuirksMode
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode<Document>} document - Document node.
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L221|default implementation.}
|
||||
*/
|
||||
exports.setQuirksMode = function (document) {
|
||||
document.quirksMode = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the document's quirks mode flag is set.
|
||||
*
|
||||
* @function isQuirksMode
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode<Document>} document - Document node.
|
||||
|
||||
* @returns {Boolean}
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L237|default implementation.}
|
||||
*/
|
||||
exports.isQuirksMode = function (document) {
|
||||
return document.quirksMode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a node from its parent.
|
||||
*
|
||||
* @function detachNode
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode} node - Node.
|
||||
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L251|default implementation.}
|
||||
*/
|
||||
exports.detachNode = function (node) {
|
||||
if (node.parentNode) {
|
||||
var idx = node.parentNode.childNodes.indexOf(node);
|
||||
|
||||
node.parentNode.childNodes.splice(idx, 1);
|
||||
node.parentNode = null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Inserts text into a node. If the last child of the node is a text node, the provided text will be appended to the
|
||||
* text node content. Otherwise, inserts a new text node with the given text.
|
||||
*
|
||||
*
|
||||
* @function insertText
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode} parentNode - Node to insert text into.
|
||||
* @param {String} text - Text to insert.
|
||||
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L273|default implementation.}
|
||||
*/
|
||||
exports.insertText = function (parentNode, text) {
|
||||
if (parentNode.childNodes.length) {
|
||||
var prevNode = parentNode.childNodes[parentNode.childNodes.length - 1];
|
||||
|
||||
if (prevNode.nodeName === '#text') {
|
||||
prevNode.value += text;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
appendChild(parentNode, createTextNode(text));
|
||||
};
|
||||
|
||||
/**
|
||||
* Inserts text into a sibling node that goes before the reference node. If this sibling node is the text node,
|
||||
* the provided text will be appended to the text node content. Otherwise, inserts a new sibling text node with
|
||||
* the given text before the reference node.
|
||||
*
|
||||
*
|
||||
* @function insertTextBefore
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode} parentNode - Node to insert text into.
|
||||
* @param {String} text - Text to insert.
|
||||
* @param {ASTNode} referenceNode - Node to insert text before.
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L301|default implementation.}
|
||||
*/
|
||||
exports.insertTextBefore = function (parentNode, text, referenceNode) {
|
||||
var prevNode = parentNode.childNodes[parentNode.childNodes.indexOf(referenceNode) - 1];
|
||||
|
||||
if (prevNode && prevNode.nodeName === '#text')
|
||||
prevNode.value += text;
|
||||
else
|
||||
insertBefore(parentNode, createTextNode(text), referenceNode);
|
||||
};
|
||||
|
||||
/**
|
||||
* Copies attributes to the given node. Only attributes that are not yet present in the node are copied.
|
||||
*
|
||||
* @function adoptAttributes
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode} recipientNode - Node to copy attributes into.
|
||||
* @param {Array} attrs - Attributes to copy.
|
||||
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L321|default implementation.}
|
||||
*/
|
||||
exports.adoptAttributes = function (recipientNode, attrs) {
|
||||
var recipientAttrsMap = [];
|
||||
|
||||
for (var i = 0; i < recipientNode.attrs.length; i++)
|
||||
recipientAttrsMap.push(recipientNode.attrs[i].name);
|
||||
|
||||
for (var j = 0; j < attrs.length; j++) {
|
||||
if (recipientAttrsMap.indexOf(attrs[j].name) === -1)
|
||||
recipientNode.attrs.push(attrs[j]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//Tree traversing
|
||||
|
||||
/**
|
||||
* Returns the first child of the given node.
|
||||
*
|
||||
* @function getFirstChild
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode} node - Node.
|
||||
*
|
||||
* @returns {ASTNode} firstChild
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L348|default implementation.}
|
||||
*/
|
||||
exports.getFirstChild = function (node) {
|
||||
return node.childNodes[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the given node's children in an array.
|
||||
*
|
||||
* @function getChildNodes
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode} node - Node.
|
||||
*
|
||||
* @returns {Array} children
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L364|default implementation.}
|
||||
*/
|
||||
exports.getChildNodes = function (node) {
|
||||
return node.childNodes;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the given node's parent.
|
||||
*
|
||||
* @function getParentNode
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode} node - Node.
|
||||
*
|
||||
* @returns {ASTNode} parent
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L380|default implementation.}
|
||||
*/
|
||||
exports.getParentNode = function (node) {
|
||||
return node.parentNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the given node's attributes in an array, in the form of name-value pairs.
|
||||
* Foreign attributes may contain `namespace` and `prefix` fields as well.
|
||||
*
|
||||
* @function getAttrList
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode} node - Node.
|
||||
*
|
||||
* @returns {Array} attributes
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L397|default implementation.}
|
||||
*/
|
||||
exports.getAttrList = function (node) {
|
||||
return node.attrs;
|
||||
};
|
||||
|
||||
//Node data
|
||||
|
||||
/**
|
||||
* Returns the given element's tag name.
|
||||
*
|
||||
* @function getTagName
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode<Element>} element - Element.
|
||||
*
|
||||
* @returns {String} tagName
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L415|default implementation.}
|
||||
*/
|
||||
exports.getTagName = function (element) {
|
||||
return element.tagName;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the given element's namespace.
|
||||
*
|
||||
* @function getNamespaceURI
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode<Element>} element - Element.
|
||||
*
|
||||
* @returns {String} namespaceURI
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L431|default implementation.}
|
||||
*/
|
||||
exports.getNamespaceURI = function (element) {
|
||||
return element.namespaceURI;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the given text node's content.
|
||||
*
|
||||
* @function getTextNodeContent
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode<Text>} textNode - Text node.
|
||||
*
|
||||
* @returns {String} text
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L447|default implementation.}
|
||||
*/
|
||||
exports.getTextNodeContent = function (textNode) {
|
||||
return textNode.value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the given comment node's content.
|
||||
*
|
||||
* @function getCommentNodeContent
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode<Comment>} commentNode - Comment node.
|
||||
*
|
||||
* @returns {String} commentText
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L463|default implementation.}
|
||||
*/
|
||||
exports.getCommentNodeContent = function (commentNode) {
|
||||
return commentNode.data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the given document type node's name.
|
||||
*
|
||||
* @function getDocumentTypeNodeName
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode<DocumentType>} doctypeNode - Document type node.
|
||||
*
|
||||
* @returns {String} name
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L479|default implementation.}
|
||||
*/
|
||||
exports.getDocumentTypeNodeName = function (doctypeNode) {
|
||||
return doctypeNode.name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the given document type node's public identifier.
|
||||
*
|
||||
* @function getDocumentTypeNodePublicId
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode<DocumentType>} doctypeNode - Document type node.
|
||||
*
|
||||
* @returns {String} publicId
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L495|default implementation.}
|
||||
*/
|
||||
exports.getDocumentTypeNodePublicId = function (doctypeNode) {
|
||||
return doctypeNode.publicId;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the given document type node's system identifier.
|
||||
*
|
||||
* @function getDocumentTypeNodeSystemId
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode<DocumentType>} doctypeNode - Document type node.
|
||||
*
|
||||
* @returns {String} systemId
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L511|default implementation.}
|
||||
*/
|
||||
exports.getDocumentTypeNodeSystemId = function (doctypeNode) {
|
||||
return doctypeNode.systemId;
|
||||
};
|
||||
|
||||
//Node types
|
||||
/**
|
||||
* Determines if the given node is a text node.
|
||||
*
|
||||
* @function isTextNode
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode} node - Node.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L526|default implementation.}
|
||||
*/
|
||||
exports.isTextNode = function (node) {
|
||||
return node.nodeName === '#text';
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the given node is a comment node.
|
||||
*
|
||||
* @function isCommentNode
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode} node - Node.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L544|default implementation.}
|
||||
*/
|
||||
exports.isCommentNode = function (node) {
|
||||
return node.nodeName === '#comment';
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the given node is a document type node.
|
||||
*
|
||||
* @function isDocumentTypeNode
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode} node - Node.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L560|default implementation.}
|
||||
*/
|
||||
exports.isDocumentTypeNode = function (node) {
|
||||
return node.nodeName === '#documentType';
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the given node is an element.
|
||||
*
|
||||
* @function isElementNode
|
||||
* @memberof TreeAdapter
|
||||
*
|
||||
* @param {ASTNode} node - Node.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*
|
||||
* @see {@link https://github.com/inikulin/parse5/blob/tree-adapter-docs-rev/lib/tree_adapters/default.js#L576|default implementation.}
|
||||
*/
|
||||
exports.isElementNode = function (node) {
|
||||
return !!node.tagName;
|
||||
};
|
||||
-327
@@ -1,327 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var doctype = require('../common/doctype');
|
||||
|
||||
//Conversion tables for DOM Level1 structure emulation
|
||||
var nodeTypes = {
|
||||
element: 1,
|
||||
text: 3,
|
||||
cdata: 4,
|
||||
comment: 8
|
||||
};
|
||||
|
||||
var nodePropertyShorthands = {
|
||||
tagName: 'name',
|
||||
childNodes: 'children',
|
||||
parentNode: 'parent',
|
||||
previousSibling: 'prev',
|
||||
nextSibling: 'next',
|
||||
nodeValue: 'data'
|
||||
};
|
||||
|
||||
//Node
|
||||
var Node = function (props) {
|
||||
for (var key in props) {
|
||||
if (props.hasOwnProperty(key))
|
||||
this[key] = props[key];
|
||||
}
|
||||
};
|
||||
|
||||
Node.prototype = {
|
||||
get firstChild() {
|
||||
var children = this.children;
|
||||
|
||||
return children && children[0] || null;
|
||||
},
|
||||
|
||||
get lastChild() {
|
||||
var children = this.children;
|
||||
|
||||
return children && children[children.length - 1] || null;
|
||||
},
|
||||
|
||||
get nodeType() {
|
||||
return nodeTypes[this.type] || nodeTypes.element;
|
||||
}
|
||||
};
|
||||
|
||||
Object.keys(nodePropertyShorthands).forEach(function (key) {
|
||||
var shorthand = nodePropertyShorthands[key];
|
||||
|
||||
Object.defineProperty(Node.prototype, key, {
|
||||
get: function () {
|
||||
return this[shorthand] || null;
|
||||
},
|
||||
set: function (val) {
|
||||
this[shorthand] = val;
|
||||
return val;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//Node construction
|
||||
exports.createDocument =
|
||||
exports.createDocumentFragment = function () {
|
||||
return new Node({
|
||||
type: 'root',
|
||||
name: 'root',
|
||||
parent: null,
|
||||
prev: null,
|
||||
next: null,
|
||||
children: []
|
||||
});
|
||||
};
|
||||
|
||||
exports.createElement = function (tagName, namespaceURI, attrs) {
|
||||
var attribs = {},
|
||||
attribsNamespace = {},
|
||||
attribsPrefix = {};
|
||||
|
||||
for (var i = 0; i < attrs.length; i++) {
|
||||
var attrName = attrs[i].name;
|
||||
|
||||
attribs[attrName] = attrs[i].value;
|
||||
attribsNamespace[attrName] = attrs[i].namespace;
|
||||
attribsPrefix[attrName] = attrs[i].prefix;
|
||||
}
|
||||
|
||||
return new Node({
|
||||
type: tagName === 'script' || tagName === 'style' ? tagName : 'tag',
|
||||
name: tagName,
|
||||
namespace: namespaceURI,
|
||||
attribs: attribs,
|
||||
'x-attribsNamespace': attribsNamespace,
|
||||
'x-attribsPrefix': attribsPrefix,
|
||||
children: [],
|
||||
parent: null,
|
||||
prev: null,
|
||||
next: null
|
||||
});
|
||||
};
|
||||
|
||||
exports.createCommentNode = function (data) {
|
||||
return new Node({
|
||||
type: 'comment',
|
||||
data: data,
|
||||
parent: null,
|
||||
prev: null,
|
||||
next: null
|
||||
});
|
||||
};
|
||||
|
||||
var createTextNode = function (value) {
|
||||
return new Node({
|
||||
type: 'text',
|
||||
data: value,
|
||||
parent: null,
|
||||
prev: null,
|
||||
next: null
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
//Tree mutation
|
||||
var appendChild = exports.appendChild = function (parentNode, newNode) {
|
||||
var prev = parentNode.children[parentNode.children.length - 1];
|
||||
|
||||
if (prev) {
|
||||
prev.next = newNode;
|
||||
newNode.prev = prev;
|
||||
}
|
||||
|
||||
parentNode.children.push(newNode);
|
||||
newNode.parent = parentNode;
|
||||
};
|
||||
|
||||
var insertBefore = exports.insertBefore = function (parentNode, newNode, referenceNode) {
|
||||
var insertionIdx = parentNode.children.indexOf(referenceNode),
|
||||
prev = referenceNode.prev;
|
||||
|
||||
if (prev) {
|
||||
prev.next = newNode;
|
||||
newNode.prev = prev;
|
||||
}
|
||||
|
||||
referenceNode.prev = newNode;
|
||||
newNode.next = referenceNode;
|
||||
|
||||
parentNode.children.splice(insertionIdx, 0, newNode);
|
||||
newNode.parent = parentNode;
|
||||
};
|
||||
|
||||
exports.setTemplateContent = function (templateElement, contentElement) {
|
||||
appendChild(templateElement, contentElement);
|
||||
};
|
||||
|
||||
exports.getTemplateContent = function (templateElement) {
|
||||
return templateElement.children[0];
|
||||
};
|
||||
|
||||
exports.setDocumentType = function (document, name, publicId, systemId) {
|
||||
var data = doctype.serializeContent(name, publicId, systemId),
|
||||
doctypeNode = null;
|
||||
|
||||
for (var i = 0; i < document.children.length; i++) {
|
||||
if (document.children[i].type === 'directive' && document.children[i].name === '!doctype') {
|
||||
doctypeNode = document.children[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (doctypeNode) {
|
||||
doctypeNode.data = data;
|
||||
doctypeNode['x-name'] = name;
|
||||
doctypeNode['x-publicId'] = publicId;
|
||||
doctypeNode['x-systemId'] = systemId;
|
||||
}
|
||||
|
||||
else {
|
||||
appendChild(document, new Node({
|
||||
type: 'directive',
|
||||
name: '!doctype',
|
||||
data: data,
|
||||
'x-name': name,
|
||||
'x-publicId': publicId,
|
||||
'x-systemId': systemId
|
||||
}));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
exports.setQuirksMode = function (document) {
|
||||
document.quirksMode = true;
|
||||
};
|
||||
|
||||
exports.isQuirksMode = function (document) {
|
||||
return document.quirksMode;
|
||||
};
|
||||
|
||||
exports.detachNode = function (node) {
|
||||
if (node.parent) {
|
||||
var idx = node.parent.children.indexOf(node),
|
||||
prev = node.prev,
|
||||
next = node.next;
|
||||
|
||||
node.prev = null;
|
||||
node.next = null;
|
||||
|
||||
if (prev)
|
||||
prev.next = next;
|
||||
|
||||
if (next)
|
||||
next.prev = prev;
|
||||
|
||||
node.parent.children.splice(idx, 1);
|
||||
node.parent = null;
|
||||
}
|
||||
};
|
||||
|
||||
exports.insertText = function (parentNode, text) {
|
||||
var lastChild = parentNode.children[parentNode.children.length - 1];
|
||||
|
||||
if (lastChild && lastChild.type === 'text')
|
||||
lastChild.data += text;
|
||||
else
|
||||
appendChild(parentNode, createTextNode(text));
|
||||
};
|
||||
|
||||
exports.insertTextBefore = function (parentNode, text, referenceNode) {
|
||||
var prevNode = parentNode.children[parentNode.children.indexOf(referenceNode) - 1];
|
||||
|
||||
if (prevNode && prevNode.type === 'text')
|
||||
prevNode.data += text;
|
||||
else
|
||||
insertBefore(parentNode, createTextNode(text), referenceNode);
|
||||
};
|
||||
|
||||
exports.adoptAttributes = function (recipientNode, attrs) {
|
||||
for (var i = 0; i < attrs.length; i++) {
|
||||
var attrName = attrs[i].name;
|
||||
|
||||
if (typeof recipientNode.attribs[attrName] === 'undefined') {
|
||||
recipientNode.attribs[attrName] = attrs[i].value;
|
||||
recipientNode['x-attribsNamespace'][attrName] = attrs[i].namespace;
|
||||
recipientNode['x-attribsPrefix'][attrName] = attrs[i].prefix;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//Tree traversing
|
||||
exports.getFirstChild = function (node) {
|
||||
return node.children[0];
|
||||
};
|
||||
|
||||
exports.getChildNodes = function (node) {
|
||||
return node.children;
|
||||
};
|
||||
|
||||
exports.getParentNode = function (node) {
|
||||
return node.parent;
|
||||
};
|
||||
|
||||
exports.getAttrList = function (node) {
|
||||
var attrList = [];
|
||||
|
||||
for (var name in node.attribs) {
|
||||
if (node.attribs.hasOwnProperty(name)) {
|
||||
attrList.push({
|
||||
name: name,
|
||||
value: node.attribs[name],
|
||||
namespace: node['x-attribsNamespace'][name],
|
||||
prefix: node['x-attribsPrefix'][name]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return attrList;
|
||||
};
|
||||
|
||||
|
||||
//Node data
|
||||
exports.getTagName = function (element) {
|
||||
return element.name;
|
||||
};
|
||||
|
||||
exports.getNamespaceURI = function (element) {
|
||||
return element.namespace;
|
||||
};
|
||||
|
||||
exports.getTextNodeContent = function (textNode) {
|
||||
return textNode.data;
|
||||
};
|
||||
|
||||
exports.getCommentNodeContent = function (commentNode) {
|
||||
return commentNode.data;
|
||||
};
|
||||
|
||||
exports.getDocumentTypeNodeName = function (doctypeNode) {
|
||||
return doctypeNode['x-name'];
|
||||
};
|
||||
|
||||
exports.getDocumentTypeNodePublicId = function (doctypeNode) {
|
||||
return doctypeNode['x-publicId'];
|
||||
};
|
||||
|
||||
exports.getDocumentTypeNodeSystemId = function (doctypeNode) {
|
||||
return doctypeNode['x-systemId'];
|
||||
};
|
||||
|
||||
|
||||
//Node types
|
||||
exports.isTextNode = function (node) {
|
||||
return node.type === 'text';
|
||||
};
|
||||
|
||||
exports.isCommentNode = function (node) {
|
||||
return node.type === 'comment';
|
||||
};
|
||||
|
||||
exports.isDocumentTypeNode = function (node) {
|
||||
return node.type === 'directive' && node.name === '!doctype';
|
||||
};
|
||||
|
||||
exports.isElementNode = function (node) {
|
||||
return !!node.attribs;
|
||||
};
|
||||
-113
@@ -1,113 +0,0 @@
|
||||
{
|
||||
"_from": "parse5@^2.2.2",
|
||||
"_id": "parse5@2.2.3",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-DE/EHBAAxea5PUiwP4CDg3g06fY=",
|
||||
"_location": "/parse5",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "parse5@^2.2.2",
|
||||
"name": "parse5",
|
||||
"escapedName": "parse5",
|
||||
"rawSpec": "^2.2.2",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^2.2.2"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/eslint-plugin-markdown"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/parse5/-/parse5-2.2.3.tgz",
|
||||
"_shasum": "0c4fc41c1000c5e6b93d48b03f8083837834e9f6",
|
||||
"_spec": "parse5@^2.2.2",
|
||||
"_where": "/Users/trott/io.js/tools/eslint-tmp/node_modules/eslint/node_modules/eslint-plugin-markdown",
|
||||
"author": {
|
||||
"name": "Ivan Nikulin",
|
||||
"email": "ifaaan@gmail.com",
|
||||
"url": "https://github.com/inikulin"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/inikulin/parse5/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Alan Clarke",
|
||||
"url": "https://github.com/alanclarke"
|
||||
},
|
||||
{
|
||||
"name": "Evan You",
|
||||
"url": "http://evanyou.me"
|
||||
},
|
||||
{
|
||||
"name": "Saksham Aggarwal",
|
||||
"email": "s.agg2021@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Sebastian Mayr",
|
||||
"email": "sebmaster16@gmail.com",
|
||||
"url": "http://blog.smayr.name"
|
||||
},
|
||||
{
|
||||
"name": "Sean Lang",
|
||||
"email": "slang800@gmail.com",
|
||||
"url": "http://slang.cx"
|
||||
}
|
||||
],
|
||||
"deprecated": false,
|
||||
"description": "WHATWG HTML5 specification-compliant, fast and ready for production HTML parsing/serialization toolset for Node.js",
|
||||
"devDependencies": {
|
||||
"del": "^2.0.2",
|
||||
"gulp": "^3.9.0",
|
||||
"gulp-benchmark": "^1.1.1",
|
||||
"gulp-concat": "^2.6.0",
|
||||
"gulp-download": "0.0.1",
|
||||
"gulp-eslint": "^3.0.1",
|
||||
"gulp-insert": "^0.5.0",
|
||||
"gulp-install": "^0.6.0",
|
||||
"gulp-jsdoc-to-markdown": "^1.1.1",
|
||||
"gulp-mocha": "^2.1.3",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"publish-please": "^2.2.0",
|
||||
"through2": "^2.0.0"
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"homepage": "https://github.com/inikulin/parse5",
|
||||
"keywords": [
|
||||
"html",
|
||||
"parser",
|
||||
"html5",
|
||||
"WHATWG",
|
||||
"specification",
|
||||
"fast",
|
||||
"html parser",
|
||||
"html5 parser",
|
||||
"htmlparser",
|
||||
"parse5",
|
||||
"serializer",
|
||||
"html serializer",
|
||||
"htmlserializer",
|
||||
"sax",
|
||||
"simple api",
|
||||
"parse",
|
||||
"tokenize",
|
||||
"serialize",
|
||||
"tokenizer"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "./lib/index.js",
|
||||
"name": "parse5",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/inikulin/parse5.git"
|
||||
},
|
||||
"scripts": {
|
||||
"prepublish": "publish-please guard",
|
||||
"publish-please": "publish-please",
|
||||
"test": "gulp test"
|
||||
},
|
||||
"version": "2.2.3"
|
||||
}
|
||||
+7
-23
@@ -1,30 +1,14 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015-2016 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse
|
||||
* @fileoverview Markdown parser.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* eslint-env commonjs */
|
||||
|
||||
/* Dependencies. */
|
||||
var unherit = require('unherit');
|
||||
var xtend = require('xtend');
|
||||
var Parser = require('./lib/parser.js');
|
||||
|
||||
/**
|
||||
* Attacher.
|
||||
*
|
||||
* @param {unified} processor - Unified processor.
|
||||
*/
|
||||
function parse(processor) {
|
||||
processor.Parser = unherit(Parser);
|
||||
}
|
||||
|
||||
/* Patch `Parser`. */
|
||||
module.exports = parse;
|
||||
parse.Parser = Parser;
|
||||
|
||||
/* Expose */
|
||||
module.exports = parse;
|
||||
function parse(options) {
|
||||
var Local = unherit(Parser);
|
||||
Local.prototype.options = xtend(Local.prototype.options, this.data('settings'), options);
|
||||
this.Parser = Local;
|
||||
}
|
||||
+66
-50
@@ -1,52 +1,68 @@
|
||||
[
|
||||
"article",
|
||||
"header",
|
||||
"aside",
|
||||
"hgroup",
|
||||
"blockquote",
|
||||
"hr",
|
||||
"iframe",
|
||||
"body",
|
||||
"li",
|
||||
"map",
|
||||
"button",
|
||||
"object",
|
||||
"canvas",
|
||||
"ol",
|
||||
"caption",
|
||||
"output",
|
||||
"col",
|
||||
"p",
|
||||
"colgroup",
|
||||
"pre",
|
||||
"dd",
|
||||
"progress",
|
||||
"div",
|
||||
"section",
|
||||
"dl",
|
||||
"table",
|
||||
"td",
|
||||
"dt",
|
||||
"tbody",
|
||||
"embed",
|
||||
"textarea",
|
||||
"fieldset",
|
||||
"tfoot",
|
||||
"figcaption",
|
||||
"th",
|
||||
"figure",
|
||||
"thead",
|
||||
"footer",
|
||||
"tr",
|
||||
"form",
|
||||
"ul",
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"h4",
|
||||
"h5",
|
||||
"h6",
|
||||
"video",
|
||||
"script",
|
||||
"style"
|
||||
"address",
|
||||
"article",
|
||||
"aside",
|
||||
"base",
|
||||
"basefont",
|
||||
"blockquote",
|
||||
"body",
|
||||
"caption",
|
||||
"center",
|
||||
"col",
|
||||
"colgroup",
|
||||
"dd",
|
||||
"details",
|
||||
"dialog",
|
||||
"dir",
|
||||
"div",
|
||||
"dl",
|
||||
"dt",
|
||||
"fieldset",
|
||||
"figcaption",
|
||||
"figure",
|
||||
"footer",
|
||||
"form",
|
||||
"frame",
|
||||
"frameset",
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"h4",
|
||||
"h5",
|
||||
"h6",
|
||||
"head",
|
||||
"header",
|
||||
"hgroup",
|
||||
"hr",
|
||||
"html",
|
||||
"iframe",
|
||||
"legend",
|
||||
"li",
|
||||
"link",
|
||||
"main",
|
||||
"menu",
|
||||
"menuitem",
|
||||
"meta",
|
||||
"nav",
|
||||
"noframes",
|
||||
"ol",
|
||||
"optgroup",
|
||||
"option",
|
||||
"p",
|
||||
"param",
|
||||
"pre",
|
||||
"section",
|
||||
"source",
|
||||
"title",
|
||||
"summary",
|
||||
"table",
|
||||
"tbody",
|
||||
"td",
|
||||
"tfoot",
|
||||
"th",
|
||||
"thead",
|
||||
"title",
|
||||
"tr",
|
||||
"track",
|
||||
"ul"
|
||||
]
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:decode
|
||||
* @fileoverview Decode entities.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var entities = require('parse-entities');
|
||||
|
||||
module.exports = factory;
|
||||
|
||||
/* Factory to create an entity decoder. */
|
||||
function factory(ctx) {
|
||||
decoder.raw = decodeRaw;
|
||||
|
||||
return decoder;
|
||||
|
||||
/* Normalize `position` to add an `indent`. */
|
||||
function normalize(position) {
|
||||
var offsets = ctx.offset;
|
||||
var line = position.line;
|
||||
var result = [];
|
||||
|
||||
while (++line) {
|
||||
if (!(line in offsets)) {
|
||||
break;
|
||||
}
|
||||
|
||||
result.push((offsets[line] || 0) + 1);
|
||||
}
|
||||
|
||||
return {
|
||||
start: position,
|
||||
indent: result
|
||||
};
|
||||
}
|
||||
|
||||
/* Handle a warning.
|
||||
* See https://github.com/wooorm/parse-entities
|
||||
* for the warnings. */
|
||||
function handleWarning(reason, position, code) {
|
||||
if (code === 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.file.message(reason, position);
|
||||
}
|
||||
|
||||
/* Decode `value` (at `position`) into text-nodes. */
|
||||
function decoder(value, position, handler) {
|
||||
entities(value, {
|
||||
position: normalize(position),
|
||||
warning: handleWarning,
|
||||
text: handler,
|
||||
reference: handler,
|
||||
textContext: ctx,
|
||||
referenceContext: ctx
|
||||
});
|
||||
}
|
||||
|
||||
/* Decode `value` (at `position`) into a string. */
|
||||
function decodeRaw(value, position) {
|
||||
return entities(value, {
|
||||
position: normalize(position),
|
||||
warning: handleWarning
|
||||
});
|
||||
}
|
||||
}
|
||||
+10
-10
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015-2016 Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:defaults
|
||||
* @fileoverview Default options for `parse`.
|
||||
@@ -8,14 +8,14 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
/* eslint-env commonjs */
|
||||
|
||||
/* Expose. */
|
||||
module.exports = {
|
||||
'position': true,
|
||||
'gfm': true,
|
||||
'yaml': true,
|
||||
'commonmark': false,
|
||||
'footnotes': false,
|
||||
'pedantic': false,
|
||||
'breaks': false
|
||||
position: true,
|
||||
gfm: true,
|
||||
yaml: true,
|
||||
commonmark: false,
|
||||
footnotes: false,
|
||||
pedantic: false,
|
||||
blocks: require('./block-elements'),
|
||||
breaks: false
|
||||
};
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
{
|
||||
"default": [
|
||||
"\\",
|
||||
"`",
|
||||
"*",
|
||||
"{",
|
||||
"}",
|
||||
"[",
|
||||
"]",
|
||||
"(",
|
||||
")",
|
||||
"#",
|
||||
"+",
|
||||
"-",
|
||||
".",
|
||||
"!",
|
||||
"_",
|
||||
">"
|
||||
],
|
||||
"gfm": [
|
||||
"\\",
|
||||
"`",
|
||||
"*",
|
||||
"{",
|
||||
"}",
|
||||
"[",
|
||||
"]",
|
||||
"(",
|
||||
")",
|
||||
"#",
|
||||
"+",
|
||||
"-",
|
||||
".",
|
||||
"!",
|
||||
"_",
|
||||
">",
|
||||
"~",
|
||||
"|"
|
||||
],
|
||||
"commonmark": [
|
||||
"\\",
|
||||
"`",
|
||||
"*",
|
||||
"{",
|
||||
"}",
|
||||
"[",
|
||||
"]",
|
||||
"(",
|
||||
")",
|
||||
"#",
|
||||
"+",
|
||||
"-",
|
||||
".",
|
||||
"!",
|
||||
"_",
|
||||
">",
|
||||
"~",
|
||||
"|",
|
||||
"\n",
|
||||
"\"",
|
||||
"$",
|
||||
"%",
|
||||
"&",
|
||||
"'",
|
||||
",",
|
||||
"/",
|
||||
":",
|
||||
";",
|
||||
"<",
|
||||
"=",
|
||||
"?",
|
||||
"@",
|
||||
"^"
|
||||
]
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:locate:break
|
||||
* @fileoverview Locate a break.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = locate;
|
||||
|
||||
function locate(value, fromIndex) {
|
||||
var index = value.indexOf('\n', fromIndex);
|
||||
|
||||
while (index > fromIndex) {
|
||||
if (value.charAt(index - 1) !== ' ') {
|
||||
break;
|
||||
}
|
||||
|
||||
index--;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:locate:code-inline
|
||||
* @fileoverview Locate inline code.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = locate;
|
||||
|
||||
function locate(value, fromIndex) {
|
||||
return value.indexOf('`', fromIndex);
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:locate:delete
|
||||
* @fileoverview Locate strikethrough.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = locate;
|
||||
|
||||
function locate(value, fromIndex) {
|
||||
return value.indexOf('~~', fromIndex);
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:locate:emphasis
|
||||
* @fileoverview Locate italics / emphasis.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = locate;
|
||||
|
||||
function locate(value, fromIndex) {
|
||||
var asterisk = value.indexOf('*', fromIndex);
|
||||
var underscore = value.indexOf('_', fromIndex);
|
||||
|
||||
if (underscore === -1) {
|
||||
return asterisk;
|
||||
}
|
||||
|
||||
if (asterisk === -1) {
|
||||
return underscore;
|
||||
}
|
||||
|
||||
return underscore < asterisk ? underscore : asterisk;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:locate:escape
|
||||
* @fileoverview Locate an escape.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = locate;
|
||||
|
||||
function locate(value, fromIndex) {
|
||||
return value.indexOf('\\', fromIndex);
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:locate:link
|
||||
* @fileoverview Locate a link.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = locate;
|
||||
|
||||
function locate(value, fromIndex) {
|
||||
var link = value.indexOf('[', fromIndex);
|
||||
var image = value.indexOf('![', fromIndex);
|
||||
|
||||
if (image === -1) {
|
||||
return link;
|
||||
}
|
||||
|
||||
/* Link can never be `-1` if an image is found, so we don’t need
|
||||
* to check for that :) */
|
||||
return link < image ? link : image;
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:locate:strong
|
||||
* @fileoverview Locate bold / strong / importance.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = locate;
|
||||
|
||||
function locate(value, fromIndex) {
|
||||
var asterisk = value.indexOf('**', fromIndex);
|
||||
var underscore = value.indexOf('__', fromIndex);
|
||||
|
||||
if (underscore === -1) {
|
||||
return asterisk;
|
||||
}
|
||||
|
||||
if (asterisk === -1) {
|
||||
return underscore;
|
||||
}
|
||||
|
||||
return underscore < asterisk ? underscore : asterisk;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:locate:tag
|
||||
* @fileoverview Locate a tag.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = locate;
|
||||
|
||||
function locate(value, fromIndex) {
|
||||
return value.indexOf('<', fromIndex);
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:locate:url
|
||||
* @fileoverview Locate a URL.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = locate;
|
||||
|
||||
var PROTOCOLS = ['https://', 'http://', 'mailto:'];
|
||||
|
||||
function locate(value, fromIndex) {
|
||||
var length = PROTOCOLS.length;
|
||||
var index = -1;
|
||||
var min = -1;
|
||||
var position;
|
||||
|
||||
if (!this.options.gfm) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (++index < length) {
|
||||
position = value.indexOf(PROTOCOLS[index], fromIndex);
|
||||
|
||||
if (position !== -1 && (position < min || min === -1)) {
|
||||
min = position;
|
||||
}
|
||||
}
|
||||
|
||||
return min;
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:parse
|
||||
* @fileoverview Parse the document
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var xtend = require('xtend');
|
||||
var removePosition = require('unist-util-remove-position');
|
||||
|
||||
module.exports = parse;
|
||||
|
||||
var C_NEWLINE = '\n';
|
||||
var EXPRESSION_LINE_BREAKS = /\r\n|\r/g;
|
||||
|
||||
/* Parse the bound file. */
|
||||
function parse() {
|
||||
var self = this;
|
||||
var value = String(self.file);
|
||||
var start = {line: 1, column: 1, offset: 0};
|
||||
var content = xtend(start);
|
||||
var node;
|
||||
|
||||
/* Clean non-unix newlines: `\r\n` and `\r` are all
|
||||
* changed to `\n`. This should not affect positional
|
||||
* information. */
|
||||
value = value.replace(EXPRESSION_LINE_BREAKS, C_NEWLINE);
|
||||
|
||||
if (value.charCodeAt(0) === 0xFEFF) {
|
||||
value = value.slice(1);
|
||||
|
||||
content.column++;
|
||||
content.offset++;
|
||||
}
|
||||
|
||||
node = {
|
||||
type: 'root',
|
||||
children: self.tokenizeBlock(value, content),
|
||||
position: {
|
||||
start: start,
|
||||
end: self.eof || xtend(start)
|
||||
}
|
||||
};
|
||||
|
||||
if (!self.options.position) {
|
||||
removePosition(node, true);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
+151
-6307
File diff suppressed because it is too large.
Load diff
+59
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse
|
||||
* @fileoverview Markdown parser.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var xtend = require('xtend');
|
||||
var escapes = require('markdown-escapes');
|
||||
var defaults = require('./defaults');
|
||||
|
||||
module.exports = setOptions;
|
||||
|
||||
/* Set options. */
|
||||
function setOptions(options) {
|
||||
var self = this;
|
||||
var current = self.options;
|
||||
var key;
|
||||
var value;
|
||||
|
||||
if (options == null) {
|
||||
options = {};
|
||||
} else if (typeof options === 'object') {
|
||||
options = xtend(options);
|
||||
} else {
|
||||
throw new Error(
|
||||
'Invalid value `' + options + '` ' +
|
||||
'for setting `options`'
|
||||
);
|
||||
}
|
||||
|
||||
for (key in defaults) {
|
||||
value = options[key];
|
||||
|
||||
if (value == null) {
|
||||
value = current[key];
|
||||
}
|
||||
|
||||
if (
|
||||
(key !== 'blocks' && typeof value !== 'boolean') ||
|
||||
(key === 'blocks' && typeof value !== 'object')
|
||||
) {
|
||||
throw new Error(
|
||||
'Invalid value `' + value + '` ' +
|
||||
'for setting `options.' + key + '`'
|
||||
);
|
||||
}
|
||||
|
||||
options[key] = value;
|
||||
}
|
||||
|
||||
self.options = options;
|
||||
self.escape = escapes(options);
|
||||
|
||||
return self;
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:auto-link
|
||||
* @fileoverview Tokenise an auto-link.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var decode = require('parse-entities');
|
||||
var locate = require('../locate/tag');
|
||||
|
||||
module.exports = autoLink;
|
||||
autoLink.locator = locate;
|
||||
autoLink.notInLink = true;
|
||||
|
||||
var C_LT = '<';
|
||||
var C_GT = '>';
|
||||
var C_AT_SIGN = '@';
|
||||
var C_SLASH = '/';
|
||||
var MAILTO = 'mailto:';
|
||||
var MAILTO_LENGTH = MAILTO.length;
|
||||
|
||||
/* Tokenise a link. */
|
||||
function autoLink(eat, value, silent) {
|
||||
var self;
|
||||
var subvalue;
|
||||
var length;
|
||||
var index;
|
||||
var queue;
|
||||
var character;
|
||||
var hasAtCharacter;
|
||||
var link;
|
||||
var now;
|
||||
var content;
|
||||
var tokenize;
|
||||
var exit;
|
||||
|
||||
if (value.charAt(0) !== C_LT) {
|
||||
return;
|
||||
}
|
||||
|
||||
self = this;
|
||||
subvalue = '';
|
||||
length = value.length;
|
||||
index = 0;
|
||||
queue = '';
|
||||
hasAtCharacter = false;
|
||||
link = '';
|
||||
|
||||
index++;
|
||||
subvalue = C_LT;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (
|
||||
character === ' ' ||
|
||||
character === C_GT ||
|
||||
character === C_AT_SIGN ||
|
||||
(character === ':' && value.charAt(index + 1) === C_SLASH)
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (!queue) {
|
||||
return;
|
||||
}
|
||||
|
||||
link += queue;
|
||||
queue = '';
|
||||
|
||||
character = value.charAt(index);
|
||||
link += character;
|
||||
index++;
|
||||
|
||||
if (character === C_AT_SIGN) {
|
||||
hasAtCharacter = true;
|
||||
} else {
|
||||
if (
|
||||
character !== ':' ||
|
||||
value.charAt(index + 1) !== C_SLASH
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
link += C_SLASH;
|
||||
index++;
|
||||
}
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === ' ' || character === C_GT) {
|
||||
break;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!queue || character !== C_GT) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* istanbul ignore if - never used (yet) */
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
link += queue;
|
||||
content = link;
|
||||
subvalue += link + character;
|
||||
now = eat.now();
|
||||
now.column++;
|
||||
now.offset++;
|
||||
|
||||
if (hasAtCharacter) {
|
||||
if (link.slice(0, MAILTO_LENGTH).toLowerCase() === MAILTO) {
|
||||
content = content.substr(MAILTO_LENGTH);
|
||||
now.column += MAILTO_LENGTH;
|
||||
now.offset += MAILTO_LENGTH;
|
||||
} else {
|
||||
link = MAILTO + link;
|
||||
}
|
||||
}
|
||||
|
||||
/* Temporarily remove support for escapes in autolinks. */
|
||||
tokenize = self.inlineTokenizers.escape;
|
||||
self.inlineTokenizers.escape = null;
|
||||
exit = self.enterLink();
|
||||
|
||||
content = self.tokenizeInline(content, now);
|
||||
|
||||
self.inlineTokenizers.escape = tokenize;
|
||||
exit();
|
||||
|
||||
return eat(subvalue)({
|
||||
type: 'link',
|
||||
title: null,
|
||||
url: decode(link),
|
||||
children: content
|
||||
});
|
||||
}
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:blockquote
|
||||
* @fileoverview Tokenise blockquote.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var trim = require('trim');
|
||||
var interrupt = require('../util/interrupt');
|
||||
|
||||
module.exports = blockquote;
|
||||
|
||||
var C_NEWLINE = '\n';
|
||||
var C_TAB = '\t';
|
||||
var C_SPACE = ' ';
|
||||
var C_GT = '>';
|
||||
|
||||
/* Tokenise a blockquote. */
|
||||
function blockquote(eat, value, silent) {
|
||||
var self = this;
|
||||
var offsets = self.offset;
|
||||
var tokenizers = self.blockTokenizers;
|
||||
var interruptors = self.interruptBlockquote;
|
||||
var now = eat.now();
|
||||
var currentLine = now.line;
|
||||
var length = value.length;
|
||||
var values = [];
|
||||
var contents = [];
|
||||
var indents = [];
|
||||
var add;
|
||||
var index = 0;
|
||||
var character;
|
||||
var rest;
|
||||
var nextIndex;
|
||||
var content;
|
||||
var line;
|
||||
var startIndex;
|
||||
var prefixed;
|
||||
var exit;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (value.charAt(index) !== C_GT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
|
||||
while (index < length) {
|
||||
nextIndex = value.indexOf(C_NEWLINE, index);
|
||||
startIndex = index;
|
||||
prefixed = false;
|
||||
|
||||
if (nextIndex === -1) {
|
||||
nextIndex = length;
|
||||
}
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (value.charAt(index) === C_GT) {
|
||||
index++;
|
||||
prefixed = true;
|
||||
|
||||
if (value.charAt(index) === C_SPACE) {
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
index = startIndex;
|
||||
}
|
||||
|
||||
content = value.slice(index, nextIndex);
|
||||
|
||||
if (!prefixed && !trim(content)) {
|
||||
index = startIndex;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!prefixed) {
|
||||
rest = value.slice(index);
|
||||
|
||||
/* Check if the following code contains a possible
|
||||
* block. */
|
||||
if (interrupt(interruptors, tokenizers, self, [eat, rest, true])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
line = startIndex === index ? content : value.slice(startIndex, nextIndex);
|
||||
|
||||
indents.push(index - startIndex);
|
||||
values.push(line);
|
||||
contents.push(content);
|
||||
|
||||
index = nextIndex + 1;
|
||||
}
|
||||
|
||||
index = -1;
|
||||
length = indents.length;
|
||||
add = eat(values.join(C_NEWLINE));
|
||||
|
||||
while (++index < length) {
|
||||
offsets[currentLine] = (offsets[currentLine] || 0) + indents[index];
|
||||
currentLine++;
|
||||
}
|
||||
|
||||
exit = self.enterBlock();
|
||||
contents = self.tokenizeBlock(contents.join(C_NEWLINE), now);
|
||||
exit();
|
||||
|
||||
return add({
|
||||
type: 'blockquote',
|
||||
children: contents
|
||||
});
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:break
|
||||
* @fileoverview Tokenise a break.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var locate = require('../locate/break');
|
||||
|
||||
module.exports = hardBreak;
|
||||
hardBreak.locator = locate;
|
||||
|
||||
var MIN_BREAK_LENGTH = 2;
|
||||
|
||||
/* Tokenise a break. */
|
||||
function hardBreak(eat, value, silent) {
|
||||
var self = this;
|
||||
var breaks = self.options.breaks;
|
||||
var length = value.length;
|
||||
var index = -1;
|
||||
var queue = '';
|
||||
var character;
|
||||
|
||||
while (++index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === '\n') {
|
||||
if (!breaks && index < MIN_BREAK_LENGTH) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* istanbul ignore if - never used (yet) */
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
|
||||
return eat(queue)({type: 'break'});
|
||||
}
|
||||
|
||||
if (character !== ' ') {
|
||||
return;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
}
|
||||
}
|
||||
+245
@@ -0,0 +1,245 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:code-fenced
|
||||
* @fileoverview Tokenise fenced code.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var trim = require('trim-trailing-lines');
|
||||
|
||||
module.exports = fencedCode;
|
||||
|
||||
var C_NEWLINE = '\n';
|
||||
var C_TAB = '\t';
|
||||
var C_SPACE = ' ';
|
||||
var C_TILDE = '~';
|
||||
var C_TICK = '`';
|
||||
|
||||
var MIN_FENCE_COUNT = 3;
|
||||
var CODE_INDENT_COUNT = 4;
|
||||
|
||||
/* Tokenise fenced code. */
|
||||
function fencedCode(eat, value, silent) {
|
||||
var self = this;
|
||||
var settings = self.options;
|
||||
var length = value.length + 1;
|
||||
var index = 0;
|
||||
var subvalue = '';
|
||||
var fenceCount;
|
||||
var marker;
|
||||
var character;
|
||||
var flag;
|
||||
var queue;
|
||||
var content;
|
||||
var exdentedContent;
|
||||
var closing;
|
||||
var exdentedClosing;
|
||||
var indent;
|
||||
var now;
|
||||
|
||||
if (!settings.gfm) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Eat initial spacing. */
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
indent = index;
|
||||
|
||||
/* Eat the fence. */
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_TILDE && character !== C_TICK) {
|
||||
return;
|
||||
}
|
||||
|
||||
index++;
|
||||
marker = character;
|
||||
fenceCount = 1;
|
||||
subvalue += character;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== marker) {
|
||||
break;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
fenceCount++;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (fenceCount < MIN_FENCE_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Eat spacing before flag. */
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
/* Eat flag. */
|
||||
flag = '';
|
||||
queue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (
|
||||
character === C_NEWLINE ||
|
||||
character === C_TILDE ||
|
||||
character === C_TICK
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (character === C_SPACE || character === C_TAB) {
|
||||
queue += character;
|
||||
} else {
|
||||
flag += queue + character;
|
||||
queue = '';
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character && character !== C_NEWLINE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
now = eat.now();
|
||||
now.column += subvalue.length;
|
||||
now.offset += subvalue.length;
|
||||
|
||||
subvalue += flag;
|
||||
flag = self.decode.raw(self.unescape(flag), now);
|
||||
|
||||
if (queue) {
|
||||
subvalue += queue;
|
||||
}
|
||||
|
||||
queue = '';
|
||||
closing = '';
|
||||
exdentedClosing = '';
|
||||
content = '';
|
||||
exdentedContent = '';
|
||||
|
||||
/* Eat content. */
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
content += closing;
|
||||
exdentedContent += exdentedClosing;
|
||||
closing = '';
|
||||
exdentedClosing = '';
|
||||
|
||||
if (character !== C_NEWLINE) {
|
||||
content += character;
|
||||
exdentedClosing += character;
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add the newline to `subvalue` if its the first
|
||||
* character. Otherwise, add it to the `closing`
|
||||
* queue. */
|
||||
if (content) {
|
||||
closing += character;
|
||||
exdentedClosing += character;
|
||||
} else {
|
||||
subvalue += character;
|
||||
}
|
||||
|
||||
queue = '';
|
||||
index++;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_SPACE) {
|
||||
break;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
closing += queue;
|
||||
exdentedClosing += queue.slice(indent);
|
||||
|
||||
if (queue.length >= CODE_INDENT_COUNT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
queue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== marker) {
|
||||
break;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
closing += queue;
|
||||
exdentedClosing += queue;
|
||||
|
||||
if (queue.length < fenceCount) {
|
||||
continue;
|
||||
}
|
||||
|
||||
queue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break;
|
||||
}
|
||||
|
||||
closing += character;
|
||||
exdentedClosing += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (!character || character === C_NEWLINE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
subvalue += content + closing;
|
||||
|
||||
return eat(subvalue)({
|
||||
type: 'code',
|
||||
lang: flag || null,
|
||||
value: trim(exdentedContent)
|
||||
});
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:code-indented
|
||||
* @fileoverview Tokenise indented code.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var repeat = require('repeat-string');
|
||||
var trim = require('trim-trailing-lines');
|
||||
|
||||
module.exports = indentedCode;
|
||||
|
||||
var C_NEWLINE = '\n';
|
||||
var C_TAB = '\t';
|
||||
var C_SPACE = ' ';
|
||||
|
||||
var CODE_INDENT_COUNT = 4;
|
||||
var CODE_INDENT = repeat(C_SPACE, CODE_INDENT_COUNT);
|
||||
|
||||
/* Tokenise indented code. */
|
||||
function indentedCode(eat, value, silent) {
|
||||
var index = -1;
|
||||
var length = value.length;
|
||||
var subvalue = '';
|
||||
var content = '';
|
||||
var subvalueQueue = '';
|
||||
var contentQueue = '';
|
||||
var character;
|
||||
var blankQueue;
|
||||
var indent;
|
||||
|
||||
while (++index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (indent) {
|
||||
indent = false;
|
||||
|
||||
subvalue += subvalueQueue;
|
||||
content += contentQueue;
|
||||
subvalueQueue = '';
|
||||
contentQueue = '';
|
||||
|
||||
if (character === C_NEWLINE) {
|
||||
subvalueQueue = character;
|
||||
contentQueue = character;
|
||||
} else {
|
||||
subvalue += character;
|
||||
content += character;
|
||||
|
||||
while (++index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!character || character === C_NEWLINE) {
|
||||
contentQueue = character;
|
||||
subvalueQueue = character;
|
||||
break;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
content += character;
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
character === C_SPACE &&
|
||||
value.charAt(index + 1) === character &&
|
||||
value.charAt(index + 2) === character &&
|
||||
value.charAt(index + 3) === character
|
||||
) {
|
||||
subvalueQueue += CODE_INDENT;
|
||||
index += 3;
|
||||
indent = true;
|
||||
} else if (character === C_TAB) {
|
||||
subvalueQueue += character;
|
||||
indent = true;
|
||||
} else {
|
||||
blankQueue = '';
|
||||
|
||||
while (character === C_TAB || character === C_SPACE) {
|
||||
blankQueue += character;
|
||||
character = value.charAt(++index);
|
||||
}
|
||||
|
||||
if (character !== C_NEWLINE) {
|
||||
break;
|
||||
}
|
||||
|
||||
subvalueQueue += blankQueue + character;
|
||||
contentQueue += character;
|
||||
}
|
||||
}
|
||||
|
||||
if (content) {
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return eat(subvalue)({
|
||||
type: 'code',
|
||||
lang: null,
|
||||
value: trim(content)
|
||||
});
|
||||
}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:code-inline
|
||||
* @fileoverview Tokenise inline code.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var whitespace = require('is-whitespace-character');
|
||||
var locate = require('../locate/code-inline');
|
||||
|
||||
module.exports = inlineCode;
|
||||
inlineCode.locator = locate;
|
||||
|
||||
var C_TICK = '`';
|
||||
|
||||
/* Tokenise inline code. */
|
||||
function inlineCode(eat, value, silent) {
|
||||
var length = value.length;
|
||||
var index = 0;
|
||||
var queue = '';
|
||||
var tickQueue = '';
|
||||
var contentQueue;
|
||||
var subqueue;
|
||||
var count;
|
||||
var openingCount;
|
||||
var subvalue;
|
||||
var character;
|
||||
var found;
|
||||
var next;
|
||||
|
||||
while (index < length) {
|
||||
if (value.charAt(index) !== C_TICK) {
|
||||
break;
|
||||
}
|
||||
|
||||
queue += C_TICK;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (!queue) {
|
||||
return;
|
||||
}
|
||||
|
||||
subvalue = queue;
|
||||
openingCount = index;
|
||||
queue = '';
|
||||
next = value.charAt(index);
|
||||
count = 0;
|
||||
|
||||
while (index < length) {
|
||||
character = next;
|
||||
next = value.charAt(index + 1);
|
||||
|
||||
if (character === C_TICK) {
|
||||
count++;
|
||||
tickQueue += character;
|
||||
} else {
|
||||
count = 0;
|
||||
queue += character;
|
||||
}
|
||||
|
||||
if (count && next !== C_TICK) {
|
||||
if (count === openingCount) {
|
||||
subvalue += queue + tickQueue;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
queue += tickQueue;
|
||||
tickQueue = '';
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
if (openingCount % 2 !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
queue = '';
|
||||
}
|
||||
|
||||
/* istanbul ignore if - never used (yet) */
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
contentQueue = '';
|
||||
subqueue = '';
|
||||
length = queue.length;
|
||||
index = -1;
|
||||
|
||||
while (++index < length) {
|
||||
character = queue.charAt(index);
|
||||
|
||||
if (whitespace(character)) {
|
||||
subqueue += character;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (subqueue) {
|
||||
if (contentQueue) {
|
||||
contentQueue += subqueue;
|
||||
}
|
||||
|
||||
subqueue = '';
|
||||
}
|
||||
|
||||
contentQueue += character;
|
||||
}
|
||||
|
||||
return eat(subvalue)({
|
||||
type: 'inlineCode',
|
||||
value: contentQueue
|
||||
});
|
||||
}
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:definition
|
||||
* @fileoverview Tokenise a definition.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var whitespace = require('is-whitespace-character');
|
||||
var normalize = require('../util/normalize');
|
||||
|
||||
module.exports = definition;
|
||||
definition.notInList = true;
|
||||
definition.notInBlock = true;
|
||||
|
||||
var C_DOUBLE_QUOTE = '"';
|
||||
var C_SINGLE_QUOTE = '\'';
|
||||
var C_BACKSLASH = '\\';
|
||||
var C_NEWLINE = '\n';
|
||||
var C_TAB = '\t';
|
||||
var C_SPACE = ' ';
|
||||
var C_BRACKET_OPEN = '[';
|
||||
var C_BRACKET_CLOSE = ']';
|
||||
var C_PAREN_OPEN = '(';
|
||||
var C_PAREN_CLOSE = ')';
|
||||
var C_COLON = ':';
|
||||
var C_LT = '<';
|
||||
var C_GT = '>';
|
||||
|
||||
/* Tokenise a definition. */
|
||||
function definition(eat, value, silent) {
|
||||
var self = this;
|
||||
var commonmark = self.options.commonmark;
|
||||
var index = 0;
|
||||
var length = value.length;
|
||||
var subvalue = '';
|
||||
var beforeURL;
|
||||
var beforeTitle;
|
||||
var queue;
|
||||
var character;
|
||||
var test;
|
||||
var identifier;
|
||||
var url;
|
||||
var title;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_BRACKET_OPEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
index++;
|
||||
subvalue += character;
|
||||
queue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === C_BRACKET_CLOSE) {
|
||||
break;
|
||||
} else if (character === C_BACKSLASH) {
|
||||
queue += character;
|
||||
index++;
|
||||
character = value.charAt(index);
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (
|
||||
!queue ||
|
||||
value.charAt(index) !== C_BRACKET_CLOSE ||
|
||||
value.charAt(index + 1) !== C_COLON
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
identifier = queue;
|
||||
subvalue += queue + C_BRACKET_CLOSE + C_COLON;
|
||||
index = subvalue.length;
|
||||
queue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (
|
||||
character !== C_TAB &&
|
||||
character !== C_SPACE &&
|
||||
character !== C_NEWLINE
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
queue = '';
|
||||
beforeURL = subvalue;
|
||||
|
||||
if (character === C_LT) {
|
||||
index++;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!isEnclosedURLCharacter(character)) {
|
||||
break;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === isEnclosedURLCharacter.delimiter) {
|
||||
subvalue += C_LT + queue + character;
|
||||
index++;
|
||||
} else {
|
||||
if (commonmark) {
|
||||
return;
|
||||
}
|
||||
|
||||
index -= queue.length + 1;
|
||||
queue = '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!queue) {
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!isUnclosedURLCharacter(character)) {
|
||||
break;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
subvalue += queue;
|
||||
}
|
||||
|
||||
if (!queue) {
|
||||
return;
|
||||
}
|
||||
|
||||
url = queue;
|
||||
queue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (
|
||||
character !== C_TAB &&
|
||||
character !== C_SPACE &&
|
||||
character !== C_NEWLINE
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
test = null;
|
||||
|
||||
if (character === C_DOUBLE_QUOTE) {
|
||||
test = C_DOUBLE_QUOTE;
|
||||
} else if (character === C_SINGLE_QUOTE) {
|
||||
test = C_SINGLE_QUOTE;
|
||||
} else if (character === C_PAREN_OPEN) {
|
||||
test = C_PAREN_CLOSE;
|
||||
}
|
||||
|
||||
if (!test) {
|
||||
queue = '';
|
||||
index = subvalue.length;
|
||||
} else if (queue) {
|
||||
subvalue += queue + character;
|
||||
index = subvalue.length;
|
||||
queue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === test) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (character === C_NEWLINE) {
|
||||
index++;
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === C_NEWLINE || character === test) {
|
||||
return;
|
||||
}
|
||||
|
||||
queue += C_NEWLINE;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== test) {
|
||||
return;
|
||||
}
|
||||
|
||||
beforeTitle = subvalue;
|
||||
subvalue += queue + character;
|
||||
index++;
|
||||
title = queue;
|
||||
queue = '';
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_TAB && character !== C_SPACE) {
|
||||
break;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!character || character === C_NEWLINE) {
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
beforeURL = eat(beforeURL).test().end;
|
||||
url = self.decode.raw(self.unescape(url), beforeURL);
|
||||
|
||||
if (title) {
|
||||
beforeTitle = eat(beforeTitle).test().end;
|
||||
title = self.decode.raw(self.unescape(title), beforeTitle);
|
||||
}
|
||||
|
||||
return eat(subvalue)({
|
||||
type: 'definition',
|
||||
identifier: normalize(identifier),
|
||||
title: title || null,
|
||||
url: url
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if `character` can be inside an enclosed URI. */
|
||||
function isEnclosedURLCharacter(character) {
|
||||
return character !== C_GT &&
|
||||
character !== C_BRACKET_OPEN &&
|
||||
character !== C_BRACKET_CLOSE;
|
||||
}
|
||||
|
||||
isEnclosedURLCharacter.delimiter = C_GT;
|
||||
|
||||
/* Check if `character` can be inside an unclosed URI. */
|
||||
function isUnclosedURLCharacter(character) {
|
||||
return character !== C_BRACKET_OPEN &&
|
||||
character !== C_BRACKET_CLOSE &&
|
||||
!whitespace(character);
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:delete
|
||||
* @fileoverview Tokenise strikethrough.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var whitespace = require('is-whitespace-character');
|
||||
var locate = require('../locate/delete');
|
||||
|
||||
module.exports = strikethrough;
|
||||
strikethrough.locator = locate;
|
||||
|
||||
var C_TILDE = '~';
|
||||
var DOUBLE = '~~';
|
||||
|
||||
/* Tokenise strikethrough. */
|
||||
function strikethrough(eat, value, silent) {
|
||||
var self = this;
|
||||
var character = '';
|
||||
var previous = '';
|
||||
var preceding = '';
|
||||
var subvalue = '';
|
||||
var index;
|
||||
var length;
|
||||
var now;
|
||||
|
||||
if (
|
||||
!self.options.gfm ||
|
||||
value.charAt(0) !== C_TILDE ||
|
||||
value.charAt(1) !== C_TILDE ||
|
||||
whitespace(value.charAt(2))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
index = 1;
|
||||
length = value.length;
|
||||
now = eat.now();
|
||||
now.column += 2;
|
||||
now.offset += 2;
|
||||
|
||||
while (++index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (
|
||||
character === C_TILDE &&
|
||||
previous === C_TILDE &&
|
||||
(!preceding || !whitespace(preceding))
|
||||
) {
|
||||
/* istanbul ignore if - never used (yet) */
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return eat(DOUBLE + subvalue + DOUBLE)({
|
||||
type: 'delete',
|
||||
children: self.tokenizeInline(subvalue, now)
|
||||
});
|
||||
}
|
||||
|
||||
subvalue += previous;
|
||||
preceding = previous;
|
||||
previous = character;
|
||||
}
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:emphasis
|
||||
* @fileoverview Tokenise emphasis.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var trim = require('trim');
|
||||
var word = require('is-word-character');
|
||||
var whitespace = require('is-whitespace-character');
|
||||
var locate = require('../locate/emphasis');
|
||||
|
||||
module.exports = emphasis;
|
||||
emphasis.locator = locate;
|
||||
|
||||
var C_ASTERISK = '*';
|
||||
var C_UNDERSCORE = '_';
|
||||
|
||||
/* Tokenise emphasis. */
|
||||
function emphasis(eat, value, silent) {
|
||||
var self = this;
|
||||
var index = 0;
|
||||
var character = value.charAt(index);
|
||||
var now;
|
||||
var pedantic;
|
||||
var marker;
|
||||
var queue;
|
||||
var subvalue;
|
||||
var length;
|
||||
var prev;
|
||||
|
||||
if (character !== C_ASTERISK && character !== C_UNDERSCORE) {
|
||||
return;
|
||||
}
|
||||
|
||||
pedantic = self.options.pedantic;
|
||||
subvalue = character;
|
||||
marker = character;
|
||||
length = value.length;
|
||||
index++;
|
||||
queue = '';
|
||||
character = '';
|
||||
|
||||
if (pedantic && whitespace(value.charAt(index))) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (index < length) {
|
||||
prev = character;
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === marker && (!pedantic || !whitespace(prev))) {
|
||||
character = value.charAt(++index);
|
||||
|
||||
if (character !== marker) {
|
||||
if (!trim(queue) || prev === marker) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pedantic && marker === C_UNDERSCORE && word(character)) {
|
||||
queue += marker;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* istanbul ignore if - never used (yet) */
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
now = eat.now();
|
||||
now.column++;
|
||||
now.offset++;
|
||||
|
||||
return eat(subvalue + queue + marker)({
|
||||
type: 'emphasis',
|
||||
children: self.tokenizeInline(queue, now)
|
||||
});
|
||||
}
|
||||
|
||||
queue += marker;
|
||||
}
|
||||
|
||||
if (!pedantic && character === '\\') {
|
||||
queue += character;
|
||||
character = value.charAt(++index);
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:escape
|
||||
* @fileoverview Tokenise an escape.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var locate = require('../locate/escape');
|
||||
|
||||
module.exports = escape;
|
||||
escape.locator = locate;
|
||||
|
||||
/* Tokenise an escape. */
|
||||
function escape(eat, value, silent) {
|
||||
var self = this;
|
||||
var character;
|
||||
var node;
|
||||
|
||||
if (value.charAt(0) === '\\') {
|
||||
character = value.charAt(1);
|
||||
|
||||
if (self.escape.indexOf(character) !== -1) {
|
||||
/* istanbul ignore if - never used (yet) */
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (character === '\n') {
|
||||
node = {type: 'break'};
|
||||
} else {
|
||||
node = {
|
||||
type: 'text',
|
||||
value: character
|
||||
};
|
||||
}
|
||||
|
||||
return eat('\\' + character)(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:footnote-definition
|
||||
* @fileoverview Tokenise footnote definition.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var whitespace = require('is-whitespace-character');
|
||||
var normalize = require('../util/normalize');
|
||||
|
||||
module.exports = footnoteDefinition;
|
||||
footnoteDefinition.notInList = true;
|
||||
footnoteDefinition.notInBlock = true;
|
||||
|
||||
var C_BACKSLASH = '\\';
|
||||
var C_NEWLINE = '\n';
|
||||
var C_TAB = '\t';
|
||||
var C_SPACE = ' ';
|
||||
var C_BRACKET_OPEN = '[';
|
||||
var C_BRACKET_CLOSE = ']';
|
||||
var C_CARET = '^';
|
||||
var C_COLON = ':';
|
||||
|
||||
var EXPRESSION_INITIAL_TAB = /^( {4}|\t)?/gm;
|
||||
|
||||
/* Tokenise a footnote definition. */
|
||||
function footnoteDefinition(eat, value, silent) {
|
||||
var self = this;
|
||||
var offsets = self.offset;
|
||||
var index;
|
||||
var length;
|
||||
var subvalue;
|
||||
var now;
|
||||
var currentLine;
|
||||
var content;
|
||||
var queue;
|
||||
var subqueue;
|
||||
var character;
|
||||
var identifier;
|
||||
var add;
|
||||
var exit;
|
||||
|
||||
if (!self.options.footnotes) {
|
||||
return;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
length = value.length;
|
||||
subvalue = '';
|
||||
now = eat.now();
|
||||
currentLine = now.line;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!whitespace(character)) {
|
||||
break;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (
|
||||
value.charAt(index) !== C_BRACKET_OPEN ||
|
||||
value.charAt(index + 1) !== C_CARET
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
subvalue += C_BRACKET_OPEN + C_CARET;
|
||||
index = subvalue.length;
|
||||
queue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === C_BRACKET_CLOSE) {
|
||||
break;
|
||||
} else if (character === C_BACKSLASH) {
|
||||
queue += character;
|
||||
index++;
|
||||
character = value.charAt(index);
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (
|
||||
!queue ||
|
||||
value.charAt(index) !== C_BRACKET_CLOSE ||
|
||||
value.charAt(index + 1) !== C_COLON
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
identifier = normalize(queue);
|
||||
subvalue += queue + C_BRACKET_CLOSE + C_COLON;
|
||||
index = subvalue.length;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_TAB && character !== C_SPACE) {
|
||||
break;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
now.column += subvalue.length;
|
||||
now.offset += subvalue.length;
|
||||
queue = '';
|
||||
content = '';
|
||||
subqueue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === C_NEWLINE) {
|
||||
subqueue = character;
|
||||
index++;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_NEWLINE) {
|
||||
break;
|
||||
}
|
||||
|
||||
subqueue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
queue += subqueue;
|
||||
subqueue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_SPACE) {
|
||||
break;
|
||||
}
|
||||
|
||||
subqueue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (subqueue.length === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
queue += subqueue;
|
||||
}
|
||||
|
||||
if (queue) {
|
||||
content += queue;
|
||||
queue = '';
|
||||
}
|
||||
|
||||
content += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
subvalue += content;
|
||||
|
||||
content = content.replace(EXPRESSION_INITIAL_TAB, function (line) {
|
||||
offsets[currentLine] = (offsets[currentLine] || 0) + line.length;
|
||||
currentLine++;
|
||||
|
||||
return '';
|
||||
});
|
||||
|
||||
add = eat(subvalue);
|
||||
|
||||
exit = self.enterBlock();
|
||||
content = self.tokenizeBlock(content, now);
|
||||
exit();
|
||||
|
||||
return add({
|
||||
type: 'footnoteDefinition',
|
||||
identifier: identifier,
|
||||
children: content
|
||||
});
|
||||
}
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:heading-atx
|
||||
* @fileoverview Tokenise an ATX-style heading.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = atxHeading;
|
||||
|
||||
var C_NEWLINE = '\n';
|
||||
var C_TAB = '\t';
|
||||
var C_SPACE = ' ';
|
||||
var C_HASH = '#';
|
||||
|
||||
var MAX_ATX_COUNT = 6;
|
||||
|
||||
/* Tokenise an ATX-style heading. */
|
||||
function atxHeading(eat, value, silent) {
|
||||
var self = this;
|
||||
var settings = self.options;
|
||||
var length = value.length + 1;
|
||||
var index = -1;
|
||||
var now = eat.now();
|
||||
var subvalue = '';
|
||||
var content = '';
|
||||
var character;
|
||||
var queue;
|
||||
var depth;
|
||||
|
||||
/* Eat initial spacing. */
|
||||
while (++index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
index--;
|
||||
break;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
}
|
||||
|
||||
/* Eat hashes. */
|
||||
depth = 0;
|
||||
|
||||
while (++index <= length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_HASH) {
|
||||
index--;
|
||||
break;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
depth++;
|
||||
}
|
||||
|
||||
if (depth > MAX_ATX_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!depth ||
|
||||
(!settings.pedantic && value.charAt(index + 1) === C_HASH)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
length = value.length + 1;
|
||||
|
||||
/* Eat intermediate white-space. */
|
||||
queue = '';
|
||||
|
||||
while (++index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
index--;
|
||||
break;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
}
|
||||
|
||||
/* Exit when not in pedantic mode without spacing. */
|
||||
if (
|
||||
!settings.pedantic &&
|
||||
queue.length === 0 &&
|
||||
character &&
|
||||
character !== C_NEWLINE
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Eat content. */
|
||||
subvalue += queue;
|
||||
queue = '';
|
||||
content = '';
|
||||
|
||||
while (++index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!character || character === C_NEWLINE) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (
|
||||
character !== C_SPACE &&
|
||||
character !== C_TAB &&
|
||||
character !== C_HASH
|
||||
) {
|
||||
content += queue + character;
|
||||
queue = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
while (character === C_SPACE || character === C_TAB) {
|
||||
queue += character;
|
||||
character = value.charAt(++index);
|
||||
}
|
||||
|
||||
while (character === C_HASH) {
|
||||
queue += character;
|
||||
character = value.charAt(++index);
|
||||
}
|
||||
|
||||
while (character === C_SPACE || character === C_TAB) {
|
||||
queue += character;
|
||||
character = value.charAt(++index);
|
||||
}
|
||||
|
||||
index--;
|
||||
}
|
||||
|
||||
now.column += subvalue.length;
|
||||
now.offset += subvalue.length;
|
||||
subvalue += content + queue;
|
||||
|
||||
return eat(subvalue)({
|
||||
type: 'heading',
|
||||
depth: depth,
|
||||
children: self.tokenizeInline(content, now)
|
||||
});
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:heading-setext
|
||||
* @fileoverview Tokenise an setext-style heading.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = setextHeading;
|
||||
|
||||
var C_NEWLINE = '\n';
|
||||
var C_TAB = '\t';
|
||||
var C_SPACE = ' ';
|
||||
var C_EQUALS = '=';
|
||||
var C_DASH = '-';
|
||||
|
||||
var MAX_HEADING_INDENT = 3;
|
||||
|
||||
/* Map of characters which can be used to mark setext
|
||||
* headers, mapping to their corresponding depth. */
|
||||
var SETEXT_MARKERS = {};
|
||||
|
||||
SETEXT_MARKERS[C_EQUALS] = 1;
|
||||
SETEXT_MARKERS[C_DASH] = 2;
|
||||
|
||||
/* Tokenise an setext-style heading. */
|
||||
function setextHeading(eat, value, silent) {
|
||||
var self = this;
|
||||
var now = eat.now();
|
||||
var length = value.length;
|
||||
var index = -1;
|
||||
var subvalue = '';
|
||||
var content;
|
||||
var queue;
|
||||
var character;
|
||||
var marker;
|
||||
var depth;
|
||||
|
||||
/* Eat initial indentation. */
|
||||
while (++index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_SPACE || index >= MAX_HEADING_INDENT) {
|
||||
index--;
|
||||
break;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
}
|
||||
|
||||
/* Eat content. */
|
||||
content = '';
|
||||
queue = '';
|
||||
|
||||
while (++index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === C_NEWLINE) {
|
||||
index--;
|
||||
break;
|
||||
}
|
||||
|
||||
if (character === C_SPACE || character === C_TAB) {
|
||||
queue += character;
|
||||
} else {
|
||||
content += queue + character;
|
||||
queue = '';
|
||||
}
|
||||
}
|
||||
|
||||
now.column += subvalue.length;
|
||||
now.offset += subvalue.length;
|
||||
subvalue += content + queue;
|
||||
|
||||
/* Ensure the content is followed by a newline and a
|
||||
* valid marker. */
|
||||
character = value.charAt(++index);
|
||||
marker = value.charAt(++index);
|
||||
|
||||
if (character !== C_NEWLINE || !SETEXT_MARKERS[marker]) {
|
||||
return;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
|
||||
/* Eat Setext-line. */
|
||||
queue = marker;
|
||||
depth = SETEXT_MARKERS[marker];
|
||||
|
||||
while (++index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== marker) {
|
||||
if (character !== C_NEWLINE) {
|
||||
return;
|
||||
}
|
||||
|
||||
index--;
|
||||
break;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
}
|
||||
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return eat(subvalue + queue)({
|
||||
type: 'heading',
|
||||
depth: depth,
|
||||
children: self.tokenizeInline(content, now)
|
||||
});
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:html-block
|
||||
* @fileoverview Tokenise block HTML.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var openCloseTag = require('../util/html').openCloseTag;
|
||||
|
||||
module.exports = blockHTML;
|
||||
|
||||
var C_TAB = '\t';
|
||||
var C_SPACE = ' ';
|
||||
var C_NEWLINE = '\n';
|
||||
var C_LT = '<';
|
||||
|
||||
/* Tokenise block HTML. */
|
||||
function blockHTML(eat, value, silent) {
|
||||
var self = this;
|
||||
var blocks = self.options.blocks;
|
||||
var length = value.length;
|
||||
var index = 0;
|
||||
var next;
|
||||
var line;
|
||||
var offset;
|
||||
var character;
|
||||
var count;
|
||||
var sequence;
|
||||
var subvalue;
|
||||
|
||||
var sequences = [
|
||||
[/^<(script|pre|style)(?=(\s|>|$))/i, /<\/(script|pre|style)>/i, true],
|
||||
[/^<!--/, /-->/, true],
|
||||
[/^<\?/, /\?>/, true],
|
||||
[/^<![A-Za-z]/, />/, true],
|
||||
[/^<!\[CDATA\[/, /\]\]>/, true],
|
||||
[new RegExp('^</?(' + blocks.join('|') + ')(?=(\\s|/?>|$))', 'i'), /^$/, true],
|
||||
[new RegExp(openCloseTag.source + '\\s*$'), /^$/, false]
|
||||
];
|
||||
|
||||
/* Eat initial spacing. */
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_TAB && character !== C_SPACE) {
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (value.charAt(index) !== C_LT) {
|
||||
return;
|
||||
}
|
||||
|
||||
next = value.indexOf(C_NEWLINE, index + 1);
|
||||
next = next === -1 ? length : next;
|
||||
line = value.slice(index, next);
|
||||
offset = -1;
|
||||
count = sequences.length;
|
||||
|
||||
while (++offset < count) {
|
||||
if (sequences[offset][0].test(line)) {
|
||||
sequence = sequences[offset];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sequence) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (silent) {
|
||||
return sequence[2];
|
||||
}
|
||||
|
||||
index = next;
|
||||
|
||||
if (!sequence[1].test(line)) {
|
||||
while (index < length) {
|
||||
next = value.indexOf(C_NEWLINE, index + 1);
|
||||
next = next === -1 ? length : next;
|
||||
line = value.slice(index + 1, next);
|
||||
|
||||
if (sequence[1].test(line)) {
|
||||
if (line) {
|
||||
index = next;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
index = next;
|
||||
}
|
||||
}
|
||||
|
||||
subvalue = value.slice(0, index);
|
||||
|
||||
return eat(subvalue)({type: 'html', value: subvalue});
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:html-inline
|
||||
* @fileoverview Tokenise inline HTML.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var alphabetical = require('is-alphabetical');
|
||||
var locate = require('../locate/tag');
|
||||
var tag = require('../util/html').tag;
|
||||
|
||||
module.exports = inlineHTML;
|
||||
inlineHTML.locator = locate;
|
||||
|
||||
var EXPRESSION_HTML_LINK_OPEN = /^<a /i;
|
||||
var EXPRESSION_HTML_LINK_CLOSE = /^<\/a>/i;
|
||||
|
||||
/* Tokenise inline HTML. */
|
||||
function inlineHTML(eat, value, silent) {
|
||||
var self = this;
|
||||
var length = value.length;
|
||||
var character;
|
||||
var subvalue;
|
||||
|
||||
if (value.charAt(0) !== '<' || length < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
character = value.charAt(1);
|
||||
|
||||
if (
|
||||
!alphabetical(character) &&
|
||||
character !== '?' &&
|
||||
character !== '!' &&
|
||||
character !== '/'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
subvalue = value.match(tag);
|
||||
|
||||
if (!subvalue) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* istanbul ignore if - not used yet. */
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
subvalue = subvalue[0];
|
||||
|
||||
if (!self.inLink && EXPRESSION_HTML_LINK_OPEN.test(subvalue)) {
|
||||
self.inLink = true;
|
||||
} else if (self.inLink && EXPRESSION_HTML_LINK_CLOSE.test(subvalue)) {
|
||||
self.inLink = false;
|
||||
}
|
||||
|
||||
return eat(subvalue)({type: 'html', value: subvalue});
|
||||
}
|
||||
+399
@@ -0,0 +1,399 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:link
|
||||
* @fileoverview Tokenise a link.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var has = require('has');
|
||||
var whitespace = require('is-whitespace-character');
|
||||
var locate = require('../locate/link');
|
||||
|
||||
module.exports = link;
|
||||
link.locator = locate;
|
||||
|
||||
var C_BACKSLASH = '\\';
|
||||
var C_BRACKET_OPEN = '[';
|
||||
var C_BRACKET_CLOSE = ']';
|
||||
var C_PAREN_OPEN = '(';
|
||||
var C_PAREN_CLOSE = ')';
|
||||
var C_LT = '<';
|
||||
var C_GT = '>';
|
||||
var C_TICK = '`';
|
||||
var C_DOUBLE_QUOTE = '"';
|
||||
var C_SINGLE_QUOTE = '\'';
|
||||
|
||||
/* Map of characters, which can be used to mark link
|
||||
* and image titles. */
|
||||
var LINK_MARKERS = {};
|
||||
|
||||
LINK_MARKERS[C_DOUBLE_QUOTE] = C_DOUBLE_QUOTE;
|
||||
LINK_MARKERS[C_SINGLE_QUOTE] = C_SINGLE_QUOTE;
|
||||
|
||||
/* Map of characters, which can be used to mark link
|
||||
* and image titles in commonmark-mode. */
|
||||
var COMMONMARK_LINK_MARKERS = {};
|
||||
|
||||
COMMONMARK_LINK_MARKERS[C_DOUBLE_QUOTE] = C_DOUBLE_QUOTE;
|
||||
COMMONMARK_LINK_MARKERS[C_SINGLE_QUOTE] = C_SINGLE_QUOTE;
|
||||
COMMONMARK_LINK_MARKERS[C_PAREN_OPEN] = C_PAREN_CLOSE;
|
||||
|
||||
/* Tokenise a link. */
|
||||
function link(eat, value, silent) {
|
||||
var self = this;
|
||||
var subvalue = '';
|
||||
var index = 0;
|
||||
var character = value.charAt(0);
|
||||
var commonmark = self.options.commonmark;
|
||||
var gfm = self.options.gfm;
|
||||
var closed;
|
||||
var count;
|
||||
var opening;
|
||||
var beforeURL;
|
||||
var beforeTitle;
|
||||
var subqueue;
|
||||
var hasMarker;
|
||||
var markers;
|
||||
var isImage;
|
||||
var content;
|
||||
var marker;
|
||||
var length;
|
||||
var title;
|
||||
var depth;
|
||||
var queue;
|
||||
var url;
|
||||
var now;
|
||||
var exit;
|
||||
var node;
|
||||
|
||||
/* Detect whether this is an image. */
|
||||
if (character === '!') {
|
||||
isImage = true;
|
||||
subvalue = character;
|
||||
character = value.charAt(++index);
|
||||
}
|
||||
|
||||
/* Eat the opening. */
|
||||
if (character !== C_BRACKET_OPEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Exit when this is a link and we’re already inside
|
||||
* a link. */
|
||||
if (!isImage && self.inLink) {
|
||||
return;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
queue = '';
|
||||
index++;
|
||||
|
||||
/* Eat the content. */
|
||||
length = value.length;
|
||||
now = eat.now();
|
||||
depth = 0;
|
||||
|
||||
now.column += index;
|
||||
now.offset += index;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
subqueue = character;
|
||||
|
||||
if (character === C_TICK) {
|
||||
/* Inline-code in link content. */
|
||||
count = 1;
|
||||
|
||||
while (value.charAt(index + 1) === C_TICK) {
|
||||
subqueue += character;
|
||||
index++;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (!opening) {
|
||||
opening = count;
|
||||
} else if (count >= opening) {
|
||||
opening = 0;
|
||||
}
|
||||
} else if (character === C_BACKSLASH) {
|
||||
/* Allow brackets to be escaped. */
|
||||
index++;
|
||||
subqueue += value.charAt(index);
|
||||
/* In GFM mode, brackets in code still count.
|
||||
* In all other modes, they don’t. This empty
|
||||
* block prevents the next statements are
|
||||
* entered. */
|
||||
} else if ((!opening || gfm) && character === C_BRACKET_OPEN) {
|
||||
depth++;
|
||||
} else if ((!opening || gfm) && character === C_BRACKET_CLOSE) {
|
||||
if (depth) {
|
||||
depth--;
|
||||
} else {
|
||||
/* Allow white-space between content and
|
||||
* url in GFM mode. */
|
||||
if (gfm) {
|
||||
while (index < length) {
|
||||
character = value.charAt(index + 1);
|
||||
|
||||
if (!whitespace(character)) {
|
||||
break;
|
||||
}
|
||||
|
||||
subqueue += character;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
if (value.charAt(index + 1) !== C_PAREN_OPEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
subqueue += C_PAREN_OPEN;
|
||||
closed = true;
|
||||
index++;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
queue += subqueue;
|
||||
subqueue = '';
|
||||
index++;
|
||||
}
|
||||
|
||||
/* Eat the content closing. */
|
||||
if (!closed) {
|
||||
return;
|
||||
}
|
||||
|
||||
content = queue;
|
||||
subvalue += queue + subqueue;
|
||||
index++;
|
||||
|
||||
/* Eat white-space. */
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!whitespace(character)) {
|
||||
break;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
/* Eat the URL. */
|
||||
character = value.charAt(index);
|
||||
markers = commonmark ? COMMONMARK_LINK_MARKERS : LINK_MARKERS;
|
||||
queue = '';
|
||||
beforeURL = subvalue;
|
||||
|
||||
if (character === C_LT) {
|
||||
index++;
|
||||
beforeURL += C_LT;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === C_GT) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (commonmark && character === '\n') {
|
||||
return;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (value.charAt(index) !== C_GT) {
|
||||
return;
|
||||
}
|
||||
|
||||
subvalue += C_LT + queue + C_GT;
|
||||
url = queue;
|
||||
index++;
|
||||
} else {
|
||||
character = null;
|
||||
subqueue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (subqueue && has(markers, character)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (whitespace(character)) {
|
||||
if (commonmark) {
|
||||
break;
|
||||
}
|
||||
|
||||
subqueue += character;
|
||||
} else {
|
||||
if (character === C_PAREN_OPEN) {
|
||||
depth++;
|
||||
} else if (character === C_PAREN_CLOSE) {
|
||||
if (depth === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
depth--;
|
||||
}
|
||||
|
||||
queue += subqueue;
|
||||
subqueue = '';
|
||||
|
||||
if (character === C_BACKSLASH) {
|
||||
queue += C_BACKSLASH;
|
||||
character = value.charAt(++index);
|
||||
}
|
||||
|
||||
queue += character;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
subvalue += queue;
|
||||
url = queue;
|
||||
index = subvalue.length;
|
||||
}
|
||||
|
||||
/* Eat white-space. */
|
||||
queue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!whitespace(character)) {
|
||||
break;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
subvalue += queue;
|
||||
|
||||
/* Eat the title. */
|
||||
if (queue && has(markers, character)) {
|
||||
index++;
|
||||
subvalue += character;
|
||||
queue = '';
|
||||
marker = markers[character];
|
||||
beforeTitle = subvalue;
|
||||
|
||||
/* In commonmark-mode, things are pretty easy: the
|
||||
* marker cannot occur inside the title.
|
||||
*
|
||||
* Non-commonmark does, however, support nested
|
||||
* delimiters. */
|
||||
if (commonmark) {
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === marker) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (character === C_BACKSLASH) {
|
||||
queue += C_BACKSLASH;
|
||||
character = value.charAt(++index);
|
||||
}
|
||||
|
||||
index++;
|
||||
queue += character;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== marker) {
|
||||
return;
|
||||
}
|
||||
|
||||
title = queue;
|
||||
subvalue += queue + character;
|
||||
index++;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!whitespace(character)) {
|
||||
break;
|
||||
}
|
||||
|
||||
subvalue += character;
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
subqueue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === marker) {
|
||||
if (hasMarker) {
|
||||
queue += marker + subqueue;
|
||||
subqueue = '';
|
||||
}
|
||||
|
||||
hasMarker = true;
|
||||
} else if (!hasMarker) {
|
||||
queue += character;
|
||||
} else if (character === C_PAREN_CLOSE) {
|
||||
subvalue += queue + marker + subqueue;
|
||||
title = queue;
|
||||
break;
|
||||
} else if (whitespace(character)) {
|
||||
subqueue += character;
|
||||
} else {
|
||||
queue += marker + subqueue + character;
|
||||
subqueue = '';
|
||||
hasMarker = false;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value.charAt(index) !== C_PAREN_CLOSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* istanbul ignore if - never used (yet) */
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
subvalue += C_PAREN_CLOSE;
|
||||
|
||||
url = self.decode.raw(self.unescape(url), eat(beforeURL).test().end);
|
||||
|
||||
if (title) {
|
||||
beforeTitle = eat(beforeTitle).test().end;
|
||||
title = self.decode.raw(self.unescape(title), beforeTitle);
|
||||
}
|
||||
|
||||
node = {
|
||||
type: isImage ? 'image' : 'link',
|
||||
title: title || null,
|
||||
url: url
|
||||
};
|
||||
|
||||
if (isImage) {
|
||||
node.alt = self.decode.raw(self.unescape(content), now) || null;
|
||||
} else {
|
||||
exit = self.enterLink();
|
||||
node.children = self.tokenizeInline(content, now);
|
||||
exit();
|
||||
}
|
||||
|
||||
return eat(subvalue)(node);
|
||||
}
|
||||
+494
@@ -0,0 +1,494 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:list
|
||||
* @fileoverview Tokenise a list.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* eslint-disable max-params */
|
||||
|
||||
var trim = require('trim');
|
||||
var repeat = require('repeat-string');
|
||||
var decimal = require('is-decimal');
|
||||
var getIndent = require('../util/get-indentation');
|
||||
var removeIndent = require('../util/remove-indentation');
|
||||
var interrupt = require('../util/interrupt');
|
||||
|
||||
module.exports = list;
|
||||
|
||||
var C_ASTERISK = '*';
|
||||
var C_UNDERSCORE = '_';
|
||||
var C_PLUS = '+';
|
||||
var C_DASH = '-';
|
||||
var C_DOT = '.';
|
||||
var C_SPACE = ' ';
|
||||
var C_NEWLINE = '\n';
|
||||
var C_TAB = '\t';
|
||||
var C_PAREN_CLOSE = ')';
|
||||
var C_X_LOWER = 'x';
|
||||
|
||||
var TAB_SIZE = 4;
|
||||
var EXPRESSION_LOOSE_LIST_ITEM = /\n\n(?!\s*$)/;
|
||||
var EXPRESSION_TASK_ITEM = /^\[([ \t]|x|X)][ \t]/;
|
||||
var EXPRESSION_BULLET = /^([ \t]*)([*+-]|\d+[.)])( {1,4}(?! )| |\t|$|(?=\n))([^\n]*)/;
|
||||
var EXPRESSION_PEDANTIC_BULLET = /^([ \t]*)([*+-]|\d+[.)])([ \t]+)/;
|
||||
var EXPRESSION_INITIAL_INDENT = /^( {1,4}|\t)?/gm;
|
||||
|
||||
/* Map of characters which can be used to mark
|
||||
* list-items. */
|
||||
var LIST_UNORDERED_MARKERS = {};
|
||||
|
||||
LIST_UNORDERED_MARKERS[C_ASTERISK] = true;
|
||||
LIST_UNORDERED_MARKERS[C_PLUS] = true;
|
||||
LIST_UNORDERED_MARKERS[C_DASH] = true;
|
||||
|
||||
/* Map of characters which can be used to mark
|
||||
* list-items after a digit. */
|
||||
var LIST_ORDERED_MARKERS = {};
|
||||
|
||||
LIST_ORDERED_MARKERS[C_DOT] = true;
|
||||
|
||||
/* Map of characters which can be used to mark
|
||||
* list-items after a digit. */
|
||||
var LIST_ORDERED_COMMONMARK_MARKERS = {};
|
||||
|
||||
LIST_ORDERED_COMMONMARK_MARKERS[C_DOT] = true;
|
||||
LIST_ORDERED_COMMONMARK_MARKERS[C_PAREN_CLOSE] = true;
|
||||
|
||||
/* Tokenise a list. */
|
||||
function list(eat, value, silent) {
|
||||
var self = this;
|
||||
var commonmark = self.options.commonmark;
|
||||
var pedantic = self.options.pedantic;
|
||||
var tokenizers = self.blockTokenizers;
|
||||
var interuptors = self.interruptList;
|
||||
var markers;
|
||||
var index = 0;
|
||||
var length = value.length;
|
||||
var start = null;
|
||||
var size = 0;
|
||||
var queue;
|
||||
var ordered;
|
||||
var character;
|
||||
var marker;
|
||||
var nextIndex;
|
||||
var startIndex;
|
||||
var prefixed;
|
||||
var currentMarker;
|
||||
var content;
|
||||
var line;
|
||||
var prevEmpty;
|
||||
var empty;
|
||||
var items;
|
||||
var allLines;
|
||||
var emptyLines;
|
||||
var item;
|
||||
var enterTop;
|
||||
var exitBlockquote;
|
||||
var isLoose;
|
||||
var node;
|
||||
var now;
|
||||
var end;
|
||||
var indented;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === C_TAB) {
|
||||
size += TAB_SIZE - (size % TAB_SIZE);
|
||||
} else if (character === C_SPACE) {
|
||||
size++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (size >= TAB_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
|
||||
markers = commonmark ?
|
||||
LIST_ORDERED_COMMONMARK_MARKERS :
|
||||
LIST_ORDERED_MARKERS;
|
||||
|
||||
if (LIST_UNORDERED_MARKERS[character] === true) {
|
||||
marker = character;
|
||||
ordered = false;
|
||||
} else {
|
||||
ordered = true;
|
||||
queue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!decimal(character)) {
|
||||
break;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!queue || markers[character] !== true) {
|
||||
return;
|
||||
}
|
||||
|
||||
start = parseInt(queue, 10);
|
||||
marker = character;
|
||||
}
|
||||
|
||||
character = value.charAt(++index);
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
items = [];
|
||||
allLines = [];
|
||||
emptyLines = [];
|
||||
|
||||
while (index < length) {
|
||||
nextIndex = value.indexOf(C_NEWLINE, index);
|
||||
startIndex = index;
|
||||
prefixed = false;
|
||||
indented = false;
|
||||
|
||||
if (nextIndex === -1) {
|
||||
nextIndex = length;
|
||||
}
|
||||
|
||||
end = index + TAB_SIZE;
|
||||
size = 0;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === C_TAB) {
|
||||
size += TAB_SIZE - (size % TAB_SIZE);
|
||||
} else if (character === C_SPACE) {
|
||||
size++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (size >= TAB_SIZE) {
|
||||
indented = true;
|
||||
}
|
||||
|
||||
if (item && size >= item.indent) {
|
||||
indented = true;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
currentMarker = null;
|
||||
|
||||
if (!indented) {
|
||||
if (LIST_UNORDERED_MARKERS[character] === true) {
|
||||
currentMarker = character;
|
||||
index++;
|
||||
size++;
|
||||
} else {
|
||||
queue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!decimal(character)) {
|
||||
break;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
index++;
|
||||
|
||||
if (queue && markers[character] === true) {
|
||||
currentMarker = character;
|
||||
size += queue.length + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentMarker) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === C_TAB) {
|
||||
size += TAB_SIZE - (size % TAB_SIZE);
|
||||
index++;
|
||||
} else if (character === C_SPACE) {
|
||||
end = index + TAB_SIZE;
|
||||
|
||||
while (index < end) {
|
||||
if (value.charAt(index) !== C_SPACE) {
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
size++;
|
||||
}
|
||||
|
||||
if (index === end && value.charAt(index) === C_SPACE) {
|
||||
index -= TAB_SIZE - 1;
|
||||
size -= TAB_SIZE - 1;
|
||||
}
|
||||
} else if (character !== C_NEWLINE && character !== '') {
|
||||
currentMarker = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentMarker) {
|
||||
if (!pedantic && marker !== currentMarker) {
|
||||
break;
|
||||
}
|
||||
|
||||
prefixed = true;
|
||||
} else {
|
||||
if (!commonmark && !indented && value.charAt(startIndex) === C_SPACE) {
|
||||
indented = true;
|
||||
} else if (commonmark && item) {
|
||||
indented = size >= item.indent || size > TAB_SIZE;
|
||||
}
|
||||
|
||||
prefixed = false;
|
||||
index = startIndex;
|
||||
}
|
||||
|
||||
line = value.slice(startIndex, nextIndex);
|
||||
content = startIndex === index ? line : value.slice(index, nextIndex);
|
||||
|
||||
if (
|
||||
currentMarker === C_ASTERISK ||
|
||||
currentMarker === C_UNDERSCORE ||
|
||||
currentMarker === C_DASH
|
||||
) {
|
||||
if (tokenizers.thematicBreak.call(self, eat, line, true)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
prevEmpty = empty;
|
||||
empty = !trim(content).length;
|
||||
|
||||
if (indented && item) {
|
||||
item.value = item.value.concat(emptyLines, line);
|
||||
allLines = allLines.concat(emptyLines, line);
|
||||
emptyLines = [];
|
||||
} else if (prefixed) {
|
||||
if (emptyLines.length !== 0) {
|
||||
item.value.push('');
|
||||
item.trail = emptyLines.concat();
|
||||
}
|
||||
|
||||
item = {
|
||||
value: [line],
|
||||
indent: size,
|
||||
trail: []
|
||||
};
|
||||
|
||||
items.push(item);
|
||||
allLines = allLines.concat(emptyLines, line);
|
||||
emptyLines = [];
|
||||
} else if (empty) {
|
||||
if (prevEmpty) {
|
||||
break;
|
||||
}
|
||||
|
||||
emptyLines.push(line);
|
||||
} else {
|
||||
if (prevEmpty) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (interrupt(interuptors, tokenizers, self, [eat, line, true])) {
|
||||
break;
|
||||
}
|
||||
|
||||
item.value = item.value.concat(emptyLines, line);
|
||||
allLines = allLines.concat(emptyLines, line);
|
||||
emptyLines = [];
|
||||
}
|
||||
|
||||
index = nextIndex + 1;
|
||||
}
|
||||
|
||||
node = eat(allLines.join(C_NEWLINE)).reset({
|
||||
type: 'list',
|
||||
ordered: ordered,
|
||||
start: start,
|
||||
loose: null,
|
||||
children: []
|
||||
});
|
||||
|
||||
enterTop = self.enterList();
|
||||
exitBlockquote = self.enterBlock();
|
||||
isLoose = false;
|
||||
index = -1;
|
||||
length = items.length;
|
||||
|
||||
while (++index < length) {
|
||||
item = items[index].value.join(C_NEWLINE);
|
||||
now = eat.now();
|
||||
|
||||
item = eat(item)(listItem(self, item, now), node);
|
||||
|
||||
if (item.loose) {
|
||||
isLoose = true;
|
||||
}
|
||||
|
||||
item = items[index].trail.join(C_NEWLINE);
|
||||
|
||||
if (index !== length - 1) {
|
||||
item += C_NEWLINE;
|
||||
}
|
||||
|
||||
eat(item);
|
||||
}
|
||||
|
||||
enterTop();
|
||||
exitBlockquote();
|
||||
|
||||
node.loose = isLoose;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list-item node.
|
||||
*
|
||||
* @example
|
||||
* listItem('- _foo_', now());
|
||||
*
|
||||
* @param {Object} ctx - Parser.
|
||||
* @param {Object} value - List-item.
|
||||
* @param {Object} position - List-item location.
|
||||
* @return {Object} - `listItem` node.
|
||||
*/
|
||||
function listItem(ctx, value, position) {
|
||||
var offsets = ctx.offset;
|
||||
var fn = ctx.options.pedantic ? pedanticListItem : normalListItem;
|
||||
var checked = null;
|
||||
var task;
|
||||
var indent;
|
||||
|
||||
value = fn.apply(null, arguments);
|
||||
|
||||
if (ctx.options.gfm) {
|
||||
task = value.match(EXPRESSION_TASK_ITEM);
|
||||
|
||||
if (task) {
|
||||
indent = task[0].length;
|
||||
checked = task[1].toLowerCase() === C_X_LOWER;
|
||||
offsets[position.line] += indent;
|
||||
value = value.slice(indent);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'listItem',
|
||||
loose: EXPRESSION_LOOSE_LIST_ITEM.test(value) ||
|
||||
value.charAt(value.length - 1) === C_NEWLINE,
|
||||
checked: checked,
|
||||
children: ctx.tokenizeBlock(value, position)
|
||||
};
|
||||
}
|
||||
|
||||
/* Create a list-item using overly simple mechanics. */
|
||||
function pedanticListItem(ctx, value, position) {
|
||||
var offsets = ctx.offset;
|
||||
var line = position.line;
|
||||
|
||||
/* Remove the list-item’s bullet. */
|
||||
value = value.replace(EXPRESSION_PEDANTIC_BULLET, replacer);
|
||||
|
||||
/* The initial line was also matched by the below, so
|
||||
* we reset the `line`. */
|
||||
line = position.line;
|
||||
|
||||
return value.replace(EXPRESSION_INITIAL_INDENT, replacer);
|
||||
|
||||
/* A simple replacer which removed all matches,
|
||||
* and adds their length to `offset`. */
|
||||
function replacer($0) {
|
||||
offsets[line] = (offsets[line] || 0) + $0.length;
|
||||
line++;
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a list-item using sane mechanics. */
|
||||
function normalListItem(ctx, value, position) {
|
||||
var offsets = ctx.offset;
|
||||
var line = position.line;
|
||||
var max;
|
||||
var bullet;
|
||||
var rest;
|
||||
var lines;
|
||||
var trimmedLines;
|
||||
var index;
|
||||
var length;
|
||||
|
||||
/* Remove the list-item’s bullet. */
|
||||
value = value.replace(EXPRESSION_BULLET, replacer);
|
||||
|
||||
lines = value.split(C_NEWLINE);
|
||||
|
||||
trimmedLines = removeIndent(value, getIndent(max).indent).split(C_NEWLINE);
|
||||
|
||||
/* We replaced the initial bullet with something
|
||||
* else above, which was used to trick
|
||||
* `removeIndentation` into removing some more
|
||||
* characters when possible. However, that could
|
||||
* result in the initial line to be stripped more
|
||||
* than it should be. */
|
||||
trimmedLines[0] = rest;
|
||||
|
||||
offsets[line] = (offsets[line] || 0) + bullet.length;
|
||||
line++;
|
||||
|
||||
index = 0;
|
||||
length = lines.length;
|
||||
|
||||
while (++index < length) {
|
||||
offsets[line] = (offsets[line] || 0) +
|
||||
lines[index].length - trimmedLines[index].length;
|
||||
line++;
|
||||
}
|
||||
|
||||
return trimmedLines.join(C_NEWLINE);
|
||||
|
||||
function replacer($0, $1, $2, $3, $4) {
|
||||
bullet = $1 + $2 + $3;
|
||||
rest = $4;
|
||||
|
||||
/* Make sure that the first nine numbered list items
|
||||
* can indent with an extra space. That is, when
|
||||
* the bullet did not receive an extra final space. */
|
||||
if (Number($2) < 10 && bullet.length % 2 === 1) {
|
||||
$2 = C_SPACE + $2;
|
||||
}
|
||||
|
||||
max = $1 + repeat(C_SPACE, $2.length) + $3;
|
||||
|
||||
return max + rest;
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:newline
|
||||
* @fileoverview Tokenise a newline.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var whitespace = require('is-whitespace-character');
|
||||
|
||||
module.exports = newline;
|
||||
|
||||
/* Tokenise newline. */
|
||||
function newline(eat, value, silent) {
|
||||
var character = value.charAt(0);
|
||||
var length;
|
||||
var subvalue;
|
||||
var queue;
|
||||
var index;
|
||||
|
||||
if (character !== '\n') {
|
||||
return;
|
||||
}
|
||||
|
||||
/* istanbul ignore if - never used (yet) */
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
index = 1;
|
||||
length = value.length;
|
||||
subvalue = character;
|
||||
queue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!whitespace(character)) {
|
||||
break;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
|
||||
if (character === '\n') {
|
||||
subvalue += queue;
|
||||
queue = '';
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
eat(subvalue);
|
||||
}
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:paragraph
|
||||
* @fileoverview Tokenise a paragraph.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var trim = require('trim');
|
||||
var decimal = require('is-decimal');
|
||||
var trimTrailingLines = require('trim-trailing-lines');
|
||||
var interrupt = require('../util/interrupt');
|
||||
|
||||
module.exports = paragraph;
|
||||
|
||||
var C_NEWLINE = '\n';
|
||||
var C_TAB = '\t';
|
||||
var C_SPACE = ' ';
|
||||
|
||||
var TAB_SIZE = 4;
|
||||
|
||||
/* Tokenise paragraph. */
|
||||
function paragraph(eat, value, silent) {
|
||||
var self = this;
|
||||
var settings = self.options;
|
||||
var commonmark = settings.commonmark;
|
||||
var gfm = settings.gfm;
|
||||
var tokenizers = self.blockTokenizers;
|
||||
var interruptors = self.interruptParagraph;
|
||||
var index = value.indexOf(C_NEWLINE);
|
||||
var length = value.length;
|
||||
var position;
|
||||
var subvalue;
|
||||
var character;
|
||||
var size;
|
||||
var now;
|
||||
|
||||
while (index < length) {
|
||||
/* Eat everything if there’s no following newline. */
|
||||
if (index === -1) {
|
||||
index = length;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Stop if the next character is NEWLINE. */
|
||||
if (value.charAt(index + 1) === C_NEWLINE) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* In commonmark-mode, following indented lines
|
||||
* are part of the paragraph. */
|
||||
if (commonmark) {
|
||||
size = 0;
|
||||
position = index + 1;
|
||||
|
||||
while (position < length) {
|
||||
character = value.charAt(position);
|
||||
|
||||
if (character === C_TAB) {
|
||||
size = TAB_SIZE;
|
||||
break;
|
||||
} else if (character === C_SPACE) {
|
||||
size++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
position++;
|
||||
}
|
||||
|
||||
if (size >= TAB_SIZE) {
|
||||
index = value.indexOf(C_NEWLINE, index + 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
subvalue = value.slice(index + 1);
|
||||
|
||||
/* Check if the following code contains a possible
|
||||
* block. */
|
||||
if (interrupt(interruptors, tokenizers, self, [eat, subvalue, true])) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Break if the following line starts a list, when
|
||||
* already in a list, or when in commonmark, or when
|
||||
* in gfm mode and the bullet is *not* numeric. */
|
||||
if (
|
||||
tokenizers.list.call(self, eat, subvalue, true) &&
|
||||
(
|
||||
self.inList ||
|
||||
commonmark ||
|
||||
(gfm && !decimal(trim.left(subvalue).charAt(0)))
|
||||
)
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
position = index;
|
||||
index = value.indexOf(C_NEWLINE, index + 1);
|
||||
|
||||
if (index !== -1 && trim(value.slice(position, index)) === '') {
|
||||
index = position;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
subvalue = value.slice(0, index);
|
||||
|
||||
if (trim(subvalue) === '') {
|
||||
eat(subvalue);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/* istanbul ignore if - never used (yet) */
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
now = eat.now();
|
||||
subvalue = trimTrailingLines(subvalue);
|
||||
|
||||
return eat(subvalue)({
|
||||
type: 'paragraph',
|
||||
children: self.tokenizeInline(subvalue, now)
|
||||
});
|
||||
}
|
||||
+219
@@ -0,0 +1,219 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:reference
|
||||
* @fileoverview Tokenise a reference.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var whitespace = require('is-whitespace-character');
|
||||
var locate = require('../locate/link');
|
||||
var normalize = require('../util/normalize');
|
||||
|
||||
module.exports = reference;
|
||||
reference.locator = locate;
|
||||
|
||||
var T_LINK = 'link';
|
||||
var T_IMAGE = 'image';
|
||||
var T_FOOTNOTE = 'footnote';
|
||||
var REFERENCE_TYPE_SHORTCUT = 'shortcut';
|
||||
var REFERENCE_TYPE_COLLAPSED = 'collapsed';
|
||||
var REFERENCE_TYPE_FULL = 'full';
|
||||
var C_CARET = '^';
|
||||
var C_BACKSLASH = '\\';
|
||||
var C_BRACKET_OPEN = '[';
|
||||
var C_BRACKET_CLOSE = ']';
|
||||
|
||||
/* Tokenise a reference. */
|
||||
function reference(eat, value, silent) {
|
||||
var self = this;
|
||||
var character = value.charAt(0);
|
||||
var index = 0;
|
||||
var length = value.length;
|
||||
var subvalue = '';
|
||||
var intro = '';
|
||||
var type = T_LINK;
|
||||
var referenceType = REFERENCE_TYPE_SHORTCUT;
|
||||
var content;
|
||||
var identifier;
|
||||
var now;
|
||||
var node;
|
||||
var exit;
|
||||
var queue;
|
||||
var bracketed;
|
||||
var depth;
|
||||
|
||||
/* Check whether we’re eating an image. */
|
||||
if (character === '!') {
|
||||
type = T_IMAGE;
|
||||
intro = character;
|
||||
character = value.charAt(++index);
|
||||
}
|
||||
|
||||
if (character !== C_BRACKET_OPEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
index++;
|
||||
intro += character;
|
||||
queue = '';
|
||||
|
||||
/* Check whether we’re eating a footnote. */
|
||||
if (
|
||||
self.options.footnotes &&
|
||||
type === T_LINK &&
|
||||
value.charAt(index) === C_CARET
|
||||
) {
|
||||
intro += C_CARET;
|
||||
index++;
|
||||
type = T_FOOTNOTE;
|
||||
}
|
||||
|
||||
/* Eat the text. */
|
||||
depth = 0;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === C_BRACKET_OPEN) {
|
||||
bracketed = true;
|
||||
depth++;
|
||||
} else if (character === C_BRACKET_CLOSE) {
|
||||
if (!depth) {
|
||||
break;
|
||||
}
|
||||
|
||||
depth--;
|
||||
}
|
||||
|
||||
if (character === C_BACKSLASH) {
|
||||
queue += C_BACKSLASH;
|
||||
character = value.charAt(++index);
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
subvalue = queue;
|
||||
content = queue;
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_BRACKET_CLOSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
index++;
|
||||
subvalue += character;
|
||||
queue = '';
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (!whitespace(character)) {
|
||||
break;
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === C_BRACKET_OPEN) {
|
||||
identifier = '';
|
||||
queue += character;
|
||||
index++;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === C_BRACKET_OPEN || character === C_BRACKET_CLOSE) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (character === C_BACKSLASH) {
|
||||
identifier += C_BACKSLASH;
|
||||
character = value.charAt(++index);
|
||||
}
|
||||
|
||||
identifier += character;
|
||||
index++;
|
||||
}
|
||||
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character === C_BRACKET_CLOSE) {
|
||||
referenceType = identifier ? REFERENCE_TYPE_FULL : REFERENCE_TYPE_COLLAPSED;
|
||||
queue += identifier + character;
|
||||
index++;
|
||||
} else {
|
||||
identifier = '';
|
||||
}
|
||||
|
||||
subvalue += queue;
|
||||
queue = '';
|
||||
} else {
|
||||
if (!content) {
|
||||
return;
|
||||
}
|
||||
|
||||
identifier = content;
|
||||
}
|
||||
|
||||
/* Brackets cannot be inside the identifier. */
|
||||
if (referenceType !== REFERENCE_TYPE_FULL && bracketed) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Inline footnotes cannot have an identifier. */
|
||||
if (type === T_FOOTNOTE && referenceType !== REFERENCE_TYPE_SHORTCUT) {
|
||||
type = T_LINK;
|
||||
intro = C_BRACKET_OPEN + C_CARET;
|
||||
content = C_CARET + content;
|
||||
}
|
||||
|
||||
subvalue = intro + subvalue;
|
||||
|
||||
if (type === T_LINK && self.inLink) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* istanbul ignore if - never used (yet) */
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type === T_FOOTNOTE && content.indexOf(' ') !== -1) {
|
||||
return eat(subvalue)({
|
||||
type: 'footnote',
|
||||
children: this.tokenizeInline(content, eat.now())
|
||||
});
|
||||
}
|
||||
|
||||
now = eat.now();
|
||||
now.column += intro.length;
|
||||
now.offset += intro.length;
|
||||
identifier = referenceType === REFERENCE_TYPE_FULL ? identifier : content;
|
||||
|
||||
node = {
|
||||
type: type + 'Reference',
|
||||
identifier: normalize(identifier)
|
||||
};
|
||||
|
||||
if (type === T_LINK || type === T_IMAGE) {
|
||||
node.referenceType = referenceType;
|
||||
}
|
||||
|
||||
if (type === T_LINK) {
|
||||
exit = self.enterLink();
|
||||
node.children = self.tokenizeInline(content, now);
|
||||
exit();
|
||||
} else if (type === T_IMAGE) {
|
||||
node.alt = self.decode.raw(self.unescape(content), now) || null;
|
||||
}
|
||||
|
||||
return eat(subvalue)(node);
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:parse:tokenize:strong
|
||||
* @fileoverview Tokenise strong.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var trim = require('trim');
|
||||
var whitespace = require('is-whitespace-character');
|
||||
var locate = require('../locate/strong');
|
||||
|
||||
module.exports = strong;
|
||||
strong.locator = locate;
|
||||
|
||||
var C_ASTERISK = '*';
|
||||
var C_UNDERSCORE = '_';
|
||||
|
||||
/* Tokenise strong. */
|
||||
function strong(eat, value, silent) {
|
||||
var self = this;
|
||||
var index = 0;
|
||||
var character = value.charAt(index);
|
||||
var now;
|
||||
var pedantic;
|
||||
var marker;
|
||||
var queue;
|
||||
var subvalue;
|
||||
var length;
|
||||
var prev;
|
||||
|
||||
if (
|
||||
(character !== C_ASTERISK && character !== C_UNDERSCORE) ||
|
||||
value.charAt(++index) !== character
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
pedantic = self.options.pedantic;
|
||||
marker = character;
|
||||
subvalue = marker + marker;
|
||||
length = value.length;
|
||||
index++;
|
||||
queue = '';
|
||||
character = '';
|
||||
|
||||
if (pedantic && whitespace(value.charAt(index))) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (index < length) {
|
||||
prev = character;
|
||||
character = value.charAt(index);
|
||||
|
||||
if (
|
||||
character === marker &&
|
||||
value.charAt(index + 1) === marker &&
|
||||
(!pedantic || !whitespace(prev))
|
||||
) {
|
||||
character = value.charAt(index + 2);
|
||||
|
||||
if (character !== marker) {
|
||||
if (!trim(queue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* istanbul ignore if - never used (yet) */
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
now = eat.now();
|
||||
now.column += 2;
|
||||
now.offset += 2;
|
||||
|
||||
return eat(subvalue + queue + subvalue)({
|
||||
type: 'strong',
|
||||
children: self.tokenizeInline(queue, now)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!pedantic && character === '\\') {
|
||||
queue += character;
|
||||
character = value.charAt(++index);
|
||||
}
|
||||
|
||||
queue += character;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
Loaded 100 of 169 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user