chore: merge blocksuite source code (#9213)

This commit is contained in:
Mirone
2024-12-20 15:38:06 +08:00
committed by GitHub
parent 2c9ef916f4
commit 30200ff86d
2031 changed files with 238888 additions and 229 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,106 @@
import { DEFAULT_NOTE_BACKGROUND_COLOR } from '@blocksuite/affine-model';
import type { SliceSnapshot } from '@blocksuite/store';
import { describe, expect, test } from 'vitest';
import { NotionTextAdapter } from '../../_common/adapters/notion-text.js';
import { nanoidReplacement } from '../../_common/test-utils/test-utils.js';
import { createJob } from '../utils/create-job.js';
describe('notion-text to snapshot', () => {
test('basic', () => {
const notionText =
'{"blockType":"text","editing":[["aaa ",[["_"],["b"],["i"]]],["nbbbb ",[["_"],["i"]]],["hjhj ",[["_"]]],["a",[["_"],["c"]]],[" ",[["_"]]],["ccc d",[["_"],["s"]]],["dd",[["_"],["s"]]]]}';
const sliceSnapshot: SliceSnapshot = {
type: 'slice',
content: [
{
type: 'block',
id: 'matchesReplaceMap[0]',
flavour: 'affine:note',
props: {
xywh: '[0,0,800,95]',
background: DEFAULT_NOTE_BACKGROUND_COLOR,
index: 'a0',
hidden: false,
displayMode: 'both',
},
children: [
{
type: 'block',
id: 'matchesReplaceMap[1]',
flavour: 'affine:paragraph',
props: {
type: 'text',
text: {
'$blocksuite:internal:text$': true,
delta: [
{
insert: 'aaa ',
attributes: {
underline: true,
bold: true,
italic: true,
},
},
{
insert: 'nbbbb ',
attributes: {
underline: true,
italic: true,
},
},
{
insert: 'hjhj ',
attributes: {
underline: true,
},
},
{
insert: 'a',
attributes: {
underline: true,
code: true,
},
},
{
insert: ' ',
attributes: {
underline: true,
},
},
{
insert: 'ccc d',
attributes: {
underline: true,
strike: true,
},
},
{
insert: 'dd',
attributes: {
underline: true,
strike: true,
},
},
],
},
},
children: [],
},
],
},
],
workspaceId: '',
pageId: '',
};
const ntAdapter = new NotionTextAdapter(createJob());
const target = ntAdapter.toSliceSnapshot({
file: notionText,
workspaceId: '',
pageId: '',
});
expect(nanoidReplacement(target!)).toEqual(sliceSnapshot);
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,235 @@
import {
type Cell,
type Column,
type DatabaseBlockModel,
DatabaseBlockSchema,
NoteBlockSchema,
ParagraphBlockSchema,
RootBlockSchema,
} from '@blocksuite/affine-model';
import { propertyModelPresets } from '@blocksuite/data-view/property-pure-presets';
import type { BlockModel, Doc } from '@blocksuite/store';
import { DocCollection, IdGeneratorType, Schema } from '@blocksuite/store';
import { beforeEach, describe, expect, test } from 'vitest';
import { databaseBlockColumns } from '../../database-block/index.js';
import {
addProperty,
copyCellsByProperty,
deleteColumn,
getCell,
getProperty,
updateCell,
} from '../../database-block/utils/block-utils.js';
const AffineSchemas = [
RootBlockSchema,
NoteBlockSchema,
ParagraphBlockSchema,
DatabaseBlockSchema,
];
function createTestOptions() {
const idGenerator = IdGeneratorType.AutoIncrement;
const schema = new Schema();
schema.register(AffineSchemas);
return { id: 'test-collection', idGenerator, schema };
}
function createTestDoc(docId = 'doc0') {
const options = createTestOptions();
const collection = new DocCollection(options);
collection.meta.initialize();
const doc = collection.createDoc({ id: docId });
doc.load();
return doc;
}
describe('DatabaseManager', () => {
let doc: Doc;
let db: DatabaseBlockModel;
let rootId: BlockModel['id'];
let noteBlockId: BlockModel['id'];
let databaseBlockId: BlockModel['id'];
let p1: BlockModel['id'];
let p2: BlockModel['id'];
let col1: Column['id'];
let col2: Column['id'];
let col3: Column['id'];
const selection = [
{ id: '1', value: 'Done', color: 'var(--affine-tag-white)' },
{ id: '2', value: 'TODO', color: 'var(--affine-tag-pink)' },
{ id: '3', value: 'WIP', color: 'var(--affine-tag-blue)' },
];
beforeEach(() => {
doc = createTestDoc();
rootId = doc.addBlock('affine:page', {
title: new doc.Text('database test'),
});
noteBlockId = doc.addBlock('affine:note', {}, rootId);
databaseBlockId = doc.addBlock(
'affine:database' as BlockSuite.Flavour,
{
columns: [],
titleColumn: 'Title',
},
noteBlockId
);
const databaseModel = doc.getBlockById(
databaseBlockId
) as DatabaseBlockModel;
db = databaseModel;
col1 = addProperty(
db,
'end',
databaseBlockColumns.numberColumnConfig.create('Number')
);
col2 = addProperty(
db,
'end',
propertyModelPresets.selectPropertyModelConfig.create('Single Select', {
options: selection,
})
);
col3 = addProperty(
db,
'end',
databaseBlockColumns.richTextColumnConfig.create('Rich Text')
);
doc.updateBlock(databaseModel, {
columns: [col1, col2, col3],
});
p1 = doc.addBlock(
'affine:paragraph',
{
text: new doc.Text('text1'),
},
databaseBlockId
);
p2 = doc.addBlock(
'affine:paragraph',
{
text: new doc.Text('text2'),
},
databaseBlockId
);
updateCell(db, p1, {
columnId: col1,
value: 0.1,
});
updateCell(db, p2, {
columnId: col2,
value: [selection[1]],
});
});
test('getColumn', () => {
const column = {
...databaseBlockColumns.numberColumnConfig.create('testColumnId'),
id: 'testColumnId',
};
addProperty(db, 'end', column);
const result = getProperty(db, column.id);
expect(result).toEqual(column);
});
test('addColumn', () => {
const column =
databaseBlockColumns.numberColumnConfig.create('Test Column');
const id = addProperty(db, 'end', column);
const result = getProperty(db, id);
expect(result).toMatchObject(column);
expect(result).toHaveProperty('id');
});
test('deleteColumn', () => {
const column = {
...databaseBlockColumns.numberColumnConfig.create('Test Column'),
id: 'testColumnId',
};
addProperty(db, 'end', column);
expect(getProperty(db, column.id)).toEqual(column);
deleteColumn(db, column.id);
expect(getProperty(db, column.id)).toBeUndefined();
});
test('getCell', () => {
const modelId = doc.addBlock(
'affine:paragraph',
{
text: new doc.Text('paragraph'),
},
noteBlockId
);
const column = {
...databaseBlockColumns.numberColumnConfig.create('Test Column'),
id: 'testColumnId',
};
const cell: Cell = {
columnId: column.id,
value: 42,
};
addProperty(db, 'end', column);
updateCell(db, modelId, cell);
const model = doc.getBlockById(modelId);
expect(model).not.toBeNull();
const result = getCell(db, model!.id, column.id);
expect(result).toEqual(cell);
});
test('updateCell', () => {
const newRowId = doc.addBlock(
'affine:paragraph',
{
text: new doc.Text('text3'),
},
databaseBlockId
);
updateCell(db, newRowId, {
columnId: col2,
value: [selection[2]],
});
const cell = getCell(db, newRowId, col2);
expect(cell).toEqual({
columnId: col2,
value: [selection[2]],
});
});
test('copyCellsByColumn', () => {
const newColId = addProperty(
db,
'end',
propertyModelPresets.selectPropertyModelConfig.create('Copied Select', {
options: selection,
})
);
copyCellsByProperty(db, col2, newColId);
const cell = getCell(db, p2, newColId);
expect(cell).toEqual({
columnId: newColId,
value: [selection[1]],
});
});
});

View File

@@ -0,0 +1,79 @@
import { type SelectTag, t, typeSystem } from '@blocksuite/data-view';
import { describe, expect, test } from 'vitest';
describe('subtyping', () => {
test('all type is subtype of unknown', () => {
expect(typeSystem.unify(t.boolean.instance(), t.unknown.instance())).toBe(
true
);
expect(typeSystem.unify(t.string.instance(), t.unknown.instance())).toBe(
true
);
expect(
typeSystem.unify(
t.array.instance(t.string.instance()),
t.unknown.instance()
)
).toBe(true);
expect(typeSystem.unify(t.tag.instance(), t.unknown.instance())).toBe(true);
});
});
describe('function apply', () => {
test('generic type function', () => {
const fn = t.fn.instance(
[t.typeVarReference.create('A'), t.typeVarReference.create('A')],
t.boolean.instance(),
[t.typeVarDefine.create('A', t.unknown.instance())]
);
const instancedFn = typeSystem.instanceFn(
fn,
[t.boolean.instance()],
t.boolean.instance(),
{}
);
expect(instancedFn?.args[1]).toStrictEqual(t.boolean.instance());
});
test('tags infer', () => {
const fn = t.fn.instance(
[
t.typeVarReference.create('A'),
t.array.instance(t.typeVarReference.create('A')),
] as const,
t.boolean.instance(),
[t.typeVarDefine.create('A', t.tag.instance())]
);
const fnArray = t.fn.instance(
[
t.array.instance(t.typeVarReference.create('A')),
t.array.instance(t.typeVarReference.create('A')),
] as const,
t.boolean.instance(),
[t.typeVarDefine.create('A', t.tag.instance())]
);
const tags: SelectTag[] = [{ id: 'a', value: 'b', color: 'c' }];
const instancedFn = typeSystem.instanceFn(
fn,
[t.tag.instance(tags)],
t.boolean.instance(),
{}
);
const instancedFnArray = typeSystem.instanceFn(
fnArray,
[t.array.instance(t.tag.instance(tags))],
t.boolean.instance(),
{}
);
expect(
typeSystem.unify(
instancedFn?.args[1],
t.array.instance(t.tag.instance(tags))
)
).toBe(true);
expect(
typeSystem.unify(
instancedFnArray?.args[1],
t.array.instance(t.tag.instance(tags))
)
).toBe(true);
});
});

View File

@@ -0,0 +1,92 @@
import { DocCollection, Schema } from '@blocksuite/store';
import { describe, expect, test } from 'vitest';
import { markdownToMindmap } from '../../surface-block/mini-mindmap/mindmap-preview.js';
describe('markdownToMindmap: convert markdown list to a mind map tree', () => {
test('basic case', () => {
const markdown = `
- Text A
- Text B
- Text C
- Text D
- Text E
`;
const collection = new DocCollection({ schema: new Schema() });
collection.meta.initialize();
const doc = collection.createDoc();
const nodes = markdownToMindmap(markdown, doc);
expect(nodes).toEqual({
text: 'Text A',
children: [
{
text: 'Text B',
children: [
{
text: 'Text C',
children: [],
},
],
},
{
text: 'Text D',
children: [
{
text: 'Text E',
children: [],
},
],
},
],
});
});
test('basic case with different indent', () => {
const markdown = `
- Text A
- Text B
- Text C
- Text D
- Text E
`;
const collection = new DocCollection({ schema: new Schema() });
collection.meta.initialize();
const doc = collection.createDoc();
const nodes = markdownToMindmap(markdown, doc);
expect(nodes).toEqual({
text: 'Text A',
children: [
{
text: 'Text B',
children: [
{
text: 'Text C',
children: [],
},
],
},
{
text: 'Text D',
children: [
{
text: 'Text E',
children: [],
},
],
},
],
});
});
test('empty case', () => {
const markdown = '';
const collection = new DocCollection({ schema: new Schema() });
collection.meta.initialize();
const doc = collection.createDoc();
const nodes = markdownToMindmap(markdown, doc);
expect(nodes).toEqual(null);
});
});

View File

@@ -0,0 +1,31 @@
import {
DocCollection,
Job,
type JobMiddleware,
Schema,
} from '@blocksuite/store';
import { defaultImageProxyMiddleware } from '../../_common/transformers/middlewares.js';
import { AffineSchemas } from '../../schemas.js';
declare global {
interface Window {
happyDOM: {
settings: {
fetch: {
disableSameOriginPolicy: boolean;
};
};
};
}
}
export function createJob(middlewares?: JobMiddleware[]) {
window.happyDOM.settings.fetch.disableSameOriginPolicy = true;
const testMiddlewares = middlewares ?? [];
testMiddlewares.push(defaultImageProxyMiddleware);
const schema = new Schema().register(AffineSchemas);
const docCollection = new DocCollection({ schema });
docCollection.meta.initialize();
return new Job({ collection: docCollection, middlewares: testMiddlewares });
}