mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-03 10:40:44 +08:00
feat: add new tool
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
import { Array as YArray, Doc, Map as YMap } from 'yjs';
|
||||
|
||||
import { diffKeyedRecords, type KeyedDiff, type KeyedRecord } from './diff';
|
||||
import { formatValue, toPlain } from './plain';
|
||||
|
||||
type RootDocMetaExtract = {
|
||||
recordsById: Map<string, KeyedRecord>;
|
||||
duplicateIds: string[];
|
||||
};
|
||||
|
||||
export function extractRootDocPagesMeta(rootDoc: Doc): RootDocMetaExtract {
|
||||
const recordsById = new Map<string, KeyedRecord>();
|
||||
const duplicateIds: string[] = [];
|
||||
|
||||
const meta = rootDoc.getMap('meta');
|
||||
const pages = meta.get('pages');
|
||||
const entries =
|
||||
pages instanceof YArray
|
||||
? pages.toArray()
|
||||
: Array.isArray(pages)
|
||||
? pages
|
||||
: null;
|
||||
if (!entries) {
|
||||
return { recordsById, duplicateIds };
|
||||
}
|
||||
|
||||
for (const entry of entries) {
|
||||
let id: string | null = null;
|
||||
if (entry instanceof YMap) {
|
||||
const idRaw = entry.get('id');
|
||||
id =
|
||||
typeof idRaw === 'string'
|
||||
? idRaw
|
||||
: typeof idRaw?.toString === 'function'
|
||||
? idRaw.toString()
|
||||
: null;
|
||||
} else if (entry && typeof entry === 'object' && !Array.isArray(entry)) {
|
||||
const record = entry as Record<string, unknown>;
|
||||
id =
|
||||
typeof record.id === 'string'
|
||||
? record.id
|
||||
: (record.id?.toString?.() ?? null);
|
||||
}
|
||||
|
||||
if (!id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (recordsById.has(id)) {
|
||||
duplicateIds.push(id);
|
||||
}
|
||||
|
||||
const metaPlain = toPlain(entry) as unknown;
|
||||
if (
|
||||
metaPlain &&
|
||||
typeof metaPlain === 'object' &&
|
||||
!Array.isArray(metaPlain)
|
||||
) {
|
||||
recordsById.set(id, metaPlain as KeyedRecord);
|
||||
}
|
||||
}
|
||||
|
||||
return { recordsById, duplicateIds };
|
||||
}
|
||||
|
||||
function docLabel(id: string, meta: KeyedRecord) {
|
||||
const title = meta.title;
|
||||
if (typeof title === 'string' && title.trim()) {
|
||||
return `${id} "${title}"`;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
export function printRootDocPairDiff(opts: {
|
||||
fromLabel: string;
|
||||
toLabel: string;
|
||||
fromMeta: RootDocMetaExtract;
|
||||
toMeta: RootDocMetaExtract;
|
||||
}) {
|
||||
const diff = diffKeyedRecords(
|
||||
opts.fromMeta.recordsById,
|
||||
opts.toMeta.recordsById
|
||||
);
|
||||
|
||||
console.log(`\n=== ${opts.fromLabel} -> ${opts.toLabel} ===`);
|
||||
console.log(
|
||||
`Docs: ${opts.fromMeta.recordsById.size} -> ${opts.toMeta.recordsById.size} (+${diff.added.length} / -${diff.removed.length} / ~${diff.changed.length})`
|
||||
);
|
||||
|
||||
if (opts.fromMeta.duplicateIds.length) {
|
||||
console.log(
|
||||
`! Warning: duplicate page ids in FROM: ${Array.from(new Set(opts.fromMeta.duplicateIds)).sort().join(', ')}`
|
||||
);
|
||||
}
|
||||
if (opts.toMeta.duplicateIds.length) {
|
||||
console.log(
|
||||
`! Warning: duplicate page ids in TO: ${Array.from(new Set(opts.toMeta.duplicateIds)).sort().join(', ')}`
|
||||
);
|
||||
}
|
||||
|
||||
if (diff.added.length) {
|
||||
console.log(`\n+ Added (${diff.added.length})`);
|
||||
for (const { id, record } of diff.added) {
|
||||
console.log(` + ${docLabel(id, record)}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (diff.removed.length) {
|
||||
console.log(`\n- Removed (${diff.removed.length})`);
|
||||
for (const { id, record } of diff.removed) {
|
||||
console.log(` - ${docLabel(id, record)}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (diff.changed.length) {
|
||||
console.log(`\n~ Changed (${diff.changed.length})`);
|
||||
for (const change of diff.changed) {
|
||||
const fromTitle = change.fromRecord.title;
|
||||
const toTitle = change.toRecord.title;
|
||||
|
||||
let header = ` ~ ${change.id}`;
|
||||
if (
|
||||
typeof fromTitle === 'string' &&
|
||||
typeof toTitle === 'string' &&
|
||||
fromTitle !== toTitle
|
||||
) {
|
||||
header += ` "${fromTitle}" -> "${toTitle}"`;
|
||||
} else if (typeof toTitle === 'string' && toTitle.trim()) {
|
||||
header += ` "${toTitle}"`;
|
||||
}
|
||||
console.log(header);
|
||||
|
||||
for (const field of change.fields) {
|
||||
console.log(
|
||||
` - ${field.key}: ${formatValue(field.key, field.from)} -> ${formatValue(field.key, field.to)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!diff.added.length && !diff.removed.length && !diff.changed.length) {
|
||||
console.log('\n(no changes)');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user