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

View File

@@ -0,0 +1,358 @@
import { DatabaseBlockSchema } from '@blocksuite/affine-model';
import {
AdapterTextUtils,
BlockNotionHtmlAdapterExtension,
type BlockNotionHtmlAdapterMatcher,
HastUtils,
} from '@blocksuite/affine-shared/adapters';
import { getTagColor } from '@blocksuite/data-view';
import { type BlockSnapshot, nanoid } from '@blocksuite/store';
const ColumnClassMap: Record<string, string> = {
typesSelect: 'select',
typesMultipleSelect: 'multi-select',
typesNumber: 'number',
typesCheckbox: 'checkbox',
typesText: 'rich-text',
typesTitle: 'title',
};
const NotionDatabaseToken = '.collection-content';
const NotionDatabaseTitleToken = '.collection-title';
type BlocksuiteTableColumn = {
type: string;
name: string;
data: {
options?: {
id: string;
value: string;
color: string;
}[];
};
id: string;
};
type BlocksuiteTableRow = Record<
string,
{
columnId: string;
value: unknown;
}
>;
const DATABASE_NODE_TYPES = new Set(['table', 'th', 'tr']);
export const databaseBlockNotionHtmlAdapterMatcher: BlockNotionHtmlAdapterMatcher =
{
flavour: DatabaseBlockSchema.model.flavour,
toMatch: o =>
HastUtils.isElement(o.node) && DATABASE_NODE_TYPES.has(o.node.tagName),
fromMatch: () => false,
toBlockSnapshot: {
enter: (o, context) => {
if (!HastUtils.isElement(o.node)) {
return;
}
const { walkerContext, deltaConverter, pageMap } = context;
switch (o.node.tagName) {
case 'th': {
const columnId = nanoid();
const columnTypeClass = HastUtils.querySelector(o.node, 'svg')
?.properties?.className;
const columnType = Array.isArray(columnTypeClass)
? (ColumnClassMap[columnTypeClass[0] ?? ''] ?? 'rich-text')
: 'rich-text';
walkerContext.pushGlobalContextStack<BlocksuiteTableColumn>(
'hast:table:column',
{
type: columnType,
name: HastUtils.getTextContent(
HastUtils.getTextChildrenOnlyAst(o.node)
),
data: Object.create(null),
id: columnId,
}
);
// disable icon img in th
walkerContext.setGlobalContext('hast:disableimg', true);
break;
}
case 'tr': {
if (
o.parent?.node.type === 'element' &&
o.parent.node.tagName === 'tbody'
) {
const columns =
walkerContext.getGlobalContextStack<BlocksuiteTableColumn>(
'hast:table:column'
);
const row = Object.create(null);
let plainTable = false;
HastUtils.getElementChildren(o.node).forEach((child, index) => {
if (plainTable || columns[index] === undefined) {
plainTable = true;
if (columns[index] === undefined) {
columns.push({
type: 'rich-text',
name: '',
data: Object.create(null),
id: nanoid(),
});
walkerContext.pushGlobalContextStack<BlockSnapshot>(
'hast:table:children',
{
type: 'block',
id: nanoid(),
flavour: 'affine:paragraph',
props: {
text: {
'$blocksuite:internal:text$': true,
delta: deltaConverter.astToDelta(child),
},
type: 'text',
},
children: [],
}
);
}
walkerContext.pushGlobalContextStack<BlockSnapshot>(
'hast:table:children',
{
type: 'block',
id: nanoid(),
flavour: 'affine:paragraph',
props: {
text: {
'$blocksuite:internal:text$': true,
delta: deltaConverter.astToDelta(child),
},
type: 'text',
},
children: [],
}
);
const column = columns[index];
if (!column) {
return;
}
row[column.id] = {
columnId: column.id,
value: HastUtils.getTextContent(child),
};
} else if (HastUtils.querySelector(child, '.cell-title')) {
walkerContext.pushGlobalContextStack<BlockSnapshot>(
'hast:table:children',
{
type: 'block',
id: nanoid(),
flavour: 'affine:paragraph',
props: {
text: {
'$blocksuite:internal:text$': true,
delta: deltaConverter.astToDelta(child, { pageMap }),
},
type: 'text',
},
children: [],
}
);
columns[index].type = 'title';
return;
}
const optionIds: string[] = [];
const column = columns[index];
if (!column) {
return;
}
if (HastUtils.querySelector(child, '.selected-value')) {
if (!('options' in column.data)) {
column.data.options = [];
}
if (!['multi-select', 'select'].includes(column.type)) {
column.type = 'select';
}
if (
column.type === 'select' &&
child.type === 'element' &&
child.children.length > 1
) {
column.type = 'multi-select';
}
child.type === 'element' &&
child.children.forEach(span => {
const filteredArray = column.data.options?.filter(
option =>
option.value === HastUtils.getTextContent(span)
);
const id = filteredArray?.length
? (filteredArray[0]?.id ?? nanoid())
: nanoid();
if (!filteredArray?.length) {
column.data.options?.push({
id,
value: HastUtils.getTextContent(span),
color: getTagColor(),
});
}
optionIds.push(id);
});
// Expand will be done when leaving the table
row[column.id] = {
columnId: column.id,
value: optionIds,
};
} else if (HastUtils.querySelector(child, '.checkbox')) {
if (column.type !== 'checkbox') {
column.type = 'checkbox';
}
row[column.id] = {
columnId: column.id,
value: HastUtils.querySelector(child, '.checkbox-on')
? true
: false,
};
} else if (column.type === 'number') {
const text = HastUtils.getTextContent(child);
const number = Number(text);
if (Number.isNaN(number)) {
column.type = 'rich-text';
row[column.id] = {
columnId: column.id,
value: AdapterTextUtils.createText(text),
};
} else {
row[column.id] = {
columnId: column.id,
value: number,
};
}
} else {
row[column.id] = {
columnId: column.id,
value: HastUtils.getTextContent(child),
};
}
if (
column.type === 'rich-text' &&
!AdapterTextUtils.isText(row[column.id].value)
) {
row[column.id] = {
columnId: column.id,
value: AdapterTextUtils.createText(row[column.id].value),
};
}
});
walkerContext.setGlobalContextStack('hast:table:column', columns);
walkerContext.pushGlobalContextStack('hast:table:rows', row);
}
}
}
},
leave: (o, context) => {
if (!HastUtils.isElement(o.node)) {
return;
}
const { walkerContext } = context;
switch (o.node.tagName) {
case 'table': {
const columns =
walkerContext.getGlobalContextStack<BlocksuiteTableColumn>(
'hast:table:column'
);
walkerContext.setGlobalContextStack('hast:table:column', []);
const children = walkerContext.getGlobalContextStack<BlockSnapshot>(
'hast:table:children'
);
walkerContext.setGlobalContextStack('hast:table:children', []);
const cells = Object.create(null);
walkerContext
.getGlobalContextStack<BlocksuiteTableRow>('hast:table:rows')
.forEach((row, i) => {
Object.keys(row).forEach(columnId => {
const cell = row[columnId];
if (!cell) {
return;
}
if (
columns.find(column => column.id === columnId)?.type ===
'select'
) {
cell.value = (cell.value as string[])[0];
}
});
cells[children.at(i)?.id ?? nanoid()] = row;
});
walkerContext.setGlobalContextStack('hast:table:cells', []);
let databaseTitle = '';
if (
o.parent?.node.type === 'element' &&
HastUtils.querySelector(o.parent.node, NotionDatabaseToken)
) {
databaseTitle = HastUtils.getTextContent(
HastUtils.querySelector(o.parent.node, NotionDatabaseTitleToken)
);
}
walkerContext.openNode(
{
type: 'block',
id: nanoid(),
flavour: DatabaseBlockSchema.model.flavour,
props: {
views: [
{
id: nanoid(),
name: 'Table View',
mode: 'table',
columns: [],
filter: {
type: 'group',
op: 'and',
conditions: [],
},
header: {
titleColumn:
columns.find(column => column.type === 'title')?.id ??
'',
iconColumn: 'type',
},
},
],
title: {
'$blocksuite:internal:text$': true,
delta: databaseTitle
? [
{
insert: databaseTitle,
},
]
: [],
},
columns,
cells,
},
children: [],
},
'children'
);
children.forEach(child => {
walkerContext.openNode(child, 'children').closeNode();
});
walkerContext.closeNode();
walkerContext.cleanGlobalContextStack('hast:table:column');
walkerContext.cleanGlobalContextStack('hast:table:rows');
walkerContext.cleanGlobalContextStack('hast:table:children');
break;
}
case 'th': {
walkerContext.setGlobalContext('hast:disableimg', false);
break;
}
}
},
},
fromBlockSnapshot: {},
};
export const DatabaseBlockNotionHtmlAdapterExtension =
BlockNotionHtmlAdapterExtension(databaseBlockNotionHtmlAdapterMatcher);