first commit
This commit is contained in:
34
public/assets/quill/blots/block.d.ts
vendored
Normal file
34
public/assets/quill/blots/block.d.ts
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import { AttributorStore, BlockBlot, EmbedBlot } from 'parchment';
|
||||
import type { Blot, Parent } from 'parchment';
|
||||
import Delta from 'quill-delta';
|
||||
declare class Block extends BlockBlot {
|
||||
cache: {
|
||||
delta?: Delta | null;
|
||||
length?: number;
|
||||
};
|
||||
delta(): Delta;
|
||||
deleteAt(index: number, length: number): void;
|
||||
formatAt(index: number, length: number, name: string, value: unknown): void;
|
||||
insertAt(index: number, value: string, def?: unknown): void;
|
||||
insertBefore(blot: Blot, ref?: Blot | null): void;
|
||||
length(): number;
|
||||
moveChildren(target: Parent, ref?: Blot | null): void;
|
||||
optimize(context: {
|
||||
[key: string]: any;
|
||||
}): void;
|
||||
path(index: number): [Blot, number][];
|
||||
removeChild(child: Blot): void;
|
||||
split(index: number, force?: boolean | undefined): Blot | null;
|
||||
}
|
||||
declare class BlockEmbed extends EmbedBlot {
|
||||
attributes: AttributorStore;
|
||||
domNode: HTMLElement;
|
||||
attach(): void;
|
||||
delta(): Delta;
|
||||
format(name: string, value: unknown): void;
|
||||
formatAt(index: number, length: number, name: string, value: unknown): void;
|
||||
insertAt(index: number, value: string, def?: unknown): void;
|
||||
}
|
||||
declare function blockDelta(blot: BlockBlot, filter?: boolean): Delta;
|
||||
declare function bubbleFormats(blot: Blot | null, formats?: Record<string, unknown>, filter?: boolean): Record<string, unknown>;
|
||||
export { blockDelta, bubbleFormats, BlockEmbed, Block as default };
|
||||
182
public/assets/quill/blots/block.js
Normal file
182
public/assets/quill/blots/block.js
Normal file
@@ -0,0 +1,182 @@
|
||||
import { AttributorStore, BlockBlot, EmbedBlot, LeafBlot, Scope } from 'parchment';
|
||||
import Delta from 'quill-delta';
|
||||
import Break from './break.js';
|
||||
import Inline from './inline.js';
|
||||
import TextBlot from './text.js';
|
||||
const NEWLINE_LENGTH = 1;
|
||||
class Block extends BlockBlot {
|
||||
cache = {};
|
||||
delta() {
|
||||
if (this.cache.delta == null) {
|
||||
this.cache.delta = blockDelta(this);
|
||||
}
|
||||
return this.cache.delta;
|
||||
}
|
||||
deleteAt(index, length) {
|
||||
super.deleteAt(index, length);
|
||||
this.cache = {};
|
||||
}
|
||||
formatAt(index, length, name, value) {
|
||||
if (length <= 0) return;
|
||||
if (this.scroll.query(name, 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) {
|
||||
super.insertAt(index, value, def);
|
||||
this.cache = {};
|
||||
return;
|
||||
}
|
||||
if (value.length === 0) return;
|
||||
const lines = value.split('\n');
|
||||
const 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 = {};
|
||||
}
|
||||
// TODO: Fix this next time the file is edited.
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
let block = this;
|
||||
lines.reduce((lineIndex, line) => {
|
||||
// @ts-expect-error Fix me later
|
||||
block = block.split(lineIndex, true);
|
||||
block.insertAt(0, line);
|
||||
return line.length;
|
||||
}, index + text.length);
|
||||
}
|
||||
insertBefore(blot, ref) {
|
||||
const {
|
||||
head
|
||||
} = this.children;
|
||||
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) {
|
||||
let force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||||
if (force && (index === 0 || index >= this.length() - NEWLINE_LENGTH)) {
|
||||
const clone = this.clone();
|
||||
if (index === 0) {
|
||||
this.parent.insertBefore(clone, this);
|
||||
return this;
|
||||
}
|
||||
this.parent.insertBefore(clone, this.next);
|
||||
return clone;
|
||||
}
|
||||
const next = super.split(index, force);
|
||||
this.cache = {};
|
||||
return next;
|
||||
}
|
||||
}
|
||||
Block.blotName = 'block';
|
||||
Block.tagName = 'P';
|
||||
Block.defaultChild = Break;
|
||||
Block.allowedChildren = [Break, Inline, EmbedBlot, TextBlot];
|
||||
class BlockEmbed extends EmbedBlot {
|
||||
attach() {
|
||||
super.attach();
|
||||
this.attributes = new AttributorStore(this.domNode);
|
||||
}
|
||||
delta() {
|
||||
return new Delta().insert(this.value(), {
|
||||
...this.formats(),
|
||||
...this.attributes.values()
|
||||
});
|
||||
}
|
||||
format(name, value) {
|
||||
const attribute = this.scroll.query(name, Scope.BLOCK_ATTRIBUTE);
|
||||
if (attribute != null) {
|
||||
// @ts-expect-error TODO: Scroll#query() should return Attributor when scope is attribute
|
||||
this.attributes.attribute(attribute, value);
|
||||
}
|
||||
}
|
||||
formatAt(index, length, name, value) {
|
||||
this.format(name, value);
|
||||
}
|
||||
insertAt(index, value, def) {
|
||||
if (def != null) {
|
||||
super.insertAt(index, value, def);
|
||||
return;
|
||||
}
|
||||
const lines = value.split('\n');
|
||||
const text = lines.pop();
|
||||
const blocks = lines.map(line => {
|
||||
const block = this.scroll.create(Block.blotName);
|
||||
block.insertAt(0, line);
|
||||
return block;
|
||||
});
|
||||
const ref = this.split(index);
|
||||
blocks.forEach(block => {
|
||||
this.parent.insertBefore(block, ref);
|
||||
});
|
||||
if (text) {
|
||||
this.parent.insertBefore(this.scroll.create('text', text), ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
BlockEmbed.scope = Scope.BLOCK_BLOT;
|
||||
// It is important for cursor behavior BlockEmbeds use tags that are block level elements
|
||||
|
||||
function blockDelta(blot) {
|
||||
let filter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
||||
return blot.descendants(LeafBlot).reduce((delta, leaf) => {
|
||||
if (leaf.length() === 0) {
|
||||
return delta;
|
||||
}
|
||||
return delta.insert(leaf.value(), bubbleFormats(leaf, {}, filter));
|
||||
}, new Delta()).insert('\n', bubbleFormats(blot));
|
||||
}
|
||||
function bubbleFormats(blot) {
|
||||
let formats = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||||
let filter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
||||
if (blot == null) return formats;
|
||||
if ('formats' in blot && typeof blot.formats === 'function') {
|
||||
formats = {
|
||||
...formats,
|
||||
...blot.formats()
|
||||
};
|
||||
if (filter) {
|
||||
// exclude syntax highlighting from deltas and getFormat()
|
||||
delete formats['code-token'];
|
||||
}
|
||||
}
|
||||
if (blot.parent == null || blot.parent.statics.blotName === 'scroll' || blot.parent.statics.scope !== blot.statics.scope) {
|
||||
return formats;
|
||||
}
|
||||
return bubbleFormats(blot.parent, formats, filter);
|
||||
}
|
||||
export { blockDelta, bubbleFormats, BlockEmbed, Block as default };
|
||||
//# sourceMappingURL=block.js.map
|
||||
1
public/assets/quill/blots/block.js.map
Normal file
1
public/assets/quill/blots/block.js.map
Normal file
File diff suppressed because one or more lines are too long
8
public/assets/quill/blots/break.d.ts
vendored
Normal file
8
public/assets/quill/blots/break.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import { EmbedBlot } from 'parchment';
|
||||
declare class Break extends EmbedBlot {
|
||||
static value(): undefined;
|
||||
optimize(): void;
|
||||
length(): number;
|
||||
value(): string;
|
||||
}
|
||||
export default Break;
|
||||
21
public/assets/quill/blots/break.js
Normal file
21
public/assets/quill/blots/break.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import { EmbedBlot } from 'parchment';
|
||||
class Break extends EmbedBlot {
|
||||
static value() {
|
||||
return undefined;
|
||||
}
|
||||
optimize() {
|
||||
if (this.prev || this.next) {
|
||||
this.remove();
|
||||
}
|
||||
}
|
||||
length() {
|
||||
return 0;
|
||||
}
|
||||
value() {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
Break.blotName = 'break';
|
||||
Break.tagName = 'BR';
|
||||
export default Break;
|
||||
//# sourceMappingURL=break.js.map
|
||||
1
public/assets/quill/blots/break.js.map
Normal file
1
public/assets/quill/blots/break.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"break.js","names":["EmbedBlot","Break","value","undefined","optimize","prev","next","remove","length","blotName","tagName"],"sources":["../../src/blots/break.ts"],"sourcesContent":["import { EmbedBlot } from 'parchment';\n\nclass Break extends EmbedBlot {\n static value() {\n return undefined;\n }\n\n optimize() {\n if (this.prev || this.next) {\n this.remove();\n }\n }\n\n length() {\n return 0;\n }\n\n value() {\n return '';\n }\n}\nBreak.blotName = 'break';\nBreak.tagName = 'BR';\n\nexport default Break;\n"],"mappings":"AAAA,SAASA,SAAS,QAAQ,WAAW;AAErC,MAAMC,KAAK,SAASD,SAAS,CAAC;EAC5B,OAAOE,KAAKA,CAAA,EAAG;IACb,OAAOC,SAAS;EAClB;EAEAC,QAAQA,CAAA,EAAG;IACT,IAAI,IAAI,CAACC,IAAI,IAAI,IAAI,CAACC,IAAI,EAAE;MAC1B,IAAI,CAACC,MAAM,CAAC,CAAC;IACf;EACF;EAEAC,MAAMA,CAAA,EAAG;IACP,OAAO,CAAC;EACV;EAEAN,KAAKA,CAAA,EAAG;IACN,OAAO,EAAE;EACX;AACF;AACAD,KAAK,CAACQ,QAAQ,GAAG,OAAO;AACxBR,KAAK,CAACS,OAAO,GAAG,IAAI;AAEpB,eAAeT,KAAK","ignoreList":[]}
|
||||
4
public/assets/quill/blots/container.d.ts
vendored
Normal file
4
public/assets/quill/blots/container.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
import { ContainerBlot } from 'parchment';
|
||||
declare class Container extends ContainerBlot {
|
||||
}
|
||||
export default Container;
|
||||
4
public/assets/quill/blots/container.js
Normal file
4
public/assets/quill/blots/container.js
Normal file
@@ -0,0 +1,4 @@
|
||||
import { ContainerBlot } from 'parchment';
|
||||
class Container extends ContainerBlot {}
|
||||
export default Container;
|
||||
//# sourceMappingURL=container.js.map
|
||||
1
public/assets/quill/blots/container.js.map
Normal file
1
public/assets/quill/blots/container.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"container.js","names":["ContainerBlot","Container"],"sources":["../../src/blots/container.ts"],"sourcesContent":["import { ContainerBlot } from 'parchment';\n\nclass Container extends ContainerBlot {}\n\nexport default Container;\n"],"mappings":"AAAA,SAASA,aAAa,QAAQ,WAAW;AAEzC,MAAMC,SAAS,SAASD,aAAa,CAAC;AAEtC,eAAeC,SAAS","ignoreList":[]}
|
||||
26
public/assets/quill/blots/cursor.d.ts
vendored
Normal file
26
public/assets/quill/blots/cursor.d.ts
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import { EmbedBlot } from 'parchment';
|
||||
import type { ScrollBlot } from 'parchment';
|
||||
import type Selection from '../core/selection.js';
|
||||
import type { EmbedContextRange } from './embed.js';
|
||||
declare class Cursor extends EmbedBlot {
|
||||
static blotName: string;
|
||||
static className: string;
|
||||
static tagName: string;
|
||||
static CONTENTS: string;
|
||||
static value(): undefined;
|
||||
selection: Selection;
|
||||
textNode: Text;
|
||||
savedLength: number;
|
||||
constructor(scroll: ScrollBlot, domNode: HTMLElement, selection: Selection);
|
||||
detach(): void;
|
||||
format(name: string, value: unknown): void;
|
||||
index(node: Node, offset: number): number;
|
||||
length(): number;
|
||||
position(): [Text, number];
|
||||
remove(): void;
|
||||
restore(): EmbedContextRange | null;
|
||||
update(mutations: MutationRecord[], context: Record<string, unknown>): void;
|
||||
optimize(context?: unknown): void;
|
||||
value(): string;
|
||||
}
|
||||
export default Cursor;
|
||||
170
public/assets/quill/blots/cursor.js
Normal file
170
public/assets/quill/blots/cursor.js
Normal file
@@ -0,0 +1,170 @@
|
||||
import { EmbedBlot, Scope } from 'parchment';
|
||||
import TextBlot from './text.js';
|
||||
class Cursor extends EmbedBlot {
|
||||
static blotName = 'cursor';
|
||||
static className = 'ql-cursor';
|
||||
static tagName = 'span';
|
||||
static CONTENTS = '\uFEFF'; // Zero width no break space
|
||||
|
||||
static value() {
|
||||
return undefined;
|
||||
}
|
||||
constructor(scroll, domNode, selection) {
|
||||
super(scroll, domNode);
|
||||
this.selection = selection;
|
||||
this.textNode = document.createTextNode(Cursor.CONTENTS);
|
||||
this.domNode.appendChild(this.textNode);
|
||||
this.savedLength = 0;
|
||||
}
|
||||
detach() {
|
||||
// super.detach() will also clear domNode.__blot
|
||||
if (this.parent != null) this.parent.removeChild(this);
|
||||
}
|
||||
format(name, value) {
|
||||
if (this.savedLength !== 0) {
|
||||
super.format(name, value);
|
||||
return;
|
||||
}
|
||||
// TODO: Fix this next time the file is edited.
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
let target = this;
|
||||
let index = 0;
|
||||
while (target != null && target.statics.scope !== Scope.BLOCK_BLOT) {
|
||||
index += target.offset(target.parent);
|
||||
target = target.parent;
|
||||
}
|
||||
if (target != null) {
|
||||
this.savedLength = Cursor.CONTENTS.length;
|
||||
// @ts-expect-error TODO: allow empty context in Parchment
|
||||
target.optimize();
|
||||
target.formatAt(index, Cursor.CONTENTS.length, name, value);
|
||||
this.savedLength = 0;
|
||||
}
|
||||
}
|
||||
index(node, offset) {
|
||||
if (node === this.textNode) return 0;
|
||||
return super.index(node, offset);
|
||||
}
|
||||
length() {
|
||||
return this.savedLength;
|
||||
}
|
||||
position() {
|
||||
return [this.textNode, this.textNode.data.length];
|
||||
}
|
||||
remove() {
|
||||
super.remove();
|
||||
// @ts-expect-error Fix me later
|
||||
this.parent = null;
|
||||
}
|
||||
restore() {
|
||||
if (this.selection.composing || this.parent == null) return null;
|
||||
const range = this.selection.getNativeRange();
|
||||
// Browser may push down styles/nodes inside the cursor blot.
|
||||
// https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#push-down-values
|
||||
while (this.domNode.lastChild != null && this.domNode.lastChild !== this.textNode) {
|
||||
// @ts-expect-error Fix me later
|
||||
this.domNode.parentNode.insertBefore(this.domNode.lastChild, this.domNode);
|
||||
}
|
||||
const prevTextBlot = this.prev instanceof TextBlot ? this.prev : null;
|
||||
const prevTextLength = prevTextBlot ? prevTextBlot.length() : 0;
|
||||
const nextTextBlot = this.next instanceof TextBlot ? this.next : null;
|
||||
// @ts-expect-error TODO: make TextBlot.text public
|
||||
const nextText = nextTextBlot ? nextTextBlot.text : '';
|
||||
const {
|
||||
textNode
|
||||
} = this;
|
||||
// take text from inside this blot and reset it
|
||||
const newText = textNode.data.split(Cursor.CONTENTS).join('');
|
||||
textNode.data = Cursor.CONTENTS;
|
||||
|
||||
// proactively merge TextBlots around cursor so that optimization
|
||||
// doesn't lose the cursor. the reason we are here in cursor.restore
|
||||
// could be that the user clicked in prevTextBlot or nextTextBlot, or
|
||||
// the user typed something.
|
||||
let mergedTextBlot;
|
||||
if (prevTextBlot) {
|
||||
mergedTextBlot = prevTextBlot;
|
||||
if (newText || nextTextBlot) {
|
||||
prevTextBlot.insertAt(prevTextBlot.length(), newText + nextText);
|
||||
if (nextTextBlot) {
|
||||
nextTextBlot.remove();
|
||||
}
|
||||
}
|
||||
} else if (nextTextBlot) {
|
||||
mergedTextBlot = nextTextBlot;
|
||||
nextTextBlot.insertAt(0, newText);
|
||||
} else {
|
||||
const newTextNode = document.createTextNode(newText);
|
||||
mergedTextBlot = this.scroll.create(newTextNode);
|
||||
this.parent.insertBefore(mergedTextBlot, this);
|
||||
}
|
||||
this.remove();
|
||||
if (range) {
|
||||
// calculate selection to restore
|
||||
const remapOffset = (node, offset) => {
|
||||
if (prevTextBlot && node === prevTextBlot.domNode) {
|
||||
return offset;
|
||||
}
|
||||
if (node === textNode) {
|
||||
return prevTextLength + offset - 1;
|
||||
}
|
||||
if (nextTextBlot && node === nextTextBlot.domNode) {
|
||||
return prevTextLength + newText.length + offset;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const start = remapOffset(range.start.node, range.start.offset);
|
||||
const end = remapOffset(range.end.node, range.end.offset);
|
||||
if (start !== null && end !== null) {
|
||||
return {
|
||||
startNode: mergedTextBlot.domNode,
|
||||
startOffset: start,
|
||||
endNode: mergedTextBlot.domNode,
|
||||
endOffset: end
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
update(mutations, context) {
|
||||
if (mutations.some(mutation => {
|
||||
return mutation.type === 'characterData' && mutation.target === this.textNode;
|
||||
})) {
|
||||
const range = this.restore();
|
||||
if (range) context.range = range;
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid .ql-cursor being a descendant of `<a/>`.
|
||||
// The reason is Safari pushes down `<a/>` on text insertion.
|
||||
// That will cause DOM nodes not sync with the model.
|
||||
//
|
||||
// For example ({I} is the caret), given the markup:
|
||||
// <a><span class="ql-cursor">\uFEFF{I}</span></a>
|
||||
// When typing a char "x", `<a/>` will be pushed down inside the `<span>` first:
|
||||
// <span class="ql-cursor"><a>\uFEFF{I}</a></span>
|
||||
// And then "x" will be inserted after `<a/>`:
|
||||
// <span class="ql-cursor"><a>\uFEFF</a>d{I}</span>
|
||||
optimize(context) {
|
||||
// @ts-expect-error Fix me later
|
||||
super.optimize(context);
|
||||
let {
|
||||
parent
|
||||
} = this;
|
||||
while (parent) {
|
||||
if (parent.domNode.tagName === 'A') {
|
||||
this.savedLength = Cursor.CONTENTS.length;
|
||||
// @ts-expect-error TODO: make isolate generic
|
||||
parent.isolate(this.offset(parent), this.length()).unwrap();
|
||||
this.savedLength = 0;
|
||||
break;
|
||||
}
|
||||
parent = parent.parent;
|
||||
}
|
||||
}
|
||||
value() {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
export default Cursor;
|
||||
//# sourceMappingURL=cursor.js.map
|
||||
1
public/assets/quill/blots/cursor.js.map
Normal file
1
public/assets/quill/blots/cursor.js.map
Normal file
File diff suppressed because one or more lines are too long
18
public/assets/quill/blots/embed.d.ts
vendored
Normal file
18
public/assets/quill/blots/embed.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { ScrollBlot } from 'parchment';
|
||||
import { EmbedBlot } from 'parchment';
|
||||
export interface EmbedContextRange {
|
||||
startNode: Node | Text;
|
||||
startOffset: number;
|
||||
endNode?: Node | Text;
|
||||
endOffset?: number;
|
||||
}
|
||||
declare class Embed extends EmbedBlot {
|
||||
contentNode: HTMLSpanElement;
|
||||
leftGuard: Text;
|
||||
rightGuard: Text;
|
||||
constructor(scroll: ScrollBlot, node: Node);
|
||||
index(node: Node, offset: number): number;
|
||||
restore(node: Text): EmbedContextRange | null;
|
||||
update(mutations: MutationRecord[], context: Record<string, unknown>): void;
|
||||
}
|
||||
export default Embed;
|
||||
72
public/assets/quill/blots/embed.js
Normal file
72
public/assets/quill/blots/embed.js
Normal file
@@ -0,0 +1,72 @@
|
||||
import { EmbedBlot } from 'parchment';
|
||||
import TextBlot from './text.js';
|
||||
const GUARD_TEXT = '\uFEFF';
|
||||
class Embed extends EmbedBlot {
|
||||
constructor(scroll, node) {
|
||||
super(scroll, node);
|
||||
this.contentNode = document.createElement('span');
|
||||
this.contentNode.setAttribute('contenteditable', 'false');
|
||||
Array.from(this.domNode.childNodes).forEach(childNode => {
|
||||
this.contentNode.appendChild(childNode);
|
||||
});
|
||||
this.leftGuard = document.createTextNode(GUARD_TEXT);
|
||||
this.rightGuard = document.createTextNode(GUARD_TEXT);
|
||||
this.domNode.appendChild(this.leftGuard);
|
||||
this.domNode.appendChild(this.contentNode);
|
||||
this.domNode.appendChild(this.rightGuard);
|
||||
}
|
||||
index(node, offset) {
|
||||
if (node === this.leftGuard) return 0;
|
||||
if (node === this.rightGuard) return 1;
|
||||
return super.index(node, offset);
|
||||
}
|
||||
restore(node) {
|
||||
let range = null;
|
||||
let textNode;
|
||||
const text = node.data.split(GUARD_TEXT).join('');
|
||||
if (node === this.leftGuard) {
|
||||
if (this.prev instanceof TextBlot) {
|
||||
const prevLength = this.prev.length();
|
||||
this.prev.insertAt(prevLength, text);
|
||||
range = {
|
||||
startNode: this.prev.domNode,
|
||||
startOffset: prevLength + text.length
|
||||
};
|
||||
} else {
|
||||
textNode = document.createTextNode(text);
|
||||
this.parent.insertBefore(this.scroll.create(textNode), this);
|
||||
range = {
|
||||
startNode: textNode,
|
||||
startOffset: text.length
|
||||
};
|
||||
}
|
||||
} else if (node === this.rightGuard) {
|
||||
if (this.next instanceof TextBlot) {
|
||||
this.next.insertAt(0, text);
|
||||
range = {
|
||||
startNode: this.next.domNode,
|
||||
startOffset: text.length
|
||||
};
|
||||
} else {
|
||||
textNode = document.createTextNode(text);
|
||||
this.parent.insertBefore(this.scroll.create(textNode), this.next);
|
||||
range = {
|
||||
startNode: textNode,
|
||||
startOffset: text.length
|
||||
};
|
||||
}
|
||||
}
|
||||
node.data = GUARD_TEXT;
|
||||
return range;
|
||||
}
|
||||
update(mutations, context) {
|
||||
mutations.forEach(mutation => {
|
||||
if (mutation.type === 'characterData' && (mutation.target === this.leftGuard || mutation.target === this.rightGuard)) {
|
||||
const range = this.restore(mutation.target);
|
||||
if (range) context.range = range;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
export default Embed;
|
||||
//# sourceMappingURL=embed.js.map
|
||||
1
public/assets/quill/blots/embed.js.map
Normal file
1
public/assets/quill/blots/embed.js.map
Normal file
File diff suppressed because one or more lines are too long
12
public/assets/quill/blots/inline.d.ts
vendored
Normal file
12
public/assets/quill/blots/inline.d.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { InlineBlot } from 'parchment';
|
||||
import type { BlotConstructor } from 'parchment';
|
||||
declare class Inline extends InlineBlot {
|
||||
static allowedChildren: BlotConstructor[];
|
||||
static order: string[];
|
||||
static compare(self: string, other: string): number;
|
||||
formatAt(index: number, length: number, name: string, value: unknown): void;
|
||||
optimize(context: {
|
||||
[key: string]: any;
|
||||
}): void;
|
||||
}
|
||||
export default Inline;
|
||||
48
public/assets/quill/blots/inline.js
Normal file
48
public/assets/quill/blots/inline.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import { EmbedBlot, InlineBlot, Scope } from 'parchment';
|
||||
import Break from './break.js';
|
||||
import Text from './text.js';
|
||||
class Inline extends InlineBlot {
|
||||
static allowedChildren = [Inline, Break, EmbedBlot, Text];
|
||||
// Lower index means deeper in the DOM tree, since not found (-1) is for embeds
|
||||
static order = ['cursor', 'inline',
|
||||
// Must be lower
|
||||
'link',
|
||||
// Chrome wants <a> to be lower
|
||||
'underline', 'strike', 'italic', 'bold', 'script', 'code' // Must be higher
|
||||
];
|
||||
static compare(self, other) {
|
||||
const selfIndex = Inline.order.indexOf(self);
|
||||
const otherIndex = Inline.order.indexOf(other);
|
||||
if (selfIndex >= 0 || otherIndex >= 0) {
|
||||
return selfIndex - otherIndex;
|
||||
}
|
||||
if (self === other) {
|
||||
return 0;
|
||||
}
|
||||
if (self < other) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
formatAt(index, length, name, value) {
|
||||
if (Inline.compare(this.statics.blotName, name) < 0 && this.scroll.query(name, Scope.BLOT)) {
|
||||
const blot = this.isolate(index, length);
|
||||
if (value) {
|
||||
blot.wrap(name, value);
|
||||
}
|
||||
} else {
|
||||
super.formatAt(index, length, name, value);
|
||||
}
|
||||
}
|
||||
optimize(context) {
|
||||
super.optimize(context);
|
||||
if (this.parent instanceof Inline && Inline.compare(this.statics.blotName, this.parent.statics.blotName) > 0) {
|
||||
const parent = this.parent.isolate(this.offset(), this.length());
|
||||
// @ts-expect-error TODO: make isolate generic
|
||||
this.moveChildren(parent);
|
||||
parent.wrap(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
export default Inline;
|
||||
//# sourceMappingURL=inline.js.map
|
||||
1
public/assets/quill/blots/inline.js.map
Normal file
1
public/assets/quill/blots/inline.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"inline.js","names":["EmbedBlot","InlineBlot","Scope","Break","Text","Inline","allowedChildren","order","compare","self","other","selfIndex","indexOf","otherIndex","formatAt","index","length","name","value","statics","blotName","scroll","query","BLOT","blot","isolate","wrap","optimize","context","parent","offset","moveChildren"],"sources":["../../src/blots/inline.ts"],"sourcesContent":["import { EmbedBlot, InlineBlot, Scope } from 'parchment';\nimport type { BlotConstructor } from 'parchment';\nimport Break from './break.js';\nimport Text from './text.js';\n\nclass Inline extends InlineBlot {\n static allowedChildren: BlotConstructor[] = [Inline, Break, EmbedBlot, Text];\n // Lower index means deeper in the DOM tree, since not found (-1) is for embeds\n static order = [\n 'cursor',\n 'inline', // Must be lower\n 'link', // Chrome wants <a> to be lower\n 'underline',\n 'strike',\n 'italic',\n 'bold',\n 'script',\n 'code', // Must be higher\n ];\n\n static compare(self: string, other: string) {\n const selfIndex = Inline.order.indexOf(self);\n const otherIndex = Inline.order.indexOf(other);\n if (selfIndex >= 0 || otherIndex >= 0) {\n return selfIndex - otherIndex;\n }\n if (self === other) {\n return 0;\n }\n if (self < other) {\n return -1;\n }\n return 1;\n }\n\n formatAt(index: number, length: number, name: string, value: unknown) {\n if (\n Inline.compare(this.statics.blotName, name) < 0 &&\n this.scroll.query(name, Scope.BLOT)\n ) {\n const blot = this.isolate(index, length);\n if (value) {\n blot.wrap(name, value);\n }\n } else {\n super.formatAt(index, length, name, value);\n }\n }\n\n optimize(context: { [key: string]: any }) {\n super.optimize(context);\n if (\n this.parent instanceof Inline &&\n Inline.compare(this.statics.blotName, this.parent.statics.blotName) > 0\n ) {\n const parent = this.parent.isolate(this.offset(), this.length());\n // @ts-expect-error TODO: make isolate generic\n this.moveChildren(parent);\n parent.wrap(this);\n }\n }\n}\n\nexport default Inline;\n"],"mappings":"AAAA,SAASA,SAAS,EAAEC,UAAU,EAAEC,KAAK,QAAQ,WAAW;AAExD,OAAOC,KAAK,MAAM,YAAY;AAC9B,OAAOC,IAAI,MAAM,WAAW;AAE5B,MAAMC,MAAM,SAASJ,UAAU,CAAC;EAC9B,OAAOK,eAAe,GAAsB,CAACD,MAAM,EAAEF,KAAK,EAAEH,SAAS,EAAEI,IAAI,CAAC;EAC5E;EACA,OAAOG,KAAK,GAAG,CACb,QAAQ,EACR,QAAQ;EAAE;EACV,MAAM;EAAE;EACR,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,MAAM,CAAE;EAAA,CACT;EAED,OAAOC,OAAOA,CAACC,IAAY,EAAEC,KAAa,EAAE;IAC1C,MAAMC,SAAS,GAAGN,MAAM,CAACE,KAAK,CAACK,OAAO,CAACH,IAAI,CAAC;IAC5C,MAAMI,UAAU,GAAGR,MAAM,CAACE,KAAK,CAACK,OAAO,CAACF,KAAK,CAAC;IAC9C,IAAIC,SAAS,IAAI,CAAC,IAAIE,UAAU,IAAI,CAAC,EAAE;MACrC,OAAOF,SAAS,GAAGE,UAAU;IAC/B;IACA,IAAIJ,IAAI,KAAKC,KAAK,EAAE;MAClB,OAAO,CAAC;IACV;IACA,IAAID,IAAI,GAAGC,KAAK,EAAE;MAChB,OAAO,CAAC,CAAC;IACX;IACA,OAAO,CAAC;EACV;EAEAI,QAAQA,CAACC,KAAa,EAAEC,MAAc,EAAEC,IAAY,EAAEC,KAAc,EAAE;IACpE,IACEb,MAAM,CAACG,OAAO,CAAC,IAAI,CAACW,OAAO,CAACC,QAAQ,EAAEH,IAAI,CAAC,GAAG,CAAC,IAC/C,IAAI,CAACI,MAAM,CAACC,KAAK,CAACL,IAAI,EAAEf,KAAK,CAACqB,IAAI,CAAC,EACnC;MACA,MAAMC,IAAI,GAAG,IAAI,CAACC,OAAO,CAACV,KAAK,EAAEC,MAAM,CAAC;MACxC,IAAIE,KAAK,EAAE;QACTM,IAAI,CAACE,IAAI,CAACT,IAAI,EAAEC,KAAK,CAAC;MACxB;IACF,CAAC,MAAM;MACL,KAAK,CAACJ,QAAQ,CAACC,KAAK,EAAEC,MAAM,EAAEC,IAAI,EAAEC,KAAK,CAAC;IAC5C;EACF;EAEAS,QAAQA,CAACC,OAA+B,EAAE;IACxC,KAAK,CAACD,QAAQ,CAACC,OAAO,CAAC;IACvB,IACE,IAAI,CAACC,MAAM,YAAYxB,MAAM,IAC7BA,MAAM,CAACG,OAAO,CAAC,IAAI,CAACW,OAAO,CAACC,QAAQ,EAAE,IAAI,CAACS,MAAM,CAACV,OAAO,CAACC,QAAQ,CAAC,GAAG,CAAC,EACvE;MACA,MAAMS,MAAM,GAAG,IAAI,CAACA,MAAM,CAACJ,OAAO,CAAC,IAAI,CAACK,MAAM,CAAC,CAAC,EAAE,IAAI,CAACd,MAAM,CAAC,CAAC,CAAC;MAChE;MACA,IAAI,CAACe,YAAY,CAACF,MAAM,CAAC;MACzBA,MAAM,CAACH,IAAI,CAAC,IAAI,CAAC;IACnB;EACF;AACF;AAEA,eAAerB,MAAM","ignoreList":[]}
|
||||
49
public/assets/quill/blots/scroll.d.ts
vendored
Normal file
49
public/assets/quill/blots/scroll.d.ts
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
import { LeafBlot, ScrollBlot } from 'parchment';
|
||||
import type { Blot, Registry } from 'parchment';
|
||||
import Delta from 'quill-delta';
|
||||
import Emitter from '../core/emitter.js';
|
||||
import type { EmitterSource } from '../core/emitter.js';
|
||||
import Block, { BlockEmbed } from './block.js';
|
||||
import Container from './container.js';
|
||||
declare class Scroll extends ScrollBlot {
|
||||
static blotName: string;
|
||||
static className: string;
|
||||
static tagName: string;
|
||||
static defaultChild: typeof Block;
|
||||
static allowedChildren: (typeof Block | typeof BlockEmbed | typeof Container)[];
|
||||
emitter: Emitter;
|
||||
batch: false | MutationRecord[];
|
||||
constructor(registry: Registry, domNode: HTMLDivElement, { emitter }: {
|
||||
emitter: Emitter;
|
||||
});
|
||||
batchStart(): void;
|
||||
batchEnd(): void;
|
||||
emitMount(blot: Blot): void;
|
||||
emitUnmount(blot: Blot): void;
|
||||
emitEmbedUpdate(blot: Blot, change: unknown): void;
|
||||
deleteAt(index: number, length: number): void;
|
||||
enable(enabled?: boolean): void;
|
||||
formatAt(index: number, length: number, format: string, value: unknown): void;
|
||||
insertAt(index: number, value: string, def?: unknown): void;
|
||||
insertBefore(blot: Blot, ref?: Blot | null): void;
|
||||
insertContents(index: number, delta: Delta): void;
|
||||
isEnabled(): boolean;
|
||||
leaf(index: number): [LeafBlot | null, number];
|
||||
line(index: number): [Block | BlockEmbed | null, number];
|
||||
lines(index?: number, length?: number): (Block | BlockEmbed)[];
|
||||
optimize(context?: {
|
||||
[key: string]: any;
|
||||
}): void;
|
||||
optimize(mutations?: MutationRecord[], context?: {
|
||||
[key: string]: any;
|
||||
}): void;
|
||||
path(index: number): [Blot, number][];
|
||||
remove(): void;
|
||||
update(source?: EmitterSource): void;
|
||||
update(mutations?: MutationRecord[]): void;
|
||||
updateEmbedAt(index: number, key: string, change: unknown): void;
|
||||
protected handleDragStart(event: DragEvent): void;
|
||||
private deltaToRenderBlocks;
|
||||
private createBlock;
|
||||
}
|
||||
export default Scroll;
|
||||
349
public/assets/quill/blots/scroll.js
Normal file
349
public/assets/quill/blots/scroll.js
Normal file
@@ -0,0 +1,349 @@
|
||||
import { ContainerBlot, LeafBlot, Scope, ScrollBlot } from 'parchment';
|
||||
import Delta, { AttributeMap, Op } from 'quill-delta';
|
||||
import Emitter from '../core/emitter.js';
|
||||
import Block, { BlockEmbed, bubbleFormats } from './block.js';
|
||||
import Break from './break.js';
|
||||
import Container from './container.js';
|
||||
function isLine(blot) {
|
||||
return blot instanceof Block || blot instanceof BlockEmbed;
|
||||
}
|
||||
function isUpdatable(blot) {
|
||||
return typeof blot.updateContent === 'function';
|
||||
}
|
||||
class Scroll extends ScrollBlot {
|
||||
static blotName = 'scroll';
|
||||
static className = 'ql-editor';
|
||||
static tagName = 'DIV';
|
||||
static defaultChild = Block;
|
||||
static allowedChildren = [Block, BlockEmbed, Container];
|
||||
constructor(registry, domNode, _ref) {
|
||||
let {
|
||||
emitter
|
||||
} = _ref;
|
||||
super(registry, domNode);
|
||||
this.emitter = emitter;
|
||||
this.batch = false;
|
||||
this.optimize();
|
||||
this.enable();
|
||||
this.domNode.addEventListener('dragstart', e => this.handleDragStart(e));
|
||||
}
|
||||
batchStart() {
|
||||
if (!Array.isArray(this.batch)) {
|
||||
this.batch = [];
|
||||
}
|
||||
}
|
||||
batchEnd() {
|
||||
if (!this.batch) return;
|
||||
const mutations = this.batch;
|
||||
this.batch = false;
|
||||
this.update(mutations);
|
||||
}
|
||||
emitMount(blot) {
|
||||
this.emitter.emit(Emitter.events.SCROLL_BLOT_MOUNT, blot);
|
||||
}
|
||||
emitUnmount(blot) {
|
||||
this.emitter.emit(Emitter.events.SCROLL_BLOT_UNMOUNT, blot);
|
||||
}
|
||||
emitEmbedUpdate(blot, change) {
|
||||
this.emitter.emit(Emitter.events.SCROLL_EMBED_UPDATE, blot, change);
|
||||
}
|
||||
deleteAt(index, length) {
|
||||
const [first, offset] = this.line(index);
|
||||
const [last] = this.line(index + length);
|
||||
super.deleteAt(index, length);
|
||||
if (last != null && first !== last && offset > 0) {
|
||||
if (first instanceof BlockEmbed || last instanceof BlockEmbed) {
|
||||
this.optimize();
|
||||
return;
|
||||
}
|
||||
const ref = last.children.head instanceof Break ? null : last.children.head;
|
||||
// @ts-expect-error
|
||||
first.moveChildren(last, ref);
|
||||
// @ts-expect-error
|
||||
first.remove();
|
||||
}
|
||||
this.optimize();
|
||||
}
|
||||
enable() {
|
||||
let enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
||||
this.domNode.setAttribute('contenteditable', enabled ? 'true' : 'false');
|
||||
}
|
||||
formatAt(index, length, format, value) {
|
||||
super.formatAt(index, length, format, value);
|
||||
this.optimize();
|
||||
}
|
||||
insertAt(index, value, def) {
|
||||
if (index >= this.length()) {
|
||||
if (def == null || this.scroll.query(value, Scope.BLOCK) == null) {
|
||||
const blot = this.scroll.create(this.statics.defaultChild.blotName);
|
||||
this.appendChild(blot);
|
||||
if (def == null && value.endsWith('\n')) {
|
||||
blot.insertAt(0, value.slice(0, -1), def);
|
||||
} else {
|
||||
blot.insertAt(0, value, def);
|
||||
}
|
||||
} else {
|
||||
const embed = this.scroll.create(value, def);
|
||||
this.appendChild(embed);
|
||||
}
|
||||
} else {
|
||||
super.insertAt(index, value, def);
|
||||
}
|
||||
this.optimize();
|
||||
}
|
||||
insertBefore(blot, ref) {
|
||||
if (blot.statics.scope === Scope.INLINE_BLOT) {
|
||||
const wrapper = this.scroll.create(this.statics.defaultChild.blotName);
|
||||
wrapper.appendChild(blot);
|
||||
super.insertBefore(wrapper, ref);
|
||||
} else {
|
||||
super.insertBefore(blot, ref);
|
||||
}
|
||||
}
|
||||
insertContents(index, delta) {
|
||||
const renderBlocks = this.deltaToRenderBlocks(delta.concat(new Delta().insert('\n')));
|
||||
const last = renderBlocks.pop();
|
||||
if (last == null) return;
|
||||
this.batchStart();
|
||||
const first = renderBlocks.shift();
|
||||
if (first) {
|
||||
const shouldInsertNewlineChar = first.type === 'block' && (first.delta.length() === 0 || !this.descendant(BlockEmbed, index)[0] && index < this.length());
|
||||
const delta = first.type === 'block' ? first.delta : new Delta().insert({
|
||||
[first.key]: first.value
|
||||
});
|
||||
insertInlineContents(this, index, delta);
|
||||
const newlineCharLength = first.type === 'block' ? 1 : 0;
|
||||
const lineEndIndex = index + delta.length() + newlineCharLength;
|
||||
if (shouldInsertNewlineChar) {
|
||||
this.insertAt(lineEndIndex - 1, '\n');
|
||||
}
|
||||
const formats = bubbleFormats(this.line(index)[0]);
|
||||
const attributes = AttributeMap.diff(formats, first.attributes) || {};
|
||||
Object.keys(attributes).forEach(name => {
|
||||
this.formatAt(lineEndIndex - 1, 1, name, attributes[name]);
|
||||
});
|
||||
index = lineEndIndex;
|
||||
}
|
||||
let [refBlot, refBlotOffset] = this.children.find(index);
|
||||
if (renderBlocks.length) {
|
||||
if (refBlot) {
|
||||
refBlot = refBlot.split(refBlotOffset);
|
||||
refBlotOffset = 0;
|
||||
}
|
||||
renderBlocks.forEach(renderBlock => {
|
||||
if (renderBlock.type === 'block') {
|
||||
const block = this.createBlock(renderBlock.attributes, refBlot || undefined);
|
||||
insertInlineContents(block, 0, renderBlock.delta);
|
||||
} else {
|
||||
const blockEmbed = this.create(renderBlock.key, renderBlock.value);
|
||||
this.insertBefore(blockEmbed, refBlot || undefined);
|
||||
Object.keys(renderBlock.attributes).forEach(name => {
|
||||
blockEmbed.format(name, renderBlock.attributes[name]);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
if (last.type === 'block' && last.delta.length()) {
|
||||
const offset = refBlot ? refBlot.offset(refBlot.scroll) + refBlotOffset : this.length();
|
||||
insertInlineContents(this, offset, last.delta);
|
||||
}
|
||||
this.batchEnd();
|
||||
this.optimize();
|
||||
}
|
||||
isEnabled() {
|
||||
return this.domNode.getAttribute('contenteditable') === 'true';
|
||||
}
|
||||
leaf(index) {
|
||||
const last = this.path(index).pop();
|
||||
if (!last) {
|
||||
return [null, -1];
|
||||
}
|
||||
const [blot, offset] = last;
|
||||
return blot instanceof LeafBlot ? [blot, offset] : [null, -1];
|
||||
}
|
||||
line(index) {
|
||||
if (index === this.length()) {
|
||||
return this.line(index - 1);
|
||||
}
|
||||
// @ts-expect-error TODO: make descendant() generic
|
||||
return this.descendant(isLine, index);
|
||||
}
|
||||
lines() {
|
||||
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
||||
let length = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Number.MAX_VALUE;
|
||||
const getLines = (blot, blotIndex, blotLength) => {
|
||||
let lines = [];
|
||||
let lengthLeft = blotLength;
|
||||
blot.children.forEachAt(blotIndex, blotLength, (child, childIndex, childLength) => {
|
||||
if (isLine(child)) {
|
||||
lines.push(child);
|
||||
} else if (child instanceof ContainerBlot) {
|
||||
lines = lines.concat(getLines(child, childIndex, lengthLeft));
|
||||
}
|
||||
lengthLeft -= childLength;
|
||||
});
|
||||
return lines;
|
||||
};
|
||||
return getLines(this, index, length);
|
||||
}
|
||||
optimize() {
|
||||
let mutations = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
||||
let context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||||
if (this.batch) return;
|
||||
super.optimize(mutations, context);
|
||||
if (mutations.length > 0) {
|
||||
this.emitter.emit(Emitter.events.SCROLL_OPTIMIZE, mutations, context);
|
||||
}
|
||||
}
|
||||
path(index) {
|
||||
return super.path(index).slice(1); // Exclude self
|
||||
}
|
||||
remove() {
|
||||
// Never remove self
|
||||
}
|
||||
update(mutations) {
|
||||
if (this.batch) {
|
||||
if (Array.isArray(mutations)) {
|
||||
this.batch = this.batch.concat(mutations);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let source = Emitter.sources.USER;
|
||||
if (typeof mutations === 'string') {
|
||||
source = mutations;
|
||||
}
|
||||
if (!Array.isArray(mutations)) {
|
||||
mutations = this.observer.takeRecords();
|
||||
}
|
||||
mutations = mutations.filter(_ref2 => {
|
||||
let {
|
||||
target
|
||||
} = _ref2;
|
||||
const blot = this.find(target, true);
|
||||
return blot && !isUpdatable(blot);
|
||||
});
|
||||
if (mutations.length > 0) {
|
||||
this.emitter.emit(Emitter.events.SCROLL_BEFORE_UPDATE, source, mutations);
|
||||
}
|
||||
super.update(mutations.concat([])); // pass copy
|
||||
if (mutations.length > 0) {
|
||||
this.emitter.emit(Emitter.events.SCROLL_UPDATE, source, mutations);
|
||||
}
|
||||
}
|
||||
updateEmbedAt(index, key, change) {
|
||||
// Currently it only supports top-level embeds (BlockEmbed).
|
||||
// We can update `ParentBlot` in parchment to support inline embeds.
|
||||
const [blot] = this.descendant(b => b instanceof BlockEmbed, index);
|
||||
if (blot && blot.statics.blotName === key && isUpdatable(blot)) {
|
||||
blot.updateContent(change);
|
||||
}
|
||||
}
|
||||
handleDragStart(event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
deltaToRenderBlocks(delta) {
|
||||
const renderBlocks = [];
|
||||
let currentBlockDelta = new Delta();
|
||||
delta.forEach(op => {
|
||||
const insert = op?.insert;
|
||||
if (!insert) return;
|
||||
if (typeof insert === 'string') {
|
||||
const splitted = insert.split('\n');
|
||||
splitted.slice(0, -1).forEach(text => {
|
||||
currentBlockDelta.insert(text, op.attributes);
|
||||
renderBlocks.push({
|
||||
type: 'block',
|
||||
delta: currentBlockDelta,
|
||||
attributes: op.attributes ?? {}
|
||||
});
|
||||
currentBlockDelta = new Delta();
|
||||
});
|
||||
const last = splitted[splitted.length - 1];
|
||||
if (last) {
|
||||
currentBlockDelta.insert(last, op.attributes);
|
||||
}
|
||||
} else {
|
||||
const key = Object.keys(insert)[0];
|
||||
if (!key) return;
|
||||
if (this.query(key, Scope.INLINE)) {
|
||||
currentBlockDelta.push(op);
|
||||
} else {
|
||||
if (currentBlockDelta.length()) {
|
||||
renderBlocks.push({
|
||||
type: 'block',
|
||||
delta: currentBlockDelta,
|
||||
attributes: {}
|
||||
});
|
||||
}
|
||||
currentBlockDelta = new Delta();
|
||||
renderBlocks.push({
|
||||
type: 'blockEmbed',
|
||||
key,
|
||||
value: insert[key],
|
||||
attributes: op.attributes ?? {}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
if (currentBlockDelta.length()) {
|
||||
renderBlocks.push({
|
||||
type: 'block',
|
||||
delta: currentBlockDelta,
|
||||
attributes: {}
|
||||
});
|
||||
}
|
||||
return renderBlocks;
|
||||
}
|
||||
createBlock(attributes, refBlot) {
|
||||
let blotName;
|
||||
const formats = {};
|
||||
Object.entries(attributes).forEach(_ref3 => {
|
||||
let [key, value] = _ref3;
|
||||
const isBlockBlot = this.query(key, Scope.BLOCK & Scope.BLOT) != null;
|
||||
if (isBlockBlot) {
|
||||
blotName = key;
|
||||
} else {
|
||||
formats[key] = value;
|
||||
}
|
||||
});
|
||||
const block = this.create(blotName || this.statics.defaultChild.blotName, blotName ? attributes[blotName] : undefined);
|
||||
this.insertBefore(block, refBlot || undefined);
|
||||
const length = block.length();
|
||||
Object.entries(formats).forEach(_ref4 => {
|
||||
let [key, value] = _ref4;
|
||||
block.formatAt(0, length, key, value);
|
||||
});
|
||||
return block;
|
||||
}
|
||||
}
|
||||
function insertInlineContents(parent, index, inlineContents) {
|
||||
inlineContents.reduce((index, op) => {
|
||||
const length = Op.length(op);
|
||||
let attributes = op.attributes || {};
|
||||
if (op.insert != null) {
|
||||
if (typeof op.insert === 'string') {
|
||||
const text = op.insert;
|
||||
parent.insertAt(index, text);
|
||||
const [leaf] = parent.descendant(LeafBlot, index);
|
||||
const formats = bubbleFormats(leaf);
|
||||
attributes = AttributeMap.diff(formats, attributes) || {};
|
||||
} else if (typeof op.insert === 'object') {
|
||||
const key = Object.keys(op.insert)[0]; // There should only be one key
|
||||
if (key == null) return index;
|
||||
parent.insertAt(index, key, op.insert[key]);
|
||||
const isInlineEmbed = parent.scroll.query(key, Scope.INLINE) != null;
|
||||
if (isInlineEmbed) {
|
||||
const [leaf] = parent.descendant(LeafBlot, index);
|
||||
const formats = bubbleFormats(leaf);
|
||||
attributes = AttributeMap.diff(formats, attributes) || {};
|
||||
}
|
||||
}
|
||||
}
|
||||
Object.keys(attributes).forEach(key => {
|
||||
parent.formatAt(index, length, key, attributes[key]);
|
||||
});
|
||||
return index + length;
|
||||
}, index);
|
||||
}
|
||||
export default Scroll;
|
||||
//# sourceMappingURL=scroll.js.map
|
||||
1
public/assets/quill/blots/scroll.js.map
Normal file
1
public/assets/quill/blots/scroll.js.map
Normal file
File diff suppressed because one or more lines are too long
5
public/assets/quill/blots/text.d.ts
vendored
Normal file
5
public/assets/quill/blots/text.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { TextBlot } from 'parchment';
|
||||
declare class Text extends TextBlot {
|
||||
}
|
||||
declare function escapeText(text: string): string;
|
||||
export { Text as default, escapeText };
|
||||
16
public/assets/quill/blots/text.js
Normal file
16
public/assets/quill/blots/text.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import { TextBlot } from 'parchment';
|
||||
class Text extends TextBlot {}
|
||||
|
||||
// https://lodash.com/docs#escape
|
||||
const entityMap = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": '''
|
||||
};
|
||||
function escapeText(text) {
|
||||
return text.replace(/[&<>"']/g, s => entityMap[s]);
|
||||
}
|
||||
export { Text as default, escapeText };
|
||||
//# sourceMappingURL=text.js.map
|
||||
1
public/assets/quill/blots/text.js.map
Normal file
1
public/assets/quill/blots/text.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"text.js","names":["TextBlot","Text","entityMap","escapeText","text","replace","s","default"],"sources":["../../src/blots/text.ts"],"sourcesContent":["import { TextBlot } from 'parchment';\n\nclass Text extends TextBlot {}\n\n// https://lodash.com/docs#escape\nconst entityMap: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n};\n\nfunction escapeText(text: string) {\n return text.replace(/[&<>\"']/g, (s) => entityMap[s]);\n}\n\nexport { Text as default, escapeText };\n"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,WAAW;AAEpC,MAAMC,IAAI,SAASD,QAAQ,CAAC;;AAE5B;AACA,MAAME,SAAiC,GAAG;EACxC,GAAG,EAAE,OAAO;EACZ,GAAG,EAAE,MAAM;EACX,GAAG,EAAE,MAAM;EACX,GAAG,EAAE,QAAQ;EACb,GAAG,EAAE;AACP,CAAC;AAED,SAASC,UAAUA,CAACC,IAAY,EAAE;EAChC,OAAOA,IAAI,CAACC,OAAO,CAAC,UAAU,EAAGC,CAAC,IAAKJ,SAAS,CAACI,CAAC,CAAC,CAAC;AACtD;AAEA,SAASL,IAAI,IAAIM,OAAO,EAAEJ,UAAU","ignoreList":[]}
|
||||
Reference in New Issue
Block a user