commit abf120a5fc5b8ff6c8a96989eb8f2da09e0e167c Author: Titus Wormer Date: Thu Oct 22 19:09:38 2020 +0200 . diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c6c8b36 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fdefc8c --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.DS_Store +*.log +.nyc_output/ +coverage/ +node_modules/ +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..e7939c4 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +coverage/ +*.json +*.md diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e108609 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - lts/dubnium + - node +after_script: bash <(curl -s https://codecov.io/bash) diff --git a/index.js b/index.js new file mode 100644 index 0000000..0063bf5 --- /dev/null +++ b/index.js @@ -0,0 +1,39 @@ +'use strict' + +var syntax = require('micromark-extension-directive') +var fromMarkdown = require('mdast-util-directive/from-markdown') +var toMarkdown = require('mdast-util-directive/to-markdown') + +var warningIssued + +module.exports = directive + +function directive() { + var data = this.data() + + /* istanbul ignore next - old remark. */ + if ( + !warningIssued && + ((this.Parser && + this.Parser.prototype && + this.Parser.prototype.blockTokenizers) || + (this.Compiler && + this.Compiler.prototype && + this.Compiler.prototype.visitors)) + ) { + warningIssued = true + console.warn( + '[remark-directive] Warning: please upgrade to remark 13 to use this plugin' + ) + } + + add('micromarkExtensions', syntax()) + add('fromMarkdownExtensions', fromMarkdown) + add('toMarkdownExtensions', toMarkdown) + + function add(field, value) { + /* istanbul ignore if - other extensions. */ + if (data[field]) data[field].push(value) + else data[field] = [value] + } +} diff --git a/license b/license new file mode 100644 index 0000000..3937235 --- /dev/null +++ b/license @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2020 Titus Wormer + +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. diff --git a/package.json b/package.json new file mode 100644 index 0000000..86504bf --- /dev/null +++ b/package.json @@ -0,0 +1,84 @@ +{ + "name": "remark-directive", + "version": "0.0.0", + "description": "remark plugin to support directives", + "license": "MIT", + "keywords": [ + "unified", + "remark", + "remark-plugin", + "plugin", + "mdast", + "markdown", + "generic", + "directive", + "container" + ], + "repository": "remarkjs/remark-directive", + "bugs": "https://github.com/remarkjs/remark-directive/issues", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "author": "Titus Wormer (https://wooorm.com)", + "contributors": [ + "Titus Wormer (https://wooorm.com)" + ], + "types": "types/index.d.ts", + "files": [ + "types/index.d.ts", + "index.js" + ], + "dependencies": { + "mdast-util-directive": "^1.0.0", + "micromark-extension-directive": "^1.0.0" + }, + "devDependencies": { + "dtslint": "^4.0.0", + "is-hidden": "^1.0.0", + "not": "^0.1.0", + "nyc": "^15.0.0", + "prettier": "^2.0.0", + "remark": "^13.0.0", + "remark-cli": "^9.0.0", + "remark-preset-wooorm": "^8.0.0", + "tape": "^5.0.0", + "to-vfile": "^6.0.0", + "unified": "^9.0.0", + "xo": "^0.34.0" + }, + "scripts": { + "format": "remark . -qfo --ignore-pattern test/ && prettier . -w --loglevel warn && xo --fix", + "test-api": "node test", + "test-coverage": "nyc --reporter lcov tape test/index.js", + "test-types": "dtslint types", + "test": "npm run format && npm run test-coverage && npm run test-types" + }, + "nyc": { + "check-coverage": true, + "lines": 100, + "functions": 100, + "branches": 100 + }, + "prettier": { + "tabWidth": 2, + "useTabs": false, + "singleQuote": true, + "bracketSpacing": false, + "semi": false, + "trailingComma": "none" + }, + "xo": { + "prettier": true, + "esnext": false, + "rules": { + "unicorn/no-fn-reference-in-iterator": "off", + "unicorn/prefer-optional-catch-binding": "off" + } + }, + "remarkConfig": { + "plugins": [ + "preset-wooorm" + ] + } +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..e2d75b3 --- /dev/null +++ b/readme.md @@ -0,0 +1,162 @@ +# remark-directive + +[![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] + +[**remark**][remark] plugin to support the [generic directives proposal][prop] +(`:cite[smith04]`, `::youtube[Video of a cat in a box]{v=01ab2cd3efg}`, and +such). + +## Important! + +This plugin is made for the new parser in remark +([`micromark`](https://github.com/micromark/micromark), +see [`remarkjs/remark#536`](https://github.com/remarkjs/remark/pull/536)). +Use this plugin for remark 13+. + +## Install + +[npm][]: + +```sh +npm install remark-directive +``` + +## Use + +Say we have the following file, `example.md`: + +```markdown +``` + +And our script, `example.js`, looks as follows: + +```js +var vfile = require('to-vfile') +var report = require('vfile-reporter') +var unified = require('unified') +var parse = require('remark-parse') +var directive = require('remark-directive') +var stringify = require('rehype-stringify') + +unified() + .use(parse) + .use(directive) + .use(remark2rehype) + .use(stringify) + .process(vfile.readSync('example.md'), function (err, file) { + console.error(report(err || file)) + console.log(String(file)) + }) +``` + +Now, running `node example` yields: + +```html +``` + +## API + +### `remark().use(directive)` + +Configures remark so that it can parse and serialize directives. +Doesn’t handle the directives: [create your own plugin][create-plugin] to do +that. +See the [micromark extension for the syntax][syntax] and the +[mdast utility for the syntax tree][syntax-tree]. + +## Security + +Use of `remark-directive` does not involve [**rehype**][rehype] +([**hast**][hast]) or user content so there are no openings for [cross-site +scripting (XSS)][xss] attacks. + +## Related + +* [`remark-gfm`](https://github.com/remarkjs/remark-gfm) + — GFM +* [`remark-github`](https://github.com/remarkjs/remark-github) + — Autolink references like in GitHub issues, PRs, and comments +* [`remark-footnotes`](https://github.com/remarkjs/remark-footnotes) + — Footnotes +* [`remark-frontmatter`](https://github.com/remarkjs/remark-frontmatter) + — Frontmatter (YAML, TOML, and more) +* [`remark-math`](https://github.com/remarkjs/remark-math) + — Math + +## 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/remarkjs/remark-directive/main.svg + +[build]: https://travis-ci.org/remarkjs/remark-directive + +[coverage-badge]: https://img.shields.io/codecov/c/github/remarkjs/remark-directive.svg + +[coverage]: https://codecov.io/github/remarkjs/remark-directive + +[downloads-badge]: https://img.shields.io/npm/dm/remark-directive.svg + +[downloads]: https://www.npmjs.com/package/remark-directive + +[size-badge]: https://img.shields.io/bundlephobia/minzip/remark-directive.svg + +[size]: https://bundlephobia.com/result?p=remark-directive + +[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg + +[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 + +[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 + +[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting + +[rehype]: https://github.com/rehypejs/rehype + +[hast]: https://github.com/syntax-tree/hast + +[prop]: https://talk.commonmark.org/t/generic-directives-plugins-syntax/444 + +[create-plugin]: https://unifiedjs.com/learn/guide/create-a-plugin/ + +[syntax]: https://github.com/micromark/micromark-extension-directive#syntax + +[syntax-tree]: https://github.com/syntax-tree/mdast-util-directive#syntax-tree diff --git a/test/fixtures/container/input.md b/test/fixtures/container/input.md new file mode 100644 index 0000000..c714fed --- /dev/null +++ b/test/fixtures/container/input.md @@ -0,0 +1,32 @@ +:::a +::: + +:::a[b] +::: + +:::a{b} +::: + +:::a[b]{c} +::: + +:::a[b *c* d **e**] +::: + +:::a{#b.c.d id=e class="f g" h="i & j k"} +::: + +:::::a +::::b +:::c +::::: + +:::::a +b +::::c +d +:::e +- - f +::: +> g h +::::: diff --git a/test/fixtures/container/output.md b/test/fixtures/container/output.md new file mode 100644 index 0000000..78291a5 --- /dev/null +++ b/test/fixtures/container/output.md @@ -0,0 +1,38 @@ +:::a +::: + +:::a[b] +::: + +:::a{b} +::: + +:::a[b]{c} +::: + +:::a[b *c* d **e**] +::: + +:::a{#e .c.d.f.g h="i & j k"} +::: + +:::::a +::::b +:::c +::: +:::: +::::: + +:::::a +b + +::::c +d + +:::e +* * f +::: + +> g h +:::: +::::: diff --git a/test/fixtures/container/tree.json b/test/fixtures/container/tree.json new file mode 100644 index 0000000..78970cd --- /dev/null +++ b/test/fixtures/container/tree.json @@ -0,0 +1,666 @@ +{ + "type": "root", + "children": [ + { + "type": "containerDirective", + "name": "a", + "attributes": {}, + "children": [], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 2, + "column": 4, + "offset": 8 + } + } + }, + { + "type": "containerDirective", + "name": "a", + "attributes": {}, + "children": [ + { + "type": "paragraph", + "data": { + "directiveLabel": true + }, + "children": [ + { + "type": "text", + "value": "b", + "position": { + "start": { + "line": 4, + "column": 6, + "offset": 15 + }, + "end": { + "line": 4, + "column": 7, + "offset": 16 + } + } + } + ], + "position": { + "start": { + "line": 4, + "column": 5, + "offset": 14 + }, + "end": { + "line": 4, + "column": 8, + "offset": 17 + } + } + } + ], + "position": { + "start": { + "line": 4, + "column": 1, + "offset": 10 + }, + "end": { + "line": 5, + "column": 4, + "offset": 21 + } + } + }, + { + "type": "containerDirective", + "name": "a", + "attributes": { + "b": "" + }, + "children": [], + "position": { + "start": { + "line": 7, + "column": 1, + "offset": 23 + }, + "end": { + "line": 8, + "column": 4, + "offset": 34 + } + } + }, + { + "type": "containerDirective", + "name": "a", + "attributes": { + "c": "" + }, + "children": [ + { + "type": "paragraph", + "data": { + "directiveLabel": true + }, + "children": [ + { + "type": "text", + "value": "b", + "position": { + "start": { + "line": 10, + "column": 6, + "offset": 41 + }, + "end": { + "line": 10, + "column": 7, + "offset": 42 + } + } + } + ], + "position": { + "start": { + "line": 10, + "column": 5, + "offset": 40 + }, + "end": { + "line": 10, + "column": 8, + "offset": 43 + } + } + } + ], + "position": { + "start": { + "line": 10, + "column": 1, + "offset": 36 + }, + "end": { + "line": 11, + "column": 4, + "offset": 50 + } + } + }, + { + "type": "containerDirective", + "name": "a", + "attributes": {}, + "children": [ + { + "type": "paragraph", + "data": { + "directiveLabel": true + }, + "children": [ + { + "type": "text", + "value": "b ", + "position": { + "start": { + "line": 13, + "column": 6, + "offset": 57 + }, + "end": { + "line": 13, + "column": 8, + "offset": 59 + } + } + }, + { + "type": "emphasis", + "children": [ + { + "type": "text", + "value": "c", + "position": { + "start": { + "line": 13, + "column": 9, + "offset": 60 + }, + "end": { + "line": 13, + "column": 10, + "offset": 61 + } + } + } + ], + "position": { + "start": { + "line": 13, + "column": 8, + "offset": 59 + }, + "end": { + "line": 13, + "column": 11, + "offset": 62 + } + } + }, + { + "type": "text", + "value": " d ", + "position": { + "start": { + "line": 13, + "column": 11, + "offset": 62 + }, + "end": { + "line": 13, + "column": 14, + "offset": 65 + } + } + }, + { + "type": "strong", + "children": [ + { + "type": "text", + "value": "e", + "position": { + "start": { + "line": 13, + "column": 16, + "offset": 67 + }, + "end": { + "line": 13, + "column": 17, + "offset": 68 + } + } + } + ], + "position": { + "start": { + "line": 13, + "column": 14, + "offset": 65 + }, + "end": { + "line": 13, + "column": 19, + "offset": 70 + } + } + } + ], + "position": { + "start": { + "line": 13, + "column": 5, + "offset": 56 + }, + "end": { + "line": 13, + "column": 20, + "offset": 71 + } + } + } + ], + "position": { + "start": { + "line": 13, + "column": 1, + "offset": 52 + }, + "end": { + "line": 14, + "column": 4, + "offset": 75 + } + } + }, + { + "type": "containerDirective", + "name": "a", + "attributes": { + "id": "e", + "class": "c d f g", + "h": "i & j k" + }, + "children": [], + "position": { + "start": { + "line": 16, + "column": 1, + "offset": 77 + }, + "end": { + "line": 17, + "column": 4, + "offset": 126 + } + } + }, + { + "type": "containerDirective", + "name": "a", + "attributes": {}, + "children": [ + { + "type": "containerDirective", + "name": "b", + "attributes": {}, + "children": [ + { + "type": "containerDirective", + "name": "c", + "attributes": {}, + "children": [], + "position": { + "start": { + "line": 21, + "column": 1, + "offset": 141 + }, + "end": { + "line": 22, + "column": 1, + "offset": 146 + } + } + } + ], + "position": { + "start": { + "line": 20, + "column": 1, + "offset": 135 + }, + "end": { + "line": 22, + "column": 1, + "offset": 146 + } + } + } + ], + "position": { + "start": { + "line": 19, + "column": 1, + "offset": 128 + }, + "end": { + "line": 22, + "column": 6, + "offset": 151 + } + } + }, + { + "type": "containerDirective", + "name": "a", + "attributes": {}, + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "b", + "position": { + "start": { + "line": 25, + "column": 1, + "offset": 160 + }, + "end": { + "line": 25, + "column": 2, + "offset": 161 + } + } + } + ], + "position": { + "start": { + "line": 25, + "column": 1, + "offset": 160 + }, + "end": { + "line": 25, + "column": 2, + "offset": 161 + } + } + }, + { + "type": "containerDirective", + "name": "c", + "attributes": {}, + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "d", + "position": { + "start": { + "line": 27, + "column": 1, + "offset": 168 + }, + "end": { + "line": 27, + "column": 2, + "offset": 169 + } + } + } + ], + "position": { + "start": { + "line": 27, + "column": 1, + "offset": 168 + }, + "end": { + "line": 27, + "column": 2, + "offset": 169 + } + } + }, + { + "type": "containerDirective", + "name": "e", + "attributes": {}, + "children": [ + { + "type": "list", + "ordered": false, + "start": null, + "spread": false, + "children": [ + { + "type": "listItem", + "spread": false, + "checked": null, + "children": [ + { + "type": "list", + "ordered": false, + "start": null, + "spread": false, + "children": [ + { + "type": "listItem", + "spread": false, + "checked": null, + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "f", + "position": { + "start": { + "line": 29, + "column": 5, + "offset": 179 + }, + "end": { + "line": 29, + "column": 6, + "offset": 180 + } + } + } + ], + "position": { + "start": { + "line": 29, + "column": 5, + "offset": 179 + }, + "end": { + "line": 29, + "column": 6, + "offset": 180 + } + } + } + ], + "position": { + "start": { + "line": 29, + "column": 3, + "offset": 177 + }, + "end": { + "line": 29, + "column": 6, + "offset": 180 + } + } + } + ], + "position": { + "start": { + "line": 29, + "column": 3, + "offset": 177 + }, + "end": { + "line": 29, + "column": 6, + "offset": 180 + } + } + } + ], + "position": { + "start": { + "line": 29, + "column": 1, + "offset": 175 + }, + "end": { + "line": 29, + "column": 6, + "offset": 180 + } + } + } + ], + "position": { + "start": { + "line": 29, + "column": 1, + "offset": 175 + }, + "end": { + "line": 29, + "column": 6, + "offset": 180 + } + } + } + ], + "position": { + "start": { + "line": 28, + "column": 1, + "offset": 170 + }, + "end": { + "line": 30, + "column": 4, + "offset": 184 + } + } + }, + { + "type": "blockquote", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "g h", + "position": { + "start": { + "line": 31, + "column": 3, + "offset": 187 + }, + "end": { + "line": 31, + "column": 6, + "offset": 190 + } + } + } + ], + "position": { + "start": { + "line": 31, + "column": 3, + "offset": 187 + }, + "end": { + "line": 31, + "column": 6, + "offset": 190 + } + } + } + ], + "position": { + "start": { + "line": 31, + "column": 1, + "offset": 185 + }, + "end": { + "line": 31, + "column": 6, + "offset": 190 + } + } + } + ], + "position": { + "start": { + "line": 26, + "column": 1, + "offset": 162 + }, + "end": { + "line": 32, + "column": 1, + "offset": 191 + } + } + } + ], + "position": { + "start": { + "line": 24, + "column": 1, + "offset": 153 + }, + "end": { + "line": 32, + "column": 6, + "offset": 196 + } + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 33, + "column": 1, + "offset": 197 + } + } +} diff --git a/test/fixtures/leaf/input.md b/test/fixtures/leaf/input.md new file mode 100644 index 0000000..e6c2236 --- /dev/null +++ b/test/fixtures/leaf/input.md @@ -0,0 +1,11 @@ +::a + +::a[b] + +::a{b} + +::a[b]{c} + +::a[b *c* d **e**] + +::a{#b.c.d id=e class="f g" h="i & j k"} diff --git a/test/fixtures/leaf/output.md b/test/fixtures/leaf/output.md new file mode 100644 index 0000000..f8652d9 --- /dev/null +++ b/test/fixtures/leaf/output.md @@ -0,0 +1,11 @@ +::a + +::a[b] + +::a{b} + +::a[b]{c} + +::a[b *c* d **e**] + +::a{#e .c.d.f.g h="i & j k"} diff --git a/test/fixtures/leaf/tree.json b/test/fixtures/leaf/tree.json new file mode 100644 index 0000000..f4cea19 --- /dev/null +++ b/test/fixtures/leaf/tree.json @@ -0,0 +1,266 @@ +{ + "type": "root", + "children": [ + { + "type": "leafDirective", + "name": "a", + "attributes": {}, + "children": [], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 4, + "offset": 3 + } + } + }, + { + "type": "leafDirective", + "name": "a", + "attributes": {}, + "children": [ + { + "type": "text", + "value": "b", + "position": { + "start": { + "line": 3, + "column": 5, + "offset": 9 + }, + "end": { + "line": 3, + "column": 6, + "offset": 10 + } + } + } + ], + "position": { + "start": { + "line": 3, + "column": 1, + "offset": 5 + }, + "end": { + "line": 3, + "column": 7, + "offset": 11 + } + } + }, + { + "type": "leafDirective", + "name": "a", + "attributes": { + "b": "" + }, + "children": [], + "position": { + "start": { + "line": 5, + "column": 1, + "offset": 13 + }, + "end": { + "line": 5, + "column": 7, + "offset": 19 + } + } + }, + { + "type": "leafDirective", + "name": "a", + "attributes": { + "c": "" + }, + "children": [ + { + "type": "text", + "value": "b", + "position": { + "start": { + "line": 7, + "column": 5, + "offset": 25 + }, + "end": { + "line": 7, + "column": 6, + "offset": 26 + } + } + } + ], + "position": { + "start": { + "line": 7, + "column": 1, + "offset": 21 + }, + "end": { + "line": 7, + "column": 10, + "offset": 30 + } + } + }, + { + "type": "leafDirective", + "name": "a", + "attributes": {}, + "children": [ + { + "type": "text", + "value": "b ", + "position": { + "start": { + "line": 9, + "column": 5, + "offset": 36 + }, + "end": { + "line": 9, + "column": 7, + "offset": 38 + } + } + }, + { + "type": "emphasis", + "children": [ + { + "type": "text", + "value": "c", + "position": { + "start": { + "line": 9, + "column": 8, + "offset": 39 + }, + "end": { + "line": 9, + "column": 9, + "offset": 40 + } + } + } + ], + "position": { + "start": { + "line": 9, + "column": 7, + "offset": 38 + }, + "end": { + "line": 9, + "column": 10, + "offset": 41 + } + } + }, + { + "type": "text", + "value": " d ", + "position": { + "start": { + "line": 9, + "column": 10, + "offset": 41 + }, + "end": { + "line": 9, + "column": 13, + "offset": 44 + } + } + }, + { + "type": "strong", + "children": [ + { + "type": "text", + "value": "e", + "position": { + "start": { + "line": 9, + "column": 15, + "offset": 46 + }, + "end": { + "line": 9, + "column": 16, + "offset": 47 + } + } + } + ], + "position": { + "start": { + "line": 9, + "column": 13, + "offset": 44 + }, + "end": { + "line": 9, + "column": 18, + "offset": 49 + } + } + } + ], + "position": { + "start": { + "line": 9, + "column": 1, + "offset": 32 + }, + "end": { + "line": 9, + "column": 19, + "offset": 50 + } + } + }, + { + "type": "leafDirective", + "name": "a", + "attributes": { + "id": "e", + "class": "c d f g", + "h": "i & j k" + }, + "children": [], + "position": { + "start": { + "line": 11, + "column": 1, + "offset": 52 + }, + "end": { + "line": 11, + "column": 45, + "offset": 96 + } + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 12, + "column": 1, + "offset": 97 + } + } +} diff --git a/test/fixtures/text/input.md b/test/fixtures/text/input.md new file mode 100644 index 0000000..e0041ee --- /dev/null +++ b/test/fixtures/text/input.md @@ -0,0 +1,7 @@ +One :a, two :a[b], three :a{b}, four :a[b]{c}. + +:a[b *c* +d **e**]. + +:a{#b.c.d id=e class="f g" h="i & j +k"}. diff --git a/test/fixtures/text/output.md b/test/fixtures/text/output.md new file mode 100644 index 0000000..6766270 --- /dev/null +++ b/test/fixtures/text/output.md @@ -0,0 +1,7 @@ +One :a, two :a[b], three :a{b}, four :a[b]{c}. + +:a[b *c* +d **e**]. + +:a{#e .c.d.f.g h="i & j +k"}. diff --git a/test/fixtures/text/tree.json b/test/fixtures/text/tree.json new file mode 100644 index 0000000..a03367b --- /dev/null +++ b/test/fixtures/text/tree.json @@ -0,0 +1,429 @@ +{ + "type": "root", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "One ", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 5, + "offset": 4 + } + } + }, + { + "type": "textDirective", + "name": "a", + "attributes": {}, + "children": [], + "position": { + "start": { + "line": 1, + "column": 5, + "offset": 4 + }, + "end": { + "line": 1, + "column": 7, + "offset": 6 + } + } + }, + { + "type": "text", + "value": ", two ", + "position": { + "start": { + "line": 1, + "column": 7, + "offset": 6 + }, + "end": { + "line": 1, + "column": 13, + "offset": 12 + } + } + }, + { + "type": "textDirective", + "name": "a", + "attributes": {}, + "children": [ + { + "type": "text", + "value": "b", + "position": { + "start": { + "line": 1, + "column": 16, + "offset": 15 + }, + "end": { + "line": 1, + "column": 17, + "offset": 16 + } + } + } + ], + "position": { + "start": { + "line": 1, + "column": 13, + "offset": 12 + }, + "end": { + "line": 1, + "column": 18, + "offset": 17 + } + } + }, + { + "type": "text", + "value": ", three ", + "position": { + "start": { + "line": 1, + "column": 18, + "offset": 17 + }, + "end": { + "line": 1, + "column": 26, + "offset": 25 + } + } + }, + { + "type": "textDirective", + "name": "a", + "attributes": { + "b": "" + }, + "children": [], + "position": { + "start": { + "line": 1, + "column": 26, + "offset": 25 + }, + "end": { + "line": 1, + "column": 31, + "offset": 30 + } + } + }, + { + "type": "text", + "value": ", four ", + "position": { + "start": { + "line": 1, + "column": 31, + "offset": 30 + }, + "end": { + "line": 1, + "column": 38, + "offset": 37 + } + } + }, + { + "type": "textDirective", + "name": "a", + "attributes": { + "c": "" + }, + "children": [ + { + "type": "text", + "value": "b", + "position": { + "start": { + "line": 1, + "column": 41, + "offset": 40 + }, + "end": { + "line": 1, + "column": 42, + "offset": 41 + } + } + } + ], + "position": { + "start": { + "line": 1, + "column": 38, + "offset": 37 + }, + "end": { + "line": 1, + "column": 46, + "offset": 45 + } + } + }, + { + "type": "text", + "value": ".", + "position": { + "start": { + "line": 1, + "column": 46, + "offset": 45 + }, + "end": { + "line": 1, + "column": 47, + "offset": 46 + } + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 47, + "offset": 46 + } + } + }, + { + "type": "paragraph", + "children": [ + { + "type": "textDirective", + "name": "a", + "attributes": {}, + "children": [ + { + "type": "text", + "value": "b ", + "position": { + "start": { + "line": 3, + "column": 4, + "offset": 51 + }, + "end": { + "line": 3, + "column": 6, + "offset": 53 + } + } + }, + { + "type": "emphasis", + "children": [ + { + "type": "text", + "value": "c", + "position": { + "start": { + "line": 3, + "column": 7, + "offset": 54 + }, + "end": { + "line": 3, + "column": 8, + "offset": 55 + } + } + } + ], + "position": { + "start": { + "line": 3, + "column": 6, + "offset": 53 + }, + "end": { + "line": 3, + "column": 9, + "offset": 56 + } + } + }, + { + "type": "text", + "value": "\nd ", + "position": { + "start": { + "line": 3, + "column": 9, + "offset": 56 + }, + "end": { + "line": 4, + "column": 3, + "offset": 59 + } + } + }, + { + "type": "strong", + "children": [ + { + "type": "text", + "value": "e", + "position": { + "start": { + "line": 4, + "column": 5, + "offset": 61 + }, + "end": { + "line": 4, + "column": 6, + "offset": 62 + } + } + } + ], + "position": { + "start": { + "line": 4, + "column": 3, + "offset": 59 + }, + "end": { + "line": 4, + "column": 8, + "offset": 64 + } + } + } + ], + "position": { + "start": { + "line": 3, + "column": 1, + "offset": 48 + }, + "end": { + "line": 4, + "column": 9, + "offset": 65 + } + } + }, + { + "type": "text", + "value": ".", + "position": { + "start": { + "line": 4, + "column": 9, + "offset": 65 + }, + "end": { + "line": 4, + "column": 10, + "offset": 66 + } + } + } + ], + "position": { + "start": { + "line": 3, + "column": 1, + "offset": 48 + }, + "end": { + "line": 4, + "column": 10, + "offset": 66 + } + } + }, + { + "type": "paragraph", + "children": [ + { + "type": "textDirective", + "name": "a", + "attributes": { + "id": "e", + "class": "c d f g", + "h": "i & j\nk" + }, + "children": [], + "position": { + "start": { + "line": 6, + "column": 1, + "offset": 68 + }, + "end": { + "line": 7, + "column": 4, + "offset": 111 + } + } + }, + { + "type": "text", + "value": ".", + "position": { + "start": { + "line": 7, + "column": 4, + "offset": 111 + }, + "end": { + "line": 7, + "column": 5, + "offset": 112 + } + } + } + ], + "position": { + "start": { + "line": 6, + "column": 1, + "offset": 68 + }, + "end": { + "line": 7, + "column": 5, + "offset": 112 + } + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 8, + "column": 1, + "offset": 113 + } + } +} diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..e83826f --- /dev/null +++ b/test/index.js @@ -0,0 +1,67 @@ +'use strict' + +var fs = require('fs') +var path = require('path') +var test = require('tape') +var vfile = require('to-vfile') +var unified = require('unified') +var remark = require('remark') +var not = require('not') +var hidden = require('is-hidden') +var directive = require('..') + +test('directive()', function (t) { + t.doesNotThrow(function () { + remark().use(directive).freeze() + }, 'should not throw if not passed options') + + t.doesNotThrow(function () { + unified().use(directive).freeze() + }, 'should not throw if without parser or compiler') + + t.end() +}) + +test('fixtures', function (t) { + var base = path.join(__dirname, 'fixtures') + var entries = fs.readdirSync(base).filter(not(hidden)) + + t.plan(entries.length) + + entries.forEach(each) + + function each(fixture) { + t.test(fixture, function (st) { + var file = vfile.readSync(path.join(base, fixture, 'input.md')) + var input = String(file.contents) + var outputPath = path.join(base, fixture, 'output.md') + var treePath = path.join(base, fixture, 'tree.json') + var proc + var actual + var output + var expected + + proc = remark().use(directive).freeze() + actual = proc.parse(file) + + try { + expected = JSON.parse(fs.readFileSync(treePath)) + } catch (_) { + // New fixture. + fs.writeFileSync(treePath, JSON.stringify(actual, 0, 2) + '\n') + expected = actual + } + + try { + output = fs.readFileSync(outputPath, 'utf8') + } catch (_) { + output = input + } + + st.deepEqual(actual, expected, 'tree') + st.equal(String(proc.processSync(file)), output, 'process') + + st.end() + }) + } +}) diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 0000000..6de6595 --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,11 @@ +// TypeScript Version: 3.4 + +import {Plugin} from 'unified' + +declare namespace remarkDirective { + type Directive = Plugin<[]> +} + +declare const remarkDirective: remarkDirective.Directive + +export = remarkDirective diff --git a/types/test.ts b/types/test.ts new file mode 100644 index 0000000..7edb336 --- /dev/null +++ b/types/test.ts @@ -0,0 +1,7 @@ +import unified = require('unified') +import directive = require('remark-directive') + +unified().use(directive) +unified().use(directive) + +unified().use(directive, {weird: true}) // $ExpectError diff --git a/types/tsconfig.json b/types/tsconfig.json new file mode 100644 index 0000000..5e24fcf --- /dev/null +++ b/types/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "lib": ["es2015"], + "strict": true, + "baseUrl": ".", + "paths": { + "remark-directive": ["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 + } +}