123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- /**
- * @typedef {import('unist').Node} Node
- * @typedef {import('unist').Point} Point
- * @typedef {import('unist').Position} Position
- */
- /**
- * @typedef {object & {type: string, position?: Position | undefined}} NodeLike
- *
- * @typedef Options
- * Configuration.
- * @property {Array<Node> | null | undefined} [ancestors]
- * Stack of (inclusive) ancestor nodes surrounding the message (optional).
- * @property {Error | null | undefined} [cause]
- * Original error cause of the message (optional).
- * @property {Point | Position | null | undefined} [place]
- * Place of message (optional).
- * @property {string | null | undefined} [ruleId]
- * Category of message (optional, example: `'my-rule'`).
- * @property {string | null | undefined} [source]
- * Namespace of who sent the message (optional, example: `'my-package'`).
- */
- import {stringifyPosition} from 'unist-util-stringify-position'
- /**
- * Message.
- */
- export class VFileMessage extends Error {
- /**
- * Create a message for `reason`.
- *
- * > 🪦 **Note**: also has obsolete signatures.
- *
- * @overload
- * @param {string} reason
- * @param {Options | null | undefined} [options]
- * @returns
- *
- * @overload
- * @param {string} reason
- * @param {Node | NodeLike | null | undefined} parent
- * @param {string | null | undefined} [origin]
- * @returns
- *
- * @overload
- * @param {string} reason
- * @param {Point | Position | null | undefined} place
- * @param {string | null | undefined} [origin]
- * @returns
- *
- * @overload
- * @param {string} reason
- * @param {string | null | undefined} [origin]
- * @returns
- *
- * @overload
- * @param {Error | VFileMessage} cause
- * @param {Node | NodeLike | null | undefined} parent
- * @param {string | null | undefined} [origin]
- * @returns
- *
- * @overload
- * @param {Error | VFileMessage} cause
- * @param {Point | Position | null | undefined} place
- * @param {string | null | undefined} [origin]
- * @returns
- *
- * @overload
- * @param {Error | VFileMessage} cause
- * @param {string | null | undefined} [origin]
- * @returns
- *
- * @param {Error | VFileMessage | string} causeOrReason
- * Reason for message, should use markdown.
- * @param {Node | NodeLike | Options | Point | Position | string | null | undefined} [optionsOrParentOrPlace]
- * Configuration (optional).
- * @param {string | null | undefined} [origin]
- * Place in code where the message originates (example:
- * `'my-package:my-rule'` or `'my-rule'`).
- * @returns
- * Instance of `VFileMessage`.
- */
- // eslint-disable-next-line complexity
- constructor(causeOrReason, optionsOrParentOrPlace, origin) {
- super()
- if (typeof optionsOrParentOrPlace === 'string') {
- origin = optionsOrParentOrPlace
- optionsOrParentOrPlace = undefined
- }
- /** @type {string} */
- let reason = ''
- /** @type {Options} */
- let options = {}
- let legacyCause = false
- if (optionsOrParentOrPlace) {
- // Point.
- if (
- 'line' in optionsOrParentOrPlace &&
- 'column' in optionsOrParentOrPlace
- ) {
- options = {place: optionsOrParentOrPlace}
- }
- // Position.
- else if (
- 'start' in optionsOrParentOrPlace &&
- 'end' in optionsOrParentOrPlace
- ) {
- options = {place: optionsOrParentOrPlace}
- }
- // Node.
- else if ('type' in optionsOrParentOrPlace) {
- options = {
- ancestors: [optionsOrParentOrPlace],
- place: optionsOrParentOrPlace.position
- }
- }
- // Options.
- else {
- options = {...optionsOrParentOrPlace}
- }
- }
- if (typeof causeOrReason === 'string') {
- reason = causeOrReason
- }
- // Error.
- else if (!options.cause && causeOrReason) {
- legacyCause = true
- reason = causeOrReason.message
- options.cause = causeOrReason
- }
- if (!options.ruleId && !options.source && typeof origin === 'string') {
- const index = origin.indexOf(':')
- if (index === -1) {
- options.ruleId = origin
- } else {
- options.source = origin.slice(0, index)
- options.ruleId = origin.slice(index + 1)
- }
- }
- if (!options.place && options.ancestors && options.ancestors) {
- const parent = options.ancestors[options.ancestors.length - 1]
- if (parent) {
- options.place = parent.position
- }
- }
- const start =
- options.place && 'start' in options.place
- ? options.place.start
- : options.place
- /* eslint-disable no-unused-expressions */
- /**
- * Stack of ancestor nodes surrounding the message.
- *
- * @type {Array<Node> | undefined}
- */
- this.ancestors = options.ancestors || undefined
- /**
- * Original error cause of the message.
- *
- * @type {Error | undefined}
- */
- this.cause = options.cause || undefined
- /**
- * Starting column of message.
- *
- * @type {number | undefined}
- */
- this.column = start ? start.column : undefined
- /**
- * State of problem.
- *
- * * `true` — error, file not usable
- * * `false` — warning, change may be needed
- * * `undefined` — change likely not needed
- *
- * @type {boolean | null | undefined}
- */
- this.fatal = undefined
- /**
- * Path of a file (used throughout the `VFile` ecosystem).
- *
- * @type {string | undefined}
- */
- this.file
- // Field from `Error`.
- /**
- * Reason for message.
- *
- * @type {string}
- */
- this.message = reason
- /**
- * Starting line of error.
- *
- * @type {number | undefined}
- */
- this.line = start ? start.line : undefined
- // Field from `Error`.
- /**
- * Serialized positional info of message.
- *
- * 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(options.place) || '1:1'
- /**
- * Place of message.
- *
- * @type {Point | Position | undefined}
- */
- this.place = options.place || undefined
- /**
- * Reason for message, should use markdown.
- *
- * @type {string}
- */
- this.reason = this.message
- /**
- * Category of message (example: `'my-rule'`).
- *
- * @type {string | undefined}
- */
- this.ruleId = options.ruleId || undefined
- /**
- * Namespace of message (example: `'my-package'`).
- *
- * @type {string | undefined}
- */
- this.source = options.source || undefined
- // Field from `Error`.
- /**
- * 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 =
- legacyCause && options.cause && typeof options.cause.stack === 'string'
- ? options.cause.stack
- : ''
- // 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 | undefined}
- */
- this.actual
- /**
- * Suggest acceptable values that can be used instead of `actual`.
- *
- * @type {Array<string> | undefined}
- */
- this.expected
- /**
- * Long form description of the message (you should use markdown).
- *
- * @type {string | undefined}
- */
- this.note
- /**
- * Link to docs for the message.
- *
- * > 👉 **Note**: this must be an absolute URL that can be passed as `x`
- * > to `new URL(x)`.
- *
- * @type {string | undefined}
- */
- this.url
- /* eslint-enable no-unused-expressions */
- }
- }
- VFileMessage.prototype.file = ''
- VFileMessage.prototype.name = ''
- VFileMessage.prototype.reason = ''
- VFileMessage.prototype.message = ''
- VFileMessage.prototype.stack = ''
- VFileMessage.prototype.column = undefined
- VFileMessage.prototype.line = undefined
- VFileMessage.prototype.ancestors = undefined
- VFileMessage.prototype.cause = undefined
- VFileMessage.prototype.fatal = undefined
- VFileMessage.prototype.place = undefined
- VFileMessage.prototype.ruleId = undefined
- VFileMessage.prototype.source = undefined
|