Latest repo

This commit is contained in:
Marc
2025-06-02 16:42:16 +00:00
parent 53ddf1a329
commit cde5fae175
27907 changed files with 3875388 additions and 1 deletions

61
node_modules/parchment/src/attributor/attributor.ts generated vendored Normal file
View File

@@ -0,0 +1,61 @@
import * as Registry from '../registry';
export interface AttributorOptions {
scope?: Registry.Scope;
whitelist?: string[];
}
export default class Attributor {
attrName: string;
keyName: string;
scope: Registry.Scope;
whitelist: string[] | undefined;
static keys(node: HTMLElement): string[] {
return [].map.call(node.attributes, function(item: Attr) {
return item.name;
});
}
constructor(attrName: string, keyName: string, options: AttributorOptions = {}) {
this.attrName = attrName;
this.keyName = keyName;
let attributeBit = Registry.Scope.TYPE & Registry.Scope.ATTRIBUTE;
if (options.scope != null) {
// Ignore type bits, force attribute bit
this.scope = (options.scope & Registry.Scope.LEVEL) | attributeBit;
} else {
this.scope = Registry.Scope.ATTRIBUTE;
}
if (options.whitelist != null) this.whitelist = options.whitelist;
}
add(node: HTMLElement, value: string): boolean {
if (!this.canAdd(node, value)) return false;
node.setAttribute(this.keyName, value);
return true;
}
canAdd(node: HTMLElement, value: any): boolean {
let match = Registry.query(node, Registry.Scope.BLOT & (this.scope | Registry.Scope.TYPE));
if (match == null) return false;
if (this.whitelist == null) return true;
if (typeof value === 'string') {
return this.whitelist.indexOf(value.replace(/["']/g, '')) > -1;
} else {
return this.whitelist.indexOf(value) > -1;
}
}
remove(node: HTMLElement): void {
node.removeAttribute(this.keyName);
}
value(node: HTMLElement): string {
let value = node.getAttribute(this.keyName);
if (this.canAdd(node, value) && value) {
return value;
}
return '';
}
}

44
node_modules/parchment/src/attributor/class.ts generated vendored Normal file
View File

@@ -0,0 +1,44 @@
import Attributor from './attributor';
function match(node: HTMLElement, prefix: string): string[] {
let className = node.getAttribute('class') || '';
return className.split(/\s+/).filter(function(name) {
return name.indexOf(`${prefix}-`) === 0;
});
}
class ClassAttributor extends Attributor {
static keys(node: HTMLElement): string[] {
return (node.getAttribute('class') || '').split(/\s+/).map(function(name) {
return name
.split('-')
.slice(0, -1)
.join('-');
});
}
add(node: HTMLElement, value: string): boolean {
if (!this.canAdd(node, value)) return false;
this.remove(node);
node.classList.add(`${this.keyName}-${value}`);
return true;
}
remove(node: HTMLElement): void {
let matches = match(node, this.keyName);
matches.forEach(function(name) {
node.classList.remove(name);
});
if (node.classList.length === 0) {
node.removeAttribute('class');
}
}
value(node: HTMLElement): string {
let result = match(node, this.keyName)[0] || '';
let value = result.slice(this.keyName.length + 1); // +1 for hyphen
return this.canAdd(node, value) ? value : '';
}
}
export default ClassAttributor;

73
node_modules/parchment/src/attributor/store.ts generated vendored Normal file
View File

@@ -0,0 +1,73 @@
import Attributor from './attributor';
import ClassAttributor from './class';
import StyleAttributor from './style';
import { Formattable } from '../blot/abstract/blot';
import * as Registry from '../registry';
class AttributorStore {
private attributes: { [key: string]: Attributor } = {};
private domNode: HTMLElement;
constructor(domNode: HTMLElement) {
this.domNode = domNode;
this.build();
}
attribute(attribute: Attributor, value: any): void {
// verb
if (value) {
if (attribute.add(this.domNode, value)) {
if (attribute.value(this.domNode) != null) {
this.attributes[attribute.attrName] = attribute;
} else {
delete this.attributes[attribute.attrName];
}
}
} else {
attribute.remove(this.domNode);
delete this.attributes[attribute.attrName];
}
}
build(): void {
this.attributes = {};
let attributes = Attributor.keys(this.domNode);
let classes = ClassAttributor.keys(this.domNode);
let styles = StyleAttributor.keys(this.domNode);
attributes
.concat(classes)
.concat(styles)
.forEach(name => {
let attr = Registry.query(name, Registry.Scope.ATTRIBUTE);
if (attr instanceof Attributor) {
this.attributes[attr.attrName] = attr;
}
});
}
copy(target: Formattable): void {
Object.keys(this.attributes).forEach(key => {
let value = this.attributes[key].value(this.domNode);
target.format(key, value);
});
}
move(target: Formattable): void {
this.copy(target);
Object.keys(this.attributes).forEach(key => {
this.attributes[key].remove(this.domNode);
});
this.attributes = {};
}
values(): { [key: string]: any } {
return Object.keys(
this.attributes,
).reduce((attributes: { [key: string]: any }, name: string) => {
attributes[name] = this.attributes[name].value(this.domNode);
return attributes;
}, {});
}
}
export default AttributorStore;

44
node_modules/parchment/src/attributor/style.ts generated vendored Normal file
View File

@@ -0,0 +1,44 @@
import Attributor from './attributor';
function camelize(name: string): string {
let parts = name.split('-');
let rest = parts
.slice(1)
.map(function(part: string) {
return part[0].toUpperCase() + part.slice(1);
})
.join('');
return parts[0] + rest;
}
class StyleAttributor extends Attributor {
static keys(node: Element): string[] {
return (node.getAttribute('style') || '').split(';').map(function(value) {
let arr = value.split(':');
return arr[0].trim();
});
}
add(node: HTMLElement, value: string): boolean {
if (!this.canAdd(node, value)) return false;
// @ts-ignore
node.style[camelize(this.keyName)] = value;
return true;
}
remove(node: HTMLElement): void {
// @ts-ignore
node.style[camelize(this.keyName)] = '';
if (!node.getAttribute('style')) {
node.removeAttribute('style');
}
}
value(node: HTMLElement): string {
// @ts-ignore
let value = node.style[camelize(this.keyName)];
return this.canAdd(node, value) ? value : '';
}
}
export default StyleAttributor;

58
node_modules/parchment/src/blot/abstract/blot.ts generated vendored Normal file
View File

@@ -0,0 +1,58 @@
import LinkedList from '../../collection/linked-list';
import LinkedNode from '../../collection/linked-node';
export interface Blot extends LinkedNode {
scroll: Parent;
parent: Parent;
prev: Blot;
next: Blot;
domNode: Node;
attach(): void;
clone(): Blot;
detach(): void;
insertInto(parentBlot: Parent, refBlot?: Blot): void;
isolate(index: number, length: number): Blot;
offset(root?: Blot): number;
remove(): void;
replace(target: Blot): void;
replaceWith(name: string, value: any): Blot;
replaceWith(replacement: Blot): Blot;
split(index: number, force?: boolean): Blot;
wrap(name: string, value: any): Parent;
wrap(wrapper: Parent): Parent;
deleteAt(index: number, length: number): void;
formatAt(index: number, length: number, name: string, value: any): void;
insertAt(index: number, value: string, def?: any): void;
optimize(context: { [key: string]: any }): void;
optimize(mutations: MutationRecord[], context: { [key: string]: any }): void;
update(mutations: MutationRecord[], context: { [key: string]: any }): void;
}
export interface Parent extends Blot {
children: LinkedList<Blot>;
domNode: HTMLElement;
appendChild(child: Blot): void;
descendant<T>(type: { new (): T }, index: number): [T, number];
descendant<T>(matcher: (blot: Blot) => boolean, index: number): [T, number];
descendants<T>(type: { new (): T }, index: number, length: number): T[];
descendants<T>(matcher: (blot: Blot) => boolean, index: number, length: number): T[];
insertBefore(child: Blot, refNode?: Blot): void;
moveChildren(parent: Parent, refNode?: Blot): void;
path(index: number, inclusive?: boolean): [Blot, number][];
removeChild(child: Blot): void;
unwrap(): void;
}
export interface Formattable extends Blot {
format(name: string, value: any): void;
formats(): { [index: string]: any };
}
export interface Leaf extends Blot {
index(node: Node, offset: number): number;
position(index: number, inclusive: boolean): [Node, number];
value(): any;
}

268
node_modules/parchment/src/blot/abstract/container.ts generated vendored Normal file
View File

@@ -0,0 +1,268 @@
import { Blot, Parent, Leaf } from './blot';
import LinkedList from '../../collection/linked-list';
import ShadowBlot from './shadow';
import * as Registry from '../../registry';
class ContainerBlot extends ShadowBlot implements Parent {
static defaultChild: string;
static allowedChildren: any[];
children!: LinkedList<Blot>;
domNode!: HTMLElement;
constructor(domNode: Node) {
super(domNode);
this.build();
}
appendChild(other: Blot): void {
this.insertBefore(other);
}
attach(): void {
super.attach();
this.children.forEach(child => {
child.attach();
});
}
build(): void {
this.children = new LinkedList<Blot>();
// Need to be reversed for if DOM nodes already in order
[].slice
.call(this.domNode.childNodes)
.reverse()
.forEach((node: Node) => {
try {
let child = makeBlot(node);
this.insertBefore(child, this.children.head || undefined);
} catch (err) {
if (err instanceof Registry.ParchmentError) return;
else throw err;
}
});
}
deleteAt(index: number, length: number): void {
if (index === 0 && length === this.length()) {
return this.remove();
}
this.children.forEachAt(index, length, function(child, offset, length) {
child.deleteAt(offset, length);
});
}
descendant(criteria: { new (): Blot }, index: number): [Blot | null, number];
descendant(criteria: (blot: Blot) => boolean, index: number): [Blot | null, number];
descendant(criteria: any, index: number): [Blot | null, number] {
let [child, offset] = this.children.find(index);
if (
(criteria.blotName == null && criteria(child)) ||
(criteria.blotName != null && child instanceof criteria)
) {
return [<any>child, offset];
} else if (child instanceof ContainerBlot) {
return child.descendant(criteria, offset);
} else {
return [null, -1];
}
}
descendants(criteria: { new (): Blot }, index: number, length: number): Blot[];
descendants(criteria: (blot: Blot) => boolean, index: number, length: number): Blot[];
descendants(criteria: any, index: number = 0, length: number = Number.MAX_VALUE): Blot[] {
let descendants: Blot[] = [];
let lengthLeft = length;
this.children.forEachAt(index, length, function(child: Blot, index: number, length: number) {
if (
(criteria.blotName == null && criteria(child)) ||
(criteria.blotName != null && child instanceof criteria)
) {
descendants.push(child);
}
if (child instanceof ContainerBlot) {
descendants = descendants.concat(child.descendants(criteria, index, lengthLeft));
}
lengthLeft -= length;
});
return descendants;
}
detach(): void {
this.children.forEach(function(child) {
child.detach();
});
super.detach();
}
formatAt(index: number, length: number, name: string, value: any): void {
this.children.forEachAt(index, length, function(child, offset, length) {
child.formatAt(offset, length, name, value);
});
}
insertAt(index: number, value: string, def?: any): void {
let [child, offset] = this.children.find(index);
if (child) {
child.insertAt(offset, value, def);
} else {
let blot = def == null ? Registry.create('text', value) : Registry.create(value, def);
this.appendChild(blot);
}
}
insertBefore(childBlot: Blot, refBlot?: Blot): void {
if (
this.statics.allowedChildren != null &&
!this.statics.allowedChildren.some(function(child: Registry.BlotConstructor) {
return childBlot instanceof child;
})
) {
throw new Registry.ParchmentError(
`Cannot insert ${(<ShadowBlot>childBlot).statics.blotName} into ${this.statics.blotName}`,
);
}
childBlot.insertInto(this, refBlot);
}
length(): number {
return this.children.reduce(function(memo, child) {
return memo + child.length();
}, 0);
}
moveChildren(targetParent: Parent, refNode?: Blot): void {
this.children.forEach(function(child) {
targetParent.insertBefore(child, refNode);
});
}
optimize(context: { [key: string]: any }) {
super.optimize(context);
if (this.children.length === 0) {
if (this.statics.defaultChild != null) {
let child = Registry.create(this.statics.defaultChild);
this.appendChild(child);
child.optimize(context);
} else {
this.remove();
}
}
}
path(index: number, inclusive: boolean = false): [Blot, number][] {
let [child, offset] = this.children.find(index, inclusive);
let position: [Blot, number][] = [[this, index]];
if (child instanceof ContainerBlot) {
return position.concat(child.path(offset, inclusive));
} else if (child != null) {
position.push([child, offset]);
}
return position;
}
removeChild(child: Blot): void {
this.children.remove(child);
}
replace(target: Blot): void {
if (target instanceof ContainerBlot) {
target.moveChildren(this);
}
super.replace(target);
}
split(index: number, force: boolean = false): Blot {
if (!force) {
if (index === 0) return this;
if (index === this.length()) return this.next;
}
let after = <ContainerBlot>this.clone();
this.parent.insertBefore(after, this.next);
this.children.forEachAt(index, this.length(), function(child, offset, length) {
child = child.split(offset, force);
after.appendChild(child);
});
return after;
}
unwrap(): void {
this.moveChildren(this.parent, this.next);
this.remove();
}
update(mutations: MutationRecord[], context: { [key: string]: any }): void {
let addedNodes: Node[] = [];
let removedNodes: Node[] = [];
mutations.forEach(mutation => {
if (mutation.target === this.domNode && mutation.type === 'childList') {
addedNodes.push.apply(addedNodes, mutation.addedNodes);
removedNodes.push.apply(removedNodes, mutation.removedNodes);
}
});
removedNodes.forEach((node: Node) => {
// Check node has actually been removed
// One exception is Chrome does not immediately remove IFRAMEs
// from DOM but MutationRecord is correct in its reported removal
if (
node.parentNode != null &&
// @ts-ignore
node.tagName !== 'IFRAME' &&
document.body.compareDocumentPosition(node) & Node.DOCUMENT_POSITION_CONTAINED_BY
) {
return;
}
let blot = Registry.find(node);
if (blot == null) return;
if (blot.domNode.parentNode == null || blot.domNode.parentNode === this.domNode) {
blot.detach();
}
});
addedNodes
.filter(node => {
return node.parentNode == this.domNode;
})
.sort(function(a, b) {
if (a === b) return 0;
if (a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING) {
return 1;
}
return -1;
})
.forEach(node => {
let refBlot: Blot | null = null;
if (node.nextSibling != null) {
refBlot = Registry.find(node.nextSibling);
}
let blot = makeBlot(node);
if (blot.next != refBlot || blot.next == null) {
if (blot.parent != null) {
blot.parent.removeChild(this);
}
this.insertBefore(blot, refBlot || undefined);
}
});
}
}
function makeBlot(node: Node): Blot {
let blot = Registry.find(node);
if (blot == null) {
try {
blot = Registry.create(node);
} catch (e) {
blot = Registry.create(Registry.Scope.INLINE);
[].slice.call(node.childNodes).forEach(function(child: Node) {
// @ts-ignore
blot.domNode.appendChild(child);
});
if (node.parentNode) {
node.parentNode.replaceChild(blot.domNode, node);
}
blot.attach();
}
}
return blot;
}
export default ContainerBlot;

71
node_modules/parchment/src/blot/abstract/format.ts generated vendored Normal file
View File

@@ -0,0 +1,71 @@
import Attributor from '../../attributor/attributor';
import AttributorStore from '../../attributor/store';
import { Blot, Parent, Formattable } from './blot';
import ContainerBlot from './container';
import ShadowBlot from './shadow';
import * as Registry from '../../registry';
class FormatBlot extends ContainerBlot implements Formattable {
protected attributes: AttributorStore;
static formats(domNode: HTMLElement): any {
if (typeof this.tagName === 'string') {
return true;
} else if (Array.isArray(this.tagName)) {
return domNode.tagName.toLowerCase();
}
return undefined;
}
constructor(domNode: Node) {
super(domNode);
this.attributes = new AttributorStore(this.domNode);
}
format(name: string, value: any): void {
let format = Registry.query(name);
if (format instanceof Attributor) {
this.attributes.attribute(format, value);
} else if (value) {
if (format != null && (name !== this.statics.blotName || this.formats()[name] !== value)) {
this.replaceWith(name, value);
}
}
}
formats(): { [index: string]: any } {
let formats = this.attributes.values();
let format = this.statics.formats(this.domNode);
if (format != null) {
formats[this.statics.blotName] = format;
}
return formats;
}
replaceWith(name: string | Blot, value?: any): Blot {
let replacement = <FormatBlot>super.replaceWith(name, value);
this.attributes.copy(replacement);
return replacement;
}
update(mutations: MutationRecord[], context: { [key: string]: any }): void {
super.update(mutations, context);
if (
mutations.some(mutation => {
return mutation.target === this.domNode && mutation.type === 'attributes';
})
) {
this.attributes.build();
}
}
wrap(name: string | Parent, value?: any): Parent {
let wrapper = super.wrap(name, value);
if (wrapper instanceof FormatBlot && wrapper.statics.scope === this.statics.scope) {
this.attributes.move(wrapper);
}
return wrapper;
}
}
export default FormatBlot;

33
node_modules/parchment/src/blot/abstract/leaf.ts generated vendored Normal file
View File

@@ -0,0 +1,33 @@
import { Formattable, Leaf } from './blot';
import ShadowBlot from './shadow';
import * as Registry from '../../registry';
class LeafBlot extends ShadowBlot implements Leaf {
static scope = Registry.Scope.INLINE_BLOT;
static value(domNode: Node): any {
return true;
}
index(node: Node, offset: number): number {
if (
this.domNode === node ||
this.domNode.compareDocumentPosition(node) & Node.DOCUMENT_POSITION_CONTAINED_BY
) {
return Math.min(offset, 1);
}
return -1;
}
position(index: number, inclusive?: boolean): [Node, number] {
let offset = [].indexOf.call(this.parent.domNode.childNodes, this.domNode);
if (index > 0) offset += 1;
return [this.parent.domNode, offset];
}
value(): any {
return { [this.statics.blotName]: this.statics.value(this.domNode) || true };
}
}
export default LeafBlot;

174
node_modules/parchment/src/blot/abstract/shadow.ts generated vendored Normal file
View File

@@ -0,0 +1,174 @@
import { Blot, Parent, Formattable } from './blot';
import * as Registry from '../../registry';
class ShadowBlot implements Blot {
static blotName = 'abstract';
static className: string;
static scope: Registry.Scope;
static tagName: string;
// @ts-ignore
prev: Blot;
// @ts-ignore
next: Blot;
// @ts-ignore
parent: Parent;
// @ts-ignore
scroll: Parent;
// Hack for accessing inherited static methods
get statics(): any {
return this.constructor;
}
static create(value: any): Node {
if (this.tagName == null) {
throw new Registry.ParchmentError('Blot definition missing tagName');
}
let node;
if (Array.isArray(this.tagName)) {
if (typeof value === 'string') {
value = value.toUpperCase();
if (parseInt(value).toString() === value) {
value = parseInt(value);
}
}
if (typeof value === 'number') {
node = document.createElement(this.tagName[value - 1]);
} else if (this.tagName.indexOf(value) > -1) {
node = document.createElement(value);
} else {
node = document.createElement(this.tagName[0]);
}
} else {
node = document.createElement(this.tagName);
}
if (this.className) {
node.classList.add(this.className);
}
return node;
}
constructor(public domNode: Node) {
// @ts-ignore
this.domNode[Registry.DATA_KEY] = { blot: this };
}
attach(): void {
if (this.parent != null) {
this.scroll = this.parent.scroll;
}
}
clone(): Blot {
let domNode = this.domNode.cloneNode(false);
return Registry.create(domNode);
}
detach() {
if (this.parent != null) this.parent.removeChild(this);
// @ts-ignore
delete this.domNode[Registry.DATA_KEY];
}
deleteAt(index: number, length: number): void {
let blot = this.isolate(index, length);
blot.remove();
}
formatAt(index: number, length: number, name: string, value: any): void {
let blot = this.isolate(index, length);
if (Registry.query(name, Registry.Scope.BLOT) != null && value) {
blot.wrap(name, value);
} else if (Registry.query(name, Registry.Scope.ATTRIBUTE) != null) {
let parent = <Parent & Formattable>Registry.create(this.statics.scope);
blot.wrap(parent);
parent.format(name, value);
}
}
insertAt(index: number, value: string, def?: any): void {
let blot = def == null ? Registry.create('text', value) : Registry.create(value, def);
let ref = this.split(index);
this.parent.insertBefore(blot, ref);
}
insertInto(parentBlot: Parent, refBlot: Blot | null = null): void {
if (this.parent != null) {
this.parent.children.remove(this);
}
let refDomNode: Node | null = null;
parentBlot.children.insertBefore(this, refBlot);
if (refBlot != null) {
refDomNode = refBlot.domNode;
}
if (this.domNode.parentNode != parentBlot.domNode ||
this.domNode.nextSibling != refDomNode) {
parentBlot.domNode.insertBefore(this.domNode, refDomNode);
}
this.parent = parentBlot;
this.attach();
}
isolate(index: number, length: number): Blot {
let target = this.split(index);
target.split(length);
return target;
}
length(): number {
return 1;
}
offset(root: Blot = this.parent): number {
if (this.parent == null || this == root) return 0;
return this.parent.children.offset(this) + this.parent.offset(root);
}
optimize(context: { [key: string]: any }): void {
// TODO clean up once we use WeakMap
// @ts-ignore
if (this.domNode[Registry.DATA_KEY] != null) {
// @ts-ignore
delete this.domNode[Registry.DATA_KEY].mutations;
}
}
remove(): void {
if (this.domNode.parentNode != null) {
this.domNode.parentNode.removeChild(this.domNode);
}
this.detach();
}
replace(target: Blot): void {
if (target.parent == null) return;
target.parent.insertBefore(this, target.next);
target.remove();
}
replaceWith(name: string | Blot, value?: any): Blot {
let replacement = typeof name === 'string' ? Registry.create(name, value) : name;
replacement.replace(this);
return replacement;
}
split(index: number, force?: boolean): Blot {
return index === 0 ? this : this.next;
}
update(mutations: MutationRecord[], context: { [key: string]: any }): void {
// Nothing to do by default
}
wrap(name: string | Parent, value?: any): Parent {
let wrapper = typeof name === 'string' ? <Parent>Registry.create(name, value) : name;
if (this.parent != null) {
this.parent.insertBefore(wrapper, this.next);
}
wrapper.appendChild(this);
return wrapper;
}
}
export default ShadowBlot;

53
node_modules/parchment/src/blot/block.ts generated vendored Normal file
View File

@@ -0,0 +1,53 @@
import FormatBlot from './abstract/format';
import * as Registry from '../registry';
class BlockBlot extends FormatBlot {
static blotName = 'block';
static scope = Registry.Scope.BLOCK_BLOT;
static tagName = 'P';
static formats(domNode: HTMLElement): any {
let tagName = (<any>Registry.query(BlockBlot.blotName)).tagName;
if (domNode.tagName === tagName) return undefined;
return super.formats(domNode);
}
format(name: string, value: any) {
if (Registry.query(name, Registry.Scope.BLOCK) == null) {
return;
} else if (name === this.statics.blotName && !value) {
this.replaceWith(BlockBlot.blotName);
} else {
super.format(name, value);
}
}
formatAt(index: number, length: number, name: string, value: any): void {
if (Registry.query(name, Registry.Scope.BLOCK) != null) {
this.format(name, value);
} else {
super.formatAt(index, length, name, value);
}
}
insertAt(index: number, value: string, def?: any): void {
if (def == null || Registry.query(value, Registry.Scope.INLINE) != null) {
// Insert text or inline
super.insertAt(index, value, def);
} else {
let after = this.split(index);
let blot = Registry.create(value, def);
after.parent.insertBefore(blot, after);
}
}
update(mutations: MutationRecord[], context: { [key: string]: any }): void {
if (navigator.userAgent.match(/Trident/)) {
this.build();
} else {
super.update(mutations, context);
}
}
}
export default BlockBlot;

29
node_modules/parchment/src/blot/embed.ts generated vendored Normal file
View File

@@ -0,0 +1,29 @@
import { Formattable } from './abstract/blot';
import LeafBlot from './abstract/leaf';
class EmbedBlot extends LeafBlot implements Formattable {
static formats(domNode: HTMLElement): any {
return undefined;
}
format(name: string, value: any): void {
// super.formatAt wraps, which is what we want in general,
// but this allows subclasses to overwrite for formats
// that just apply to particular embeds
super.formatAt(0, this.length(), name, value);
}
formatAt(index: number, length: number, name: string, value: any): void {
if (index === 0 && length === this.length()) {
this.format(name, value);
} else {
super.formatAt(index, length, name, value);
}
}
formats(): { [index: string]: any } {
return this.statics.formats(this.domNode);
}
}
export default EmbedBlot;

64
node_modules/parchment/src/blot/inline.ts generated vendored Normal file
View File

@@ -0,0 +1,64 @@
import FormatBlot from './abstract/format';
import LeafBlot from './abstract/leaf';
import ShadowBlot from './abstract/shadow';
import * as Registry from '../registry';
// Shallow object comparison
function isEqual(obj1: Object, obj2: Object): boolean {
if (Object.keys(obj1).length !== Object.keys(obj2).length) return false;
// @ts-ignore
for (let prop in obj1) {
// @ts-ignore
if (obj1[prop] !== obj2[prop]) return false;
}
return true;
}
class InlineBlot extends FormatBlot {
static blotName = 'inline';
static scope = Registry.Scope.INLINE_BLOT;
static tagName = 'SPAN';
static formats(domNode: HTMLElement): any {
if (domNode.tagName === InlineBlot.tagName) return undefined;
return super.formats(domNode);
}
format(name: string, value: any) {
if (name === this.statics.blotName && !value) {
this.children.forEach(child => {
if (!(child instanceof FormatBlot)) {
child = child.wrap(InlineBlot.blotName, true);
}
this.attributes.copy(<FormatBlot>child);
});
this.unwrap();
} else {
super.format(name, value);
}
}
formatAt(index: number, length: number, name: string, value: any): void {
if (this.formats()[name] != null || Registry.query(name, Registry.Scope.ATTRIBUTE)) {
let blot = <InlineBlot>this.isolate(index, length);
blot.format(name, value);
} else {
super.formatAt(index, length, name, value);
}
}
optimize(context: { [key: string]: any }): void {
super.optimize(context);
let formats = this.formats();
if (Object.keys(formats).length === 0) {
return this.unwrap(); // unformatted span
}
let next = this.next;
if (next instanceof InlineBlot && next.prev === this && isEqual(formats, next.formats())) {
next.moveChildren(this);
next.remove();
}
}
}
export default InlineBlot;

166
node_modules/parchment/src/blot/scroll.ts generated vendored Normal file
View File

@@ -0,0 +1,166 @@
import { Blot } from './abstract/blot';
import ContainerBlot from './abstract/container';
import LinkedList from '../collection/linked-list';
import * as Registry from '../registry';
const OBSERVER_CONFIG = {
attributes: true,
characterData: true,
characterDataOldValue: true,
childList: true,
subtree: true,
};
const MAX_OPTIMIZE_ITERATIONS = 100;
class ScrollBlot extends ContainerBlot {
static blotName = 'scroll';
static defaultChild = 'block';
static scope = Registry.Scope.BLOCK_BLOT;
static tagName = 'DIV';
observer: MutationObserver;
constructor(node: HTMLDivElement) {
super(node);
this.scroll = this;
this.observer = new MutationObserver((mutations: MutationRecord[]) => {
this.update(mutations);
});
this.observer.observe(this.domNode, OBSERVER_CONFIG);
this.attach();
}
detach() {
super.detach();
this.observer.disconnect();
}
deleteAt(index: number, length: number): void {
this.update();
if (index === 0 && length === this.length()) {
this.children.forEach(function(child) {
child.remove();
});
} else {
super.deleteAt(index, length);
}
}
formatAt(index: number, length: number, name: string, value: any): void {
this.update();
super.formatAt(index, length, name, value);
}
insertAt(index: number, value: string, def?: any): void {
this.update();
super.insertAt(index, value, def);
}
optimize(context: { [key: string]: any }): void;
optimize(mutations: MutationRecord[], context: { [key: string]: any }): void;
optimize(mutations: any = [], context: any = {}): void {
super.optimize(context);
// We must modify mutations directly, cannot make copy and then modify
let records = [].slice.call(this.observer.takeRecords());
// Array.push currently seems to be implemented by a non-tail recursive function
// so we cannot just mutations.push.apply(mutations, this.observer.takeRecords());
while (records.length > 0) mutations.push(records.pop());
// TODO use WeakMap
let mark = (blot: Blot | null, markParent: boolean = true) => {
if (blot == null || blot === this) return;
if (blot.domNode.parentNode == null) return;
// @ts-ignore
if (blot.domNode[Registry.DATA_KEY].mutations == null) {
// @ts-ignore
blot.domNode[Registry.DATA_KEY].mutations = [];
}
if (markParent) mark(blot.parent);
};
let optimize = function(blot: Blot) {
// Post-order traversal
if (
// @ts-ignore
blot.domNode[Registry.DATA_KEY] == null ||
// @ts-ignore
blot.domNode[Registry.DATA_KEY].mutations == null
) {
return;
}
if (blot instanceof ContainerBlot) {
blot.children.forEach(optimize);
}
blot.optimize(context);
};
let remaining = mutations;
for (let i = 0; remaining.length > 0; i += 1) {
if (i >= MAX_OPTIMIZE_ITERATIONS) {
throw new Error('[Parchment] Maximum optimize iterations reached');
}
remaining.forEach(function(mutation: MutationRecord) {
let blot = Registry.find(mutation.target, true);
if (blot == null) return;
if (blot.domNode === mutation.target) {
if (mutation.type === 'childList') {
mark(Registry.find(mutation.previousSibling, false));
[].forEach.call(mutation.addedNodes, function(node: Node) {
let child = Registry.find(node, false);
mark(child, false);
if (child instanceof ContainerBlot) {
child.children.forEach(function(grandChild: Blot) {
mark(grandChild, false);
});
}
});
} else if (mutation.type === 'attributes') {
mark(blot.prev);
}
}
mark(blot);
});
this.children.forEach(optimize);
remaining = [].slice.call(this.observer.takeRecords());
records = remaining.slice();
while (records.length > 0) mutations.push(records.pop());
}
}
update(mutations?: MutationRecord[], context: { [key: string]: any } = {}): void {
mutations = mutations || this.observer.takeRecords();
// TODO use WeakMap
mutations
.map(function(mutation: MutationRecord) {
let blot = Registry.find(mutation.target, true);
if (blot == null) return null;
// @ts-ignore
if (blot.domNode[Registry.DATA_KEY].mutations == null) {
// @ts-ignore
blot.domNode[Registry.DATA_KEY].mutations = [mutation];
return blot;
} else {
// @ts-ignore
blot.domNode[Registry.DATA_KEY].mutations.push(mutation);
return null;
}
})
.forEach((blot: Blot | null) => {
if (
blot == null ||
blot === this ||
//@ts-ignore
blot.domNode[Registry.DATA_KEY] == null
)
return;
// @ts-ignore
blot.update(blot.domNode[Registry.DATA_KEY].mutations || [], context);
});
// @ts-ignore
if (this.domNode[Registry.DATA_KEY].mutations != null) {
// @ts-ignore
super.update(this.domNode[Registry.DATA_KEY].mutations, context);
}
this.optimize(mutations, context);
}
}
export default ScrollBlot;

93
node_modules/parchment/src/blot/text.ts generated vendored Normal file
View File

@@ -0,0 +1,93 @@
import { Blot, Leaf } from './abstract/blot';
import LeafBlot from './abstract/leaf';
import * as Registry from '../registry';
class TextBlot extends LeafBlot implements Leaf {
static blotName = 'text';
static scope = Registry.Scope.INLINE_BLOT;
public domNode!: Text;
protected text: string;
static create(value: string): Text {
return document.createTextNode(value);
}
static value(domNode: Text): string {
let text = domNode.data;
// @ts-ignore
if (text['normalize']) text = text['normalize']();
return text;
}
constructor(node: Node) {
super(node);
this.text = this.statics.value(this.domNode);
}
deleteAt(index: number, length: number): void {
this.domNode.data = this.text = this.text.slice(0, index) + this.text.slice(index + length);
}
index(node: Node, offset: number): number {
if (this.domNode === node) {
return offset;
}
return -1;
}
insertAt(index: number, value: string, def?: any): void {
if (def == null) {
this.text = this.text.slice(0, index) + value + this.text.slice(index);
this.domNode.data = this.text;
} else {
super.insertAt(index, value, def);
}
}
length(): number {
return this.text.length;
}
optimize(context: { [key: string]: any }): void {
super.optimize(context);
this.text = this.statics.value(this.domNode);
if (this.text.length === 0) {
this.remove();
} else if (this.next instanceof TextBlot && this.next.prev === this) {
this.insertAt(this.length(), (<TextBlot>this.next).value());
this.next.remove();
}
}
position(index: number, inclusive: boolean = false): [Node, number] {
return [this.domNode, index];
}
split(index: number, force: boolean = false): Blot {
if (!force) {
if (index === 0) return this;
if (index === this.length()) return this.next;
}
let after = Registry.create(this.domNode.splitText(index));
this.parent.insertBefore(after, this.next);
this.text = this.statics.value(this.domNode);
return after;
}
update(mutations: MutationRecord[], context: { [key: string]: any }): void {
if (
mutations.some(mutation => {
return mutation.type === 'characterData' && mutation.target === this.domNode;
})
) {
this.text = this.statics.value(this.domNode);
}
}
value(): string {
return this.text;
}
}
export default TextBlot;

143
node_modules/parchment/src/collection/linked-list.ts generated vendored Normal file
View File

@@ -0,0 +1,143 @@
import LinkedNode from './linked-node';
class LinkedList<T extends LinkedNode> {
head: T | null;
tail: T | null;
length: number;
constructor() {
this.head = this.tail = null;
this.length = 0;
}
append(...nodes: T[]): void {
this.insertBefore(nodes[0], null);
if (nodes.length > 1) {
this.append.apply(this, nodes.slice(1));
}
}
contains(node: T): boolean {
let cur,
next = this.iterator();
while ((cur = next())) {
if (cur === node) return true;
}
return false;
}
insertBefore(node: T | null, refNode: T | null): void {
if (!node) return
node.next = refNode;
if (refNode != null) {
node.prev = refNode.prev;
if (refNode.prev != null) {
refNode.prev.next = node;
}
refNode.prev = node;
if (refNode === this.head) {
this.head = node;
}
} else if (this.tail != null) {
this.tail.next = node;
node.prev = this.tail;
this.tail = node;
} else {
node.prev = null;
this.head = this.tail = node;
}
this.length += 1;
}
offset(target: T): number {
let index = 0,
cur = this.head;
while (cur != null) {
if (cur === target) return index;
index += cur.length();
cur = <T>cur.next;
}
return -1;
}
remove(node: T): void {
if (!this.contains(node)) return;
if (node.prev != null) node.prev.next = node.next;
if (node.next != null) node.next.prev = node.prev;
if (node === this.head) this.head = <T>node.next;
if (node === this.tail) this.tail = <T>node.prev;
this.length -= 1;
}
iterator(curNode: T | null = this.head): () => T | null {
// TODO use yield when we can
return function(): T | null {
let ret = curNode;
if (curNode != null) curNode = <T>curNode.next;
return ret;
};
}
find(index: number, inclusive: boolean = false): [T | null, number] {
let cur,
next = this.iterator();
while ((cur = next())) {
let length = cur.length();
if (
index < length ||
(inclusive && index === length && (cur.next == null || cur.next.length() !== 0))
) {
return [cur, index];
}
index -= length;
}
return [null, 0];
}
forEach(callback: (cur: T) => void): void {
let cur,
next = this.iterator();
while ((cur = next())) {
callback(cur);
}
}
forEachAt(
index: number,
length: number,
callback: (cur: T, offset: number, length: number) => void,
): void {
if (length <= 0) return;
let [startNode, offset] = this.find(index);
let cur,
curIndex = index - offset,
next = this.iterator(startNode);
while ((cur = next()) && curIndex < index + length) {
let curLength = cur.length();
if (index > curIndex) {
callback(cur, index - curIndex, Math.min(length, curIndex + curLength - index));
} else {
callback(cur, 0, Math.min(curLength, index + length - curIndex));
}
curIndex += curLength;
}
}
map(callback: (cur: T | null) => any): any[] {
return this.reduce(function(memo: (T | null)[], cur: T | null) {
memo.push(callback(cur));
return memo;
}, []);
}
reduce<M>(callback: (memo: M, cur: T) => M, memo: M): M {
let cur,
next = this.iterator();
while ((cur = next())) {
memo = callback(memo, cur);
}
return memo;
}
}
export default LinkedList;

8
node_modules/parchment/src/collection/linked-node.ts generated vendored Normal file
View File

@@ -0,0 +1,8 @@
interface LinkedNode {
prev: LinkedNode | null;
next: LinkedNode | null;
length(): number;
}
export default LinkedNode;

46
node_modules/parchment/src/parchment.ts generated vendored Normal file
View File

@@ -0,0 +1,46 @@
import { Blot } from './blot/abstract/blot';
import ContainerBlot from './blot/abstract/container';
import FormatBlot from './blot/abstract/format';
import LeafBlot from './blot/abstract/leaf';
import ScrollBlot from './blot/scroll';
import InlineBlot from './blot/inline';
import BlockBlot from './blot/block';
import EmbedBlot from './blot/embed';
import TextBlot from './blot/text';
import Attributor from './attributor/attributor';
import ClassAttributor from './attributor/class';
import StyleAttributor from './attributor/style';
import AttributorStore from './attributor/store';
import * as Registry from './registry';
let Parchment = {
Scope: Registry.Scope,
create: Registry.create,
find: Registry.find,
query: Registry.query,
register: Registry.register,
Container: ContainerBlot,
Format: FormatBlot,
Leaf: LeafBlot,
Embed: EmbedBlot,
Scroll: ScrollBlot,
Block: BlockBlot,
Inline: InlineBlot,
Text: TextBlot,
Attributor: {
Attribute: Attributor,
Class: ClassAttributor,
Style: StyleAttributor,
Store: AttributorStore,
},
};
export default Parchment;

133
node_modules/parchment/src/registry.ts generated vendored Normal file
View File

@@ -0,0 +1,133 @@
import Attributor from './attributor/attributor';
import { Blot, Formattable } from './blot/abstract/blot';
export interface BlotConstructor {
blotName: string;
new (node: Node, value?: any): Blot;
create(value?: any): Node;
}
export class ParchmentError extends Error {
message: string;
name: string;
stack!: string;
constructor(message: string) {
message = '[Parchment] ' + message;
super(message);
this.message = message;
this.name = (<any>this.constructor).name;
}
}
let attributes: { [key: string]: Attributor } = {};
let classes: { [key: string]: BlotConstructor } = {};
let tags: { [key: string]: BlotConstructor } = {};
let types: { [key: string]: Attributor | BlotConstructor } = {};
export const DATA_KEY = '__blot';
export enum Scope {
TYPE = (1 << 2) - 1, // 0011 Lower two bits
LEVEL = ((1 << 2) - 1) << 2, // 1100 Higher two bits
ATTRIBUTE = (1 << 0) | LEVEL, // 1101
BLOT = (1 << 1) | LEVEL, // 1110
INLINE = (1 << 2) | TYPE, // 0111
BLOCK = (1 << 3) | TYPE, // 1011
BLOCK_BLOT = BLOCK & BLOT, // 1010
INLINE_BLOT = INLINE & BLOT, // 0110
BLOCK_ATTRIBUTE = BLOCK & ATTRIBUTE, // 1001
INLINE_ATTRIBUTE = INLINE & ATTRIBUTE, // 0101
ANY = TYPE | LEVEL,
}
export function create(input: Node | string | Scope, value?: any): Blot {
let match = query(input);
if (match == null) {
throw new ParchmentError(`Unable to create ${input} blot`);
}
let BlotClass = <BlotConstructor>match;
let node =
// @ts-ignore
input instanceof Node || input['nodeType'] === Node.TEXT_NODE ? input : BlotClass.create(value);
return new BlotClass(<Node>node, value);
}
export function find(node: Node | null, bubble: boolean = false): Blot | null {
if (node == null) return null;
// @ts-ignore
if (node[DATA_KEY] != null) return node[DATA_KEY].blot;
if (bubble) return find(node.parentNode, bubble);
return null;
}
export function query(
query: string | Node | Scope,
scope: Scope = Scope.ANY,
): Attributor | BlotConstructor | null {
let match;
if (typeof query === 'string') {
match = types[query] || attributes[query];
// @ts-ignore
} else if (query instanceof Text || query['nodeType'] === Node.TEXT_NODE) {
match = types['text'];
} else if (typeof query === 'number') {
if (query & Scope.LEVEL & Scope.BLOCK) {
match = types['block'];
} else if (query & Scope.LEVEL & Scope.INLINE) {
match = types['inline'];
}
} else if (query instanceof HTMLElement) {
let names = (query.getAttribute('class') || '').split(/\s+/);
for (let i in names) {
match = classes[names[i]];
if (match) break;
}
match = match || tags[query.tagName];
}
if (match == null) return null;
// @ts-ignore
if (scope & Scope.LEVEL & match.scope && scope & Scope.TYPE & match.scope) return match;
return null;
}
export function register(...Definitions: any[]): any {
if (Definitions.length > 1) {
return Definitions.map(function(d) {
return register(d);
});
}
let Definition = Definitions[0];
if (typeof Definition.blotName !== 'string' && typeof Definition.attrName !== 'string') {
throw new ParchmentError('Invalid definition');
} else if (Definition.blotName === 'abstract') {
throw new ParchmentError('Cannot register abstract class');
}
types[Definition.blotName || Definition.attrName] = Definition;
if (typeof Definition.keyName === 'string') {
attributes[Definition.keyName] = Definition;
} else {
if (Definition.className != null) {
classes[Definition.className] = Definition;
}
if (Definition.tagName != null) {
if (Array.isArray(Definition.tagName)) {
Definition.tagName = Definition.tagName.map(function(tagName: string) {
return tagName.toUpperCase();
});
} else {
Definition.tagName = Definition.tagName.toUpperCase();
}
let tagNames = Array.isArray(Definition.tagName) ? Definition.tagName : [Definition.tagName];
tagNames.forEach(function(tag: string) {
if (tags[tag] == null || Definition.className == null) {
tags[tag] = Definition;
}
});
}
}
return Definition;
}