视频会议

This commit is contained in:
wangqiong
2024-01-18 10:46:33 +08:00
parent d7f5ce05ea
commit 37a88df277
28922 changed files with 2797396 additions and 19461 deletions
+58
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
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
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
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
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;