forked from FINAKON/HelpProject
1. Initial Commit - a boiler plate code and POC to realize the concept of context sensitive help 2. Frontend code written in ReactJS 3. Backend code written in Java, Spring Boot Framework 4. Frontend Start: pre-requisites : node, npm npm run dev ==> to start the frontend vite server 5. Backend Start: pre-requisites : java, mvn mvn spring-boot:run ==> to start the backend server 6. Visit http://localhost:5173/ for basic demo of help, press F1 in textboxes 7. Visit http://localhost:5173/editor and enter "admin123" to add/modify texts. Happy Coding !!! Thank you, Bhargava.
319 lines
8.1 KiB
JavaScript
319 lines
8.1 KiB
JavaScript
/**
|
||
* @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
|