@mnemosyne_os/affine-reader 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +42 -0
  3. package/README.md +89 -0
  4. package/dist/cli.d.ts +14 -0
  5. package/dist/cli.js +79 -0
  6. package/dist/exportMarkdown.d.ts +46 -0
  7. package/dist/exportMarkdown.js +104 -0
  8. package/dist/index.d.ts +17 -0
  9. package/dist/index.js +34 -0
  10. package/dist/locate.d.ts +24 -0
  11. package/dist/locate.js +91 -0
  12. package/dist/nodeSqlite.d.ts +20 -0
  13. package/dist/nodeSqlite.js +50 -0
  14. package/dist/read.d.ts +45 -0
  15. package/dist/read.js +197 -0
  16. package/dist/stage.d.ts +27 -0
  17. package/dist/stage.js +54 -0
  18. package/dist/types.d.ts +72 -0
  19. package/dist/types.js +10 -0
  20. package/dist/vendor/affine/blocksuite-types.d.ts +25 -0
  21. package/dist/vendor/affine/blocksuite-types.js +14 -0
  22. package/dist/vendor/affine/delta-to-md/delta-converters.d.ts +39 -0
  23. package/dist/vendor/affine/delta-to-md/delta-converters.js +81 -0
  24. package/dist/vendor/affine/delta-to-md/delta-to-md.d.ts +1 -0
  25. package/dist/vendor/affine/delta-to-md/delta-to-md.js +132 -0
  26. package/dist/vendor/affine/delta-to-md/index.d.ts +2 -0
  27. package/dist/vendor/affine/delta-to-md/index.js +7 -0
  28. package/dist/vendor/affine/delta-to-md/utils/node.d.ts +13 -0
  29. package/dist/vendor/affine/delta-to-md/utils/node.js +59 -0
  30. package/dist/vendor/affine/delta-to-md/utils/url.d.ts +1 -0
  31. package/dist/vendor/affine/delta-to-md/utils/url.js +8 -0
  32. package/dist/vendor/affine/parser.d.ts +5 -0
  33. package/dist/vendor/affine/parser.js +386 -0
  34. package/dist/vendor/affine/types.d.ts +100 -0
  35. package/dist/vendor/affine/types.js +2 -0
  36. package/package.json +64 -0
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deltaToMd = void 0;
4
+ // oxlint-disable
5
+ // @ts-nocheck
6
+ const node_1 = require("./utils/node");
7
+ const deltaToMd = (delta, converters) => {
8
+ return convert(delta, converters).render().trimEnd() + '\n';
9
+ };
10
+ exports.deltaToMd = deltaToMd;
11
+ function convert(ops, converters) {
12
+ let group, line, el, activeInline, beginningOfLine;
13
+ let root = new node_1.Node();
14
+ function newLine() {
15
+ el = line = new node_1.Node(['', '\n']);
16
+ root.append(line);
17
+ activeInline = {};
18
+ }
19
+ newLine();
20
+ for (let i = 0; i < ops.length; i++) {
21
+ let op = ops[i];
22
+ if (typeof op.insert === 'object') {
23
+ for (let k in op.insert) {
24
+ if (converters.embed[k]) {
25
+ applyInlineAttributes(op.attributes);
26
+ converters.embed[k].call(el, op.insert[k], op.attributes);
27
+ }
28
+ }
29
+ }
30
+ else {
31
+ let lines = op.insert.split('\n');
32
+ if (hasBlockLevelAttribute(op.attributes, converters)) {
33
+ // Some line-level styling (ie headings) is applied by inserting a \n
34
+ // with the style; the style applies back to the previous \n.
35
+ // There *should* only be one style in an insert operation.
36
+ for (let j = 1; j < lines.length; j++) {
37
+ for (let attr in op.attributes) {
38
+ if (converters.block[attr]) {
39
+ let fn = converters.block[attr];
40
+ if (typeof fn === 'object') {
41
+ if (group && group.type !== attr) {
42
+ group = null;
43
+ }
44
+ if (!group && fn.group) {
45
+ group = {
46
+ el: fn.group(),
47
+ type: attr,
48
+ value: op.attributes[attr],
49
+ distance: 0,
50
+ };
51
+ root.append(group.el);
52
+ }
53
+ if (group) {
54
+ group.el.append(line);
55
+ group.distance = 0;
56
+ }
57
+ fn = fn.line;
58
+ }
59
+ fn.call(line, op.attributes, group);
60
+ newLine();
61
+ break;
62
+ }
63
+ }
64
+ }
65
+ beginningOfLine = true;
66
+ }
67
+ else {
68
+ for (let l = 0; l < lines.length; l++) {
69
+ if ((l > 0 || beginningOfLine) && group && ++group.distance >= 2) {
70
+ group = null;
71
+ }
72
+ applyInlineAttributes(op.attributes, ops[i + 1] && ops[i + 1].attributes);
73
+ el.append(lines[l]);
74
+ if (l < lines.length - 1) {
75
+ newLine();
76
+ }
77
+ }
78
+ beginningOfLine = false;
79
+ }
80
+ }
81
+ }
82
+ return root;
83
+ function applyInlineAttributes(attrs, next) {
84
+ let first = [];
85
+ let then = [];
86
+ attrs = attrs || {};
87
+ let tag = el, seen = {};
88
+ while (tag._format) {
89
+ seen[tag._format] = true;
90
+ if (!attrs[tag._format] || tag.open !== tag.close) {
91
+ for (let k in seen) {
92
+ delete activeInline[k];
93
+ }
94
+ el = tag.parent();
95
+ }
96
+ tag = tag.parent();
97
+ }
98
+ for (let attr in attrs) {
99
+ if (converters.inline[attr] && attrs[attr]) {
100
+ if (activeInline[attr] && activeInline[attr] === attrs[attr]) {
101
+ continue; // do nothing -- we should already be inside this style's tag
102
+ }
103
+ if (next && attrs[attr] === next[attr]) {
104
+ first.push(attr); // if the next operation has the same style, this should be the outermost tag
105
+ }
106
+ else {
107
+ then.push(attr);
108
+ }
109
+ activeInline[attr] = attrs[attr];
110
+ }
111
+ }
112
+ first.forEach(apply);
113
+ then.forEach(apply);
114
+ function apply(fmt) {
115
+ let newEl = converters.inline[fmt].call(null, attrs[fmt]);
116
+ if (Array.isArray(newEl)) {
117
+ newEl = new node_1.Node(newEl);
118
+ }
119
+ newEl._format = fmt;
120
+ el.append(newEl);
121
+ el = newEl;
122
+ }
123
+ }
124
+ }
125
+ function hasBlockLevelAttribute(attrs, converters) {
126
+ for (let k in attrs) {
127
+ if (Object.keys(converters.block).includes(k)) {
128
+ return true;
129
+ }
130
+ }
131
+ return false;
132
+ }
@@ -0,0 +1,2 @@
1
+ export { getConverters } from './delta-converters';
2
+ export { deltaToMd } from './delta-to-md';
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deltaToMd = exports.getConverters = void 0;
4
+ var delta_converters_1 = require("./delta-converters");
5
+ Object.defineProperty(exports, "getConverters", { enumerable: true, get: function () { return delta_converters_1.getConverters; } });
6
+ var delta_to_md_1 = require("./delta-to-md");
7
+ Object.defineProperty(exports, "deltaToMd", { enumerable: true, get: function () { return delta_to_md_1.deltaToMd; } });
@@ -0,0 +1,13 @@
1
+ export declare class Node {
2
+ id: number;
3
+ children: Node[];
4
+ open: string;
5
+ close: string;
6
+ text: string;
7
+ _format: string;
8
+ _parent: Node;
9
+ constructor(data?: string[] | string);
10
+ append(e: Node): void;
11
+ render(): any;
12
+ parent(): Node;
13
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Node = void 0;
4
+ // oxlint-disable
5
+ // @ts-nocheck
6
+ let id = 0;
7
+ class Node {
8
+ id = ++id;
9
+ children;
10
+ open;
11
+ close;
12
+ text;
13
+ _format;
14
+ _parent;
15
+ constructor(data) {
16
+ if (Array.isArray(data)) {
17
+ this.open = data[0];
18
+ this.close = data[1];
19
+ }
20
+ else if (typeof data === 'string') {
21
+ this.text = data;
22
+ }
23
+ this.children = [];
24
+ }
25
+ append(e) {
26
+ if (!(e instanceof Node)) {
27
+ e = new Node(e);
28
+ }
29
+ if (e._parent) {
30
+ const idx = e._parent.children.indexOf(e);
31
+ e._parent.children.splice(idx, 1);
32
+ }
33
+ e._parent = this;
34
+ this.children = this.children.concat(e);
35
+ }
36
+ render() {
37
+ const inner = (this.text || '') + this.children.map(c => c.render()).join('');
38
+ if (inner.trim() === '' &&
39
+ this.open === this.close &&
40
+ this.open &&
41
+ this.close) {
42
+ return '';
43
+ }
44
+ const wrapped = this.open && this.close;
45
+ const emptyInner = inner.trim() === '';
46
+ const fragments = [
47
+ inner.startsWith(' ') && !emptyInner && wrapped ? ' ' : '',
48
+ this.open,
49
+ wrapped ? inner.trim() : inner,
50
+ this.close,
51
+ inner.endsWith(' ') && !emptyInner && wrapped ? ' ' : '',
52
+ ].filter(f => f);
53
+ return fragments.join('');
54
+ }
55
+ parent() {
56
+ return this._parent;
57
+ }
58
+ }
59
+ exports.Node = Node;
@@ -0,0 +1 @@
1
+ export declare const encodeLink: (link: string) => string;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.encodeLink = void 0;
4
+ const encodeLink = (link) => encodeURI(link)
5
+ .replaceAll('(', '%28')
6
+ .replaceAll(')', '%29')
7
+ .replace(/(\?|&)response-content-disposition=attachment.*$/, '');
8
+ exports.encodeLink = encodeLink;
@@ -0,0 +1,5 @@
1
+ import type { BaseParsedBlock, ParsedBlock, ParsedDoc, ParserContext, YBlock, YBlocks } from './types';
2
+ export declare const parseBlockToMd: (block: BaseParsedBlock, padding?: string) => string;
3
+ export declare function parseBlock(context: ParserContext, yBlock: YBlock | undefined, yBlocks: YBlocks, // all blocks
4
+ aiEditable?: boolean, blockLevel?: number): ParsedBlock | null;
5
+ export declare const parsePageDoc: (ctx: ParserContext) => ParsedDoc;
@@ -0,0 +1,386 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parsePageDoc = exports.parseBlockToMd = void 0;
4
+ exports.parseBlock = parseBlock;
5
+ const yjs_1 = require("yjs");
6
+ const delta_to_md_1 = require("./delta-to-md");
7
+ const parseBlockToMd = (block, padding = '') => {
8
+ if (block.content) {
9
+ return (block.content
10
+ .split('\n')
11
+ .map(line => padding + line)
12
+ .slice(0, -1)
13
+ .join('\n') +
14
+ '\n' +
15
+ block.children.map(b => (0, exports.parseBlockToMd)(b, padding + ' ')).join(''));
16
+ }
17
+ else {
18
+ return block.children.map(b => (0, exports.parseBlockToMd)(b, padding)).join('');
19
+ }
20
+ };
21
+ exports.parseBlockToMd = parseBlockToMd;
22
+ function parseBlock(context, yBlock, yBlocks, // all blocks
23
+ aiEditable = false, blockLevel = 0) {
24
+ if (!yBlock) {
25
+ return null;
26
+ }
27
+ const deltaConverters = (0, delta_to_md_1.getConverters)({
28
+ convertInlineReferenceLink: ref => {
29
+ return {
30
+ title: ref.title || context.renderDocTitle?.(ref.pageId) || '',
31
+ link: context.buildDocUrl(ref.pageId),
32
+ };
33
+ },
34
+ });
35
+ const id = yBlock.get('sys:id');
36
+ const flavour = yBlock.get('sys:flavour');
37
+ const type = yBlock.get('prop:type');
38
+ const toMd = () => (0, delta_to_md_1.deltaToMd)(yBlock.get('prop:text').toDelta(), deltaConverters);
39
+ const hidden = yBlock.get('prop:hidden');
40
+ const displayMode = yBlock.get('prop:displayMode');
41
+ const childrenIds = yBlock.get('sys:children') instanceof yjs_1.Array
42
+ ? yBlock.get('sys:children').toJSON()
43
+ : [];
44
+ let result = {
45
+ id,
46
+ flavour,
47
+ content: '',
48
+ children: [],
49
+ type,
50
+ };
51
+ if (hidden || displayMode === 'edgeless') {
52
+ return result;
53
+ }
54
+ let placeholder = false;
55
+ try {
56
+ switch (flavour) {
57
+ case 'affine:paragraph': {
58
+ let initial = '';
59
+ if (type === 'h1') {
60
+ initial = '# ';
61
+ }
62
+ else if (type === 'h2') {
63
+ initial = '## ';
64
+ }
65
+ else if (type === 'h3') {
66
+ initial = '### ';
67
+ }
68
+ else if (type === 'h4') {
69
+ initial = '#### ';
70
+ }
71
+ else if (type === 'h5') {
72
+ initial = '##### ';
73
+ }
74
+ else if (type === 'h6') {
75
+ initial = '###### ';
76
+ }
77
+ else if (type === 'quote') {
78
+ initial = '> ';
79
+ }
80
+ result.content = initial + toMd() + '\n';
81
+ break;
82
+ }
83
+ case 'affine:divider': {
84
+ result.content = '\n---\n\n';
85
+ break;
86
+ }
87
+ case 'affine:list': {
88
+ let prefix = type === 'bulleted' ? '* ' : '1. ';
89
+ if (type === 'todo') {
90
+ const checked = yBlock.get('prop:checked');
91
+ prefix = checked ? '- [x] ' : '- [ ] ';
92
+ }
93
+ result.content = prefix + toMd();
94
+ break;
95
+ }
96
+ case 'affine:code': {
97
+ const lang = yBlock.get('prop:language')?.toLowerCase() || 'txt';
98
+ // do not transform to delta for code block
99
+ const caption = yBlock.get('prop:caption');
100
+ result.content =
101
+ '```' +
102
+ lang +
103
+ (caption ? ` ${caption}` : '') +
104
+ '\n' +
105
+ yBlock.get('prop:text').toJSON() +
106
+ '\n```\n\n';
107
+ break;
108
+ }
109
+ case 'affine:image': {
110
+ const sourceId = yBlock.get('prop:sourceId');
111
+ const width = yBlock.get('prop:width');
112
+ const height = yBlock.get('prop:height');
113
+ // fixme: this may not work if workspace is not public
114
+ const blobUrl = context.buildBlobUrl(sourceId);
115
+ const caption = yBlock.get('prop:caption');
116
+ if (width || height || caption) {
117
+ result.content =
118
+ `<img
119
+ src="${blobUrl}"
120
+ alt="${caption}"
121
+ width="${width || 'auto'}"
122
+ height="${height || 'auto'}"
123
+ />
124
+ ` + '\n\n';
125
+ }
126
+ else {
127
+ result.content = `\n![${caption || sourceId}](${blobUrl})\n\n`;
128
+ }
129
+ Object.assign(result, {
130
+ sourceId,
131
+ width,
132
+ height,
133
+ caption,
134
+ blobUrl,
135
+ });
136
+ break;
137
+ }
138
+ case 'affine:attachment': {
139
+ const sourceId = yBlock.get('prop:sourceId');
140
+ const blobUrl = context.buildBlobUrl(sourceId);
141
+ const caption = yBlock.get('prop:caption');
142
+ if (type.startsWith('video')) {
143
+ result.content =
144
+ `<video muted autoplay loop preload="auto" playsinline>
145
+ <source src="${blobUrl}" type="${type}" />
146
+ </video>
147
+ ` + '\n\n';
148
+ }
149
+ else {
150
+ // assume it is an image
151
+ result.content = `\n![${caption || sourceId}](${blobUrl})\n\n`;
152
+ }
153
+ Object.assign(result, {
154
+ sourceId,
155
+ blobUrl,
156
+ caption,
157
+ });
158
+ break;
159
+ }
160
+ case 'affine:embed-youtube': {
161
+ const videoId = yBlock.get('prop:videoId');
162
+ // prettier-ignore
163
+ result.content = `
164
+ <iframe
165
+ type="text/html"
166
+ width="100%"
167
+ height="410px"
168
+ src="https://www.youtube.com/embed/${videoId}"
169
+ frameborder="0"
170
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
171
+ allowfullscreen
172
+ credentialless>
173
+ </iframe>` + '\n\n';
174
+ break;
175
+ }
176
+ case 'affine:bookmark': {
177
+ const url = yBlock.get('prop:url');
178
+ const caption = yBlock.get('prop:caption');
179
+ result.content = `\n[](Bookmark,${url})\n\n`;
180
+ Object.assign(result, {
181
+ url,
182
+ caption,
183
+ });
184
+ break;
185
+ }
186
+ case 'affine:embed-linked-doc':
187
+ case 'affine:embed-synced-doc': {
188
+ const pageId = yBlock.get('prop:pageId');
189
+ const caption = yBlock.get('prop:caption');
190
+ result.content = `\n[${caption}](${context.buildDocUrl(pageId)})\n\n`;
191
+ Object.assign(result, {
192
+ pageId,
193
+ caption,
194
+ });
195
+ break;
196
+ }
197
+ case 'affine:surface':
198
+ case 'affine:page':
199
+ case 'affine:note':
200
+ case 'affine:frame': {
201
+ result.content = '';
202
+ break;
203
+ }
204
+ case 'affine:database': {
205
+ const title = yBlock.get('prop:title').toJSON();
206
+ const childrenTitleById = Object.fromEntries(childrenIds.map(cid => {
207
+ const child = parseBlock(context, yBlocks.get(cid), yBlocks, aiEditable, blockLevel + 1);
208
+ if (!child) {
209
+ return [cid, ''];
210
+ }
211
+ return [cid, (0, exports.parseBlockToMd)(child)];
212
+ }));
213
+ const cols = yBlock.get('prop:columns').toJSON();
214
+ const cells = yBlock.get('prop:cells').toJSON();
215
+ const optionToTagHtml = (option) => {
216
+ return `<span data-affine-option data-value="${option.id}" data-option-color="${option.color}">${option.value}</span>`;
217
+ };
218
+ const dbRows = childrenIds
219
+ .map(cid => {
220
+ const row = cells[cid];
221
+ return cols.map(col => {
222
+ const value = row?.[col.id]?.value;
223
+ if (col.type !== 'title' && !value) {
224
+ return '';
225
+ }
226
+ switch (col.type) {
227
+ case 'title':
228
+ return childrenTitleById[cid];
229
+ case 'select':
230
+ return optionToTagHtml(col.data['options'].find((opt) => opt.id === value));
231
+ case 'multi-select':
232
+ return col.data['options']
233
+ .filter((opt) => value.includes(opt.id))
234
+ .map(optionToTagHtml)
235
+ .join('');
236
+ default:
237
+ return value ?? '';
238
+ }
239
+ });
240
+ })
241
+ .filter(row => !row.every(v => !v));
242
+ const header = cols.map(col => {
243
+ return col.name;
244
+ });
245
+ const divider = cols.map(() => {
246
+ return '---';
247
+ });
248
+ // convert to markdown table
249
+ result.content =
250
+ [header, divider, ...dbRows]
251
+ .map(row => {
252
+ return ('|' +
253
+ row
254
+ .map(cell => String(cell || '')?.trim())
255
+ .join('|')
256
+ .replace(/\n+/g, '<br />') +
257
+ '|');
258
+ })
259
+ .join('\n') + '\n\n';
260
+ Object.assign(result, {
261
+ title,
262
+ rows: dbRows.map(row => {
263
+ return Object.fromEntries(row.map((v, i) => [cols[i].name, v]));
264
+ }),
265
+ });
266
+ break;
267
+ }
268
+ case 'affine:table': {
269
+ // Extract row IDs and their order
270
+ const rowEntries = Object.entries(yBlock.toJSON())
271
+ .filter(([key]) => key.startsWith('prop:rows.') && key.endsWith('.rowId'))
272
+ .map(([key, value]) => {
273
+ const rowId = value;
274
+ const orderKey = key.replace('.rowId', '.order');
275
+ const order = yBlock.get(orderKey);
276
+ const backgroundColor = yBlock.get(key.replace('.rowId', '.backgroundColor'));
277
+ return { rowId, order, backgroundColor };
278
+ })
279
+ .sort((a, b) => a.order.localeCompare(b.order));
280
+ // Extract column IDs and their order
281
+ const columnEntries = Object.entries(yBlock.toJSON())
282
+ .filter(([key]) => key.startsWith('prop:columns.') && key.endsWith('.columnId'))
283
+ .map(([key, value]) => {
284
+ const columnId = value;
285
+ const orderKey = key.replace('.columnId', '.order');
286
+ const order = yBlock.get(orderKey);
287
+ return { columnId, order };
288
+ })
289
+ .sort((a, b) => a.order.localeCompare(b.order));
290
+ // Build the table rows with cell data
291
+ const tableRows = rowEntries.map(({ rowId }) => {
292
+ return columnEntries.map(({ columnId }) => {
293
+ const cellKey = `prop:cells.${rowId}:${columnId}.text`;
294
+ const cellText = yBlock.get(cellKey);
295
+ return cellText || '';
296
+ });
297
+ });
298
+ // Store column IDs for reference
299
+ const columnIds = columnEntries.map(({ columnId }) => columnId);
300
+ // Use the first row as header and the rest as data rows
301
+ if (tableRows.length > 0) {
302
+ const headerRow = tableRows[0];
303
+ const dataRows = tableRows.slice(1);
304
+ const separators = headerRow.map(() => '---');
305
+ // Convert to markdown table with first row as header
306
+ result.content =
307
+ [headerRow, separators, ...dataRows]
308
+ .map(row => {
309
+ return ('|' +
310
+ row
311
+ .map(cell => String(cell || '')?.trim())
312
+ .join('|')
313
+ .replace(/\n+/g, '<br />') +
314
+ '|');
315
+ })
316
+ .join('\n') + '\n\n';
317
+ }
318
+ else {
319
+ // Handle empty table case
320
+ result.content = '';
321
+ }
322
+ Object.assign(result, {
323
+ columns: columnIds,
324
+ rows: tableRows,
325
+ });
326
+ break;
327
+ }
328
+ default: {
329
+ // console.warn("Unknown or unsupported flavour", flavour);
330
+ placeholder = true;
331
+ }
332
+ }
333
+ result.children =
334
+ flavour !== 'affine:database'
335
+ ? childrenIds
336
+ .map(cid => parseBlock(context, yBlocks.get(cid), yBlocks, aiEditable, blockLevel + 1))
337
+ .filter((block) => !!block &&
338
+ !(block.content === '' && block.children.length === 0))
339
+ : [];
340
+ }
341
+ catch (e) {
342
+ console.warn('Error converting block to md', e);
343
+ }
344
+ if (result.content && aiEditable && blockLevel === 2) {
345
+ // add a placeholder comment for the block level 2
346
+ if (flavour === 'affine:database' || placeholder) {
347
+ result.content = `<!-- block_id=${id} flavour=${flavour} placeholder -->\n`;
348
+ result.children = [];
349
+ }
350
+ else {
351
+ result.content = `<!-- block_id=${id} flavour=${flavour} -->\n${result.content}`;
352
+ }
353
+ }
354
+ return result;
355
+ }
356
+ const parsePageDoc = (ctx) => {
357
+ // we assume that the first block is the page block
358
+ const yBlocks = ctx.doc.getMap('blocks');
359
+ const maybePageBlock = Object.entries(yBlocks.toJSON()).findLast(([_, b]) => b['sys:flavour'] === 'affine:page');
360
+ // there are cases that the page is empty due to some weird issues
361
+ if (!maybePageBlock) {
362
+ return {
363
+ title: '',
364
+ md: '',
365
+ };
366
+ }
367
+ else {
368
+ const yPage = yBlocks.get(maybePageBlock[0]);
369
+ const title = yPage.get('prop:title');
370
+ const rootBlock = parseBlock(ctx, yPage, yBlocks, ctx.aiEditable);
371
+ if (!rootBlock) {
372
+ return {
373
+ title: '',
374
+ md: '',
375
+ };
376
+ }
377
+ rootBlock.children = rootBlock.children.filter((block) => block.flavour === 'affine:note');
378
+ const md = (0, exports.parseBlockToMd)(rootBlock);
379
+ return {
380
+ title: title.toJSON(),
381
+ parsedBlock: rootBlock,
382
+ md,
383
+ };
384
+ }
385
+ };
386
+ exports.parsePageDoc = parsePageDoc;