souvikinator / notion-to-md

Convert notion pages, block and list of blocks to markdown (supports nesting and custom parsing)
https://www.npmjs.com/package/notion-to-md
MIT License
1.08k stars 90 forks source link

Reference Synced Blocks are not supported #54

Closed GorvGoyl closed 1 year ago

GorvGoyl commented 1 year ago

Please add support for reference synced blocks as well. Currently, these are silently ignored in output. original synced blocks are working fine though

block: {
  "object": "block",
  "id": "77b645b9-2edee724eb",
  "parent": {
    "type": "page_id",
    "page_id": "77e1abf5cd665865"
  },
  "created_time": "2022-10-14T06:08:00.000Z",
  "last_edited_time": "2022-10-14T06:08:00.000Z",
  "created_by": {
    "object": "user",
    "id": "ecc52c68-e563-491698"
  },
  "last_edited_by": {
    "object": "user",
    "id": "ecc52c68-e563-4f65-9561-1e"
  },
  "has_children": true,
  "archived": false,
  "type": "synced_block",
  "synced_block": {
    "synced_from": {
      "type": "block_id",
      "block_id": "52edd340-0926a7c9e2"
    }
  }
}
GorvGoyl commented 1 year ago

current workaround

n2m.setCustomTransformer("synced_block", async (block) => {
    const syncedBlock = block as SyncedBlockBlockObjectResponse;
    const originalSyncedBlockId =
      syncedBlock.synced_block.synced_from?.block_id;

    const isReferenceSyncedBlock = !!originalSyncedBlockId;
    // check if it's a 'reference synced block'
    if (isReferenceSyncedBlock) {
      const mdBlocks = await n2m.pageToMarkdown(originalSyncedBlockId);
      const mdString = n2m.toMarkdownString(mdBlocks);
      return mdString;
    } else {
      return ""; // 'original synced blocks' are handled like normal blocks by n2m so avoid rendering it twice
    }
  });
GorvGoyl commented 1 year ago

Nevermind it's working again without setCustomTransformer of synced block.

dionjwa commented 1 year ago

This is my workaround:

/**
 * Replacing synced blocks is returning either the synced block, or
 * the first child of the synced block, and keep going until you reach
 * a non-synced block.
 */
const replaceSyncedBlockWithTarget = async (
  block: NotionBlock,
  client: Client
): Promise<NotionBlock> => {
  if (block.type !== "synced_block") {
    return block;
  }
  const synced_from = block?.synced_block?.synced_from?.block_id;
  if (synced_from) {
    const syncedBlock = await client.blocks.retrieve({ block_id: synced_from });
    return await replaceSyncedBlockWithTarget(
      syncedBlock as NotionBlock,
      client
    );
  }

  const children = await client.blocks.children.list({ block_id: block.id });
  if (children.results.length === 0) {
    return block;
  }
  return await replaceSyncedBlockWithTarget(
    children.results[0] as NotionBlock,
    client
  );
};