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 89 forks source link

Adding a custom transformer for synced blocks produces double output #62

Closed dionjwa closed 1 year ago

dionjwa commented 1 year ago

I'm using docu-notion which consumes this module.

I created a custom transformer for synced blocks since they were getting ignored.

However, the markdown output is doubled. Somehow the transform function is getting called twice.

The code for handling synced blocks is a bit unclear.

I suspect it's complicated by that for synced blocks, you need to dig into the children and then follow the synced blocks there. But even if my custom transformer just returns some hard-coded text string, that output is also doubled, so the doubling is not due to the custom transformer, it's seems the problem is upstream.

Relevant notion doc:

image

Then the relevant output is:

image

The transformer to test is:

{
  type: "synced_block",
  getStringFromBlock: async (
    context: IDocuNotionContext,
    block: NotionBlock
  ) => {
    return `test output ${Math.random()}`;
  }
}
souvikinator commented 1 year ago

So I tried it out and the synced block is not getting ignored when not using setCustomTransformer. Just the mermaid syntax is not being rendered which is why you are using a custom transformer.

Now custom transformer does produce duplicate output but only for synced_block. I'll into it and get back to you.

dionjwa commented 1 year ago

Sorry, you're right, the content wasn't ignored per se.

Here is my function for getting the content of the synced blocks. I am only getting the first child each time, I only have a single block in the synced blocks, maybe that's an edge case, not sure:

/**
 * 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
  );
};
souvikinator commented 1 year ago

This issue is fixed and is live in v3.0.0 Thanks for your contribution. Closing the issue, feel free to reopen if needed.