unified-message-control
Advanced tools
Comparing version 3.0.3 to 4.0.0
205
index.d.ts
@@ -1,116 +0,103 @@ | ||
// TypeScript Version: 3.4 | ||
import {Node} from 'unist' | ||
import {Transformer} from 'unified' | ||
import {Test} from 'unist-util-is' | ||
declare namespace messageControl { | ||
/** | ||
* @type {import('unified').Plugin<[Options]>} | ||
* @returns {(tree: Node, file: VFile) => void} | ||
*/ | ||
export default function messageControl( | ||
options: Options | ||
): (tree: Node, file: VFile) => void | ||
export type Node = import('unist').Node | ||
export type Parent = import('unist').Parent | ||
export type Point = import('unist').Point | ||
export type Test = import('unist-util-is').Test | ||
export type VFile = import('vfile').VFile | ||
export type VFileMessage = import('vfile-message').VFileMessage | ||
export type Options = OptionsWithoutReset | OptionsWithReset | ||
export type OptionsWithoutReset = OptionsBaseFields & OptionsWithoutResetFields | ||
export type OptionsWithReset = OptionsBaseFields & OptionsWithResetFields | ||
export type OptionsWithoutResetFields = { | ||
/** | ||
* A comment marker. | ||
* Whether to treat all messages as turned off initially. | ||
*/ | ||
interface Marker<N extends Node> { | ||
/** | ||
* Name of marker | ||
*/ | ||
name: string | ||
/** | ||
* Value after name | ||
*/ | ||
attributes: string | ||
/** | ||
* Parsed attributes | ||
*/ | ||
parameters: Record<string, unknown> | ||
/** | ||
* Reference to given node | ||
*/ | ||
node: N | ||
} | ||
reset?: false | undefined | ||
/** | ||
* Parse a possible comment marker node to a Marker | ||
* List of `ruleId`s to turn off. | ||
*/ | ||
type MarkerParser<N extends Node> = (node: N) => Marker<N> | null | ||
interface MessageControlOptionsWithReset<T extends Node> | ||
extends BaseMessageControlOptions<T> { | ||
/** | ||
* Whether to treat all messages as turned off initially | ||
*/ | ||
reset: true | ||
/** | ||
* List of `ruleId`s to initially turn on. | ||
*/ | ||
enable?: string[] | ||
} | ||
interface MessageControlOptionsWithoutReset<T extends Node> | ||
extends BaseMessageControlOptions<T> { | ||
/** | ||
* Whether to treat all messages as turned off initially | ||
*/ | ||
reset?: false | ||
/** | ||
* List of `ruleId`s to turn off | ||
*/ | ||
disable?: string[] | ||
} | ||
interface BaseMessageControlOptions<T extends Node> { | ||
/** | ||
* Name of markers that can control the message sources. | ||
* | ||
* For example. `{name: 'alpha'}` controls `alpha` markers: | ||
* | ||
* `<!--alpha ignore-->` | ||
*/ | ||
name: string | ||
/** | ||
* Test for possible markers | ||
*/ | ||
test: Test<T> | ||
/** | ||
* Parse a possible marker to a comment marker object (Marker) | ||
* if possible the marker isn't a marker, should return `null`. | ||
*/ | ||
marker: MarkerParser<T> | ||
/** | ||
* List of allowed `ruleId`s. When given a warning is shown | ||
* when someone tries to control an unknown rule. | ||
* | ||
* For example, `{name: 'alpha', known: ['bravo']}` results | ||
* in a warning if `charlie is configured: | ||
* | ||
* `<!--alpha ignore charlie-->` | ||
*/ | ||
known?: string[] | ||
/** | ||
* Sources that can be controlled with `name` markers. | ||
* | ||
* @defaultValue `MessageControlOptions.name` | ||
*/ | ||
sources?: string | string[] | ||
} | ||
type MessageControlOptions<T extends Node> = | ||
| MessageControlOptionsWithoutReset<T> | ||
| MessageControlOptionsWithReset<T> | ||
disable?: string[] | undefined | ||
} | ||
export type OptionsWithResetFields = { | ||
/** | ||
* Whether to treat all messages as turned off initially. | ||
*/ | ||
reset: true | ||
/** | ||
* List of `ruleId`s to initially turn on. | ||
*/ | ||
enable?: string[] | undefined | ||
} | ||
export type OptionsBaseFields = { | ||
/** | ||
* Name of markers that can control the message sources. | ||
* | ||
* For example, `{name: 'alpha'}` controls `alpha` markers: | ||
* | ||
* ```html | ||
* <!--alpha ignore--> | ||
* ``` | ||
*/ | ||
name: string | ||
/** | ||
* Parse a possible marker to a comment marker object (Marker). | ||
* If the marker isn't a marker, should return `null`. | ||
*/ | ||
marker: MarkerParser | ||
/** | ||
* Test for possible markers | ||
*/ | ||
test?: Test | ||
/** | ||
* List of allowed `ruleId`s. When given a warning is shown | ||
* when someone tries to control an unknown rule. | ||
* | ||
* For example, `{name: 'alpha', known: ['bravo']}` results in a warning if | ||
* `charlie` is configured: | ||
* | ||
* ```html | ||
* <!--alpha ignore charlie--> | ||
* ``` | ||
*/ | ||
known?: string[] | undefined | ||
/** | ||
* Sources that can be controlled with `name` markers. | ||
* Defaults to `name`. | ||
*/ | ||
source?: string | string[] | undefined | ||
} | ||
/** | ||
* Enable, disable, and ignore messages with unified. | ||
* Parse a possible comment marker node to a Marker. | ||
*/ | ||
declare function messageControl<T extends Node>( | ||
options?: messageControl.MessageControlOptions<T> | ||
): Transformer | ||
export = messageControl | ||
export type MarkerParser = (node: Node) => any | ||
/** | ||
* A comment marker. | ||
*/ | ||
export type Marker = { | ||
/** | ||
* Name of marker. | ||
*/ | ||
name: string | ||
/** | ||
* Value after name. | ||
*/ | ||
attributes: string | ||
/** | ||
* Parsed attributes. | ||
*/ | ||
parameters: Record<string, string | number | boolean> | ||
/** | ||
* Reference to given node. | ||
*/ | ||
node: Node | ||
} | ||
export type Mark = { | ||
point: Point | undefined | ||
state: boolean | ||
} |
341
index.js
@@ -1,66 +0,148 @@ | ||
'use strict' | ||
/** | ||
* @typedef {import('unist').Node} Node | ||
* @typedef {import('unist').Parent} Parent | ||
* @typedef {import('unist').Point} Point | ||
* @typedef {import('unist-util-is').Test} Test | ||
* @typedef {import('vfile').VFile} VFile | ||
* @typedef {import('vfile-message').VFileMessage} VFileMessage | ||
* | ||
* @typedef {OptionsWithoutReset|OptionsWithReset} Options | ||
* @typedef {OptionsBaseFields & OptionsWithoutResetFields} OptionsWithoutReset | ||
* @typedef {OptionsBaseFields & OptionsWithResetFields} OptionsWithReset | ||
* | ||
* @typedef OptionsWithoutResetFields | ||
* @property {false} [reset] | ||
* Whether to treat all messages as turned off initially. | ||
* @property {string[]} [disable] | ||
* List of `ruleId`s to turn off. | ||
* | ||
* @typedef OptionsWithResetFields | ||
* @property {true} reset | ||
* Whether to treat all messages as turned off initially. | ||
* @property {string[]} [enable] | ||
* List of `ruleId`s to initially turn on. | ||
* | ||
* @typedef OptionsBaseFields | ||
* @property {string} name | ||
* Name of markers that can control the message sources. | ||
* | ||
* For example, `{name: 'alpha'}` controls `alpha` markers: | ||
* | ||
* ```html | ||
* <!--alpha ignore--> | ||
* ``` | ||
* @property {MarkerParser} marker | ||
* Parse a possible marker to a comment marker object (Marker). | ||
* If the marker isn't a marker, should return `null`. | ||
* @property {Test} [test] | ||
* Test for possible markers | ||
* @property {string[]} [known] | ||
* List of allowed `ruleId`s. When given a warning is shown | ||
* when someone tries to control an unknown rule. | ||
* | ||
* For example, `{name: 'alpha', known: ['bravo']}` results in a warning if | ||
* `charlie` is configured: | ||
* | ||
* ```html | ||
* <!--alpha ignore charlie--> | ||
* ``` | ||
* @property {string|string[]} [source] | ||
* Sources that can be controlled with `name` markers. | ||
* Defaults to `name`. | ||
* | ||
* @callback MarkerParser | ||
* Parse a possible comment marker node to a Marker. | ||
* @param {Node} node | ||
* Node to parse | ||
* | ||
* @typedef Marker | ||
* A comment marker. | ||
* @property {string} name | ||
* Name of marker. | ||
* @property {string} attributes | ||
* Value after name. | ||
* @property {Record<string, string|number|boolean>} parameters | ||
* Parsed attributes. | ||
* @property {Node} node | ||
* Reference to given node. | ||
* | ||
* @typedef Mark | ||
* @property {Point|undefined} point | ||
* @property {boolean} state | ||
*/ | ||
var location = require('vfile-location') | ||
var visit = require('unist-util-visit') | ||
import {location} from 'vfile-location' | ||
import {visit} from 'unist-util-visit' | ||
module.exports = messageControl | ||
const own = {}.hasOwnProperty | ||
function messageControl(options) { | ||
var settings = options || {} | ||
var enable = settings.enable || [] | ||
var disable = settings.disable || [] | ||
var sources = settings.source | ||
var reset = settings.reset | ||
if (!settings.name) { | ||
throw new Error('Expected `name` in `options`, got `' + settings.name + '`') | ||
/** | ||
* @type {import('unified').Plugin<[Options]>} | ||
* @returns {(tree: Node, file: VFile) => void} | ||
*/ | ||
export default function messageControl(options) { | ||
if (!options || typeof options !== 'object' || !options.name) { | ||
throw new Error( | ||
'Expected `name` in `options`, got `' + (options || {}).name + '`' | ||
) | ||
} | ||
if (!settings.marker) { | ||
if (!options.marker) { | ||
throw new Error( | ||
'Expected `marker` in `options`, got `' + settings.marker + '`' | ||
'Expected `marker` in `options`, got `' + options.marker + '`' | ||
) | ||
} | ||
if (!sources) { | ||
sources = [settings.name] | ||
} else if (typeof sources === 'string') { | ||
sources = [sources] | ||
} | ||
const enable = 'enable' in options && options.enable ? options.enable : [] | ||
const disable = 'disable' in options && options.disable ? options.disable : [] | ||
let reset = options.reset | ||
const sources = | ||
typeof options.source === 'string' | ||
? [options.source] | ||
: options.source || [options.name] | ||
return transformer | ||
/** | ||
* @param {Node} tree | ||
* @param {VFile} file | ||
*/ | ||
function transformer(tree, file) { | ||
var toOffset = location(file).toOffset | ||
var initial = !reset | ||
var gaps = detectGaps(tree, file) | ||
var scope = {} | ||
var globals = [] | ||
const toOffset = location(file).toOffset | ||
const initial = !reset | ||
const gaps = detectGaps(tree, file) | ||
/** @type {Record<string, Mark[]>} */ | ||
const scope = {} | ||
/** @type {Mark[]} */ | ||
const globals = [] | ||
visit(tree, settings.test, visitor) | ||
visit(tree, options.test, visitor) | ||
file.messages = file.messages.filter(filter) | ||
file.messages = file.messages.filter((m) => filter(m)) | ||
/** | ||
* @param {Node} node | ||
* @param {number|null} position | ||
* @param {Parent|null} parent | ||
*/ | ||
function visitor(node, position, parent) { | ||
var mark = settings.marker(node) | ||
var ruleIds | ||
var verb | ||
var pos | ||
var tail | ||
var index | ||
var ruleId | ||
/** @type {Marker|null} */ | ||
const mark = options.marker(node) | ||
if (!mark || mark.name !== settings.name) { | ||
if (!mark || mark.name !== options.name) { | ||
return | ||
} | ||
ruleIds = mark.attributes.split(/\s/g) | ||
verb = ruleIds.shift() | ||
pos = mark.node.position && mark.node.position.start | ||
tail = | ||
parent.children[position + 1] && | ||
parent.children[position + 1].position && | ||
parent.children[position + 1].position.end | ||
index = -1 | ||
const ruleIds = mark.attributes.split(/\s/g) | ||
const point = mark.node.position && mark.node.position.start | ||
const next = | ||
(parent && position !== null && parent.children[position + 1]) || | ||
undefined | ||
const tail = (next && next.position && next.position.end) || undefined | ||
let index = -1 | ||
/** @type {string} */ | ||
// @ts-expect-error: we’ll check for unknown values next. | ||
const verb = ruleIds.shift() | ||
if (verb !== 'enable' && verb !== 'disable' && verb !== 'ignore') { | ||
@@ -77,8 +159,8 @@ file.fail( | ||
// Apply to all rules. | ||
if (ruleIds.length) { | ||
if (ruleIds.length > 0) { | ||
while (++index < ruleIds.length) { | ||
ruleId = ruleIds[index] | ||
const ruleId = ruleIds[index] | ||
if (isKnown(ruleId, verb, mark.node)) { | ||
toggle(pos, verb === 'enable', ruleId) | ||
toggle(point, verb === 'enable', ruleId) | ||
@@ -91,6 +173,6 @@ if (verb === 'ignore') { | ||
} else if (verb === 'ignore') { | ||
toggle(pos, false) | ||
toggle(point, false) | ||
toggle(tail, true) | ||
} else { | ||
toggle(pos, verb === 'enable') | ||
toggle(point, verb === 'enable') | ||
reset = verb !== 'enable' | ||
@@ -100,8 +182,11 @@ } | ||
/** | ||
* @param {VFileMessage} message | ||
* @returns {boolean} | ||
*/ | ||
function filter(message) { | ||
var gapIndex = gaps.length | ||
var pos | ||
let gapIndex = gaps.length | ||
// Keep messages from a different source. | ||
if (!message.source || sources.indexOf(message.source) === -1) { | ||
if (!message.source || !sources.includes(message.source)) { | ||
return true | ||
@@ -121,6 +206,7 @@ } | ||
// Check whether the warning is inside a gap. | ||
pos = toOffset(message) | ||
// @ts-expect-error: we just normalized `null` to `number`s. | ||
const offset = toOffset(message) | ||
while (gapIndex--) { | ||
if (gaps[gapIndex].start <= pos && gaps[gapIndex].end > pos) { | ||
if (gaps[gapIndex][0] <= offset && gaps[gapIndex][1] > offset) { | ||
return false | ||
@@ -132,3 +218,4 @@ } | ||
return ( | ||
check(message, scope[message.ruleId], message.ruleId) && | ||
(!message.ruleId || | ||
check(message, scope[message.ruleId], message.ruleId)) && | ||
check(message, globals) | ||
@@ -138,5 +225,12 @@ ) | ||
// Helper to check (and possibly warn) if a `ruleId` is unknown. | ||
function isKnown(ruleId, verb, pos) { | ||
var result = settings.known ? settings.known.indexOf(ruleId) !== -1 : true | ||
/** | ||
* Helper to check (and possibly warn) if a `ruleId` is unknown. | ||
* | ||
* @param {string} ruleId | ||
* @param {string} verb | ||
* @param {Node} node | ||
* @returns {boolean} | ||
*/ | ||
function isKnown(ruleId, verb, node) { | ||
const result = options.known ? options.known.includes(ruleId) : true | ||
@@ -146,3 +240,3 @@ if (!result) { | ||
'Unknown rule: cannot ' + verb + " `'" + ruleId + "'`", | ||
pos | ||
node | ||
) | ||
@@ -154,8 +248,13 @@ } | ||
// Get the latest state of a rule. | ||
// When without `ruleId`, gets global state. | ||
/** | ||
* Get the latest state of a rule. | ||
* When without `ruleId`, gets global state. | ||
* | ||
* @param {string|undefined} ruleId | ||
* @returns {boolean} | ||
*/ | ||
function getState(ruleId) { | ||
var ranges = ruleId ? scope[ruleId] : globals | ||
const ranges = ruleId ? scope[ruleId] : globals | ||
if (ranges && ranges.length) { | ||
if (ranges && ranges.length > 0) { | ||
return ranges[ranges.length - 1].state | ||
@@ -168,19 +267,25 @@ } | ||
return reset ? enable.indexOf(ruleId) > -1 : disable.indexOf(ruleId) < 0 | ||
return reset ? enable.includes(ruleId) : !disable.includes(ruleId) | ||
} | ||
// Handle a rule. | ||
function toggle(pos, state, ruleId) { | ||
var markers = ruleId ? scope[ruleId] : globals | ||
var previousState | ||
/** | ||
* Handle a rule. | ||
* | ||
* @param {Point|undefined} point | ||
* @param {boolean} state | ||
* @param {string|undefined} [ruleId] | ||
* @returns {void} | ||
*/ | ||
function toggle(point, state, ruleId) { | ||
let markers = ruleId ? scope[ruleId] : globals | ||
if (!markers) { | ||
markers = [] | ||
scope[ruleId] = markers | ||
scope[String(ruleId)] = markers | ||
} | ||
previousState = getState(ruleId) | ||
const previousState = getState(ruleId) | ||
if (state !== previousState) { | ||
markers.push({state: state, position: pos}) | ||
markers.push({state, point}) | ||
} | ||
@@ -191,3 +296,5 @@ | ||
for (ruleId in scope) { | ||
toggle(pos, state, ruleId) | ||
if (own.call(scope, ruleId)) { | ||
toggle(point, state, ruleId) | ||
} | ||
} | ||
@@ -197,17 +304,30 @@ } | ||
// Check all `ranges` for `message`. | ||
/** | ||
* Check all `ranges` for `message`. | ||
* | ||
* @param {VFileMessage} message | ||
* @param {Mark[]|undefined} ranges | ||
* @param {string|undefined} [ruleId] | ||
* @returns {boolean} | ||
*/ | ||
function check(message, ranges, ruleId) { | ||
// Check the state at the message’s position. | ||
var index = ranges && ranges.length | ||
if (ranges && ranges.length > 0) { | ||
// Check the state at the message’s position. | ||
let index = ranges.length | ||
while (index--) { | ||
if ( | ||
ranges[index].position && | ||
ranges[index].position.line && | ||
ranges[index].position.column && | ||
(ranges[index].position.line < message.line || | ||
(ranges[index].position.line === message.line && | ||
ranges[index].position.column <= message.column)) | ||
) { | ||
return ranges[index].state === true | ||
while (index--) { | ||
const range = ranges[index] | ||
if ( | ||
message.line && | ||
message.column && | ||
range.point && | ||
range.point.line && | ||
range.point.column && | ||
(range.point.line < message.line || | ||
(range.point.line === message.line && | ||
range.point.column <= message.column)) | ||
) { | ||
return range.state === true | ||
} | ||
} | ||
@@ -219,6 +339,6 @@ } | ||
if (!ruleId) { | ||
return initial || reset | ||
return Boolean(initial || reset) | ||
} | ||
return reset ? enable.indexOf(ruleId) > -1 : disable.indexOf(ruleId) < 0 | ||
return reset ? enable.includes(ruleId) : !disable.includes(ruleId) | ||
} | ||
@@ -228,9 +348,18 @@ } | ||
// Detect gaps in `tree`. | ||
/** | ||
* Detect gaps in `tree`. | ||
* | ||
* @param {Node} tree | ||
* @param {VFile} file | ||
*/ | ||
function detectGaps(tree, file) { | ||
var children = tree.children || [] | ||
var lastNode = children[children.length - 1] | ||
var offset = 0 | ||
var gaps = [] | ||
var gap | ||
/** @type {Node[]} */ | ||
// @ts-expect-error: fine. | ||
const children = tree.children || [] | ||
const lastNode = children[children.length - 1] | ||
/** @type {[number, number][]} */ | ||
const gaps = [] | ||
let offset = 0 | ||
/** @type {boolean|undefined} */ | ||
let gap | ||
@@ -249,3 +378,3 @@ // Find all gaps. | ||
offset === lastNode.position.end.offset && | ||
trim(file.toString().slice(offset)) !== '' | ||
file.toString().slice(offset).trim() !== '' | ||
) { | ||
@@ -255,3 +384,7 @@ update() | ||
update( | ||
tree && tree.position && tree.position.end && tree.position.end.offset - 1 | ||
tree && | ||
tree.position && | ||
tree.position.end && | ||
tree.position.end.offset && | ||
tree.position.end.offset - 1 | ||
) | ||
@@ -262,6 +395,9 @@ } | ||
/** | ||
* @param {Node} node | ||
*/ | ||
function one(node) { | ||
update(node.position && node.position.start && node.position.start.offset) | ||
if (!node.children) { | ||
if (!('children' in node)) { | ||
update(node.position && node.position.end && node.position.end.offset) | ||
@@ -271,3 +407,8 @@ } | ||
// Detect a new position. | ||
/** | ||
* Detect a new position. | ||
* | ||
* @param {number|undefined} [latest] | ||
* @returns {void} | ||
*/ | ||
function update(latest) { | ||
@@ -278,4 +419,4 @@ if (latest === null || latest === undefined) { | ||
if (gap) { | ||
gaps.push({start: offset, end: latest}) | ||
gap = null | ||
gaps.push([offset, latest]) | ||
gap = undefined | ||
} | ||
@@ -287,5 +428,1 @@ | ||
} | ||
function trim(value) { | ||
return value.replace(/^\s+|\s+$/g, '') | ||
} |
{ | ||
"name": "unified-message-control", | ||
"version": "3.0.3", | ||
"version": "4.0.0", | ||
"description": "Enable, disable, and ignore messages from unified processors", | ||
@@ -26,18 +26,22 @@ "license": "MIT", | ||
], | ||
"sideEffects": false, | ||
"type": "module", | ||
"main": "index.js", | ||
"types": "index.d.ts", | ||
"files": [ | ||
"index.js", | ||
"index.d.ts" | ||
"index.d.ts", | ||
"index.js" | ||
], | ||
"dependencies": { | ||
"unist-util-visit": "^2.0.0", | ||
"vfile-location": "^3.0.0" | ||
"@types/unist": "^2.0.0", | ||
"unist-util-is": "^5.0.0", | ||
"unist-util-visit": "^3.0.0", | ||
"vfile": "^5.0.0", | ||
"vfile-location": "^4.0.0", | ||
"vfile-message": "^3.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/hast": "^2.0.0", | ||
"@types/mdast": "^3.0.0", | ||
"@types/unist": "^2.0.0", | ||
"browserify": "^17.0.0", | ||
"dtslint": "^4.0.0", | ||
"mdast-comment-marker": "^1.0.0", | ||
"nyc": "^15.0.0", | ||
"@types/tape": "^4.0.0", | ||
"c8": "^7.0.0", | ||
"mdast-comment-marker": "^2.0.0", | ||
"prettier": "^2.0.0", | ||
@@ -48,24 +52,16 @@ "remark": "^13.0.0", | ||
"remark-toc": "^7.0.0", | ||
"rimraf": "^3.0.0", | ||
"tape": "^5.0.0", | ||
"tinyify": "^3.0.0", | ||
"unified": "^9.0.0", | ||
"unist-util-is": "^4.0.0", | ||
"xo": "^0.37.0" | ||
"type-coverage": "^2.0.0", | ||
"typescript": "^4.0.0", | ||
"unified": "^10.0.0", | ||
"xo": "^0.39.0" | ||
}, | ||
"scripts": { | ||
"format": "remark . -qfo && prettier . --write && xo --fix", | ||
"build-bundle": "browserify index.js -s unifiedMessageControl -o unified-message-control.js", | ||
"build-mangle": "browserify index.js -s unifiedMessageControl -p tinyify -o unified-message-control.min.js", | ||
"build": "npm run build-bundle && npm run build-mangle", | ||
"test-api": "node test", | ||
"test-coverage": "nyc --reporter lcov tape test.js", | ||
"test-types": "dtslint", | ||
"test": "npm run test-types && npm run format && npm run build && npm run test-coverage" | ||
"build": "rimraf \"*.d.ts\" && tsc && type-coverage", | ||
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", | ||
"test-api": "node --conditions development test.js", | ||
"test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node --conditions development test.js", | ||
"test": "npm run build && npm run format && npm run test-coverage" | ||
}, | ||
"nyc": { | ||
"check-coverage": true, | ||
"lines": 100, | ||
"functions": 100, | ||
"branches": 100 | ||
}, | ||
"prettier": { | ||
@@ -80,15 +76,3 @@ "tabWidth": 2, | ||
"xo": { | ||
"prettier": true, | ||
"esnext": false, | ||
"rules": { | ||
"guard-for-in": "off", | ||
"unicorn/explicit-length-check": "off", | ||
"unicorn/no-array-callback-reference": "off", | ||
"unicorn/prefer-includes": "off", | ||
"unicorn/string-content": "off" | ||
}, | ||
"ignores": [ | ||
"*.ts", | ||
"unified-message-control.js" | ||
] | ||
"prettier": true | ||
}, | ||
@@ -99,3 +83,9 @@ "remarkConfig": { | ||
] | ||
}, | ||
"typeCoverage": { | ||
"atLeast": 100, | ||
"detail": true, | ||
"strict": true, | ||
"ignoreCatch": true | ||
} | ||
} |
@@ -15,2 +15,5 @@ # unified-message-control | ||
This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): | ||
Node 12+ is needed to use it and it must be `import`ed instead of `require`d. | ||
[npm][]: | ||
@@ -35,20 +38,27 @@ | ||
```js | ||
var vfile = require('to-vfile') | ||
var report = require('vfile-reporter') | ||
var remark = require('remark') | ||
var control = require('unified-message-control') | ||
var mdastMarker = require('mdast-comment-marker') | ||
import {toVFile} from 'to-vfile' | ||
import {reporter} from 'vfile-reporter' | ||
import {commentMarker} from 'mdast-comment-marker' | ||
import {unified} from 'unified' | ||
import unifiedMessageControl from 'unified-message-control' | ||
import remarkParse from 'remark-parse' | ||
import remarkStringify from 'remark-stringify' | ||
remark() | ||
.use(warn) | ||
.use(control, {name: 'foo', marker: mdastMarker, test: 'html'}) | ||
.process(vfile.readSync('example.md'), function (err, file) { | ||
console.error(report(err || file)) | ||
}) | ||
function warn() { | ||
return function (tree, file) { | ||
file.message('Whoops!', tree.children[1], 'foo:thing') | ||
} | ||
} | ||
toVFile.read('example.md').then((file) => { | ||
unified() | ||
.use(remarkParse) | ||
.use(remarkStringify) | ||
.use(() => (tree, file) => { | ||
file.message('Whoops!', tree.children[1], 'foo:thing') | ||
}) | ||
.use(unifiedMessageControl, { | ||
name: 'foo', | ||
marker: commentMarker, | ||
test: 'html' | ||
}) | ||
.process(file) | ||
.then((file) => { | ||
console.error(reporter(file)) | ||
}) | ||
}) | ||
``` | ||
@@ -64,7 +74,10 @@ | ||
### `unified.use(control, options)` | ||
This package exports the following identifiers: `messageControl`. | ||
There is no default export. | ||
### `unified().use(messageControl, options)` | ||
Let comment markers control messages from certain sources. | ||
##### Options | ||
##### `options` | ||
@@ -71,0 +84,0 @@ ###### `options.name` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
22621
14
462
243
Yes
6
1
+ Added@types/unist@^2.0.0
+ Addedunist-util-is@^5.0.0
+ Addedvfile@^5.0.0
+ Addedvfile-message@^3.0.0
+ Addedis-buffer@2.0.5(transitive)
+ Addedunist-util-is@5.2.1(transitive)
+ Addedunist-util-stringify-position@3.0.3(transitive)
+ Addedunist-util-visit@3.1.0(transitive)
+ Addedunist-util-visit-parents@4.1.1(transitive)
+ Addedvfile@5.3.7(transitive)
+ Addedvfile-location@4.1.0(transitive)
+ Addedvfile-message@3.1.4(transitive)
- Removedunist-util-is@4.1.0(transitive)
- Removedunist-util-visit@2.0.3(transitive)
- Removedunist-util-visit-parents@3.1.1(transitive)
- Removedvfile-location@3.2.0(transitive)
Updatedunist-util-visit@^3.0.0
Updatedvfile-location@^4.0.0