diff --git a/index.js b/index.js index a6d412b..17019f0 100644 --- a/index.js +++ b/index.js @@ -1,216 +1 @@ -/** - * @typedef {import('unist').Node} Node - * @typedef {import('unist').Position} Position - * @typedef {import('unist').Point} Point - * @typedef {object & {type: string, position?: Position | undefined}} NodeLike - */ - -import {stringifyPosition} from 'unist-util-stringify-position' - -export class VFileMessage extends Error { - /** - * Create a message for `reason` at `place` from `origin`. - * - * When an error is passed in as `reason`, the `stack` is copied. - * - * @param {string | Error | VFileMessage} reason - * Reason for message. - * Uses the stack and message of the error if given. - * @param {Node | NodeLike | Position | Point | null | undefined} [place] - * Place at which the message occurred in a file. - * @param {string | null | undefined} [origin] - * Place in code the message originates from (example `'my-package:my-rule-name'`) - */ - // To do: next major: expose `undefined` everywhere instead of `null`. - constructor(reason, place, origin) { - /** @type {[string | null, string | null]} */ - const parts = [null, null] - /** @type {Position} */ - let position = { - // @ts-expect-error: we always follows the structure of `position`. - start: {line: null, column: null}, - // @ts-expect-error: " - end: {line: null, column: null} - } - - super() - - if (typeof place === 'string') { - origin = place - place = undefined - } - - if (typeof origin === 'string') { - const index = origin.indexOf(':') - - if (index === -1) { - parts[1] = origin - } else { - parts[0] = origin.slice(0, index) - parts[1] = origin.slice(index + 1) - } - } - - if (place) { - // Node. - if ('type' in place || 'position' in place) { - if (place.position) { - // @ts-expect-error: looks like a position. - position = place.position - } - } - // Position. - else if ('start' in place || 'end' in place) { - // @ts-expect-error: looks like a position. - position = place - } - // Point. - else if ('line' in place || 'column' in place) { - position.start = place - } - } - - // Fields from `Error`. - /** - * Serialized positional info of error. - * - * On normal errors, this would be something like `ParseError`, buit in - * `VFile` messages we use this space to show where an error happened. - */ - this.name = stringifyPosition(place) || '1:1' - - /** - * Reason for message. - * - * @type {string} - */ - this.message = typeof reason === 'object' ? reason.message : reason - - /** - * Stack of message. - * - * This is used by normal errors to show where something happened in - * programming code, irrelevant for `VFile` messages, - * - * @type {string} - */ - this.stack = '' - - if (typeof reason === 'object' && reason.stack) { - this.stack = reason.stack - } - - /** - * Reason for message. - * - * @type {string} - */ - this.reason = this.message - - /* eslint-disable no-unused-expressions */ - /** - * Whether this is a fatal problem that marks an associated file as no - * longer processable. - * - * If `true`, marks associated file as no longer processable. - * If `false`, necessitates a (potential) change. - * The value can also be `null` or `undefined`, for things that might not - * need changing. - * - * @type {boolean | null | undefined} - */ - this.fatal - - /** - * Starting line of error. - * - * @type {number | null} - */ - this.line = position.start.line - - /** - * Starting column of error. - * - * @type {number | null} - */ - this.column = position.start.column - - /** - * Full range information, when available. - * - * Has `start` and `end` fields, both set to an object with `line` and - * `column`, set to `number | null`. - * - * @type {Position | null} - */ - this.position = position - - /** - * Namespace of warning (example: `'my-package'`). - * - * @type {string | null} - */ - this.source = parts[0] - - /** - * Category of message (example: `'my-rule-name'`). - * - * @type {string | null} - */ - this.ruleId = parts[1] - - /** - * Path of a file (used throughout the `VFile` ecosystem). - * - * @type {string | null} - */ - this.file - - // The following fields are “well known”. - // Not standard. - // Feel free to add other non-standard fields to your messages. - - /** - * Specify the source value that’s being reported, which is deemed - * incorrect. - * - * @type {string | null} - */ - this.actual - - /** - * Suggest values that should be used instead of `actual`, one or more - * values that are deemed as acceptable. - * - * @type {Array | null} - */ - this.expected - - /** - * Link to documentation for the message. - * - * @type {string | null} - */ - this.url - - /** - * Long form description of the message (supported by `vfile-reporter`). - * - * @type {string | null} - */ - this.note - /* eslint-enable no-unused-expressions */ - } -} - -VFileMessage.prototype.file = '' -VFileMessage.prototype.name = '' -VFileMessage.prototype.reason = '' -VFileMessage.prototype.message = '' -VFileMessage.prototype.stack = '' -VFileMessage.prototype.fatal = null -VFileMessage.prototype.column = null -VFileMessage.prototype.line = null -VFileMessage.prototype.source = null -VFileMessage.prototype.ruleId = null -VFileMessage.prototype.position = null +export {VFileMessage} from './lib/index.js' diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..a6d412b --- /dev/null +++ b/lib/index.js @@ -0,0 +1,216 @@ +/** + * @typedef {import('unist').Node} Node + * @typedef {import('unist').Position} Position + * @typedef {import('unist').Point} Point + * @typedef {object & {type: string, position?: Position | undefined}} NodeLike + */ + +import {stringifyPosition} from 'unist-util-stringify-position' + +export class VFileMessage extends Error { + /** + * Create a message for `reason` at `place` from `origin`. + * + * When an error is passed in as `reason`, the `stack` is copied. + * + * @param {string | Error | VFileMessage} reason + * Reason for message. + * Uses the stack and message of the error if given. + * @param {Node | NodeLike | Position | Point | null | undefined} [place] + * Place at which the message occurred in a file. + * @param {string | null | undefined} [origin] + * Place in code the message originates from (example `'my-package:my-rule-name'`) + */ + // To do: next major: expose `undefined` everywhere instead of `null`. + constructor(reason, place, origin) { + /** @type {[string | null, string | null]} */ + const parts = [null, null] + /** @type {Position} */ + let position = { + // @ts-expect-error: we always follows the structure of `position`. + start: {line: null, column: null}, + // @ts-expect-error: " + end: {line: null, column: null} + } + + super() + + if (typeof place === 'string') { + origin = place + place = undefined + } + + if (typeof origin === 'string') { + const index = origin.indexOf(':') + + if (index === -1) { + parts[1] = origin + } else { + parts[0] = origin.slice(0, index) + parts[1] = origin.slice(index + 1) + } + } + + if (place) { + // Node. + if ('type' in place || 'position' in place) { + if (place.position) { + // @ts-expect-error: looks like a position. + position = place.position + } + } + // Position. + else if ('start' in place || 'end' in place) { + // @ts-expect-error: looks like a position. + position = place + } + // Point. + else if ('line' in place || 'column' in place) { + position.start = place + } + } + + // Fields from `Error`. + /** + * Serialized positional info of error. + * + * On normal errors, this would be something like `ParseError`, buit in + * `VFile` messages we use this space to show where an error happened. + */ + this.name = stringifyPosition(place) || '1:1' + + /** + * Reason for message. + * + * @type {string} + */ + this.message = typeof reason === 'object' ? reason.message : reason + + /** + * Stack of message. + * + * This is used by normal errors to show where something happened in + * programming code, irrelevant for `VFile` messages, + * + * @type {string} + */ + this.stack = '' + + if (typeof reason === 'object' && reason.stack) { + this.stack = reason.stack + } + + /** + * Reason for message. + * + * @type {string} + */ + this.reason = this.message + + /* eslint-disable no-unused-expressions */ + /** + * Whether this is a fatal problem that marks an associated file as no + * longer processable. + * + * If `true`, marks associated file as no longer processable. + * If `false`, necessitates a (potential) change. + * The value can also be `null` or `undefined`, for things that might not + * need changing. + * + * @type {boolean | null | undefined} + */ + this.fatal + + /** + * Starting line of error. + * + * @type {number | null} + */ + this.line = position.start.line + + /** + * Starting column of error. + * + * @type {number | null} + */ + this.column = position.start.column + + /** + * Full range information, when available. + * + * Has `start` and `end` fields, both set to an object with `line` and + * `column`, set to `number | null`. + * + * @type {Position | null} + */ + this.position = position + + /** + * Namespace of warning (example: `'my-package'`). + * + * @type {string | null} + */ + this.source = parts[0] + + /** + * Category of message (example: `'my-rule-name'`). + * + * @type {string | null} + */ + this.ruleId = parts[1] + + /** + * Path of a file (used throughout the `VFile` ecosystem). + * + * @type {string | null} + */ + this.file + + // The following fields are “well known”. + // Not standard. + // Feel free to add other non-standard fields to your messages. + + /** + * Specify the source value that’s being reported, which is deemed + * incorrect. + * + * @type {string | null} + */ + this.actual + + /** + * Suggest values that should be used instead of `actual`, one or more + * values that are deemed as acceptable. + * + * @type {Array | null} + */ + this.expected + + /** + * Link to documentation for the message. + * + * @type {string | null} + */ + this.url + + /** + * Long form description of the message (supported by `vfile-reporter`). + * + * @type {string | null} + */ + this.note + /* eslint-enable no-unused-expressions */ + } +} + +VFileMessage.prototype.file = '' +VFileMessage.prototype.name = '' +VFileMessage.prototype.reason = '' +VFileMessage.prototype.message = '' +VFileMessage.prototype.stack = '' +VFileMessage.prototype.fatal = null +VFileMessage.prototype.column = null +VFileMessage.prototype.line = null +VFileMessage.prototype.source = null +VFileMessage.prototype.ruleId = null +VFileMessage.prototype.position = null diff --git a/package.json b/package.json index 229b03b..2f42f54 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "main": "index.js", "types": "index.d.ts", "files": [ + "lib/", "index.d.ts", "index.js" ],