Compare commits
55 commits
Author | SHA1 | Date | |
---|---|---|---|
f67c8452ab | |||
5e61c16964 | |||
722e6bee28 | |||
|
103c85adba | ||
|
b685b00060 | ||
|
7ca8974f14 | ||
|
8f29f1e456 | ||
|
7e9a5a78b8 | ||
|
f2eefc2418 | ||
|
a29bc053db | ||
|
9f8e165510 | ||
|
6fe12e7771 | ||
|
320c56aacf | ||
|
7831904974 | ||
|
876a45ad4c | ||
|
e1027d13bd | ||
|
edef661a1f | ||
|
733932dd91 | ||
|
20c4a6b5e1 | ||
|
9e219a3603 | ||
|
a952370494 | ||
|
c223cd8e31 | ||
|
d2b583b5ba | ||
|
6e6c0ed89f | ||
|
055840baf2 | ||
|
086fca9a90 | ||
|
f525f4c172 | ||
|
bd953c935e | ||
|
bf126a045a | ||
|
c40caa2682 | ||
|
3d93cc085c | ||
|
decd688110 | ||
|
2cfea20ae7 | ||
|
6f1683ea00 | ||
|
92038d21e0 | ||
|
eb52b1adc1 | ||
|
c369fcb50b | ||
|
bddb81b066 | ||
|
52501b7de6 | ||
|
a56e309f80 | ||
|
86376c703c | ||
|
faac6e3148 | ||
|
2631e46657 | ||
|
5855467c0b | ||
|
0451eb5539 | ||
|
3b94de5255 | ||
|
35e8ccfd16 | ||
|
e30accdd27 | ||
|
cd45dd6c6d | ||
|
0b9dc4284e | ||
|
1d5afb9f28 | ||
|
e671b71418 | ||
|
980f376e84 | ||
|
1e52e472ef | ||
|
8424e85af2 |
21 changed files with 706 additions and 304 deletions
|
@ -1,9 +1,9 @@
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
end_of_line = lf
|
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
end_of_line = lf
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
13
.github/workflows/bb.yml
vendored
Normal file
13
.github/workflows/bb.yml
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
jobs:
|
||||||
|
main:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: unifiedjs/beep-boop-beta@main
|
||||||
|
with:
|
||||||
|
repo-token: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
name: bb
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types: [closed, edited, labeled, opened, reopened, unlabeled]
|
||||||
|
pull_request_target:
|
||||||
|
types: [closed, edited, labeled, opened, reopened, unlabeled]
|
21
.github/workflows/main.yml
vendored
Normal file
21
.github/workflows/main.yml
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
jobs:
|
||||||
|
main:
|
||||||
|
name: ${{matrix.node}}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{matrix.node}}
|
||||||
|
- run: npm install
|
||||||
|
- run: npm test
|
||||||
|
- uses: codecov/codecov-action@v5
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node:
|
||||||
|
- lts/hydrogen
|
||||||
|
- node
|
||||||
|
name: main
|
||||||
|
on:
|
||||||
|
- pull_request
|
||||||
|
- push
|
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -1,6 +1,9 @@
|
||||||
.DS_Store
|
*.d.ts
|
||||||
*.log
|
*.log
|
||||||
.nyc_output/
|
*.map
|
||||||
|
*.tsbuildinfo
|
||||||
|
.DS_Store
|
||||||
coverage/
|
coverage/
|
||||||
node_modules/
|
node_modules/
|
||||||
yarn.lock
|
yarn.lock
|
||||||
|
!/index.d.ts
|
||||||
|
|
1
.npmrc
1
.npmrc
|
@ -1 +1,2 @@
|
||||||
|
ignore-scripts=true
|
||||||
package-lock=false
|
package-lock=false
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
coverage/
|
|
||||||
*.json
|
|
||||||
*.md
|
*.md
|
||||||
|
coverage/
|
||||||
|
|
1
.remarkignore
Normal file
1
.remarkignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
test/fixtures/
|
|
@ -1,5 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- lts/dubnium
|
|
||||||
- node
|
|
||||||
after_script: bash <(curl -s https://codecov.io/bash)
|
|
15
index.d.ts
vendored
Normal file
15
index.d.ts
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import type {ToMarkdownOptions} from 'mdast-util-directive'
|
||||||
|
|
||||||
|
export {default} from './lib/index.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for `remark-directive`.
|
||||||
|
*
|
||||||
|
* Currently supports
|
||||||
|
* `collapseEmptyAttributes`,
|
||||||
|
* `preferShortcut`,
|
||||||
|
* `preferUnquoted`,
|
||||||
|
* `quoteSmart`,
|
||||||
|
* and `quote` as serialization options.
|
||||||
|
*/
|
||||||
|
export interface Options extends ToMarkdownOptions {}
|
41
index.js
41
index.js
|
@ -1,39 +1,2 @@
|
||||||
'use strict'
|
// Note: types exposed from `index.d.ts`.
|
||||||
|
export {default} from './lib/index.js'
|
||||||
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]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
38
lib/index.js
Normal file
38
lib/index.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* @import {} from 'mdast-util-directive'
|
||||||
|
* @import {Root} from 'mdast'
|
||||||
|
* @import {} from 'remark-arse'
|
||||||
|
* @import {} from 'remark-stringify'
|
||||||
|
* @import {Processor} from 'unified'
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
directiveFromMarkdown,
|
||||||
|
directiveToMarkdown,
|
||||||
|
} from "mdast-util-directive";
|
||||||
|
import { directive } from "micromark-extension-directive";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add support for generic directives.
|
||||||
|
*
|
||||||
|
* ###### Notes
|
||||||
|
*
|
||||||
|
* Doesn’t handle the directives: create your own plugin to do that.
|
||||||
|
*
|
||||||
|
* @returns {undefined}
|
||||||
|
* Nothing.
|
||||||
|
*/
|
||||||
|
export default function remarkDirective() {
|
||||||
|
const data = this.data();
|
||||||
|
|
||||||
|
const micromarkExtensions =
|
||||||
|
data.micromarkExtensions || (data.micromarkExtensions = []);
|
||||||
|
const fromMarkdownExtensions =
|
||||||
|
data.fromMarkdownExtensions || (data.fromMarkdownExtensions = []);
|
||||||
|
const toMarkdownExtensions =
|
||||||
|
data.toMarkdownExtensions || (data.toMarkdownExtensions = []);
|
||||||
|
|
||||||
|
micromarkExtensions.push(directive());
|
||||||
|
fromMarkdownExtensions.push(directiveFromMarkdown());
|
||||||
|
toMarkdownExtensions.push(directiveToMarkdown());
|
||||||
|
}
|
2
license
2
license
|
@ -1,6 +1,6 @@
|
||||||
(The MIT License)
|
(The MIT License)
|
||||||
|
|
||||||
Copyright (c) 2020 Titus Wormer <tituswormer@gmail.com>
|
Copyright (c) Titus Wormer <tituswormer@gmail.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
|
|
160
package.json
160
package.json
|
@ -1,84 +1,106 @@
|
||||||
{
|
{
|
||||||
"name": "remark-directive",
|
"author": "Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)",
|
||||||
"version": "1.0.1",
|
|
||||||
"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",
|
"bugs": "https://github.com/remarkjs/remark-directive/issues",
|
||||||
|
"contributors": ["Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)"],
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"mdast-util-directive": "^3.0.0",
|
||||||
|
"micromark-extension-directive": "git+https://git.v-sli.me/HidemaruOwO/micromark-extension-directive.git#fix.1",
|
||||||
|
"unified": "^11.0.0"
|
||||||
|
},
|
||||||
|
"description": "remark plugin to support directives",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^22.0.0",
|
||||||
|
"c8": "^10.0.0",
|
||||||
|
"is-hidden": "^2.0.0",
|
||||||
|
"prettier": "^3.0.0",
|
||||||
|
"remark": "^15.0.0",
|
||||||
|
"remark-cli": "^12.0.0",
|
||||||
|
"remark-preset-wooorm": "^10.0.0",
|
||||||
|
"to-vfile": "^8.0.0",
|
||||||
|
"type-coverage": "^2.0.0",
|
||||||
|
"typescript": "^5.0.0",
|
||||||
|
"xo": "^0.60.0"
|
||||||
|
},
|
||||||
|
"exports": "./index.js",
|
||||||
|
"files": ["index.d.ts", "index.js", "lib/"],
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
},
|
},
|
||||||
"author": "Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)",
|
"keywords": [
|
||||||
"contributors": [
|
"container",
|
||||||
"Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)"
|
"directive",
|
||||||
|
"generic",
|
||||||
|
"markdown",
|
||||||
|
"mdast",
|
||||||
|
"plugin",
|
||||||
|
"remark-plugin",
|
||||||
|
"remark",
|
||||||
|
"unified"
|
||||||
],
|
],
|
||||||
"types": "types/index.d.ts",
|
"license": "MIT",
|
||||||
"files": [
|
"name": "remark-directive",
|
||||||
"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": {
|
"prettier": {
|
||||||
"tabWidth": 2,
|
|
||||||
"useTabs": false,
|
|
||||||
"singleQuote": true,
|
|
||||||
"bracketSpacing": false,
|
"bracketSpacing": false,
|
||||||
|
"singleQuote": true,
|
||||||
"semi": false,
|
"semi": false,
|
||||||
"trailingComma": "none"
|
"tabWidth": 2,
|
||||||
},
|
"trailingComma": "none",
|
||||||
"xo": {
|
"useTabs": false
|
||||||
"prettier": true,
|
|
||||||
"esnext": false,
|
|
||||||
"rules": {
|
|
||||||
"unicorn/no-fn-reference-in-iterator": "off",
|
|
||||||
"unicorn/prefer-optional-catch-binding": "off"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"remarkConfig": {
|
"remarkConfig": {
|
||||||
"plugins": [
|
"plugins": ["remark-preset-wooorm"]
|
||||||
"preset-wooorm"
|
},
|
||||||
|
"repository": "remarkjs/remark-directive",
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc --build --clean && tsc --build && type-coverage",
|
||||||
|
"format": "remark --frail --output --quiet -- . && prettier --log-level warn --write -- . && xo --fix",
|
||||||
|
"prepack": "npm run build && npm run format",
|
||||||
|
"test-api": "node --conditions development test/index.js",
|
||||||
|
"test-coverage": "c8 --100 --reporter lcov -- npm run test-api",
|
||||||
|
"test": "npm run build && npm run format && npm run test-coverage"
|
||||||
|
},
|
||||||
|
"sideEffects": false,
|
||||||
|
"typeCoverage": {
|
||||||
|
"atLeast": 100,
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"version": "3.0.1",
|
||||||
|
"xo": {
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["**/*.d.ts"],
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/array-type": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"default": "generic"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/ban-types": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"extendDefaults": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/consistent-type-definitions": [
|
||||||
|
"error",
|
||||||
|
"interface"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["test/**/*.js"],
|
||||||
|
"rules": {
|
||||||
|
"no-await-in-loop": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prettier": true,
|
||||||
|
"rules": {
|
||||||
|
"logical-assignment-operators": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
499
readme.md
499
readme.md
|
@ -8,28 +8,86 @@
|
||||||
[![Backers][backers-badge]][collective]
|
[![Backers][backers-badge]][collective]
|
||||||
[![Chat][chat-badge]][chat]
|
[![Chat][chat-badge]][chat]
|
||||||
|
|
||||||
[**remark**][remark] plugin to support the [generic directives proposal][prop]
|
**[remark][]** plugin to support the [generic directives
|
||||||
(`:cite[smith04]`, `::youtube[Video of a cat in a box]{v=01ab2cd3efg}`, and
|
proposal][commonmark-prop] (`:cite[smith04]`,
|
||||||
such).
|
`::youtube[Video of a cat in a box]{v=01ab2cd3efg}`, and such).
|
||||||
|
|
||||||
## Important!
|
## Contents
|
||||||
|
|
||||||
This plugin is made for the new parser in remark
|
* [What is this?](#what-is-this)
|
||||||
([`micromark`](https://github.com/micromark/micromark),
|
* [When should I use this?](#when-should-i-use-this)
|
||||||
see [`remarkjs/remark#536`](https://github.com/remarkjs/remark/pull/536)).
|
* [Install](#install)
|
||||||
Use this plugin for remark 13+.
|
* [Use](#use)
|
||||||
|
* [API](#api)
|
||||||
|
* [`unified().use(remarkDirective[, options])`](#unifieduseremarkdirective-options)
|
||||||
|
* [`Options`](#options)
|
||||||
|
* [Examples](#examples)
|
||||||
|
* [Example: YouTube](#example-youtube)
|
||||||
|
* [Example: Styled blocks](#example-styled-blocks)
|
||||||
|
* [Authoring](#authoring)
|
||||||
|
* [HTML](#html)
|
||||||
|
* [CSS](#css)
|
||||||
|
* [Syntax](#syntax)
|
||||||
|
* [Syntax tree](#syntax-tree)
|
||||||
|
* [Types](#types)
|
||||||
|
* [Compatibility](#compatibility)
|
||||||
|
* [Security](#security)
|
||||||
|
* [Related](#related)
|
||||||
|
* [Contribute](#contribute)
|
||||||
|
* [License](#license)
|
||||||
|
|
||||||
|
## What is this?
|
||||||
|
|
||||||
|
This package is a [unified][] ([remark][]) plugin to add support for directives:
|
||||||
|
one syntax for arbitrary extensions in markdown.
|
||||||
|
|
||||||
|
## When should I use this?
|
||||||
|
|
||||||
|
Directives are one of the four ways to extend markdown: an arbitrary extension
|
||||||
|
syntax (see [Extending markdown][micromark-extending-markdown] in micromark’s
|
||||||
|
docs for the alternatives and more info).
|
||||||
|
This mechanism works well when you control the content: who authors it, what
|
||||||
|
tools handle it, and where it’s displayed.
|
||||||
|
When authors can read a guide on how to embed a tweet but are not expected to
|
||||||
|
know the ins and outs of HTML or JavaScript.
|
||||||
|
Directives don’t work well if you don’t know who authors content, what tools
|
||||||
|
handle it, and where it ends up.
|
||||||
|
Example use cases are a docs website for a project or product, or blogging
|
||||||
|
tools and static site generators.
|
||||||
|
|
||||||
|
If you *just* want to turn markdown into HTML (with maybe a few extensions such
|
||||||
|
as this one), we recommend [`micromark`][micromark] with
|
||||||
|
[`micromark-extension-directive`][micromark-extension-directive] instead.
|
||||||
|
If you don’t use plugins and want to access the syntax tree, you can use
|
||||||
|
[`mdast-util-from-markdown`][mdast-util-from-markdown] with
|
||||||
|
[`mdast-util-directive`][mdast-util-directive].
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
[npm][]:
|
This package is [ESM only][esm].
|
||||||
|
In Node.js (version 16+), install with [npm][]:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm install remark-directive
|
npm install remark-directive
|
||||||
```
|
```
|
||||||
|
|
||||||
|
In Deno with [`esm.sh`][esmsh]:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import remarkDirective from 'https://esm.sh/remark-directive@3'
|
||||||
|
```
|
||||||
|
|
||||||
|
In browsers with [`esm.sh`][esmsh]:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script type="module">
|
||||||
|
import remarkDirective from 'https://esm.sh/remark-directive@3?bundle'
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
## Use
|
## Use
|
||||||
|
|
||||||
Say we have the following file, `example.md`:
|
Say our document `example.md` contains:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
:::main{#readme}
|
:::main{#readme}
|
||||||
|
@ -44,58 +102,67 @@ A :i[lovely] language know as :abbr[HTML]{title="HyperText Markup Language"}.
|
||||||
:::
|
:::
|
||||||
```
|
```
|
||||||
|
|
||||||
And our script, `example.js`, looks as follows:
|
…and our module `example.js` contains:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var vfile = require('to-vfile')
|
/**
|
||||||
var report = require('vfile-reporter')
|
* @import {} from 'mdast-util-directive'
|
||||||
var unified = require('unified')
|
* @import {} from 'mdast-util-to-hast'
|
||||||
var parse = require('remark-parse')
|
* @import {Root} from 'mdast'
|
||||||
var directive = require('remark-directive')
|
*/
|
||||||
var remark2rehype = require('remark-rehype')
|
|
||||||
var format = require('rehype-format')
|
import {h} from 'hastscript'
|
||||||
var stringify = require('rehype-stringify')
|
import rehypeFormat from 'rehype-format'
|
||||||
var visit = require('unist-util-visit')
|
import rehypeStringify from 'rehype-stringify'
|
||||||
var h = require('hastscript')
|
import remarkDirective from 'remark-directive'
|
||||||
|
import remarkParse from 'remark-parse'
|
||||||
|
import remarkRehype from 'remark-rehype'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {unified} from 'unified'
|
||||||
|
import {visit} from 'unist-util-visit'
|
||||||
|
|
||||||
|
const file = await unified()
|
||||||
|
.use(remarkParse)
|
||||||
|
.use(remarkDirective)
|
||||||
|
.use(myRemarkPlugin)
|
||||||
|
.use(remarkRehype)
|
||||||
|
.use(rehypeFormat)
|
||||||
|
.use(rehypeStringify)
|
||||||
|
.process(await read('example.md'))
|
||||||
|
|
||||||
unified()
|
|
||||||
.use(parse)
|
|
||||||
.use(directive)
|
|
||||||
.use(htmlDirectives)
|
|
||||||
.use(remark2rehype)
|
|
||||||
.use(format)
|
|
||||||
.use(stringify)
|
|
||||||
.process(vfile.readSync('example.md'), function (err, file) {
|
|
||||||
console.error(report(err || file))
|
|
||||||
console.log(String(file))
|
console.log(String(file))
|
||||||
})
|
|
||||||
|
|
||||||
// This plugin is just an example! You can handle directives however you please!
|
// This plugin is an example to let users write HTML with directives.
|
||||||
function htmlDirectives() {
|
// It’s informative but rather useless.
|
||||||
return transform
|
// See below for others examples.
|
||||||
|
function myRemarkPlugin() {
|
||||||
function transform(tree) {
|
/**
|
||||||
visit(tree, ['textDirective', 'leafDirective', 'containerDirective'], ondirective)
|
* @param {Root} tree
|
||||||
}
|
* Tree.
|
||||||
|
* @returns {undefined}
|
||||||
function ondirective(node) {
|
* Nothing.
|
||||||
var data = node.data || (node.data = {})
|
*/
|
||||||
var hast = h(node.name, node.attributes)
|
return function (tree) {
|
||||||
|
visit(tree, function (node) {
|
||||||
|
if (
|
||||||
|
node.type === 'containerDirective' ||
|
||||||
|
node.type === 'leafDirective' ||
|
||||||
|
node.type === 'textDirective'
|
||||||
|
) {
|
||||||
|
const data = node.data || (node.data = {})
|
||||||
|
const hast = h(node.name, node.attributes || {})
|
||||||
|
|
||||||
data.hName = hast.tagName
|
data.hName = hast.tagName
|
||||||
data.hProperties = hast.properties
|
data.hProperties = hast.properties
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Now, running `node example` yields:
|
…then running `node example.js` yields:
|
||||||
|
|
||||||
```txt
|
|
||||||
example.md: no issues found
|
|
||||||
```
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
example.md: no issues found
|
|
||||||
<main id="readme">
|
<main id="readme">
|
||||||
<p>Lorem<br>ipsum.</p>
|
<p>Lorem<br>ipsum.</p>
|
||||||
<hr class="red">
|
<hr class="red">
|
||||||
|
@ -105,32 +172,284 @@ example.md: no issues found
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
### `remark().use(directive)`
|
This package exports no identifiers.
|
||||||
|
The default export is [`remarkDirective`][api-remark-directive].
|
||||||
|
|
||||||
Configures remark so that it can parse and serialize directives.
|
### `unified().use(remarkDirective[, options])`
|
||||||
Doesn’t handle the directives: [create your own plugin][create-plugin] to do
|
|
||||||
that.
|
Add support for generic directives.
|
||||||
See the [micromark extension for the syntax][syntax] and the
|
|
||||||
[mdast utility for the syntax tree][syntax-tree].
|
###### Parameters
|
||||||
|
|
||||||
|
* `options` ([`Options`][api-options], optional)
|
||||||
|
— configuration
|
||||||
|
|
||||||
|
###### Returns
|
||||||
|
|
||||||
|
Nothing (`undefined`).
|
||||||
|
|
||||||
|
###### Notes
|
||||||
|
|
||||||
|
Doesn’t handle the directives:
|
||||||
|
[create your own plugin][unified-create-plugin] to do that.
|
||||||
|
|
||||||
|
### `Options`
|
||||||
|
|
||||||
|
Configuration (TypeScript type).
|
||||||
|
|
||||||
|
###### Fields
|
||||||
|
|
||||||
|
* `collapseEmptyAttributes`
|
||||||
|
(`boolean`, default: `true`)
|
||||||
|
— collapse empty attributes: get `title` instead of `title=""`
|
||||||
|
* `preferShortcut`
|
||||||
|
(`boolean`, default: `true`)
|
||||||
|
— prefer `#` and `.` shortcuts for `id` and `class`
|
||||||
|
* `preferUnquoted`
|
||||||
|
(`boolean`, default: `false`)
|
||||||
|
— leave attributes unquoted if that results in less bytes
|
||||||
|
* `quoteSmart`
|
||||||
|
(`boolean`, default: `false`)
|
||||||
|
— use the other quote if that results in less bytes
|
||||||
|
* `quote`
|
||||||
|
(`'"'` or `"'"`,
|
||||||
|
default: the [`quote`][quote] used by `remark-stringify` for titles)
|
||||||
|
— preferred quote to use around attribute values
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Example: YouTube
|
||||||
|
|
||||||
|
This example shows how directives can be used for YouTube embeds.
|
||||||
|
It’s based on the example in Use above.
|
||||||
|
If `myRemarkPlugin` was replaced with this function:
|
||||||
|
|
||||||
|
```js
|
||||||
|
/**
|
||||||
|
* @import {} from 'mdast-util-directive'
|
||||||
|
* @import {} from 'mdast-util-to-hast'
|
||||||
|
* @import {Root} from 'mdast'
|
||||||
|
* @import {VFile} from 'vfile'
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {visit} from 'unist-util-visit'
|
||||||
|
|
||||||
|
// This plugin is an example to turn `::youtube` into iframes.
|
||||||
|
function myRemarkPlugin() {
|
||||||
|
/**
|
||||||
|
* @param {Root} tree
|
||||||
|
* Tree.
|
||||||
|
* @param {VFile} file
|
||||||
|
* File.
|
||||||
|
* @returns {undefined}
|
||||||
|
* Nothing.
|
||||||
|
*/
|
||||||
|
return (tree, file) => {
|
||||||
|
visit(tree, function (node) {
|
||||||
|
if (
|
||||||
|
node.type === 'containerDirective' ||
|
||||||
|
node.type === 'leafDirective' ||
|
||||||
|
node.type === 'textDirective'
|
||||||
|
) {
|
||||||
|
if (node.name !== 'youtube') return
|
||||||
|
|
||||||
|
const data = node.data || (node.data = {})
|
||||||
|
const attributes = node.attributes || {}
|
||||||
|
const id = attributes.id
|
||||||
|
|
||||||
|
if (node.type === 'textDirective') {
|
||||||
|
file.fail(
|
||||||
|
'Unexpected `:youtube` text directive, use two colons for a leaf directive',
|
||||||
|
node
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
file.fail('Unexpected missing `id` on `youtube` directive', node)
|
||||||
|
}
|
||||||
|
|
||||||
|
data.hName = 'iframe'
|
||||||
|
data.hProperties = {
|
||||||
|
src: 'https://www.youtube.com/embed/' + id,
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
frameBorder: 0,
|
||||||
|
allow: 'picture-in-picture',
|
||||||
|
allowFullScreen: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
…and `example.md` contains:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Cat videos
|
||||||
|
|
||||||
|
::youtube[Video of a cat in a box]{#01ab2cd3efg}
|
||||||
|
```
|
||||||
|
|
||||||
|
…then running `node example.js` yields:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<h1>Cat videos</h1>
|
||||||
|
<iframe src="https://www.youtube.com/embed/01ab2cd3efg" width="200" height="200" frameborder="0" allow="picture-in-picture" allowfullscreen>Video of a cat in a box</iframe>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example: Styled blocks
|
||||||
|
|
||||||
|
> 👉 **Note**: This is sometimes called admonitions, callouts, etc.
|
||||||
|
|
||||||
|
This example shows how directives can be used to style blocks.
|
||||||
|
It’s based on the example in Use above.
|
||||||
|
If `myRemarkPlugin` was replaced with this function:
|
||||||
|
|
||||||
|
```js
|
||||||
|
/**
|
||||||
|
* @import {} from 'mdast-util-directive'
|
||||||
|
* @import {} from 'mdast-util-to-hast'
|
||||||
|
* @import {Root} from 'mdast'
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {h} from 'hastscript'
|
||||||
|
import {visit} from 'unist-util-visit'
|
||||||
|
|
||||||
|
// This plugin is an example to turn `::note` into divs, passing arbitrary
|
||||||
|
// attributes.
|
||||||
|
function myRemarkPlugin() {
|
||||||
|
/**
|
||||||
|
* @param {Root} tree
|
||||||
|
* Tree.
|
||||||
|
* @returns {undefined}
|
||||||
|
* Nothing.
|
||||||
|
*/
|
||||||
|
return (tree) => {
|
||||||
|
visit(tree, (node) => {
|
||||||
|
if (
|
||||||
|
node.type === 'containerDirective' ||
|
||||||
|
node.type === 'leafDirective' ||
|
||||||
|
node.type === 'textDirective'
|
||||||
|
) {
|
||||||
|
if (node.name !== 'note') return
|
||||||
|
|
||||||
|
const data = node.data || (node.data = {})
|
||||||
|
const tagName = node.type === 'textDirective' ? 'span' : 'div'
|
||||||
|
|
||||||
|
data.hName = tagName
|
||||||
|
data.hProperties = h(tagName, node.attributes || {}).properties
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
…and `example.md` contains:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# How to use xxx
|
||||||
|
|
||||||
|
You can use xxx.
|
||||||
|
|
||||||
|
:::note{.warning}
|
||||||
|
if you chose xxx, you should also use yyy somewhere…
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
…then running `node example` yields:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<h1>How to use xxx</h1>
|
||||||
|
<p>You can use xxx.</p>
|
||||||
|
<div class="warning">
|
||||||
|
<p>if you chose xxx, you should also use yyy somewhere…</p>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Authoring
|
||||||
|
|
||||||
|
When authoring markdown with directives, keep in mind that they don’t work in
|
||||||
|
most places.
|
||||||
|
On your own site it can be great!
|
||||||
|
|
||||||
|
## HTML
|
||||||
|
|
||||||
|
You can define how directives are turned into HTML.
|
||||||
|
If directives are not handled, they do not emit anything.
|
||||||
|
|
||||||
|
## CSS
|
||||||
|
|
||||||
|
How to display directives is left as an exercise for the reader.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
See [*Syntax* in
|
||||||
|
`micromark-extension-directive`](https://github.com/micromark/micromark-extension-directive#syntax).
|
||||||
|
|
||||||
|
## Syntax tree
|
||||||
|
|
||||||
|
See [*Syntax tree* in
|
||||||
|
`mdast-util-directive`](https://github.com/syntax-tree/mdast-util-directive#syntax-tree).
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
This package is fully typed with [TypeScript][].
|
||||||
|
It exports no additional options.
|
||||||
|
|
||||||
|
If you’re working with the syntax tree, you can register the new node types
|
||||||
|
with `@types/mdast` by adding a reference:
|
||||||
|
|
||||||
|
```js
|
||||||
|
/**
|
||||||
|
* @import {} from 'mdast-util-directive'
|
||||||
|
* @import {Root} from 'mdast'
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {visit} from 'unist-util-visit'
|
||||||
|
|
||||||
|
function myRemarkPlugin() {
|
||||||
|
/**
|
||||||
|
* @param {Root} tree
|
||||||
|
* Tree.
|
||||||
|
* @returns {undefined}
|
||||||
|
* Nothing.
|
||||||
|
*/
|
||||||
|
return (tree) => {
|
||||||
|
visit(tree, function (node) {
|
||||||
|
console.log(node) // `node` can now be one of the nodes for directives.
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
Projects maintained by the unified collective are compatible with maintained
|
||||||
|
versions of Node.js.
|
||||||
|
|
||||||
|
When we cut a new major release, we drop support for unmaintained versions of
|
||||||
|
Node.
|
||||||
|
This means we try to keep the current release line, `remark-directive@^3`,
|
||||||
|
compatible with Node.js 16.
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
Use of `remark-directive` does not involve [**rehype**][rehype]
|
Use of `remark-directive` does not involve **[rehype][]** ([hast][]) or user
|
||||||
([**hast**][hast]) or user content so there are no openings for [cross-site
|
content so there are no openings for [cross-site scripting (XSS)][wiki-xss]
|
||||||
scripting (XSS)][xss] attacks.
|
attacks.
|
||||||
|
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
* [`remark-gfm`](https://github.com/remarkjs/remark-gfm)
|
* [`remark-gfm`](https://github.com/remarkjs/remark-gfm)
|
||||||
— GFM
|
— support GFM (autolink literals, footnotes, strikethrough, tables,
|
||||||
* [`remark-github`](https://github.com/remarkjs/remark-github)
|
tasklists)
|
||||||
— 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)
|
* [`remark-frontmatter`](https://github.com/remarkjs/remark-frontmatter)
|
||||||
— Frontmatter (YAML, TOML, and more)
|
— support frontmatter (YAML, TOML, and more)
|
||||||
* [`remark-math`](https://github.com/remarkjs/remark-math)
|
* [`remark-math`](https://github.com/remarkjs/remark-math)
|
||||||
— Math
|
— support math
|
||||||
|
* [`remark-mdx`](https://github.com/mdx-js/mdx/tree/main/packages/remark-mdx)
|
||||||
|
— support MDX (ESM, JSX, expressions)
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
|
|
||||||
|
@ -148,9 +467,9 @@ abide by its terms.
|
||||||
|
|
||||||
<!-- Definitions -->
|
<!-- Definitions -->
|
||||||
|
|
||||||
[build-badge]: https://img.shields.io/travis/remarkjs/remark-directive/main.svg
|
[build-badge]: https://github.com/remarkjs/remark-directive/workflows/main/badge.svg
|
||||||
|
|
||||||
[build]: https://travis-ci.org/remarkjs/remark-directive
|
[build]: https://github.com/remarkjs/remark-directive/actions
|
||||||
|
|
||||||
[coverage-badge]: https://img.shields.io/codecov/c/github/remarkjs/remark-directive.svg
|
[coverage-badge]: https://img.shields.io/codecov/c/github/remarkjs/remark-directive.svg
|
||||||
|
|
||||||
|
@ -160,9 +479,9 @@ abide by its terms.
|
||||||
|
|
||||||
[downloads]: https://www.npmjs.com/package/remark-directive
|
[downloads]: https://www.npmjs.com/package/remark-directive
|
||||||
|
|
||||||
[size-badge]: https://img.shields.io/bundlephobia/minzip/remark-directive.svg
|
[size-badge]: https://img.shields.io/bundlejs/size/remark-directive
|
||||||
|
|
||||||
[size]: https://bundlephobia.com/result?p=remark-directive
|
[size]: https://bundlejs.com/?q=remark-directive
|
||||||
|
|
||||||
[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
|
[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
|
||||||
|
|
||||||
|
@ -176,30 +495,50 @@ abide by its terms.
|
||||||
|
|
||||||
[npm]: https://docs.npmjs.com/cli/install
|
[npm]: https://docs.npmjs.com/cli/install
|
||||||
|
|
||||||
|
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
|
||||||
|
|
||||||
|
[esmsh]: https://esm.sh
|
||||||
|
|
||||||
[health]: https://github.com/remarkjs/.github
|
[health]: https://github.com/remarkjs/.github
|
||||||
|
|
||||||
[contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md
|
[contributing]: https://github.com/remarkjs/.github/blob/main/contributing.md
|
||||||
|
|
||||||
[support]: https://github.com/remarkjs/.github/blob/HEAD/support.md
|
[support]: https://github.com/remarkjs/.github/blob/main/support.md
|
||||||
|
|
||||||
[coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md
|
[coc]: https://github.com/remarkjs/.github/blob/main/code-of-conduct.md
|
||||||
|
|
||||||
[license]: license
|
[license]: license
|
||||||
|
|
||||||
[author]: https://wooorm.com
|
[author]: https://wooorm.com
|
||||||
|
|
||||||
[remark]: https://github.com/remarkjs/remark
|
[commonmark-prop]: https://talk.commonmark.org/t/generic-directives-plugins-syntax/444
|
||||||
|
|
||||||
[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
|
|
||||||
|
|
||||||
[rehype]: https://github.com/rehypejs/rehype
|
|
||||||
|
|
||||||
[hast]: https://github.com/syntax-tree/hast
|
[hast]: https://github.com/syntax-tree/hast
|
||||||
|
|
||||||
[prop]: https://talk.commonmark.org/t/generic-directives-plugins-syntax/444
|
[mdast-util-directive]: https://github.com/syntax-tree/mdast-util-directive
|
||||||
|
|
||||||
[create-plugin]: https://unifiedjs.com/learn/guide/create-a-plugin/
|
[mdast-util-from-markdown]: https://github.com/syntax-tree/mdast-util-from-markdown
|
||||||
|
|
||||||
[syntax]: https://github.com/micromark/micromark-extension-directive#syntax
|
[micromark]: https://github.com/micromark/micromark
|
||||||
|
|
||||||
[syntax-tree]: https://github.com/syntax-tree/mdast-util-directive#syntax-tree
|
[micromark-extension-directive]: https://github.com/micromark/micromark-extension-directive
|
||||||
|
|
||||||
|
[micromark-extending-markdown]: https://github.com/micromark/micromark#extending-markdown
|
||||||
|
|
||||||
|
[quote]: https://github.com/remarkjs/remark/tree/main/packages/remark-stringify#options
|
||||||
|
|
||||||
|
[rehype]: https://github.com/rehypejs/rehype
|
||||||
|
|
||||||
|
[remark]: https://github.com/remarkjs/remark
|
||||||
|
|
||||||
|
[typescript]: https://www.typescriptlang.org
|
||||||
|
|
||||||
|
[unified]: https://github.com/unifiedjs/unified
|
||||||
|
|
||||||
|
[unified-create-plugin]: https://unifiedjs.com/learn/guide/create-a-plugin/
|
||||||
|
|
||||||
|
[wiki-xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
|
||||||
|
|
||||||
|
[api-remark-directive]: #unifieduseremarkdirective-options
|
||||||
|
|
||||||
|
[api-options]: #options
|
||||||
|
|
111
test/index.js
111
test/index.js
|
@ -1,67 +1,78 @@
|
||||||
'use strict'
|
/**
|
||||||
|
* @typedef {import('mdast').Root} Root
|
||||||
|
*/
|
||||||
|
|
||||||
var fs = require('fs')
|
import assert from 'node:assert/strict'
|
||||||
var path = require('path')
|
import fs from 'node:fs/promises'
|
||||||
var test = require('tape')
|
import process from 'node:process'
|
||||||
var vfile = require('to-vfile')
|
import test from 'node:test'
|
||||||
var unified = require('unified')
|
import {isHidden} from 'is-hidden'
|
||||||
var remark = require('remark')
|
import {remark} from 'remark'
|
||||||
var not = require('not')
|
import remarkDirective from 'remark-directive'
|
||||||
var hidden = require('is-hidden')
|
|
||||||
var directive = require('..')
|
|
||||||
|
|
||||||
test('directive()', function (t) {
|
test('remarkDirective', async function (t) {
|
||||||
t.doesNotThrow(function () {
|
await t.test('should expose the public api', async function () {
|
||||||
remark().use(directive).freeze()
|
assert.deepEqual(Object.keys(await import('remark-directive')).sort(), [
|
||||||
}, 'should not throw if not passed options')
|
'default'
|
||||||
|
])
|
||||||
t.doesNotThrow(function () {
|
|
||||||
unified().use(directive).freeze()
|
|
||||||
}, 'should not throw if without parser or compiler')
|
|
||||||
|
|
||||||
t.end()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('fixtures', function (t) {
|
await t.test('should not throw if not passed options', async function () {
|
||||||
var base = path.join(__dirname, 'fixtures')
|
assert.doesNotThrow(function () {
|
||||||
var entries = fs.readdirSync(base).filter(not(hidden))
|
remark().use(remarkDirective).freeze()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
t.plan(entries.length)
|
test('fixtures', async function (t) {
|
||||||
|
const base = new URL('fixtures/', import.meta.url)
|
||||||
|
const folders = await fs.readdir(base)
|
||||||
|
|
||||||
entries.forEach(each)
|
let index = -1
|
||||||
|
|
||||||
function each(fixture) {
|
while (++index < folders.length) {
|
||||||
t.test(fixture, function (st) {
|
const folder = folders[index]
|
||||||
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()
|
if (isHidden(folder)) continue
|
||||||
actual = proc.parse(file)
|
|
||||||
|
await t.test(folder, async function () {
|
||||||
|
const folderUrl = new URL(folder + '/', base)
|
||||||
|
const inputUrl = new URL('input.md', folderUrl)
|
||||||
|
const outputUrl = new URL('output.md', folderUrl)
|
||||||
|
const treeUrl = new URL('tree.json', folderUrl)
|
||||||
|
|
||||||
|
const input = String(await fs.readFile(inputUrl))
|
||||||
|
|
||||||
|
/** @type {Root} */
|
||||||
|
let expected
|
||||||
|
/** @type {string} */
|
||||||
|
let output
|
||||||
|
|
||||||
|
const processor = remark().use(remarkDirective)
|
||||||
|
const actual = processor.parse(input)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
expected = JSON.parse(fs.readFileSync(treePath))
|
output = String(await fs.readFile(outputUrl))
|
||||||
} catch (_) {
|
} catch {
|
||||||
// New fixture.
|
|
||||||
fs.writeFileSync(treePath, JSON.stringify(actual, 0, 2) + '\n')
|
|
||||||
expected = actual
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
output = fs.readFileSync(outputPath, 'utf8')
|
|
||||||
} catch (_) {
|
|
||||||
output = input
|
output = input
|
||||||
}
|
}
|
||||||
|
|
||||||
st.deepEqual(actual, expected, 'tree')
|
try {
|
||||||
st.equal(String(proc.processSync(file)), output, 'process')
|
if ('UPDATE' in process.env) {
|
||||||
|
throw new Error('Updating…')
|
||||||
|
}
|
||||||
|
|
||||||
st.end()
|
expected = JSON.parse(String(await fs.readFile(treeUrl)))
|
||||||
|
} catch {
|
||||||
|
expected = actual
|
||||||
|
|
||||||
|
// New fixture.
|
||||||
|
await fs.writeFile(treeUrl, JSON.stringify(actual, undefined, 2) + '\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.deepEqual(actual, expected)
|
||||||
|
|
||||||
|
assert.equal(String(await processor.process(input)), String(output))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
16
tsconfig.json
Normal file
16
tsconfig.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"checkJs": true,
|
||||||
|
"customConditions": ["development"],
|
||||||
|
"declarationMap": true,
|
||||||
|
"declaration": true,
|
||||||
|
"emitDeclarationOnly": true,
|
||||||
|
"exactOptionalPropertyTypes": true,
|
||||||
|
"lib": ["es2022"],
|
||||||
|
"module": "node16",
|
||||||
|
"strict": true,
|
||||||
|
"target": "es2022"
|
||||||
|
},
|
||||||
|
"exclude": ["coverage/", "node_modules/"],
|
||||||
|
"include": ["**/*.js", "index.d.ts"]
|
||||||
|
}
|
11
types/index.d.ts
vendored
11
types/index.d.ts
vendored
|
@ -1,11 +0,0 @@
|
||||||
// TypeScript Version: 3.4
|
|
||||||
|
|
||||||
import {Plugin} from 'unified'
|
|
||||||
|
|
||||||
declare namespace remarkDirective {
|
|
||||||
type Directive = Plugin<[]>
|
|
||||||
}
|
|
||||||
|
|
||||||
declare const remarkDirective: remarkDirective.Directive
|
|
||||||
|
|
||||||
export = remarkDirective
|
|
|
@ -1,7 +0,0 @@
|
||||||
import unified = require('unified')
|
|
||||||
import directive = require('remark-directive')
|
|
||||||
|
|
||||||
unified().use(directive)
|
|
||||||
unified().use(directive)
|
|
||||||
|
|
||||||
unified().use(directive, {weird: true}) // $ExpectError
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"lib": ["es2015"],
|
|
||||||
"strict": true,
|
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
|
||||||
"remark-directive": ["index.d.ts"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"extends": "dtslint/dtslint.json",
|
|
||||||
"rules": {
|
|
||||||
"semicolon": false,
|
|
||||||
"whitespace": false
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue