diff --git a/.gitignore b/.gitignore index f1f245a..0e01a0d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ coverage/ node_modules/ remark-html.js remark-html.min.js +yarn.lock diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..43c97e7 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..dabdf7e --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +coverage/ +remark-html.js +remark-html.min.js +*.html +*.json +*.md diff --git a/.travis.yml b/.travis.yml index be610d7..64435f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,24 +1,15 @@ language: node_js node_js: -- '4.0' -- '9.0' + - lts/dubnium + - node after_script: bash <(curl -s https://codecov.io/bash) deploy: - - provider: npm - skip_cleanup: true - email: tituswormer@gmail.com - api_key: - secure: Mx+xbzp3lsuFaDw8kvcYtyC6FZxyQ/yn8fQTl/76QDBTncKcVnuEjhdP7P4fGjvUogvAKnvj66tmpBZUi+Jgua0lY8D1z0qK6ECmQ3QVHVOi1MrwUSJ4EwWgmfCI+Sy2SvWYOVMCF7K1eia6DFz9zVeRLSGF3L5adhRffLnSegD/rElt1XaTQFam7xlG3QoQ8M056GU7HHom88yhWauBXkAG1TWiSftcJYj0jkY37+PDHP8ejoiMeio249QJByW5QxgEfQ6DFgliw7h9JRhozX0W6N6hoVmQ3xiJINbTacJ2tBQgNxs9C9BltCo/jbqV2qw0Pczy57IA+KNUcfq0z9tOss7xp7y4/3Ii1zc7g8pi+WQ+EbtOqgOgm3VJr81In8IHb0+F58CWWL20Cxbvof4ryxFsCuQ/ajqso8faAQhd+X/1A6/nGKGI1V09juhpBgajAdRgsjhBaPXlwMbwct2scWPS4by6mFXfwUX1bLF9YJ8QetQD5eKbTkVZoYIMSokRtU0voE47Thg5CzdHvWpjHWS2SHoaZQtQ5yBNoBhVTJXdkPcjobJygu7D+YeBkkMCVFk8JapF+SHlVehjFf//p2y8cp3PGYNSViFURf3letPGDx7kndSqBfwA65gybrY6G3II74ox/+60rFnqJdb6GR451IkgcgFQAD4uhgk= - on: - tags: true - node: '9.0' - - provider: releases - skip_cleanup: true - api_key: - secure: UWoYUAQpsaIYjq9Xa3CYP1sjWkI3hBC0DbYr8fDCB2cM5gH3zxGBQvhzGSX8XMzuWkQJnWfU5LElifb1lKUPoIcErgny3qZG61pD8jwEo9NgMFRrHGW9dYEXXXbBDfz7wCn2GfIAhNfTZj9zNoS7BVwUgxmB/+7JtDGWehTb4MXLKHQ8ff41FcLwSFk9ynq40Pcmy4aMKb6IY9ijQvZ/E4ReSFeidm1o4XGyHKSZec6oIWKDYLVb/7LNUQZ8rIjl2KwXDK8cNCHNYLC9dQTpMiHNu+9hBxeYDIz+P5e9NTWsf9FQK5+at8zoxKx34ZZARaOti2z9vZXYSkp44X8CkpQ6hEnVc6zBP3+FfIFmBYpEwrB9XOT7Ib5TdROSmi0no6wXkKc+t4OOZ3hnCWZfEjbEtqBUrhEmfi5qccvcPy5KdCyLi26BAQFXimayjU/i7Z597+uX55H+P2hI3PyTELzoKpK6mdHb04D7Gep50Cdlayd9ZqkRxoLKNG3IpJkN1kz5UTCBXswe1S3m0pcyTNL8HwoIQ8U040O/4xmpUhWhWQn78zbunOYBJ+d2UhH04SckpFjBVpbx59BtuirkhQeClfByKy9LQZGUAk1VjByn6HMmerj0NIzfbkb4gEPAadpqF8o6ISmiNyKV8tK9z2wjEP48HfLm/KV/S6ne4+k= - file: - - "remark-html.js" - - "remark-html.min.js" - on: - tags: true - node: '9.0' + provider: releases + skip_cleanup: true + api_key: + secure: Dk+BizJGxzQopL8tVdknG6+dB/6QyruT2qlbNNT3RRiJNDuji8Ux3certNqclRe4NtxfU+haOZDcQ+7mdoMATP6zwFEG5IAOuUUA5JMxTyVfDHG/SErae1nq9w7U4JkpuKNu+pbQlxL+BjkJaqkPJexElYnGxjJgcnh3hGjEpU3cIk/QrthFYq9Bd0PbrpHsaopTwzAMz1uiqWIA/mF03I+l3FC+iRYRqK/9TOhecYiMV0PT027Q1gnYwpDGVAvrkoFqtXWnDZxYRWqguwQXbTUvcoL8KdSeJXslKiS9YiqW/4Q+x9sM1KuycQK1DZi23g733nKtfnUX0NTHuAZ+Kihsgn0ltikI9F9JiFwwJ5kB9sGpE34Xjflr2+bBCsnAfMwK4Ao5tgBKJrHupK+dw5yg53+KmBL/WZTj/xy5ygI1mqcJT+282RTr7J8XGsNLrQP0C+PExFQbBVdqdvN72d/BRnPoI8ubUdMB0dgffkKEQkzPlOyE1MwoOy9ZyI9O7XXgXxZCPPRQoTCZmKR4mRkBgd5k3ZuV5nQWIC7vNihfEeqABz0S7Ed3DWvmu0aworH2wsI3GGAMFs/Ssi0MjhlEBp6dJ+zhJ86p+FY1BzHer2FzG4b4ouZFBcKmY1SN00b8XW1UhHhA3LSYq8HsEAMcMuRGvAn0UZb7oGq7R6I= + file: + - 'remark-html.js' + - 'remark-html.min.js' + on: + tags: true diff --git a/index.js b/index.js index 70362df..fa02227 100644 --- a/index.js +++ b/index.js @@ -1,42 +1,52 @@ -'use strict'; +'use strict' -var xtend = require('xtend'); -var toHAST = require('mdast-util-to-hast'); -var toHTML = require('hast-util-to-html'); -var sanitize = require('hast-util-sanitize'); +var toHast = require('mdast-util-to-hast') +var toHtml = require('hast-util-to-html') +var sanitize = require('hast-util-sanitize') -module.exports = plugin; +module.exports = plugin function plugin(options) { - var settings = options || {}; - var clean = settings.sanitize; - var schema = clean && typeof clean === 'object' ? clean : null; - var handlers = settings.handlers || {}; + var settings = Object.assign({}, options || {}) + let clean - this.Compiler = compiler; + if (typeof settings.sanitize === 'boolean') { + clean = settings.sanitize + settings.sanitize = undefined + } + + if (typeof clean !== 'boolean') { + clean = true + } + + this.Compiler = compiler function compiler(node, file) { - var root = node && node.type && node.type === 'root'; - var hast = toHAST(node, {allowDangerousHTML: !clean, handlers: handlers}); - var result; + var root = node && node.type && node.type === 'root' + var hast = toHast(node, { + allowDangerousHtml: !clean, + handlers: settings.handlers + }) + var result if (file.extname) { - file.extname = '.html'; + file.extname = '.html' } if (clean) { - hast = sanitize(hast, schema); + hast = sanitize(hast, settings.sanitize) } - result = toHTML(hast, xtend(settings, { - allowDangerousHTML: !clean - })); + result = toHtml( + hast, + Object.assign({}, settings, {allowDangerousHtml: !clean}) + ) - /* Add a final newline. */ - if (root && result.charAt(result.length - 1) !== '\n') { - result += '\n'; + // Add an eof eol. + if (root && result && /[^\r\n]/.test(result.charAt(result.length - 1))) { + result += '\n' } - return result; + return result } } diff --git a/LICENSE b/license similarity index 100% rename from LICENSE rename to license diff --git a/package.json b/package.json index 96b97da..d5524b6 100644 --- a/package.json +++ b/package.json @@ -1,58 +1,74 @@ { "name": "remark-html", - "version": "7.0.0", - "description": "Compile Markdown to HTML with remark", + "version": "13.0.2", + "description": "remark plugin to compile Markdown to HTML", "license": "MIT", "keywords": [ + "unified", + "remark", + "remark-plugin", + "plugin", + "mdast", "markdown", "html", "stringify", - "compile", - "remark" + "compile" ], - "repository": "https://github.com/wooorm/remark-html", - "bugs": "https://github.com/wooorm/remark-html/issues", - "author": "Titus Wormer (http://wooorm.com)", + "repository": "remarkjs/remark-html", + "bugs": "https://github.com/remarkjs/remark-html/issues", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "author": "Titus Wormer (https://wooorm.com)", "contributors": [ - "Titus Wormer (http://wooorm.com)", + "Titus Wormer (https://wooorm.com)", "Ben Briggs ", "Seth Vincent ", "Junyoung Choi ", "Jonathan Soeder " ], + "types": "types/index.d.ts", "files": [ + "types/index.d.ts", "index.js" ], "dependencies": { - "hast-util-sanitize": "^1.0.0", - "hast-util-to-html": "^3.0.0", - "mdast-util-to-hast": "^3.0.0", - "xtend": "^4.0.1" + "hast-util-sanitize": "^3.0.0", + "hast-util-to-html": "^7.0.0", + "mdast-util-to-hast": "^10.0.0" }, "devDependencies": { - "browserify": "^14.0.0", - "commonmark.json": "^0.27.0", - "esmangle": "^1.0.0", - "is-hidden": "^1.0.1", - "nyc": "^11.0.0", - "remark": "^8.0.0", - "remark-cli": "^4.0.0", - "remark-github": "^7.0.0", - "remark-preset-wooorm": "^3.0.0", - "remark-toc": "^4.0.0", - "tape": "^4.0.0", - "to-vfile": "^2.0.0", - "xo": "^0.18.0" + "browserify": "^16.0.0", + "commonmark.json": "^0.29.0", + "dtslint": "^4.0.0", + "is-hidden": "^1.0.0", + "not": "^0.1.0", + "nyc": "^15.0.0", + "prettier": "^2.0.0", + "rehype-parse": "^7.0.0", + "rehype-stringify": "^8.0.0", + "remark": "^13.0.0-alpha.0", + "remark-cli": "^8.0.0", + "remark-github": "^9.0.0", + "remark-preset-wooorm": "^7.0.0", + "remark-slug": "^6.0.0", + "remark-toc": "^7.0.0", + "tape": "^5.0.0", + "tinyify": "^3.0.0", + "to-vfile": "^6.0.0", + "unified": "^9.0.0", + "xo": "^0.33.0" }, "scripts": { - "build-md": "remark *.md doc/*.md -qfo", - "build-bundle": "browserify index.js --bare -s remarkHTML > remark-html.js", - "build-mangle": "esmangle remark-html.js > remark-html.min.js", - "build": "npm run build-md && npm run build-bundle && npm run build-mangle", - "lint": "xo", - "test-api": "node test/index.js", + "format": "remark . -qfo --ignore-pattern test/ && prettier . --write && xo --fix", + "build-bundle": "browserify . -s remarkHtml > remark-html.js", + "build-mangle": "browserify . -s remarkHtml -p tinyify > remark-html.min.js", + "build": "npm run build-bundle && npm run build-mangle", + "test-api": "node test", "test-coverage": "nyc --reporter lcov tape test/index.js", - "test": "npm run build && npm run lint && npm run test-coverage" + "test-types": "dtslint types", + "test": "npm run format && npm run build && npm run test-coverage && npm run test-types" }, "nyc": { "check-coverage": true, @@ -60,14 +76,29 @@ "functions": 100, "branches": 100 }, + "prettier": { + "tabWidth": 2, + "useTabs": false, + "singleQuote": true, + "bracketSpacing": false, + "semi": false, + "trailingComma": "none" + }, "xo": { - "space": true, + "prettier": true, "esnext": false, + "rules": { + "unicorn/no-fn-reference-in-iterator": "off", + "unicorn/prefer-includes": "off", + "unicorn/prefer-optional-catch-binding": "off" + }, "ignores": [ "remark-html.js" ] }, "remarkConfig": { - "plugins": ["preset-wooorm"] + "plugins": [ + "preset-wooorm" + ] } } diff --git a/readme.md b/readme.md index ffc7a3d..28c5140 100644 --- a/readme.md +++ b/readme.md @@ -1,22 +1,37 @@ -# remark-html [![Build Status][build-badge]][build-status] [![Coverage Status][coverage-badge]][coverage-status] [![Chat][chat-badge]][chat] +# remark-html -Compile markdown to HTML with [**remark**][remark]. +[![Build][build-badge]][build] +[![Coverage][coverage-badge]][coverage] +[![Downloads][downloads-badge]][downloads] +[![Size][size-badge]][size] +[![Sponsors][sponsors-badge]][collective] +[![Backers][backers-badge]][collective] +[![Chat][chat-badge]][chat] -> :warning: This package essentially packs [`remark-rehype`][remark2rehype] and +[**remark**][remark] plugin to serialize Markdown as HTML. + +> ⚠️ This package essentially packs [`remark-rehype`][remark2rehype] and > [`rehype-stringify`][rehype-stringify], and although it does support some -> customisation, it isn’t very pluggable. It’s probably smarter to use -> `remark-rehype` directly and benefit from the [**rehype**][rehype] -> ecosystem. +> customisation, it isn’t very pluggable. +> It’s probably smarter to use `remark-rehype` directly and benefit from the +> [**rehype**][rehype] ecosystem. + +## Note! + +This plugin is ready for the new parser in remark +([`remarkjs/remark#536`](https://github.com/remarkjs/remark/pull/536)). +The current and previous version of the plugin works with the current and +previous version of remark. -## Installation +## Install [npm][]: -```bash +```sh npm install remark-html ``` -## Usage +## Use Say we have the following file, `example.md`: @@ -30,19 +45,19 @@ Say we have the following file, `example.md`: And our script, `example.js`, looks as follows: -```javascript -var fs = require('fs'); -var unified = require('unified'); -var markdown = require('remark-parse'); -var html = require('remark-html'); +```js +var fs = require('fs') +var unified = require('unified') +var markdown = require('remark-parse') +var html = require('remark-html') unified() .use(markdown) .use(html) .process(fs.readFileSync('example.md'), function (err, file) { - if (err) throw err; - console.log(String(file)); - }); + if (err) throw err + console.log(String(file)) + }) ``` Now, running `node example` yields: @@ -59,79 +74,86 @@ Now, running `node example` yields: ## API -### `remark.use(html[, options])` +### `remark().use(html[, options])` + +Serialize Markdown as HTML. ##### `options` -All options except for `sanitize` are passed to +All options except for `sanitize` and `handlers` are passed to [`hast-util-to-html`][to-html]. +###### `options.handlers` + +Object mapping [mdast][] [nodes][mdast-node] to functions handling them. +This option is passed to [`mdast-util-to-hast`][to-hast-handlers]. + ###### `options.sanitize` -How to sanitise the output (`Object` or `boolean`, default: `false`). +How to sanitize the output (`Object` or `boolean`, default: `true`): -If `true` or an `object`, sanitation is done by -[`hast-util-sanitize`][sanitize]. If an object is passed in, it’s -given as a schema to `sanitize`. If `true`, input is sanitised -according to [GitHub’s sanitation rules][github]. +* `false` + — HTML is not sanitized, dangerous HTML persists +* `true` + — HTML is sanitized according to [GitHub’s sanitation rules][github], + dangerous HTML is dropped +* `Object` + — the object is treated as a `schema` for how to sanitize with + [`hast-util-sanitize`][sanitize], dangerous HTML is dropped -For example, to add strict sanitation but allowing `className`s, use -something like: +> Note that raw HTML in Markdown cannot be sanitized, so it’s removed. +> A schema can still be used to allow certain values from [integrations][] +> though. +> To support HTML in Markdown, use [`rehype-raw`][raw]. + +For example, to add strict sanitation but allowing `className`s, use something +like: ```js // ... -var merge = require('deepmerge'); -var github = require('hast-util-sanitize/lib/github'); +var merge = require('deepmerge') +var github = require('hast-util-sanitize/lib/github') -var schema = merge(github, {attributes: {'*': ['className']}}); +var schema = merge(github, {attributes: {'*': ['className']}}) -remark().use(html, {sanitize: schema}).processSync(/*...*/); +remark() + .use(html, {sanitize: schema}) + .processSync(/* … */) ``` -## CommonMark - -> You still need to set `commonmark: true` in -> [`remark-parse`s options][remark-options]. - -[CommonMark][] support is a goal but not (yet) a necessity. There are -some (roughly 115 of 550, relating to inline precedence, lists, emphasis -and importance) issues which I’d like to cover in the future. Note that -this sounds like a lot, but they have to do with obscure differences -which do not often occur in the real world. - ## Integrations `remark-html` works great with: * [`remark-autolink-headings`](https://github.com/ben-eb/remark-autolink-headings) — Automatically add links to headings in Markdown -* [`remark-github`](https://github.com/wooorm/remark-github) +* [`remark-github`](https://github.com/remarkjs/remark-github) — Generate references to GitHub issues, PRs, users, and more * [`remark-highlight.js`](https://github.com/ben-eb/remark-highlight.js) — Highlight code blocks * [`remark-html-emoji-image`](https://github.com/jackycute/remark-html-emoji-image) — Transform emoji unicodes into html images -* [`remark-html-katex`](https://github.com/rokt33r/remark-math/blob/master/packages/remark-html-katex/readme.md) +* [`remark-html-katex`](https://github.com/remark/remark-math/blob/HEAD/packages/remark-html-katex/readme.md) — Transform math to HTML with KaTeX * [`remark-math`](https://github.com/rokt33r/remark-math) - — Math support for markdown (inline and block) + — Math support for Markdown (inline and block) * [`remark-midas`](https://github.com/ben-eb/remark-midas) — Highlight CSS code with [midas](https://github.com/ben-eb/midas) -* [`remark-toc`](https://github.com/wooorm/remark-toc) +* [`remark-toc`](https://github.com/remarkjs/remark-toc) — Generate a Tables of Contents -* ...and [more][remark-plugins] +* …and [more][remark-plugins] -All [**MDAST** nodes][mdast] can be compiled to HTML. Unknown **MDAST** -nodes are compiled to `div` nodes if they have `children` or `text` nodes -if they have `value`. +All [**mdast** nodes][mdast] can be compiled to HTML. +Unknown **mdast** nodes are compiled to `div` nodes if they have `children` or +`text` nodes if they have `value`. In addition, **remark-html** can be told how to compile nodes through three `data` properties ([more information][to-hast]): -* `hName` — Tag-name to compile as -* `hChildren` — HTML content to add (instead of `children` and `value`), - in [`HAST`][hast] -* `hProperties` — Map of attributes to add +* `hName` — Tag name to compile as +* `hChildren` — HTML content to add (instead of `children` and `value`), in + [`hast`][hast] +* `hProperties` — Map of properties to add For example, the following node: @@ -140,73 +162,110 @@ For example, the following node: type: 'emphasis', data: { hName: 'i', - hProperties: { - className: 'foo' - }, - hChildren: [{ - type: 'text', - value: 'bar' - }] + hProperties: {className: 'foo'}, + hChildren: [{type: 'text', value: 'bar'}] }, - children: [{ - type: 'text', - value: 'baz', - }] + children: [{type: 'text', value: 'baz'}] } ``` -...would yield: +…would yield: ```markdown bar ``` +## Security + +Use of `remark-html` is *unsafe* by default and opens you up to a +[cross-site scripting (XSS)][xss] attack. +Pass `sanitize: true` to prevent attacks. +Settings `sanitize` to anything else may be unsafe. + +## Contribute + +See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways +to get started. +See [`support.md`][support] for ways to get help. + +This project has a [code of conduct][coc]. +By interacting with this repository, organization, or community you agree to +abide by its terms. + ## License [MIT][license] © [Titus Wormer][author] -[build-badge]: https://img.shields.io/travis/wooorm/remark-html.svg +[build-badge]: https://img.shields.io/travis/remarkjs/remark-html/main.svg + +[build]: https://travis-ci.org/remarkjs/remark-html + +[coverage-badge]: https://img.shields.io/codecov/c/github/remarkjs/remark-html.svg -[build-status]: https://travis-ci.org/wooorm/remark-html +[coverage]: https://codecov.io/github/remarkjs/remark-html -[coverage-badge]: https://img.shields.io/codecov/c/github/wooorm/remark-html.svg +[downloads-badge]: https://img.shields.io/npm/dm/remark-html.svg -[coverage-status]: https://codecov.io/github/wooorm/remark-html +[downloads]: https://www.npmjs.com/package/remark-html -[chat-badge]: https://img.shields.io/gitter/room/wooorm/remark.svg +[size-badge]: https://img.shields.io/bundlephobia/minzip/remark-html.svg -[chat]: https://gitter.im/wooorm/remark +[size]: https://bundlephobia.com/result?p=remark-html -[license]: LICENSE +[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg -[author]: http://wooorm.com +[backers-badge]: https://opencollective.com/unified/backers/badge.svg + +[collective]: https://opencollective.com/unified + +[chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg + +[chat]: https://github.com/remarkjs/remark/discussions [npm]: https://docs.npmjs.com/cli/install -[remark]: https://github.com/wooorm/remark +[health]: https://github.com/remarkjs/.github + +[contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md + +[support]: https://github.com/remarkjs/.github/blob/HEAD/support.md + +[coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md + +[license]: license + +[author]: https://wooorm.com + +[remark]: https://github.com/remarkjs/remark -[remark-options]: https://github.com/wooorm/remark/tree/master/packages/remark-parse#options +[remark-plugins]: https://github.com/remarkjs/remark/blob/HEAD/doc/plugins.md#list-of-plugins -[commonmark]: http://commonmark.org +[remark2rehype]: https://github.com/remarkjs/remark-rehype -[remark-plugins]: https://github.com/wooorm/remark/blob/master/doc/plugins.md#list-of-plugins +[rehype]: https://github.com/rehypejs/rehype + +[rehype-stringify]: https://github.com/rehypejs/rehype/tree/HEAD/packages/rehype-stringify + +[raw]: https://github.com/rehypejs/rehype-raw [mdast]: https://github.com/syntax-tree/mdast +[mdast-node]: https://github.com/syntax-tree/mdast#nodes + +[hast]: https://github.com/syntax-tree/hast + [to-html]: https://github.com/syntax-tree/hast-util-to-html +[to-hast-handlers]: https://github.com/syntax-tree/mdast-util-to-hast#optionshandlers + [sanitize]: https://github.com/syntax-tree/hast-util-sanitize [github]: https://github.com/syntax-tree/hast-util-sanitize#schema [to-hast]: https://github.com/syntax-tree/mdast-util-to-hast#note -[remark2rehype]: https://github.com/wooorm/remark-rehype - -[rehype-stringify]: https://github.com/wooorm/rehype/tree/master/packages/rehype-stringify +[integrations]: #integrations -[rehype]: https://github.com/wooorm/rehype - -[hast]: https://github.com/syntax-tree/hast +[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting diff --git a/test/fixtures/blockquote/output.html b/test/fixtures/blockquote/output.html index 2b7ec57..4a95075 100644 --- a/test/fixtures/blockquote/output.html +++ b/test/fixtures/blockquote/output.html @@ -10,7 +10,7 @@

Block Quote

  • Normal list

    -

    Paragraph.

  • +

    Paragraph.

    diff --git a/test/fixtures/code/output.html b/test/fixtures/code/output.html index e88dc38..f14ae1a 100644 --- a/test/fixtures/code/output.html +++ b/test/fixtures/code/output.html @@ -7,8 +7,8 @@

    Code

      two spaces
    -    one
    -        two
    -    one
    -      mixed.
    +	one
    +		two
    +	one
    +	  mixed.
     
    diff --git a/test/fixtures/entities-named/output.html b/test/fixtures/entities-named/output.html index f8fd278..071e009 100644 --- a/test/fixtures/entities-named/output.html +++ b/test/fixtures/entities-named/output.html @@ -9,7 +9,7 @@

    Entities

    Something in the AT&T language
     

    Automatic links:

    -

    http://at&t.com, http://at&t.com, and http://at&t.com.

    +

    http://at&amp;t.com, http://at&#x26;t.com, and http://at&t.com.

    Link href:

    With entity, numeric entity, without entity.

    Link title:

    diff --git a/test/fixtures/entities-numerical/output.html b/test/fixtures/entities-numerical/output.html index 130270a..c4fa09e 100644 --- a/test/fixtures/entities-numerical/output.html +++ b/test/fixtures/entities-numerical/output.html @@ -9,7 +9,7 @@

    Entities

    Something in the AT&T language
     

    Automatic links:

    -

    http://at&t.com, http://at&t.com, and http://at&t.com.

    +

    http://at&amp;t.com, http://at&#x26;t.com, and http://at&t.com.

    Link href:

    With entity, numeric entity, without entity.

    Link title:

    diff --git a/test/fixtures/escape/output.html b/test/fixtures/escape/output.html index 6dfcd64..934d342 100644 --- a/test/fixtures/escape/output.html +++ b/test/fixtures/escape/output.html @@ -19,21 +19,21 @@

    Pipe: |

    Tilde: ~

    Commonmark:

    -

    Quote: \"

    -

    Dollar: \$

    -

    Percentage: \%

    -

    Ampersand: \&

    -

    Single quote: \'

    -

    Comma: \,

    -

    Forward slash: \/

    -

    Colon: \:

    -

    Semicolon: \;

    -

    Less-than: \<

    -

    Equals: \=

    -

    Question mark: \?

    -

    At-sign: \@

    -

    Caret: \^

    -

    New line: \ +

    Quote: "

    +

    Dollar: $

    +

    Percentage: %

    +

    Ampersand: &

    +

    Single quote: '

    +

    Comma: ,

    +

    Forward slash: /

    +

    Colon: :

    +

    Semicolon: ;

    +

    Less-than: <

    +

    Equals: =

    +

    Question mark: ?

    +

    At-sign: @

    +

    Caret: ^

    +

    New line:
    only works in paragraphs.

    Two spaces:
    only works in paragraphs.

    diff --git a/test/fixtures/footnotes/config.json b/test/fixtures/footnotes/config.json deleted file mode 100644 index 7f76e14..0000000 --- a/test/fixtures/footnotes/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "footnotes": true -} diff --git a/test/fixtures/footnotes/input.md b/test/fixtures/footnotes/input.md deleted file mode 100644 index b347841..0000000 --- a/test/fixtures/footnotes/input.md +++ /dev/null @@ -1,83 +0,0 @@ -# Footnotes - -Alpha bravo[^charlie india]. - -Delta Echo[^1]. - -Foxtrot Golf Hotel[^2]. - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - -[^1]: This reference style footnote can contains paragraphs. - - - and lists - -[^2]: Normal footnote. diff --git a/test/fixtures/footnotes/output.html b/test/fixtures/footnotes/output.html deleted file mode 100644 index 2d801e1..0000000 --- a/test/fixtures/footnotes/output.html +++ /dev/null @@ -1,84 +0,0 @@ -

    Footnotes

    -

    Alpha bravo3.

    -

    Delta Echo1.

    -

    Foxtrot Golf Hotel2.

    -

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

    -

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

    -

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

    -

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

    -

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

    -

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

    -

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

    -

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

    -

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

    -

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

    -
    -
    -
      -
    1. -

      This reference style footnote can contains paragraphs.

      -
        -
      • and lists
      • -
      - -
    2. -
    3. -

      Normal footnote.

      - -
    4. -
    5. -charlie india - -
    6. -
    -
    diff --git a/test/fixtures/images/output.html b/test/fixtures/images/output.html index 6d50996..11dab25 100644 --- a/test/fixtures/images/output.html +++ b/test/fixtures/images/output.html @@ -1,6 +1,6 @@

    Example

    Example

    -

    -

    -

    -

    +

    +

    +

    +

    diff --git a/test/fixtures/list/output.html b/test/fixtures/list/output.html index 506b488..bd5dfdb 100644 --- a/test/fixtures/list/output.html +++ b/test/fixtures/list/output.html @@ -1,29 +1,19 @@

    List

      -
    • -

      One;

      -
    • -
    • -

      Two;

      -
    • -
    • -

      Three.

      -
    • -
    • -

      One;

      -
    • -
    • -

      Two;

      -
    • +
    • One;
    • +
    • Two;
    • +
    • ~~Three~~.
    +
      +
    1. One;
    2. +
    3. Two;
    4. +
      -
    1. -

      Four.

      -
    2. -
    3. -

      Five.

      -
    4. +
    5. Four.
    6. +
    7. Five.
    8. +
    +
    • Loose:

        @@ -40,7 +30,7 @@

        List

      • Foxtrot.
    • - +

    And a rule.
     
    diff --git a/test/fixtures/references/output.html b/test/fixtures/references/output.html index f4925d6..f074a30 100644 --- a/test/fixtures/references/output.html +++ b/test/fixtures/references/output.html @@ -1,6 +1,6 @@

    References

    Entities contains some serious entity tests relating to titles and links in definitions.

    -

    However, the [missing], missing, and missing are omitted.

    -

    However, the ![missing], missing, and missing are omitted.

    -

    Same goes for and .

    +

    However, the [missing], [missing][], and [missing][missing] are omitted.

    +

    However, the ![missing], ![missing][], and ![missing][missing] are omitted.

    +

    Same goes for [][empty] and ![][empty].

    diff --git a/test/fixtures/tables/config.json b/test/fixtures/tables/config.json deleted file mode 100644 index fb3bbe6..0000000 --- a/test/fixtures/tables/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "sanitize": false -} diff --git a/test/fixtures/tables/input.md b/test/fixtures/tables/input.md deleted file mode 100644 index f2b948e..0000000 --- a/test/fixtures/tables/input.md +++ /dev/null @@ -1,7 +0,0 @@ -| Alpha | Bravo | Charlie | Delta | -| ------- | :------- | -------: | :------: | -| Echo | Foxtrot | **Golf** | -| India | Juliett | Kilo | Lima | -| Mike | November | Oscar | ~~Papa~~ | -| Quebec | _Romeo_ | Sierra | Tango | -| Uniform | Victor | Whiskey | diff --git a/test/fixtures/tables/output.html b/test/fixtures/tables/output.html deleted file mode 100644 index 7199145..0000000 --- a/test/fixtures/tables/output.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    AlphaBravoCharlieDelta
    EchoFoxtrotGolf
    IndiaJuliettKiloLima
    MikeNovemberOscarPapa
    QuebecRomeoSierraTango
    UniformVictorWhiskey
    diff --git a/test/fixtures/yaml/config.json b/test/fixtures/yaml/config.json deleted file mode 100644 index d573bf8..0000000 --- a/test/fixtures/yaml/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "yaml": true -} \ No newline at end of file diff --git a/test/fixtures/yaml/input.md b/test/fixtures/yaml/input.md deleted file mode 100644 index 8bd77ae..0000000 --- a/test/fixtures/yaml/input.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -YAML: cool ---- - -# Hello world diff --git a/test/fixtures/yaml/output.html b/test/fixtures/yaml/output.html deleted file mode 100644 index 159202e..0000000 --- a/test/fixtures/yaml/output.html +++ /dev/null @@ -1 +0,0 @@ -

    Hello world

    diff --git a/test/index.js b/test/index.js index 2f85ee3..5f1e4e1 100644 --- a/test/index.js +++ b/test/index.js @@ -1,159 +1,58 @@ -'use strict'; - -var path = require('path'); -var fs = require('fs'); -var assert = require('assert'); -var test = require('tape'); -var remark = require('remark'); -var toc = require('remark-toc'); -var github = require('remark-github'); -var commonmark = require('commonmark.json'); -var toVFile = require('to-vfile'); -var hidden = require('is-hidden'); -var all = require('mdast-util-to-hast/lib/all'); -var html = require('..'); - -var read = fs.readFileSync; -var exists = fs.existsSync; -var join = path.join; - -/* By default, CommonMark failures are accepted. - * To fail on CommonMark exceptions, set the `CMARK` - * environment variable. */ -var ignoreCommonMarkException = !('CMARK' in global.process.env); - -var INTEGRATION_MAP = {github: github, toc: toc}; -var INTEGRATION_ROOT = join(__dirname, 'integrations'); -var FIXTURE_ROOT = join(__dirname, 'fixtures'); - -var CMARK_OPTIONS = { - entities: { - escapeOnly: true, - useNamedReferences: true - }, - commonmark: true, - yaml: false, - closeSelfClosing: true, - sanitize: false -}; - -/* List of CommonMark tests I dissagree with. - * For reasoning, see `doc/commonmark.md`. - * Note that these differences have to do with not - * puting more time into features which IMHO produce - * less quality HTML. So if you’d like to write the - * features, I’ll gladly merge! */ -var CMARK_IGNORE = [ - /* Exception 1. */ - 247, - 248, - - /* Exception 2. */ - 3, - 50, - 76, - 77, - 80, - 86, - 89, - 98, - 118, - 176, - 230, - 231, - 233, - 236, - 257, - 258, - 261, - 262, - 263, - 264, - 265, - 266, - 267, - 268, - 269, - 270, - 395, - 396, - 433, - 445, - 520, - 522, - 551, - - /* Exception 3. */ - 428, - 477, - 478, - 479, - 480, - 481, - 489, - 493 -]; - -var fixtures = fs.readdirSync(FIXTURE_ROOT); -var integrations = fs.readdirSync(INTEGRATION_ROOT); - -fixtures = fixtures.filter(hidden); -integrations = integrations.filter(hidden); - -var section; -var start; - -commonmark.forEach(function (test, position) { - if (section !== test.section) { - section = test.section; - start = position; - } - - test.relative = position - start + 1; -}); +'use strict' + +var path = require('path') +var fs = require('fs') +var test = require('tape') +var remark = require('remark') +var slug = require('remark-slug') +var toc = require('remark-toc') +var github = require('remark-github') +var commonmark = require('commonmark.json') +var vfile = require('to-vfile') +var hidden = require('is-hidden') +var not = require('not') +var unified = require('unified') +var parse = require('remark-parse') +var rehypeParse = require('rehype-parse') +var rehypeStringify = require('rehype-stringify') +var all = require('mdast-util-to-hast/lib/all') +var html = require('..') test('remark-html()', function (t) { - var processor; + var processor - t.equal(typeof html, 'function', 'should be a function'); + t.equal(typeof html, 'function', 'should be a function') t.doesNotThrow(function () { - html.call(remark()); - }, 'should not throw if not passed options'); + remark().use(html).freeze() + }, 'should not throw if not passed options') t.throws( function () { - remark().use(html).stringify({ - type: 'root', - children: [{value: 'baz'}] - }); + remark() + .use(html) + .stringify({type: 'root', children: [{value: 'baz'}]}) }, /Expected node, got `\[object Object]`/, 'should throw when not given a node' - ); + ) - processor = remark().use(html); + processor = remark().use(html, {sanitize: false}) t.equal( processor.stringify({type: 'alpha'}), '
    ', 'should stringify unknown nodes' - ); + ) t.equal( processor.stringify({ type: 'alpha', - children: [{ - type: 'strong', - children: [{ - type: 'text', - value: 'bravo' - }] - }] + children: [{type: 'strong', children: [{type: 'text', value: 'bravo'}]}] }), '
    bravo
    ', 'should stringify unknown nodes' - ); + ) t.equal( processor.stringify({ @@ -167,240 +66,268 @@ test('remark-html()', function (t) { }), 'delta', 'should stringify unknown nodes' - ); + ) - processor = remark() - .use(html, {handlers: { + processor = remark().use(html, { + sanitize: false, + handlers: { paragraph: function (h, node) { - node.children[0].value = 'changed'; - return h(node, 'p', all(h, node)); + node.children[0].value = 'changed' + return h(node, 'p', all(h, node)) } - }}); + } + }) t.equal( processor.processSync('paragraph text').toString(), '

    changed

    \n', 'should allow overriding handlers' - ); + ) processor = remark() .use(function () { return function (ast) { ast.children[0].children[0].data = { hProperties: {title: 'overwrite'} - }; - }; + } + } }) - .use(html); + .use(html, {sanitize: false}) t.equal( processor.processSync('![hello](example.jpg "overwritten")').toString(), '

    hello

    \n', 'should patch and merge attributes' - ); + ) processor = remark() .use(function () { return function (ast) { - ast.children[0].children[0].data = {hName: 'b'}; - }; + ast.children[0].children[0].data = {hName: 'b'} + } }) - .use(html); + .use(html, {sanitize: false}) t.equal( processor.processSync('**Bold!**').toString(), '

    Bold!

    \n', 'should overwrite a tag-name' - ); + ) processor = remark() .use(function () { return function (ast) { - var code = ast.children[0].children[0]; + var code = ast.children[0].children[0] code.data = { - hChildren: [{ - type: 'element', - tagName: 'span', - properties: {className: ['token']}, - children: [{type: 'text', value: code.value}] - }] - }; - }; + hChildren: [ + { + type: 'element', + tagName: 'span', + properties: {className: ['token']}, + children: [{type: 'text', value: code.value}] + } + ] + } + } }) - .use(html); + .use(html, {sanitize: false}) t.equal( processor.processSync('`var`').toString(), '

    var

    \n', 'should overwrite content' - ); + ) processor = remark() .use(function () { return function (ast) { - var code = ast.children[0].children[0]; + var code = ast.children[0].children[0] code.data = { - hChildren: [{ - type: 'element', - tagName: 'span', - properties: {className: ['token']}, - children: [{type: 'text', value: code.value}] - }] - }; - }; + hChildren: [ + { + type: 'element', + tagName: 'output', + properties: {className: ['token']}, + children: [{type: 'text', value: code.value}] + } + ] + } + } }) - .use(html, {sanitize: true}); + .use(html, {sanitize: true}) t.equal( processor.processSync('`var`').toString(), '

    var

    \n', 'should not overwrite content in `sanitize` mode' - ); + ) processor = remark() .use(function () { return function (ast) { ast.children[0].data = { hProperties: {className: 'foo'} - }; - }; + } + } }) - .use(html); + .use(html, {sanitize: false}) t.equal( processor.processSync('```js\nvar\n```\n').toString(), '
    var\n
    \n', 'should overwrite classes on code' - ); + ) t.equal( - remark().use(html).processSync('## Hello world').toString(), + remark() + .use(html, {sanitize: false}) + .processSync('## Hello world') + .toString(), '

    Hello world

    \n', 'should be `sanitation: false` by default' - ); + ) t.equal( - remark().use(html, { - sanitize: true - }).processSync('## Hello world').toString(), + remark() + .use(html, {sanitize: true}) + .processSync('## Hello world') + .toString(), '

    Hello world

    \n', 'should support sanitation: true' - ); + ) t.equal( - remark().use(html, { - sanitize: null - }).processSync('## Hello world').toString(), - '

    Hello world

    \n', + remark() + .use(html, {sanitize: null}) + .processSync('## Hello world') + .toString(), + '

    Hello world

    \n', 'should support sanitation: null' - ); + ) t.equal( - remark().use(html, { - sanitize: false - }).processSync('## Hello world').toString(), + remark() + .use(html, {sanitize: false}) + .processSync('## Hello world') + .toString(), '

    Hello world

    \n', 'should support sanitation: false' - ); + ) t.equal( - remark().use(html, { - sanitize: {tagNames: []} - }).processSync('## Hello world').toString(), + remark() + .use(html, {sanitize: {tagNames: []}}) + .processSync('## Hello world') + .toString(), 'Hello world\n', 'should support sanitation schemas' - ); + ) - t.end(); -}); + t.end() +}) -/* Assert fixtures. */ +// Assert fixtures. test('Fixtures', function (t) { - fixtures.forEach(function (fixture) { - var filepath = join(FIXTURE_ROOT, fixture); - var output = read(join(filepath, 'output.html'), 'utf-8'); - var input = read(join(filepath, 'input.md'), 'utf-8'); - var config = join(filepath, 'config.json'); - var file = toVFile(fixture + '.md'); - var result; + var base = path.join(__dirname, 'fixtures') - file.contents = input; + fs.readdirSync(base).filter(not(hidden)).forEach(each) - config = exists(config) ? JSON.parse(read(config, 'utf-8')) : {}; - result = processSync(file, config); + t.end() - t.equal(result, output, 'should work on `' + fixture + '`'); - }); + function each(name) { + var output = String(fs.readFileSync(path.join(base, name, 'output.html'))) + var input = String(fs.readFileSync(path.join(base, name, 'input.md'))) + var config = {} + var file = vfile(name + '.md') + var result - t.end(); -}); + file.contents = input -/* Assert CommonMark. */ -test('CommonMark', function (t) { - commonmark.forEach(function (test, n) { - var name = test.section + ' ' + test.relative; - var file = toVFile(name + '.md'); - var result; - var message; - var exception; + try { + config = JSON.parse(fs.readFileSync(path.join(base, name, 'config.json'))) + } catch (_) {} - file.contents = test.markdown; - result = processSync(file, CMARK_OPTIONS); + result = processSync(file, config) - n += 1; + t.equal(result, output, 'should work on `' + name + '`') + } +}) - try { - assert.equal(result, test.html); - } catch (err) { - exception = err; - } +test('CommonMark', function (t) { + var start = 0 + var section + + commonmark.forEach(each) - message = '(' + n + ') should work on ' + name; + t.end() - if ( - CMARK_IGNORE.indexOf(n) !== -1 || - (ignoreCommonMarkException && exception) - ) { - t.skip(message); - } else { - t.equal(result, test.html, message); + function each(example, index) { + if (section !== example.section) { + section = example.section + start = index } - }); - t.end(); -}); + var actual = unified() + .use(parse) + .use(html, {sanitize: false}) + .processSync(example.markdown) + .toString() + + var reformat = unified() + .use(rehypeParse, {fragment: true}) + .use(rehypeStringify) + + // Normalize meaningless stuff, like character references, `
    ` is `
    `, + // etc. + t.equal( + String(reformat.processSync(actual)), + String(reformat.processSync(example.html)), + index + ': ' + example.section + ' (' + (index - start + 1) + ')' + ) + } +}) -/* Assert integrations. */ test('Integrations', function (t) { - integrations.forEach(function (integration) { - var filepath = join(INTEGRATION_ROOT, integration); - var output = read(join(filepath, 'output.html'), 'utf-8'); - var input = read(join(filepath, 'input.md'), 'utf-8'); - var config = join(filepath, 'config.json'); - var file = toVFile(integration + '.md'); - var result; + var integrationMap = {github: github, toc: [slug, toc]} + var base = path.join(__dirname, 'integrations') - file.contents = input; + fs.readdirSync(base) + .filter(not(hidden)) + // Ignore `github` for now, which needs to be updated for remark@next. + // To do: add gfm, footnotes, frontmatter integrations. + .filter((d) => d !== 'github') + .forEach(each) - config = exists(config) ? JSON.parse(read(config, 'utf-8')) : {}; + t.end() - config.sanitize = false; + function each(name) { + var output = String(fs.readFileSync(path.join(base, name, 'output.html'))) + var input = String(fs.readFileSync(path.join(base, name, 'input.md'))) + var file = vfile(name + '.md') + var config = {} + var result - result = remark() - .data('settings', config) - .use(html, config) - .use(INTEGRATION_MAP[integration], config) - .processSync(file) - .toString(); + file.contents = input + + try { + config = JSON.parse(fs.readFileSync(path.join(base, name, 'config.json'))) + } catch (_) {} - t.equal(result, output, 'should work on `' + integration + '`'); - }); + config.sanitize = false - t.end(); -}); + result = remark() + .data('settings', config) + .use(html, config) + .use(integrationMap[name], config) + .processSync(file) + .toString() + + t.equal(result, output, 'should work on `' + name + '`') + } +}) function processSync(file, config) { - return remark().data('settings', config).use(html, config).processSync(file).toString(); + return remark().use(html, config).processSync(file).toString() } diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 0000000..84762cf --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,21 @@ +// TypeScript Version: 3.5 + +import {Plugin} from 'unified' +import {HastUtilToHtmlOptions} from 'hast-util-to-html' +import {Schema} from 'hast-util-sanitize' +import {Handlers} from 'mdast-util-to-hast' + +interface htmlOptions extends HastUtilToHtmlOptions { + /** + * How to sanitize the output + */ + sanitize?: boolean | Schema + + /** + * Object mapping mdast nodes to functions handling them + */ + handlers?: Handlers +} + +declare const html: Plugin<[htmlOptions?]> +export = html diff --git a/types/remark-html-tests.ts b/types/remark-html-tests.ts new file mode 100644 index 0000000..b3a51df --- /dev/null +++ b/types/remark-html-tests.ts @@ -0,0 +1,9 @@ +import unified = require('unified') +import html = require('remark-html') + +unified().use(html) +unified().use(html, {preferUnquoted: true}) +unified().use(html, {sanitize: false}) +unified().use(html, {sanitize: false}) +unified().use(html, {sanitize: {allowComments: false}}) +unified().use(html, {handlers: {hr: (h, node) => h(node, 'hr')}}) diff --git a/types/tsconfig.json b/types/tsconfig.json new file mode 100644 index 0000000..0053c89 --- /dev/null +++ b/types/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "lib": ["es2015"], + "strict": true, + "baseUrl": ".", + "paths": { + "remark-html": ["index.d.ts"] + } + } +} diff --git a/types/tslint.json b/types/tslint.json new file mode 100644 index 0000000..70c4494 --- /dev/null +++ b/types/tslint.json @@ -0,0 +1,7 @@ +{ + "extends": "dtslint/dtslint.json", + "rules": { + "semicolon": false, + "whitespace": false + } +}