Bhargava 6063bd1724 Help Project:
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.
2025-07-04 15:54:13 +05:30

175 lines
4.4 KiB
JavaScript

import extend from 'extend';
import Delta from 'quill-delta';
import Parchment from 'parchment';
import Break from './break';
import Inline from './inline';
import TextBlot from './text';
const NEWLINE_LENGTH = 1;
class BlockEmbed extends Parchment.Embed {
attach() {
super.attach();
this.attributes = new Parchment.Attributor.Store(this.domNode);
}
delta() {
return new Delta().insert(this.value(), extend(this.formats(), this.attributes.values()));
}
format(name, value) {
let attribute = Parchment.query(name, Parchment.Scope.BLOCK_ATTRIBUTE);
if (attribute != null) {
this.attributes.attribute(attribute, value);
}
}
formatAt(index, length, name, value) {
this.format(name, value);
}
insertAt(index, value, def) {
if (typeof value === 'string' && value.endsWith('\n')) {
let block = Parchment.create(Block.blotName);
this.parent.insertBefore(block, index === 0 ? this : this.next);
block.insertAt(0, value.slice(0, -1));
} else {
super.insertAt(index, value, def);
}
}
}
BlockEmbed.scope = Parchment.Scope.BLOCK_BLOT;
// It is important for cursor behavior BlockEmbeds use tags that are block level elements
class Block extends Parchment.Block {
constructor(domNode) {
super(domNode);
this.cache = {};
}
delta() {
if (this.cache.delta == null) {
this.cache.delta = this.descendants(Parchment.Leaf).reduce((delta, leaf) => {
if (leaf.length() === 0) {
return delta;
} else {
return delta.insert(leaf.value(), bubbleFormats(leaf));
}
}, new Delta()).insert('\n', bubbleFormats(this));
}
return this.cache.delta;
}
deleteAt(index, length) {
super.deleteAt(index, length);
this.cache = {};
}
formatAt(index, length, name, value) {
if (length <= 0) return;
if (Parchment.query(name, Parchment.Scope.BLOCK)) {
if (index + length === this.length()) {
this.format(name, value);
}
} else {
super.formatAt(index, Math.min(length, this.length() - index - 1), name, value);
}
this.cache = {};
}
insertAt(index, value, def) {
if (def != null) return super.insertAt(index, value, def);
if (value.length === 0) return;
let lines = value.split('\n');
let text = lines.shift();
if (text.length > 0) {
if (index < this.length() - 1 || this.children.tail == null) {
super.insertAt(Math.min(index, this.length() - 1), text);
} else {
this.children.tail.insertAt(this.children.tail.length(), text);
}
this.cache = {};
}
let block = this;
lines.reduce(function(index, line) {
block = block.split(index, true);
block.insertAt(0, line);
return line.length;
}, index + text.length);
}
insertBefore(blot, ref) {
let head = this.children.head;
super.insertBefore(blot, ref);
if (head instanceof Break) {
head.remove();
}
this.cache = {};
}
length() {
if (this.cache.length == null) {
this.cache.length = super.length() + NEWLINE_LENGTH;
}
return this.cache.length;
}
moveChildren(target, ref) {
super.moveChildren(target, ref);
this.cache = {};
}
optimize(context) {
super.optimize(context);
this.cache = {};
}
path(index) {
return super.path(index, true);
}
removeChild(child) {
super.removeChild(child);
this.cache = {};
}
split(index, force = false) {
if (force && (index === 0 || index >= this.length() - NEWLINE_LENGTH)) {
let clone = this.clone();
if (index === 0) {
this.parent.insertBefore(clone, this);
return this;
} else {
this.parent.insertBefore(clone, this.next);
return clone;
}
} else {
let next = super.split(index, force);
this.cache = {};
return next;
}
}
}
Block.blotName = 'block';
Block.tagName = 'P';
Block.defaultChild = 'break';
Block.allowedChildren = [Inline, Parchment.Embed, TextBlot];
function bubbleFormats(blot, formats = {}) {
if (blot == null) return formats;
if (typeof blot.formats === 'function') {
formats = extend(formats, blot.formats());
}
if (blot.parent == null || blot.parent.blotName == 'scroll' || blot.parent.statics.scope !== blot.statics.scope) {
return formats;
}
return bubbleFormats(blot.parent, formats);
}
export { bubbleFormats, BlockEmbed, Block as default };