refactor(editor): unify directories naming (#11516)

**Directory Structure Changes**

- Renamed multiple block-related directories by removing the "block-" prefix:
  - `block-attachment` → `attachment`
  - `block-bookmark` → `bookmark`
  - `block-callout` → `callout`
  - `block-code` → `code`
  - `block-data-view` → `data-view`
  - `block-database` → `database`
  - `block-divider` → `divider`
  - `block-edgeless-text` → `edgeless-text`
  - `block-embed` → `embed`
This commit is contained in:
Saul-Mirone
2025-04-07 12:34:40 +00:00
parent e1bd2047c4
commit 1f45cc5dec
893 changed files with 439 additions and 460 deletions
@@ -0,0 +1,114 @@
import type { IVec, IVec3 } from '@blocksuite/global/gfx';
import { almostEqual } from '@blocksuite/global/gfx';
import { describe, expect, it } from 'vitest';
import { AStarRunner } from '../utils/a-star.js';
function mergePath(points: IVec3[]) {
if (points.length === 0) return points;
const rst: IVec3[] = [points[0]];
for (let i = 1; i < points.length - 1; i++) {
const cur = points[i];
const last = points[i - 1];
const next = points[i + 1];
if (
almostEqual(last[0], cur[0], 0.02) &&
almostEqual(cur[0], next[0], 0.02)
)
continue;
if (
almostEqual(last[1], cur[1], 0.02) &&
almostEqual(cur[1], next[1], 0.02)
)
continue;
rst.push(cur);
}
rst.push(points[points.length - 1]);
return rst;
}
describe('a* algorithm', () => {
/**
* 0 ----------------
* |
* |
* ------------------- 0
*/
it('width is greater than height', () => {
const sp: IVec3 = [0, 0, 0];
const ep: IVec3 = [200, 100, 0];
const osp: IVec3 = [-1, 0, 0];
const oep: IVec3 = [201, 100, 0];
const points: IVec3[] = [
sp,
ep,
[100, 0, 0],
[200, 0, 0],
[0, 50, 0],
[100, 50, 3],
[200, 50, 0],
[0, 100, 0],
[100, 100, 0],
] as IVec3[];
const aStar = new AStarRunner(points, sp, ep, osp, oep);
aStar.run();
let path: IVec[] | IVec3[] = aStar.path;
path.pop();
path.shift();
path = mergePath(path as IVec3[]);
const expected = [
[0, 0],
[100, 0],
[100, 100],
[200, 100],
];
path.forEach((p, i) => {
expect(p[0]).toBe(expected[i][0]);
expect(p[1]).toBe(expected[i][1]);
});
});
/**
* 0
* |
* |
* |
* |----|
* |
* |
* |
* 0
*/
it('height is greater than width', () => {
const sp: IVec3 = [0, 0, 0];
const ep: IVec3 = [100, 200, 0];
const osp: IVec3 = [0, -1, 0];
const oep: IVec3 = [100, 201, 0];
const points: IVec3[] = [
sp,
[50, 0, 0],
[100, 0, 0],
[0, 100, 0],
[50, 100, 3],
[100, 100, 0],
[0, 200, 0],
[50, 200, 0],
ep,
];
const aStar = new AStarRunner(points, sp, ep, osp, oep);
aStar.run();
let path = aStar.path;
path.pop();
path.shift();
path = mergePath(path);
const expected = [
[0, 0],
[0, 100],
[100, 100],
[100, 200],
];
path.forEach((p, i) => {
expect(p[0]).toBe(expected[i][0]);
expect(p[1]).toBe(expected[i][1]);
});
});
});
@@ -0,0 +1,180 @@
import {
Bound,
getCommonBound,
inflateBound,
transformPointsToNewBound,
} from '@blocksuite/global/gfx';
import { describe, expect, it } from 'vitest';
describe('bound utils', () => {
it('Bound basic', () => {
const bound = new Bound(1, 1, 2, 2);
const serialized = bound.serialize();
expect(serialized).toBe('[1,1,2,2]');
expect(Bound.deserialize(serialized)).toMatchObject(bound);
expect(bound.center).toMatchObject([2, 2]);
expect(bound.minX).toBe(1);
expect(bound.minY).toBe(1);
expect(bound.maxX).toBe(3);
expect(bound.maxY).toBe(3);
expect(bound.tl).toMatchObject([1, 1]);
expect(bound.tr).toMatchObject([3, 1]);
expect(bound.bl).toMatchObject([1, 3]);
expect(bound.br).toMatchObject([3, 3]);
});
it('from', () => {
const b1 = new Bound(1, 1, 2, 2);
const b2 = Bound.from(b1);
expect(b1).toMatchObject(b2);
});
it('getCommonBound basic', () => {
const bounds = Array.from({ length: 10 })
.fill(0)
.map((_, index) => {
return {
x: index,
y: index,
w: 1,
h: 1,
};
});
expect(getCommonBound(bounds)).toMatchObject({
x: 0,
y: 0,
w: 10,
h: 10,
});
});
it('getCommonBound parameters length equal to 0', () => {
expect(getCommonBound([])).toBeNull();
});
it('getCommonBound parameters length less than 2', () => {
const b1 = {
x: 0,
y: 0,
w: 1,
h: 1,
};
expect(getCommonBound([b1])).toMatchObject(b1);
});
it('inflateBound', () => {
const a = new Bound(0, 0, 10, 10);
const b = inflateBound(a, 4);
expect(b.serialize()).toBe('[-2,-2,14,14]');
expect(() => inflateBound(a, -12)).toThrowError(
'Invalid delta range or bound size.'
);
});
it('transformPointsToNewBound basic', () => {
const a = new Bound(0, 0, 20, 20);
const b = new Bound(4, 4, 18, 18);
const marginA = 4;
const marginB = 6;
const points = [{ x: 6, y: 6, other: 10 }];
const transformed = transformPointsToNewBound(
points,
a,
marginA,
b,
marginB
);
expect(transformed.bound.serialize()).toBe(b.serialize());
expect(transformed.points[0]).toMatchObject({
x: 7,
y: 7,
other: 10,
});
});
it('transformPointsToNewBound, new bound too small', () => {
const a = new Bound(0, 0, 20, 20);
const b = new Bound(4, 4, 4, 4);
const marginA = 4;
const marginB = 6;
const points = [{ x: 6, y: 6, other: 10 }];
const transformed = transformPointsToNewBound(
points,
a,
marginA,
b,
marginB
);
expect(transformed.bound.serialize()).toBe('[4,4,13,13]');
expect(transformed.points[0].x).toBeCloseTo(6.1667);
expect(transformed.points[0].y).toBeCloseTo(6.1667);
expect(transformed.points[0].other).toBe(10);
});
it('intersectLine', () => {
const bound = new Bound(0, 0, 10, 10);
expect(bound.intersectLine([0, 0], [10, 10])).toBeTruthy();
});
it('intersectline no intersection', () => {
const bound = new Bound(0, 0, 10, 10);
expect(bound.intersectLine([0, -1], [10, -10])).toBeFalsy();
});
it('isIntersectWithBound', () => {
const a = new Bound(0, 0, 10, 10);
const b = new Bound(5, 5, 10, 10);
expect(a.isIntersectWithBound(b)).toBeTruthy();
});
it('isIntersectWithBound no intersection', () => {
const a = new Bound(0, 0, 10, 10);
const b = new Bound(11, 11, 10, 10);
expect(a.isIntersectWithBound(b)).toBeFalsy();
});
it('unite', () => {
const a = new Bound(0, 0, 10, 10);
const b = new Bound(5, 5, 10, 10);
expect(a.unite(b).serialize()).toBe('[0,0,15,15]');
});
it('isHorizontalCross', () => {
const a = new Bound(0, 0, 10, 10);
const b = new Bound(5, 5, 10, 10);
expect(a.isHorizontalCross(b)).toBeTruthy();
});
it('isHorizontalCross no intersection', () => {
const a = new Bound(0, 0, 10, 10);
const b = new Bound(11, 11, 10, 10);
expect(a.isHorizontalCross(b)).toBeFalsy();
});
it('isVerticalCross', () => {
const a = new Bound(0, 0, 10, 10);
const b = new Bound(5, 5, 10, 10);
expect(a.isVerticalCross(b)).toBeTruthy();
});
it('isVerticalCross no intersection', () => {
const a = new Bound(0, 0, 10, 10);
const b = new Bound(11, 11, 10, 10);
expect(a.isVerticalCross(b)).toBeFalsy();
});
it('horizontalDistance', () => {
const a = new Bound(0, 0, 10, 10);
const b = new Bound(15, 15, 10, 10);
expect(a.horizontalDistance(b)).toBe(5);
});
it('verticalDistance', () => {
const a = new Bound(0, 0, 10, 10);
const b = new Bound(15, 15, 10, 10);
expect(a.verticalDistance(b)).toBe(5);
});
});
@@ -0,0 +1,23 @@
import { Bound } from '@blocksuite/global/gfx';
import { describe, expect, it } from 'vitest';
import { Graph } from '../utils/graph.js';
describe('graph', () => {
it('neighbors', () => {
const bound = new Bound(-5, 5, 10, 10);
const graph = new Graph(
[
[0, 0],
[100, 0],
[0, 100],
[100, 100],
],
[bound]
);
const neighbors = graph.neighbors([0, 0]);
expect(neighbors.length).toBe(1);
expect(neighbors[0][0]).toBe(100);
expect(neighbors[0][1]).toBe(0);
});
});
@@ -0,0 +1,157 @@
import {
almostEqual,
isPointOnLineSegment,
type IVec,
lineEllipseIntersects,
lineIntersects,
linePolygonIntersects,
linePolylineIntersects,
pointAlmostEqual,
polygonGetPointTangent,
rotatePoints,
toDegree,
toRadian,
} from '@blocksuite/global/gfx';
import { describe, expect, it } from 'vitest';
describe('Line', () => {
it('should intersect', () => {
let rst = lineIntersects([0, 0], [1, 1], [0, 1], [1, 0]);
expect(rst).toBeDefined();
expect(rst).toMatchObject([0.5, 0.5]);
rst = lineIntersects([5, 5], [15, 5], [10, 0], [10, 10]);
expect(rst).toBeDefined();
expect(rst).toMatchObject([10, 5]);
});
it('should not intersect', () => {
const rst = lineIntersects([0, 0], [1, 0], [0, 1], [1, 1]);
expect(rst).toBeNull();
});
it('should intersect when infinity', () => {
const rst = lineIntersects([0, 0], [0, 10], [1, 1], [10, 1], true);
expect(rst).toBeDefined();
expect(rst).toMatchObject([0, 1]);
});
it('lineEllipseIntersects', () => {
const rst = lineEllipseIntersects([0, -5], [0, 5], [0, 0], 1, 1);
const expected: IVec[] = [
[0, 1],
[0, -1],
];
if (!rst) throw new Error('Failed to get line ellipse intersects');
expect(
rst.every((point, index) => pointAlmostEqual(point, expected[index]))
).toBeTruthy();
});
it('lineEllipseIntersects with rotate', () => {
const rst = lineEllipseIntersects(
[0, -5],
[0, 5],
[0, 0],
3,
2,
Math.PI / 2
);
expect(rst).toBeDefined();
if (rst) {
pointAlmostEqual(rst[0], [0, 3]);
pointAlmostEqual(rst[1], [0, -3]);
}
});
it('linePolygonIntersects', () => {
const rst = linePolygonIntersects(
[5, 5],
[15, 5],
[
[0, 0],
[10, 0],
[10, 10],
[0, 10],
]
);
if (!rst) throw new Error('Failed to get line polygon intersects');
expect(pointAlmostEqual(rst[0], [10, 5])).toBeTruthy();
});
it('linePolylineIntersects', () => {
const rst = linePolylineIntersects(
[5, 5],
[-5, 5],
[
[0, 0],
[10, 0],
[10, 10],
[0, 10],
]
);
expect(rst).toBeNull();
});
it('isPointOnLineSegment', () => {
const line: IVec[] = [
[0, 0],
[1, 0],
];
const point: IVec = [0.5, 0];
expect(isPointOnLineSegment(point, line)).toBe(true);
expect(isPointOnLineSegment([0.01, 0], line)).toBe(true);
expect(isPointOnLineSegment([-0.01, 0], line)).toBe(false);
expect(isPointOnLineSegment([0.5, 0.1], line)).toBe(false);
expect(isPointOnLineSegment([0.5, -0.1], line)).toBe(false);
});
it('rotatePoints', () => {
const points: IVec[] = [
[0, 0],
[1, 0],
[1, 1],
[0, 1],
];
const rst = rotatePoints(points, [0.5, 0.5], 90);
const expected = [
[1, 0],
[1, 1],
[0, 1],
[0, 0],
];
expect(
rst.every((p, i) => {
return (
almostEqual(p[0], expected[i][0]) && almostEqual(p[1], expected[i][1])
);
})
).toBeTruthy();
});
it('polygonGetPointTangent', () => {
const points: IVec[] = [
[0, 0],
[1, 0],
[1, 1],
[0, 1],
];
expect(polygonGetPointTangent(points, [0, 0.5])).toMatchObject([0, -1]);
expect(polygonGetPointTangent(points, [0.5, 0])).toMatchObject([1, 0]);
});
it('toRadian', () => {
expect(toRadian(180)).toBe(Math.PI);
expect(toRadian(90)).toBe(Math.PI / 2);
expect(toRadian(0)).toBe(0);
expect(toRadian(360)).toBe(Math.PI * 2);
});
it('toDegree', () => {
expect(toDegree(Math.PI)).toBe(180);
expect(toDegree(Math.PI / 2)).toBe(90);
expect(toDegree(0)).toBe(0);
expect(toDegree(Math.PI * 2)).toBe(360);
});
});
@@ -0,0 +1,22 @@
import { describe, expect, it } from 'vitest';
import { PriorityQueue } from '../utils/priority-queue.js';
describe('priority queue', () => {
it('should dequeue the smallest item', () => {
const pq = new PriorityQueue<string, number>((a, b) => a - b);
pq.enqueue('d', 4);
pq.enqueue('c', 3);
expect(pq.dequeue()).toBe('c');
pq.enqueue('b', 2);
pq.enqueue('a', 1);
expect(pq.dequeue()).toBe('a');
expect(pq.dequeue()).toBe('b');
pq.enqueue('e', 5);
expect(pq.dequeue()).toBe('d');
expect(pq.dequeue()).toBe('e');
expect(pq.dequeue()).toBe(null);
});
});
@@ -0,0 +1,99 @@
import { describe, expect, it } from 'vitest';
import { loadingSort } from '../utils/sort.js';
describe('loadingSort', () => {
it('should sort correctly', () => {
const elements = [
{
id: '1',
deps: ['2', '3'],
},
{
id: '2',
deps: ['4', '5'],
},
{
id: '3',
deps: ['a'],
},
{
id: '4',
deps: ['b', '5'],
},
{
id: '5',
deps: [],
},
];
const sorted = loadingSort(elements);
expect(sorted.map(val => val.id)).toEqual(['3', '5', '4', '2', '1']);
});
it('should sort correctly when no deps', () => {
const elements = [
{
id: '1',
deps: [],
},
{
id: '2',
deps: [],
},
{
id: '3',
deps: [],
},
];
const sorted = loadingSort(elements);
expect(sorted.map(val => val.id)).toEqual(['1', '2', '3']);
});
it('should sort correctly elements deps same element', () => {
const elements = [
{
id: '1',
deps: ['2', '3'],
},
{
id: '2',
deps: ['4', '5'],
},
{
id: '3',
deps: ['6', '7'],
},
{
id: '4',
deps: ['b', '5'],
},
{
id: '5',
deps: ['7'],
},
{
id: '6',
deps: [],
},
{
id: '7',
deps: [],
},
];
const sorted = loadingSort(elements);
expect(sorted.map(val => val.id)).toEqual([
'6',
'7',
'3',
'5',
'4',
'2',
'1',
]);
});
});