├── .editorconfig ├── .github └── workflows │ ├── bb.yml │ └── main.yml ├── .gitignore ├── .npmrc ├── .prettierignore ├── index.js ├── lib └── index.js ├── license ├── package.json ├── readme.md ├── test.js └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /.github/workflows/bb.yml: -------------------------------------------------------------------------------- 1 | name: bb 2 | on: 3 | issues: 4 | types: [opened, reopened, edited, closed, labeled, unlabeled] 5 | pull_request_target: 6 | types: [opened, reopened, edited, closed, labeled, unlabeled] 7 | jobs: 8 | main: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: unifiedjs/beep-boop-beta@main 12 | with: 13 | repo-token: ${{secrets.GITHUB_TOKEN}} 14 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: main 2 | on: 3 | - pull_request 4 | - push 5 | jobs: 6 | main: 7 | name: ${{matrix.node}} 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v3 11 | - uses: actions/setup-node@v3 12 | with: 13 | node-version: ${{matrix.node}} 14 | - run: npm install 15 | - run: npm test 16 | - uses: codecov/codecov-action@v3 17 | strategy: 18 | matrix: 19 | node: 20 | - lts/gallium 21 | - node 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.d.ts 3 | *.log 4 | coverage/ 5 | node_modules/ 6 | yarn.lock 7 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | ignore-scripts=true 2 | package-lock=false 3 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | *.md 3 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @typedef {import('./lib/index.js').Marker} Marker 3 | * @typedef {import('./lib/index.js').MarkerParameterValue} MarkerParameterValue 4 | * @typedef {import('./lib/index.js').MarkerParameters} MarkerParameters 5 | */ 6 | 7 | export {commentMarker} from './lib/index.js' 8 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @typedef {import('mdast').Html} Html 3 | * @typedef {import('mdast').Nodes} Nodes 4 | * @typedef {import('mdast-util-mdx-expression').MdxFlowExpression} MdxFlowExpression 5 | * @typedef {import('mdast-util-mdx-expression').MdxTextExpression} MdxTextExpression 6 | */ 7 | 8 | /** 9 | * 10 | * @typedef {number | string | boolean} MarkerParameterValue 11 | * Value. 12 | * 13 | * If it looks like a number (to JavaScript), it’s cast as number. 14 | * The strings `true` and `false` are turned into their corresponding 15 | * booleans. 16 | * The empty string is also considered the `true` boolean. 17 | * @typedef {Record} MarkerParameters 18 | * Parameters. 19 | * 20 | * @typedef Marker 21 | * Comment marker. 22 | * @property {string} name 23 | * Name of marker. 24 | * @property {string} attributes 25 | * Value after name. 26 | * @property {MarkerParameters} parameters 27 | * Parsed attributes. 28 | * @property {Html | MdxFlowExpression | MdxTextExpression} node 29 | * Reference to given node. 30 | */ 31 | 32 | const commentExpression = /\s*([a-zA-Z\d-]+)(\s+([\s\S]*))?\s*/ 33 | const esCommentExpression = new RegExp( 34 | '(\\s*\\/\\*' + commentExpression.source + '\\*\\/\\s*)' 35 | ) 36 | const markerExpression = new RegExp( 37 | '(\\s*\\s*)' 38 | ) 39 | 40 | /** 41 | * Parse a comment marker. 42 | * 43 | * @param {unknown} value 44 | * Thing to parse, typically `Node`. 45 | * @returns {Marker | undefined} 46 | * Info when applicable or `undefined`. 47 | */ 48 | export function commentMarker(value) { 49 | if ( 50 | isNode(value) && 51 | (value.type === 'html' || 52 | value.type === 'mdxFlowExpression' || 53 | value.type === 'mdxTextExpression') 54 | ) { 55 | const match = value.value.match( 56 | value.type === 'html' ? markerExpression : esCommentExpression 57 | ) 58 | 59 | if (match && match[0].length === value.value.length) { 60 | const parameters = parseParameters(match[3] || '') 61 | 62 | if (parameters) { 63 | return { 64 | name: match[2], 65 | attributes: (match[4] || '').trim(), 66 | parameters, 67 | node: value 68 | } 69 | } 70 | } 71 | } 72 | } 73 | 74 | /** 75 | * Parse a string of “attributes”. 76 | * 77 | * @param {string} value 78 | * Attributes. 79 | * @returns {MarkerParameters | undefined} 80 | * Parameters. 81 | */ 82 | function parseParameters(value) { 83 | /** @type {MarkerParameters} */ 84 | const parameters = {} 85 | 86 | return value 87 | .replace( 88 | /\s+([-\w]+)(?:=(?:"((?:\\[\s\S]|[^"])*)"|'((?:\\[\s\S]|[^'])*)'|((?:\\[\s\S]|[^"'\s])+)))?/gi, 89 | replacer 90 | ) 91 | .replace(/\s+/g, '') 92 | ? undefined 93 | : parameters 94 | 95 | /** 96 | * @param {string} _ 97 | * @param {string} $1 98 | * @param {string} $2 99 | * @param {string} $3 100 | * @param {string} $4 101 | * @returns {string} 102 | */ 103 | // eslint-disable-next-line max-params 104 | function replacer(_, $1, $2, $3, $4) { 105 | /** @type {MarkerParameterValue} */ 106 | 107 | let value = $2 === undefined ? ($3 === undefined ? $4 : $3) : $2 108 | const number = Number(value) 109 | 110 | if (value === 'true' || value === undefined) { 111 | value = true 112 | } else if (value === 'false') { 113 | value = false 114 | } else if (value.trim() && !Number.isNaN(number)) { 115 | value = number 116 | } 117 | 118 | parameters[$1] = value 119 | 120 | return '' 121 | } 122 | } 123 | 124 | /** 125 | * Check if something looks like a node. 126 | * 127 | * @param {unknown} value 128 | * Thing. 129 | * @returns {value is Nodes} 130 | * It’s a node! 131 | */ 132 | function isNode(value) { 133 | return Boolean(value && typeof value === 'object' && 'type' in value) 134 | } 135 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2016 Titus Wormer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mdast-comment-marker", 3 | "version": "3.0.0", 4 | "description": "mdast utility to parse a comment marker", 5 | "license": "MIT", 6 | "keywords": [ 7 | "unist", 8 | "mdast", 9 | "mdast-util", 10 | "util", 11 | "utility", 12 | "marker", 13 | "comment" 14 | ], 15 | "repository": "syntax-tree/mdast-comment-marker", 16 | "bugs": "https://github.com/syntax-tree/mdast-comment-marker/issues", 17 | "funding": { 18 | "type": "opencollective", 19 | "url": "https://opencollective.com/unified" 20 | }, 21 | "author": "Titus Wormer (https://wooorm.com)", 22 | "contributors": [ 23 | "Titus Wormer (https://wooorm.com)", 24 | "Masayuki Izumi (http://izumin.info)" 25 | ], 26 | "sideEffects": false, 27 | "type": "module", 28 | "exports": "./index.js", 29 | "files": [ 30 | "lib/", 31 | "index.d.ts", 32 | "index.js" 33 | ], 34 | "dependencies": { 35 | "@types/mdast": "^4.0.0", 36 | "mdast-util-mdx-expression": "^2.0.0" 37 | }, 38 | "devDependencies": { 39 | "@types/node": "^20.0.0", 40 | "c8": "^8.0.0", 41 | "prettier": "^2.0.0", 42 | "remark-cli": "^11.0.0", 43 | "remark-preset-wooorm": "^9.0.0", 44 | "type-coverage": "^2.0.0", 45 | "typescript": "^5.0.0", 46 | "xo": "^0.54.0" 47 | }, 48 | "scripts": { 49 | "prepack": "npm run build && npm run format", 50 | "build": "tsc --build --clean && tsc --build && type-coverage", 51 | "format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", 52 | "test-api": "node --conditions development test.js", 53 | "test-coverage": "c8 --100 --reporter lcov npm run test-api", 54 | "test": "npm run build && npm run format && npm run test-coverage" 55 | }, 56 | "prettier": { 57 | "bracketSpacing": false, 58 | "semi": false, 59 | "singleQuote": true, 60 | "tabWidth": 2, 61 | "trailingComma": "none", 62 | "useTabs": false 63 | }, 64 | "remarkConfig": { 65 | "plugins": [ 66 | "remark-preset-wooorm" 67 | ] 68 | }, 69 | "typeCoverage": { 70 | "atLeast": 100, 71 | "detail": true, 72 | "ignoreCatch": true, 73 | "strict": true 74 | }, 75 | "xo": { 76 | "prettier": true 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # mdast-comment-marker 2 | 3 | [![Build][build-badge]][build] 4 | [![Coverage][coverage-badge]][coverage] 5 | [![Downloads][downloads-badge]][downloads] 6 | [![Size][size-badge]][size] 7 | [![Sponsors][sponsors-badge]][collective] 8 | [![Backers][backers-badge]][collective] 9 | [![Chat][chat-badge]][chat] 10 | 11 | [mdast][] utility to parse comment markers. 12 | 13 | ## Contents 14 | 15 | * [What is this?](#what-is-this) 16 | * [When should I use this?](#when-should-i-use-this) 17 | * [Install](#install) 18 | * [Use](#use) 19 | * [API](#api) 20 | * [`commentMarker(value)`](#commentmarkervalue) 21 | * [`Marker`](#marker) 22 | * [`MarkerParameters`](#markerparameters) 23 | * [`MarkerParameterValue`](#markerparametervalue) 24 | * [Types](#types) 25 | * [Compatibility](#compatibility) 26 | * [Security](#security) 27 | * [Related](#related) 28 | * [Contribute](#contribute) 29 | * [License](#license) 30 | 31 | ## What is this? 32 | 33 | This package is a utility that tries to parse a structured marker from a 34 | comment. 35 | 36 | ## When should I use this? 37 | 38 | Comments are a hidden part of markdown, so they can be used as processing 39 | instructions. 40 | For example, this utility is used in [`remark-lint`][remark-lint] to control 41 | whether lint rules are turned on or ignored, and by [`mdast-zone`][mdast-zone] 42 | to replace sections between two markers. 43 | 44 | ## Install 45 | 46 | This package is [ESM only][esm]. 47 | In Node.js (version 16+), install with [npm][]: 48 | 49 | ```sh 50 | npm install mdast-comment-marker 51 | ``` 52 | 53 | In Deno with [`esm.sh`][esmsh]: 54 | 55 | ```js 56 | import {commentMarker} from 'https://esm.sh/mdast-comment-marker@3' 57 | ``` 58 | 59 | In browsers with [`esm.sh`][esmsh]: 60 | 61 | ```html 62 | 65 | ``` 66 | 67 | ## Use 68 | 69 | ```js 70 | import {commentMarker} from 'mdast-comment-marker' 71 | 72 | console.log(commentMarker({type: 'html', value: ''})); 73 | 74 | console.log(commentMarker({ 75 | type: 'html', 76 | value: '' 77 | })); 78 | 79 | console.log(commentMarker({type: 'html', value: ''})); 80 | 81 | // Also supports MDX expressions: 82 | console.log(commentMarker({ 83 | type: 'mdxFlowExpression', 84 | value: '/* lint disable heading-style */' 85 | })); 86 | ``` 87 | 88 | Yields: 89 | 90 | ```js 91 | { 92 | name: 'foo', 93 | attributes: '', 94 | parameters: {}, 95 | node: { type: 'html', value: '' } 96 | } 97 | { 98 | name: 'foo', 99 | attributes: `bar baz=12.4 qux="test test" quux='false'`, 100 | parameters: { bar: true, baz: 12.4, qux: 'test test', quux: false }, 101 | node: { 102 | type: 'html', 103 | value: `` 104 | } 105 | } 106 | undefined 107 | { 108 | name: 'lint', 109 | attributes: 'disable heading-style', 110 | parameters: { disable: true, 'heading-style': true }, 111 | node: { 112 | type: 'mdxFlowExpression', 113 | value: '/* lint disable heading-style */' 114 | } 115 | } 116 | ``` 117 | 118 | ## API 119 | 120 | This package exports the identifier [`commentMarker`][api-comment-marker]. 121 | There is no default export. 122 | 123 | ### `commentMarker(value)` 124 | 125 | Parse a comment marker. 126 | 127 | ###### Parameters 128 | 129 | * `value` (`unknown`) 130 | — thing to parse, typically [`Node`][node] 131 | 132 | ###### Returns 133 | 134 | Info ([`Marker`][api-marker]) when applicable or `undefined`. 135 | 136 | ### `Marker` 137 | 138 | Comment marker (TypeScript type). 139 | 140 | ###### Properties 141 | 142 | * `name` (`string`) 143 | — name of marker 144 | * `attributes` (`string`) 145 | — value after name 146 | * `parameters` ([`MarkerParameters`][api-marker-parameters]) 147 | — parsed attributes 148 | * `node` ([`Node`][node]) 149 | — reference to given node 150 | 151 | ### `MarkerParameters` 152 | 153 | Parameters (TypeScript type). 154 | 155 | ###### type 156 | 157 | ```ts 158 | type MarkerParameters = Record 159 | ``` 160 | 161 | ### `MarkerParameterValue` 162 | 163 | Value (TypeScript type). 164 | 165 | If it looks like a number (to JavaScript), it’s cast as number. 166 | The strings `true` and `false` are turned into their corresponding 167 | booleans. 168 | The empty string is also considered the `true` boolean. 169 | 170 | ###### type 171 | 172 | ```ts 173 | type MarkerParameterValue = number | string | boolean 174 | ``` 175 | 176 | ## Types 177 | 178 | This package is fully typed with [TypeScript][]. 179 | This package exports the types [`Marker`][api-marker], 180 | [`MarkerParameters`][api-marker-parameters], and 181 | [`MarkerParameterValue`][api-marker-parameter-value] 182 | 183 | ## Compatibility 184 | 185 | Projects maintained by the unified collective are compatible with maintained 186 | versions of Node.js. 187 | 188 | When we cut a new major release, we drop support for unmaintained versions of 189 | Node. 190 | This means we try to keep the current release line, `mdast-comment-marker@^3`, 191 | compatible with Node.js 16. 192 | 193 | ## Security 194 | 195 | Use of `mdast-comment-marker` does not involve [hast][], user content, or change 196 | the tree, so there are no openings for [cross-site scripting (XSS)][xss] 197 | attacks. 198 | 199 | ## Related 200 | 201 | * [`mdast-zone`](https://github.com/syntax-tree/mdast-zone) 202 | — change or replace a section marked by comments 203 | 204 | ## Contribute 205 | 206 | See [`contributing.md`][contributing] in [`syntax-tree/.github`][health] for 207 | ways to get started. 208 | See [`support.md`][support] for ways to get help. 209 | 210 | This project has a [code of conduct][coc]. 211 | By interacting with this repository, organization, or community you agree to 212 | abide by its terms. 213 | 214 | ## License 215 | 216 | [MIT][license] © [Titus Wormer][author] 217 | 218 | 219 | 220 | [build-badge]: https://github.com/syntax-tree/mdast-comment-marker/workflows/main/badge.svg 221 | 222 | [build]: https://github.com/syntax-tree/mdast-comment-marker/actions 223 | 224 | [coverage-badge]: https://img.shields.io/codecov/c/github/syntax-tree/mdast-comment-marker.svg 225 | 226 | [coverage]: https://codecov.io/github/syntax-tree/mdast-comment-marker 227 | 228 | [downloads-badge]: https://img.shields.io/npm/dm/mdast-comment-marker.svg 229 | 230 | [downloads]: https://www.npmjs.com/package/mdast-comment-marker 231 | 232 | [size-badge]: https://img.shields.io/badge/dynamic/json?label=minzipped%20size&query=$.size.compressedSize&url=https://deno.bundlejs.com/?q=mdast-comment-marker 233 | 234 | [size]: https://bundlejs.com/?q=mdast-comment-marker 235 | 236 | [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg 237 | 238 | [backers-badge]: https://opencollective.com/unified/backers/badge.svg 239 | 240 | [collective]: https://opencollective.com/unified 241 | 242 | [chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg 243 | 244 | [chat]: https://github.com/syntax-tree/unist/discussions 245 | 246 | [npm]: https://docs.npmjs.com/cli/install 247 | 248 | [esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c 249 | 250 | [esmsh]: https://esm.sh 251 | 252 | [typescript]: https://www.typescriptlang.org 253 | 254 | [license]: license 255 | 256 | [author]: https://wooorm.com 257 | 258 | [health]: https://github.com/syntax-tree/.github 259 | 260 | [contributing]: https://github.com/syntax-tree/.github/blob/main/contributing.md 261 | 262 | [support]: https://github.com/syntax-tree/.github/blob/main/support.md 263 | 264 | [coc]: https://github.com/syntax-tree/.github/blob/main/code-of-conduct.md 265 | 266 | [mdast]: https://github.com/syntax-tree/mdast 267 | 268 | [node]: https://github.com/syntax-tree/unist#node 269 | 270 | [xss]: https://en.wikipedia.org/wiki/Cross-site_scripting 271 | 272 | [hast]: https://github.com/syntax-tree/hast 273 | 274 | [remark-lint]: https://github.com/remarkjs/remark-lint 275 | 276 | [mdast-zone]: https://github.com/syntax-tree/mdast-zone 277 | 278 | [api-comment-marker]: #commentmarkervalue 279 | 280 | [api-marker]: #marker 281 | 282 | [api-marker-parameters]: #markerparameters 283 | 284 | [api-marker-parameter-value]: #markerparametervalue 285 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict' 2 | import test from 'node:test' 3 | import {commentMarker} from 'mdast-comment-marker' 4 | 5 | test('commentMaker', async function (t) { 6 | await t.test('should expose the public api', async function () { 7 | assert.deepEqual(Object.keys(await import('mdast-comment-marker')).sort(), [ 8 | 'commentMarker' 9 | ]) 10 | }) 11 | 12 | await t.test('should work without node', async function () { 13 | assert.equal( 14 | // @ts-expect-error: check that the runtime handles a missing node. 15 | commentMarker(), 16 | undefined 17 | ) 18 | }) 19 | 20 | await t.test('should work without html node', async function () { 21 | const paragraph = {type: 'paragraph', children: []} 22 | 23 | assert.equal(commentMarker(paragraph), undefined) 24 | }) 25 | 26 | await t.test('should work without comment', async function () { 27 | const html = {type: 'html', value: '
'} 28 | 29 | assert.equal(commentMarker(html), undefined) 30 | }) 31 | 32 | await t.test('should work for empty comments', async function () { 33 | const html = {type: 'html', value: ''} 34 | 35 | assert.equal(commentMarker(html), undefined) 36 | }) 37 | 38 | await t.test('should work for partial comments', async function () { 39 | const html = {type: 'html', value: 'this is something else.'} 40 | 41 | assert.equal(commentMarker(html), undefined) 42 | }) 43 | 44 | await t.test('should support a marker without attributes', async function () { 45 | const html = {type: 'html', value: ''} 46 | 47 | assert.deepEqual(commentMarker(html), { 48 | name: 'foo', 49 | attributes: '', 50 | parameters: {}, 51 | node: html 52 | }) 53 | }) 54 | 55 | await t.test( 56 | 'should support a marker without attributes ignoring spaces', 57 | async function () { 58 | const html = {type: 'html', value: ''} 59 | 60 | assert.deepEqual(commentMarker(html), { 61 | name: 'foo', 62 | attributes: '', 63 | parameters: {}, 64 | node: html 65 | }) 66 | } 67 | ) 68 | 69 | await t.test( 70 | 'should support a marker with boolean attributes', 71 | async function () { 72 | const html = {type: 'html', value: ''} 73 | 74 | assert.deepEqual(commentMarker(html), { 75 | name: 'foo', 76 | attributes: 'bar', 77 | parameters: {bar: true}, 78 | node: html 79 | }) 80 | } 81 | ) 82 | 83 | await t.test( 84 | 'should support a marker with unquoted attributes', 85 | async function () { 86 | const html = {type: 'html', value: ''} 87 | 88 | assert.deepEqual(commentMarker(html), { 89 | name: 'foo', 90 | attributes: 'bar=baz qux', 91 | parameters: {bar: 'baz', qux: true}, 92 | node: html 93 | }) 94 | } 95 | ) 96 | 97 | await t.test( 98 | 'should support a marker with double quoted attributes', 99 | async function () { 100 | const html = {type: 'html', value: ''} 101 | 102 | assert.deepEqual(commentMarker(html), { 103 | name: 'foo', 104 | attributes: 'bar="baz qux"', 105 | parameters: {bar: 'baz qux'}, 106 | node: html 107 | }) 108 | } 109 | ) 110 | 111 | await t.test( 112 | 'should support a marker with single quoted attributes', 113 | async function () { 114 | const html = {type: 'html', value: ""} 115 | 116 | assert.deepEqual(commentMarker(html), { 117 | name: 'foo', 118 | attributes: "bar='baz qux'", 119 | parameters: {bar: 'baz qux'}, 120 | node: html 121 | }) 122 | } 123 | ) 124 | 125 | await t.test('should support a marker with numbers', async function () { 126 | const html = {type: 'html', value: ''} 127 | 128 | assert.deepEqual(commentMarker(html), { 129 | name: 'foo', 130 | attributes: 'bar=3', 131 | parameters: {bar: 3}, 132 | node: html 133 | }) 134 | }) 135 | 136 | await t.test('should support a marker with boolean true', async function () { 137 | const html = {type: 'html', value: ''} 138 | 139 | assert.deepEqual(commentMarker(html), { 140 | name: 'foo', 141 | attributes: 'bar=true', 142 | parameters: {bar: true}, 143 | node: html 144 | }) 145 | }) 146 | 147 | await t.test('should support a marker with boolean false', async function () { 148 | const html = {type: 'html', value: ''} 149 | 150 | assert.deepEqual(commentMarker(html), { 151 | name: 'foo', 152 | attributes: 'bar=false', 153 | parameters: {bar: false}, 154 | node: html 155 | }) 156 | }) 157 | 158 | await t.test( 159 | 'should support a marker stop for invalid parameters (#1)', 160 | async function () { 161 | const html = {type: 'html', value: ''} 162 | 163 | assert.equal(commentMarker(html), undefined) 164 | } 165 | ) 166 | 167 | await t.test( 168 | 'should support a marker stop for invalid parameters (#2)', 169 | async function () { 170 | const html = {type: 'html', value: ''} 171 | 172 | assert.equal(commentMarker(html), undefined) 173 | } 174 | ) 175 | 176 | await t.test( 177 | 'should support a marker stop for invalid parameters (#3)', 178 | async function () { 179 | const html = {type: 'html', value: ''} 180 | 181 | assert.equal(commentMarker(html), undefined) 182 | } 183 | ) 184 | 185 | await t.test( 186 | 'should support a marker with empty string attribute', 187 | async function () { 188 | const html = {type: 'html', value: ''} 189 | 190 | assert.deepEqual(commentMarker(html), { 191 | name: 'foo', 192 | attributes: 'bar=""', 193 | parameters: {bar: ''}, 194 | node: html 195 | }) 196 | } 197 | ) 198 | 199 | await t.test( 200 | 'should support a marker with whitespace attribute', 201 | async function () { 202 | const html = {type: 'html', value: ''} 203 | 204 | assert.deepEqual(commentMarker(html), { 205 | name: 'foo', 206 | attributes: 'bar=" "', 207 | parameters: {bar: ' '}, 208 | node: html 209 | }) 210 | } 211 | ) 212 | }) 213 | 214 | test('MDX@2 expressions', async function (t) { 215 | await t.test('should work for comments', async function () { 216 | const node = { 217 | type: 'mdxFlowExpression', 218 | value: '/* lint disable heading-style */' 219 | } 220 | 221 | assert.deepEqual(commentMarker(node), { 222 | name: 'lint', 223 | attributes: 'disable heading-style', 224 | parameters: {disable: true, 'heading-style': true}, 225 | node 226 | }) 227 | }) 228 | 229 | await t.test('should work for comments', async function () { 230 | const node = {type: 'mdxTextExpression', value: '/* lint enable */'} 231 | 232 | assert.deepEqual(commentMarker(node), { 233 | name: 'lint', 234 | attributes: 'enable', 235 | parameters: {enable: true}, 236 | node 237 | }) 238 | }) 239 | }) 240 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "checkJs": true, 4 | "customConditions": ["development"], 5 | "declaration": true, 6 | "emitDeclarationOnly": true, 7 | "exactOptionalPropertyTypes": true, 8 | "lib": ["es2022"], 9 | "module": "node16", 10 | "strict": true, 11 | "target": "es2022" 12 | }, 13 | "exclude": ["coverage/", "node_modules/"], 14 | "include": ["**/*.js"] 15 | } 16 | --------------------------------------------------------------------------------