Skip to content

Commit

Permalink
Improve types for Quill.register
Browse files Browse the repository at this point in the history
  • Loading branch information
luin committed May 13, 2024
1 parent bb079b2 commit 2e59f38
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 33 deletions.
55 changes: 26 additions & 29 deletions packages/quill/src/core/quill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,7 @@ const debug = logger('quill');
const globalRegistry = new Parchment.Registry();
Parchment.ParentBlot.uiClass = 'ql-ui';

type ClassToConstructor<T> = { new (...args: any[]): T & object };

type RegistryTarget = Parchment.RegistryDefinition | Module | boolean;

interface RegistryRecord {
[key: `blots/${string}`]: Parchment.BlotConstructor;
[key: `formats/${string}`]: Parchment.RegistryDefinition;
[key: `attributors/${string}`]: Parchment.Attributor;
[key: `modules/${string}`]: ClassToConstructor<Module>;
[key: `themes/${string}`]: ClassToConstructor<Theme>;
[key: string]: any;
}
type RegisterTarget = Parchment.RegistryDefinition | Theme | Module | Function; // ES5 constructor functions

/**
* Options for initializing a Quill instance
Expand Down Expand Up @@ -134,21 +123,39 @@ class Quill {
return this.imports[name];
}

static register(record: RegistryRecord, overwrite?: boolean): void;
static register(
target: Exclude<RegistryTarget, boolean | Module>,
targets: Record<string, RegisterTarget>,
overwrite?: boolean,
): void;
static register(
target: Parchment.RegistryDefinition,
overwrite?: boolean,
): void;
static register(
path: string,
target: RegistryTarget,
target: RegisterTarget,
overwrite?: boolean,
): void;
static register(...args: any[]): void {
const path = typeof args[0] === 'string' ? args[0] : '';
const target = path ? args[1] : args[0];
const overwrite = (path ? args[2] : args[1]) ?? false;
if (path) {
if (typeof args[0] !== 'string') {
const target = args[0];
const overwrite = !!args[1];

const name = 'attrName' in target ? target.attrName : target.blotName;
if (typeof name === 'string') {
// Shortcut for formats:
// register(Blot | Attributor, overwrite)
this.register(`formats/${name}`, target, overwrite);
} else {
Object.keys(target).forEach((key) => {
this.register(key, target[key], overwrite);
});
}
} else {
const path = args[0];
const target = args[1];
const overwrite = !!args[2];

if (this.imports[path] != null && !overwrite) {
debug.warn(`Overwriting ${path} with`, target);
}
Expand All @@ -164,16 +171,6 @@ class Quill {
if (typeof target.register === 'function') {
target.register(globalRegistry);
}
return;
}
const name: string | undefined = target['attrName'] ?? target['blotName'];
if (typeof name === 'string') {
// register(Blot | Attributor, overwrite)
this.register(`formats/${name}`, target, overwrite);
} else {
Object.keys(target).forEach((key) => {
this.register(key, target[key], overwrite);
});
}
}

Expand Down
1 change: 0 additions & 1 deletion packages/quill/src/modules/syntax.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ class SyntaxCodeBlock extends CodeBlock {
}
}

// TODO maybe something wrong
replaceWith(name: string | Blot, value?: any) {
this.formatAt(0, this.length(), CodeToken.blotName, false);
return super.replaceWith(name, value);
Expand Down
2 changes: 1 addition & 1 deletion packages/quill/src/quill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ Quill.register(
true,
);

export { default as Module } from './core/module.js';
export { Module } from './core.js';
export type {
Bounds,
DebugLevel,
Expand Down
31 changes: 31 additions & 0 deletions packages/quill/test/types/quill.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,37 @@ import Quill from '../../src/quill.js';
import type { EmitterSource, Parchment, Range } from '../../src/quill.js';
import Delta from 'quill-delta';
import type { default as Block, BlockEmbed } from '../../src/blots/block.js';
import SnowTheme from '../../src/themes/snow.js';
import { LeafBlot } from 'parchment';

{
const Counter = (quill: Quill, options: { unit: string }) => {
console.log(quill, options);
};
Quill.register('modules/counter', Counter);
Quill.register('themes/snow', SnowTheme);
Quill.register('themes/snow', SnowTheme, true);

class MyBlot extends LeafBlot {}

Quill.register(MyBlot);
Quill.register(MyBlot, true);
// @ts-expect-error
Quill.register(SnowTheme);
Quill.register({
'modules/counter': Counter,
'themes/snow': SnowTheme,
'formats/my-blot': MyBlot,
});
Quill.register(
{
'modules/counter': Counter,
'themes/snow': SnowTheme,
'formats/my-blot': MyBlot,
},
true,
);
}

const quill = new Quill('#editor');

Expand Down
45 changes: 43 additions & 2 deletions packages/quill/test/unit/core/quill.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import '../../../src/quill.js';
import Delta from 'quill-delta';
import { Registry } from 'parchment';
import { beforeEach, describe, expect, test, vitest } from 'vitest';
import { LeafBlot, Registry } from 'parchment';
import { afterEach, beforeEach, describe, expect, test, vitest } from 'vitest';
import type { MockedFunction } from 'vitest';
import Emitter from '../../../src/core/emitter.js';
import Theme from '../../../src/core/theme.js';
Expand Down Expand Up @@ -29,6 +29,47 @@ describe('Quill', () => {
});
});

describe('register', () => {
const imports = { ...Quill.imports };
afterEach(() => {
Quill.imports = imports;
});

test('register(path, target)', () => {
class Counter {}
Quill.register('modules/counter', Counter);

expect(Quill.imports).toHaveProperty('modules/counter', Counter);
expect(Quill.import('modules/counter')).toEqual(Counter);
});

test('register(formats)', () => {
class MyCounterBlot extends LeafBlot {
static blotName = 'my-counter';
static className = 'ql-my-counter';
}
Quill.register(MyCounterBlot);

expect(Quill.imports).toHaveProperty('formats/my-counter', MyCounterBlot);
expect(Quill.import('formats/my-counter')).toEqual(MyCounterBlot);
});

test('register(targets)', () => {
class ABlot extends LeafBlot {
static blotName = 'a-blot';
static className = 'ql-a-blot';
}
class AModule {}
Quill.register({
'formats/a-blot': ABlot,
'modules/a-module': AModule,
});

expect(Quill.import('formats/a-blot')).toEqual(ABlot);
expect(Quill.import('modules/a-module')).toEqual(AModule);
});
});

describe('construction', () => {
test('empty', () => {
const quill = new Quill(createContainer());
Expand Down

0 comments on commit 2e59f38

Please sign in to comment.