Skip to content

Instantly share code, notes, and snippets.

@martinjlowm
Created June 30, 2023 08:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save martinjlowm/7e1d0bbc9b073cf95c88e1dc11435509 to your computer and use it in GitHub Desktop.
Save martinjlowm/7e1d0bbc9b073cf95c88e1dc11435509 to your computer and use it in GitHub Desktop.
Walks through a whole workspace and replaces `<search-term>` with `<replace-term>` for various text blocks
const { Client } = require("@notionhq/client");
const notion = new Client({
auth: process.env.NOTION_TOKEN,
});
const searchValue = "<search-term>";
const newValue = "<replace-term>";
(async () => {
let next_cursor;
let results;
let has_more = true;
while (has_more) {
({ results, next_cursor, has_more } = await notion.search({
filter: {
value: "page",
property: "object",
},
start_cursor: next_cursor,
}));
await processChildren(
results.filter((page) => page.parent.type === "workspace"),
1
);
}
})();
async function processChildren(blocks, depth) {
if (!blocks.length) {
return;
}
await findAndReplace(blocks, depth);
for (const block of blocks) {
await processChildren(await retrieveBlocks(block.id), depth + 1);
}
}
async function retrieveBlocks(pageId) {
const page = await notion.blocks.children.list({
block_id: pageId,
});
return page.results;
}
const textTypes = [
"callout",
"paragraph",
"heading_1",
"heading_2",
"heading_3",
"bulleted_list_item",
"numbered_list_item",
"quote",
];
async function findAndReplace(blocks, depth) {
for (const block of blocks) {
const type = block.type;
if (!textTypes.includes(type)) {
continue;
}
if (
!block[type].rich_text.some((text) =>
text.plain_text.includes(searchValue)
)
) {
continue;
}
const textItems = block[type].rich_text;
const newTextItems = textItems.map((item) => {
if (item.type !== "text") {
return item;
}
if (!item.plain_text.includes(searchValue)) {
return item;
}
const newItem = {
...item,
text: {
...item.text,
content: item.text.content.replaceAll(searchValue, newValue),
},
plain_text: item.plain_text.replaceAll(searchValue, newValue),
};
return newItem;
});
await updateBlock(block, type, newTextItems);
}
}
async function updateBlock(block, type, newTextItems) {
const selectedBlock = await notion.blocks.update({
block_id: block.id,
[type]: {
rich_text: newTextItems,
},
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment