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.
213 lines
5.0 KiB
JavaScript
213 lines
5.0 KiB
JavaScript
/**
|
|
* @import {
|
|
* CompileContext,
|
|
* Extension as FromMarkdownExtension,
|
|
* Handle as FromMarkdownHandle
|
|
* } from 'mdast-util-from-markdown'
|
|
* @import {ToMarkdownOptions} from 'mdast-util-gfm-footnote'
|
|
* @import {
|
|
* Handle as ToMarkdownHandle,
|
|
* Map,
|
|
* Options as ToMarkdownExtension
|
|
* } from 'mdast-util-to-markdown'
|
|
* @import {FootnoteDefinition, FootnoteReference} from 'mdast'
|
|
*/
|
|
|
|
import {ok as assert} from 'devlop'
|
|
import {normalizeIdentifier} from 'micromark-util-normalize-identifier'
|
|
|
|
footnoteReference.peek = footnoteReferencePeek
|
|
|
|
/**
|
|
* @this {CompileContext}
|
|
* @type {FromMarkdownHandle}
|
|
*/
|
|
function enterFootnoteCallString() {
|
|
this.buffer()
|
|
}
|
|
|
|
/**
|
|
* @this {CompileContext}
|
|
* @type {FromMarkdownHandle}
|
|
*/
|
|
function enterFootnoteCall(token) {
|
|
this.enter({type: 'footnoteReference', identifier: '', label: ''}, token)
|
|
}
|
|
|
|
/**
|
|
* @this {CompileContext}
|
|
* @type {FromMarkdownHandle}
|
|
*/
|
|
function enterFootnoteDefinitionLabelString() {
|
|
this.buffer()
|
|
}
|
|
|
|
/**
|
|
* @this {CompileContext}
|
|
* @type {FromMarkdownHandle}
|
|
*/
|
|
function enterFootnoteDefinition(token) {
|
|
this.enter(
|
|
{type: 'footnoteDefinition', identifier: '', label: '', children: []},
|
|
token
|
|
)
|
|
}
|
|
|
|
/**
|
|
* @this {CompileContext}
|
|
* @type {FromMarkdownHandle}
|
|
*/
|
|
function exitFootnoteCallString(token) {
|
|
const label = this.resume()
|
|
const node = this.stack[this.stack.length - 1]
|
|
assert(node.type === 'footnoteReference')
|
|
node.identifier = normalizeIdentifier(
|
|
this.sliceSerialize(token)
|
|
).toLowerCase()
|
|
node.label = label
|
|
}
|
|
|
|
/**
|
|
* @this {CompileContext}
|
|
* @type {FromMarkdownHandle}
|
|
*/
|
|
function exitFootnoteCall(token) {
|
|
this.exit(token)
|
|
}
|
|
|
|
/**
|
|
* @this {CompileContext}
|
|
* @type {FromMarkdownHandle}
|
|
*/
|
|
function exitFootnoteDefinitionLabelString(token) {
|
|
const label = this.resume()
|
|
const node = this.stack[this.stack.length - 1]
|
|
assert(node.type === 'footnoteDefinition')
|
|
node.identifier = normalizeIdentifier(
|
|
this.sliceSerialize(token)
|
|
).toLowerCase()
|
|
node.label = label
|
|
}
|
|
|
|
/**
|
|
* @this {CompileContext}
|
|
* @type {FromMarkdownHandle}
|
|
*/
|
|
function exitFootnoteDefinition(token) {
|
|
this.exit(token)
|
|
}
|
|
|
|
/** @type {ToMarkdownHandle} */
|
|
function footnoteReferencePeek() {
|
|
return '['
|
|
}
|
|
|
|
/**
|
|
* @type {ToMarkdownHandle}
|
|
* @param {FootnoteReference} node
|
|
*/
|
|
function footnoteReference(node, _, state, info) {
|
|
const tracker = state.createTracker(info)
|
|
let value = tracker.move('[^')
|
|
const exit = state.enter('footnoteReference')
|
|
const subexit = state.enter('reference')
|
|
value += tracker.move(
|
|
state.safe(state.associationId(node), {after: ']', before: value})
|
|
)
|
|
subexit()
|
|
exit()
|
|
value += tracker.move(']')
|
|
return value
|
|
}
|
|
|
|
/**
|
|
* Create an extension for `mdast-util-from-markdown` to enable GFM footnotes
|
|
* in markdown.
|
|
*
|
|
* @returns {FromMarkdownExtension}
|
|
* Extension for `mdast-util-from-markdown`.
|
|
*/
|
|
export function gfmFootnoteFromMarkdown() {
|
|
return {
|
|
enter: {
|
|
gfmFootnoteCallString: enterFootnoteCallString,
|
|
gfmFootnoteCall: enterFootnoteCall,
|
|
gfmFootnoteDefinitionLabelString: enterFootnoteDefinitionLabelString,
|
|
gfmFootnoteDefinition: enterFootnoteDefinition
|
|
},
|
|
exit: {
|
|
gfmFootnoteCallString: exitFootnoteCallString,
|
|
gfmFootnoteCall: exitFootnoteCall,
|
|
gfmFootnoteDefinitionLabelString: exitFootnoteDefinitionLabelString,
|
|
gfmFootnoteDefinition: exitFootnoteDefinition
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create an extension for `mdast-util-to-markdown` to enable GFM footnotes
|
|
* in markdown.
|
|
*
|
|
* @param {ToMarkdownOptions | null | undefined} [options]
|
|
* Configuration (optional).
|
|
* @returns {ToMarkdownExtension}
|
|
* Extension for `mdast-util-to-markdown`.
|
|
*/
|
|
export function gfmFootnoteToMarkdown(options) {
|
|
// To do: next major: change default.
|
|
let firstLineBlank = false
|
|
|
|
if (options && options.firstLineBlank) {
|
|
firstLineBlank = true
|
|
}
|
|
|
|
return {
|
|
handlers: {footnoteDefinition, footnoteReference},
|
|
// This is on by default already.
|
|
unsafe: [{character: '[', inConstruct: ['label', 'phrasing', 'reference']}]
|
|
}
|
|
|
|
/**
|
|
* @type {ToMarkdownHandle}
|
|
* @param {FootnoteDefinition} node
|
|
*/
|
|
function footnoteDefinition(node, _, state, info) {
|
|
const tracker = state.createTracker(info)
|
|
let value = tracker.move('[^')
|
|
const exit = state.enter('footnoteDefinition')
|
|
const subexit = state.enter('label')
|
|
value += tracker.move(
|
|
state.safe(state.associationId(node), {before: value, after: ']'})
|
|
)
|
|
subexit()
|
|
|
|
value += tracker.move(']:')
|
|
|
|
if (node.children && node.children.length > 0) {
|
|
tracker.shift(4)
|
|
|
|
value += tracker.move(
|
|
(firstLineBlank ? '\n' : ' ') +
|
|
state.indentLines(
|
|
state.containerFlow(node, tracker.current()),
|
|
firstLineBlank ? mapAll : mapExceptFirst
|
|
)
|
|
)
|
|
}
|
|
|
|
exit()
|
|
|
|
return value
|
|
}
|
|
}
|
|
|
|
/** @type {Map} */
|
|
function mapExceptFirst(line, index, blank) {
|
|
return index === 0 ? line : mapAll(line, index, blank)
|
|
}
|
|
|
|
/** @type {Map} */
|
|
function mapAll(line, index, blank) {
|
|
return (blank ? '' : ' ') + line
|
|
}
|