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.
185 lines
4.2 KiB
JavaScript
185 lines
4.2 KiB
JavaScript
/**
|
||
* @import {
|
||
* Code,
|
||
* Construct,
|
||
* Resolver,
|
||
* State,
|
||
* TokenizeContext,
|
||
* Tokenizer
|
||
* } from 'micromark-util-types'
|
||
*/
|
||
|
||
import { factorySpace } from 'micromark-factory-space';
|
||
import { markdownLineEnding, markdownSpace } from 'micromark-util-character';
|
||
/** @type {Construct} */
|
||
export const setextUnderline = {
|
||
name: 'setextUnderline',
|
||
resolveTo: resolveToSetextUnderline,
|
||
tokenize: tokenizeSetextUnderline
|
||
};
|
||
|
||
/** @type {Resolver} */
|
||
function resolveToSetextUnderline(events, context) {
|
||
// To do: resolve like `markdown-rs`.
|
||
let index = events.length;
|
||
/** @type {number | undefined} */
|
||
let content;
|
||
/** @type {number | undefined} */
|
||
let text;
|
||
/** @type {number | undefined} */
|
||
let definition;
|
||
|
||
// Find the opening of the content.
|
||
// It’ll always exist: we don’t tokenize if it isn’t there.
|
||
while (index--) {
|
||
if (events[index][0] === 'enter') {
|
||
if (events[index][1].type === "content") {
|
||
content = index;
|
||
break;
|
||
}
|
||
if (events[index][1].type === "paragraph") {
|
||
text = index;
|
||
}
|
||
}
|
||
// Exit
|
||
else {
|
||
if (events[index][1].type === "content") {
|
||
// Remove the content end (if needed we’ll add it later)
|
||
events.splice(index, 1);
|
||
}
|
||
if (!definition && events[index][1].type === "definition") {
|
||
definition = index;
|
||
}
|
||
}
|
||
}
|
||
const heading = {
|
||
type: "setextHeading",
|
||
start: {
|
||
...events[content][1].start
|
||
},
|
||
end: {
|
||
...events[events.length - 1][1].end
|
||
}
|
||
};
|
||
|
||
// Change the paragraph to setext heading text.
|
||
events[text][1].type = "setextHeadingText";
|
||
|
||
// If we have definitions in the content, we’ll keep on having content,
|
||
// but we need move it.
|
||
if (definition) {
|
||
events.splice(text, 0, ['enter', heading, context]);
|
||
events.splice(definition + 1, 0, ['exit', events[content][1], context]);
|
||
events[content][1].end = {
|
||
...events[definition][1].end
|
||
};
|
||
} else {
|
||
events[content][1] = heading;
|
||
}
|
||
|
||
// Add the heading exit at the end.
|
||
events.push(['exit', heading, context]);
|
||
return events;
|
||
}
|
||
|
||
/**
|
||
* @this {TokenizeContext}
|
||
* Context.
|
||
* @type {Tokenizer}
|
||
*/
|
||
function tokenizeSetextUnderline(effects, ok, nok) {
|
||
const self = this;
|
||
/** @type {NonNullable<Code>} */
|
||
let marker;
|
||
return start;
|
||
|
||
/**
|
||
* At start of heading (setext) underline.
|
||
*
|
||
* ```markdown
|
||
* | aa
|
||
* > | ==
|
||
* ^
|
||
* ```
|
||
*
|
||
* @type {State}
|
||
*/
|
||
function start(code) {
|
||
let index = self.events.length;
|
||
/** @type {boolean | undefined} */
|
||
let paragraph;
|
||
// Find an opening.
|
||
while (index--) {
|
||
// Skip enter/exit of line ending, line prefix, and content.
|
||
// We can now either have a definition or a paragraph.
|
||
if (self.events[index][1].type !== "lineEnding" && self.events[index][1].type !== "linePrefix" && self.events[index][1].type !== "content") {
|
||
paragraph = self.events[index][1].type === "paragraph";
|
||
break;
|
||
}
|
||
}
|
||
|
||
// To do: handle lazy/pierce like `markdown-rs`.
|
||
// To do: parse indent like `markdown-rs`.
|
||
if (!self.parser.lazy[self.now().line] && (self.interrupt || paragraph)) {
|
||
effects.enter("setextHeadingLine");
|
||
marker = code;
|
||
return before(code);
|
||
}
|
||
return nok(code);
|
||
}
|
||
|
||
/**
|
||
* After optional whitespace, at `-` or `=`.
|
||
*
|
||
* ```markdown
|
||
* | aa
|
||
* > | ==
|
||
* ^
|
||
* ```
|
||
*
|
||
* @type {State}
|
||
*/
|
||
function before(code) {
|
||
effects.enter("setextHeadingLineSequence");
|
||
return inside(code);
|
||
}
|
||
|
||
/**
|
||
* In sequence.
|
||
*
|
||
* ```markdown
|
||
* | aa
|
||
* > | ==
|
||
* ^
|
||
* ```
|
||
*
|
||
* @type {State}
|
||
*/
|
||
function inside(code) {
|
||
if (code === marker) {
|
||
effects.consume(code);
|
||
return inside;
|
||
}
|
||
effects.exit("setextHeadingLineSequence");
|
||
return markdownSpace(code) ? factorySpace(effects, after, "lineSuffix")(code) : after(code);
|
||
}
|
||
|
||
/**
|
||
* After sequence, after optional whitespace.
|
||
*
|
||
* ```markdown
|
||
* | aa
|
||
* > | ==
|
||
* ^
|
||
* ```
|
||
*
|
||
* @type {State}
|
||
*/
|
||
function after(code) {
|
||
if (code === null || markdownLineEnding(code)) {
|
||
effects.exit("setextHeadingLine");
|
||
return ok(code);
|
||
}
|
||
return nok(code);
|
||
}
|
||
} |