UNPKG

notion-helper

Version:

A library of functions for working more easily with the Notion API

1,319 lines (1,255 loc) 73.8 kB
import { buildRichTextObj, enforceRichText } from "./rich-text.mjs"; import { setIcon } from "./emoji-and-files.mjs"; import { isValidURL, isValidUUID, validateImageURL, validatePDFURL, validateVideoURL, validateAudioURL, enforceStringLength, } from "./utils.mjs"; /* * TODO * * ? Create a wrapper class that can give blocks internal labels. Will be useful for appending child block arrays to specific blocks, and editing blocks after creation but before they are sent to Notion * - Implement columns */ /** * Object with methods to construct the majority of block types supported by the Notion API. * * Block types include audio, bookmark, breadcrumb, bulleted list item, callout, code, column_list, column, divider, embed, file, heading, image, numbered list item, paragraph, pdf, quote, table, table row, table of contents, to-do, toggle, and video. Some block types return null if they are provided with invalid data; you should filter these out your final children array. * * Not supported: Link preview, synced block. Equation and Mention are supported within the buildRichTextObj() function, not here. * * @namespace */ export const block = { /** * Methods for audio blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ audio: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: false, /** * Creates an audio block. * * @function * @param {string|Object} options - A string representing the audio URL, a file upload ID, or an options object. * @param {string} options.url - The URL for the audio. * @param {string} options.id - The ID of the file upload. * @param {string|string[]|Array<Object>} [options.caption=[]] - The caption as a string, an array of strings, or an array of rich text objects. * @returns {Object|null} An audio block object compatible with Notion's API, or null if the URL/ID is invalid. * @example * // Use with an external URL * const externalAudio = block.audio.createBlock("https://thomasjfrank.com/wp-content/uploads/2025/05/output3.mp3"); * * // Use with a file upload ID * const fileUploadAudio = block.audio.createBlock("123e4567-e89b-12d3-a456-426614174000"); * * // Use with options object for external audio * const externalAudio = block.audio.createBlock({ * url: "https://thomasjfrank.com/wp-content/uploads/2025/05/output3.mp3", * caption: "Check out my mixtape, man." * }); * * // Use with options object for file upload * const fileUploadAudio = block.audio.createBlock({ * id: "123e4567-e89b-12d3-a456-426614174000", * caption: "Check out my mixtape, man." * }); */ createBlock: (options) => { let url, id, caption; if (typeof options === "string") { url = options; caption = []; } else { ({ url, id, caption = [] } = options); } let urlOrId = url || id; const isValidAudio = validateAudioURL(urlOrId) || isValidUUID(urlOrId); const isFileUpload = isValidUUID(urlOrId); const isExternal = isValidURL(urlOrId); const audioType = isFileUpload ? "file_upload" : isExternal ? "external" : "file"; if (!isValidAudio) { console.warn(`${urlOrId} is not a valid audio URL or file upload ID.`) } return isValidAudio ? { type: "audio", audio: { type: audioType, [audioType]: { [audioType === "file_upload" ? "id" : "url"]: urlOrId, }, caption: enforceRichText(caption), }, } : null; }, }, /** * Methods for bookmark blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ bookmark: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: false, /** * Creates a bookmark block. * * @function * @param {string|Object} options - A string representing the URL, or an options object. * @param {string} options.url - The URL to be bookmarked. * @param {string|string[]|Array<Object>} [options.caption=[]] - The caption as a string, an array of strings, or an array of rich text objects. * @returns {Object} A bookmark block object compatible with Notion's API. * @example * // Use with just a URL * const simpleBookmark = block.bookmark.createBlock("https://www.flylighter.com"); * * // Use with options object * const complexBookmark = block.bookmark.createBlock({ * url: "https://www.flylighter.com", * caption: "Flylighter is a super-rad web clipper for Notion." * }); * * // Use with options object and array of strings for caption * const multiLineBookmark = block.bookmark.createBlock({ * url: "https://www.flylighter.com", * caption: ["Flylighter is a web clipper for Notion...", "...and Obsidian, too."] * }); */ createBlock: (options) => { let url, caption; if (typeof options === "string") { url = options; caption = []; } else { ({ url, caption = [] } = options); } return { type: "bookmark", bookmark: { url: url, caption: enforceRichText(caption), }, }; }, }, /** * Methods for breadcrumb blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ breadcrumb: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: false, /** * Creates a breadcrumb block. * * @returns {Object} A breadcrumb block object. * * @example * // Create a breadcrumb block * const breadcrumbBlock = block.breadcrumb.createBlock(); */ createBlock: () => { return { type: "breadcrumb", breadcrumb: {}, }; }, }, /** * Methods for bulleted list item blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ bulleted_list_item: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: true, /** * Creates a bulleted list item block. * * @function * @param {string|string[]|Object} options - A string, an array of strings, or an options object representing the list item content. * @param {string|string[]|Array<Object>} [options.rich_text=[]] - The item's content as a string, an array of strings, or an array of rich text objects. * @param {Array<Object>} [options.children=[]] - An array of child block objects. * @param {string} [options.color="default"] - Color for the text. * @returns {Object} A bulleted list item block object compatible with Notion's API. * @example * // Use with a string * const simpleItem = block.bulleted_list_item.createBlock("Simple list item"); * * // Use with an array of strings * const multiLineItem = block.bulleted_list_item.createBlock(["Line 1", "Line 2"]); * * // Use with options object * const complexItem = block.bulleted_list_item.createBlock({ * rich_text: "Complex item", * color: "red", * children: [ * // Child blocks would go here * ] * }); */ createBlock: (options) => { let rich_text, children, color; if (typeof options === "string" || Array.isArray(options)) { rich_text = options; children = []; color = "default"; } else { ({ rich_text = [], children = [], color = "default", } = options); } return { type: "bulleted_list_item", bulleted_list_item: { rich_text: enforceRichText(rich_text), color: color, ...(children.length > 0 && { children }), }, }; }, }, /** * Methods for callout blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ callout: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: true, /** * Creates a callout block. * * @function * @param {string|string[]|Object} options - A string, an array of strings, or an options object representing the callout content. * @param {string|string[]|Array<Object>} [options.rich_text=[]] - The content as a string, an array of strings, or an array of rich text objects. * @param {string} [options.icon=""] - An optional icon value (URL for "external" or emoji character for "emoji"). * @param {Array<Object>} [options.children=[]] - An array of child block objects. * @param {string} [options.color="default"] - Color for the callout background. * @returns {Object} A callout block object compatible with Notion's API. * @example * // Use with a string * const simpleCallout = block.callout.createBlock("I though I told you never to come in here, McFly!"); * * // Use with options object * const complexCallout = block.callout.createBlock({ * rich_text: "Now make like a tree and get outta here.", * icon: "💡", * color: "blue_background", * children: [ * // Child blocks would go here * ] * }); */ createBlock: (options) => { let rich_text, icon, children, color; if (typeof options === "string" || Array.isArray(options)) { rich_text = options; icon = ""; children = []; color = "default"; } else { ({ rich_text = [], icon = "", children = [], color = "default", } = options); } return { type: "callout", callout: { rich_text: enforceRichText(rich_text), icon: setIcon(icon), color: color, ...(children.length > 0 && { children }), }, }; }, }, /** * Methods for code blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ code: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: false, /** * Creates a code block. * * @function * @param {string|Object} options - A string representing the code content, or an options object. * @param {string|string[]|Array<Object>} [options.rich_text=[]] - The code content as a string, an array of strings, or an array of rich text objects. * @param {string|string[]|Array<Object>} [options.caption=[]] - The caption as a string, an array of strings, or an array of rich text objects. * @param {string} [options.language="plain text"] - Programming language of the code block. * @returns {Object} A code block object compatible with Notion's API. * @example * // Use with a string * const simpleCode = block.code.createBlock("console.log('Give me all the bacon and eggs you have.');"); * * // Use with options object * const complexCode = block.code.createBlock({ * rich_text: "const name = 'Monkey D. Luffy'\n console.log(`My name is ${name} and I will be king of the pirates!`)", * language: "JavaScript", * caption: "A simple JavaScript greeting function" * }); */ createBlock: (options) => { let rich_text, caption, language; if (typeof options === "string") { rich_text = options; caption = []; language = "plain text"; } else { ({ rich_text = [], caption = [], language = "plain text", } = options); } return { type: "code", code: { rich_text: enforceRichText(rich_text), caption: enforceRichText(caption), language: language, }, }; }, }, /** * Methods for column list blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ column_list: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: true, /** * Creates a column list block. Column list blocks must have at least two column child blocks, each of which must have at least one child block - otherwise, the Notion API will throw an error. * * @see https://developers.notion.com/reference/block#column-list-and-column * * @param {(number|Array|undefined)} options - The options for creating the column list block. * @param {number} [options] - The number of columns to create. Each will contain an empty paragraph block. * @param {Array} [options] - An array where each element represents a column. Each element can be: * - A column object (will be added to the final column list's children array directly) * - A string (will create a column object containing a paragraph block with the string's value) * - An array (will create a column object containing the elements as children. Each element should be a string or a valid block object. Strings will be converted to paragraph blocks.) * * @returns {Object|null} The created column list block object, or null if invalid input is provided. * * @example * // Create a column list with 3 empty columns * const emptyColumns = block.column_list.createBlock(3); * * @example * // Create a column list with 2 columns, each containing a paragraph * const twoColumnList = block.column_list.createBlock(["First column", "Second column"]); * * @example * // Create a column list with mixed content * const mixedColumnList = block.column_list.createBlock([ * "Text in first column", * ["Paragraph 1 in second column", "Paragraph 2 in second column"], * { * type: "column", * column: {}, * children: [block.heading_2.createBlock("Custom heading in third column")] * } * ]); * * @example * // Create an empty column list * const emptyColumnList = block.column_list.createBlock(); */ createBlock: (options) => { if ( typeof options === "string" || typeof options === "function" ) { return null; } if (!options || (Array.isArray(options) && options.length === 0) || (typeof options === "object" && Object.keys(options).length < 1)) { return { type: "column_list", column_list: {}, }; } if (typeof options === "number") { let columns = []; for (let i = 0; i < options; i++) { const column = { type: "column", column: { children: [block.paragraph.createBlock("")], }, }; columns.push(column); } return { type: "column_list", column_list: { children: columns, }, }; } if (Array.isArray(options)) { let columns = []; for (let option of options) { if ( typeof option === "object" && option.hasOwnProperty("column") ) { columns.push(option); } if (Array.isArray(option)) { let blocks = []; for (let singleBlock of option) { if (typeof singleBlock === "string") { const paragraph = block.paragraph.createBlock(singleBlock); blocks.push(paragraph); } else if ( typeof singleBlock === "object" && singleBlock !== null && !singleBlock.hasOwnProperty("column") ) { blocks.push(singleBlock); } } const column = { type: "column", column: { children: blocks, }, }; columns.push(column); } if (typeof option === "string") { const column = { type: "column", column: { children: [block.paragraph.createBlock(option)], }, }; columns.push(column); } if (!Array.isArray(option) && typeof option === "object" && !option.hasOwnProperty('column')) { const column = { type: "column", column: { children: [ option ], }, }; columns.push(column); } } return { type: "column_list", column_list: { children: columns, }, }; } }, }, /** * Methods for column blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ column: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: true, /** * Creates a column block. A column block must have at least one non-column block in its children array, and the column block itself must be appended as a child block to a column_list block. * * @see https://developers.notion.com/reference/block#column-list-and-column * * @param {(Array|string|undefined)} options - The options for creating the column block. * @param {Array} [options] - An array where each element becomes a child block of the column. Each element should be: * - A block object (will be added directly to the column's children array) * - A string (will be converted to a paragraph block) * @param {string} [options] - A string that will be converted into a paragraph block within the column. * * @returns {Object} The created column block object. * * @example * // Create an empty column * const emptyColumn = block.column.createBlock(); * * @example * // Create a column with a single paragraph * const singleParagraphColumn = block.column.createBlock("This is a paragraph in a column"); * * @example * // Create a column with multiple blocks * const multiBlockColumn = block.column.createBlock([ * "First paragraph", * block.heading_2.createBlock("Heading in column"), * "Another paragraph" * ]); * * @example * // Create a column with custom blocks * const customBlocksColumn = block.column.createBlock([ * block.paragraph.createBlock("Custom paragraph"), * block.bulleted_list_item.createBlock("Bullet point in column"), * block.image.createBlock({ url: "https://example.com/image.jpg" }) * ]); */ createBlock: (options) => { if (!options || (Array.isArray(options) && options.length === 0) || (typeof options === "object" && Object.keys(options).length < 1)) { return { type: "column", column: { children: [], }, }; } if (typeof options === "string") { return { type: "column", column: { children: [block.paragraph.createBlock(options)], }, }; } if (Array.isArray(options)) { let blocks = []; for (let singleBlock of options) { if (typeof singleBlock === "string") { const paragraph = block.paragraph.createBlock(singleBlock); blocks.push(paragraph); } else if ( typeof singleBlock === "object" && singleBlock !== null && !singleBlock.hasOwnProperty("column") ) { blocks.push(singleBlock); } } return { type: "column", column: { children: blocks, }, }; } }, }, /** * Methods for divider blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ divider: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: false, /** * Creates a divider block. * * @function * @returns {Object} A divider block object compatible with Notion's API. * @example * const divider = block.divider.createBlock(); */ createBlock: () => ({ type: "divider", divider: {}, }), }, /** * Methods for embed blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ embed: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: false, /** * Creates an embed block. * * @function * @param {string|Object} options - A string representing the URL to be embedded, or an options object. * @param {string} options.url - The URL to be embedded. * @returns {Object} An embed block object compatible with Notion's API. * @example * // Use with a string * const simpleEmbed = block.embed.createBlock("https://www.youtube.com/watch?v=ec5m6t77eYM"); * * // Use with options object * const complexEmbed = block.embed.createBlock({ * url: "https://www.youtube.com/watch?v=ec5m6t77eYM" * }); */ createBlock: (options) => { const url = typeof options === "string" ? options : options.url; return { type: "embed", embed: { url: url, }, }; }, }, /** * Methods for file blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ file: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: false, /** * Creates a file block. * * @function * @param {string|Object} options - A string representing the file URL, a file upload ID, or an options object. * @param {string} options.url - The URL for the file. * @param {string} options.id - The ID of the file upload. * @param {string} [options.name] - The name of the file. * @param {string|string[]|Array<Object>} [options.caption=[]] - The caption as a string, an array of strings, or an array of rich text objects. * @returns {Object|null} A file block object compatible with Notion's API, or null if the URL/ID is invalid. * @example * // Use with a file URL * const externalFile = block.file.createBlock("https://collegeinfogeek.com/wp-content/uploads/2015/01/10steps-reddit.pdf"); * * // Use with a file upload ID * const fileUploadFile = block.file.createBlock("123e4567-e89b-12d3-a456-426614174000"); * * // Use with options object for external file * const externalFile = block.file.createBlock({ * url: "https://collegeinfogeek.com/wp-content/uploads/2015/01/10steps-reddit.pdf", * name: "10 Steps to Earning Awesome Grades (preview)", * caption: "The Reddit preview of the 10 Steps to Earning Awesome Grades book." * }); * * // Use with options object for file upload * const fileUploadFile = block.file.createBlock({ * id: "123e4567-e89b-12d3-a456-426614174000", * name: "10 Steps to Earning Awesome Grades (preview)", * caption: "The Reddit preview of the 10 Steps to Earning Awesome Grades book." * }); */ createBlock: (options) => { let url, id, name, caption; if (typeof options === "string") { url = options; name = ""; caption = []; } else { ({ url, id, name = "", caption = [] } = options); } let urlOrId = url || id; const isValid = isValidURL(urlOrId) || isValidUUID(urlOrId); const isFileUpload = isValidUUID(urlOrId); const isExternal = isValidURL(urlOrId); const fileType = isFileUpload ? "file_upload" : isExternal ? "external" : "file"; if (!isValid) { console.warn(`${urlOrId} is not a valid file URL or file upload ID.`) } return isValid ? { type: "file", file: { type: fileType, [fileType]: { [fileType === "file_upload" ? "id" : "url"]: urlOrId, }, caption: enforceRichText(caption), name: name && name !== "" ? name : undefined, }, } : null; }, }, /** * Methods for heading_1 blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ heading_1: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: true, /** * Creates a heading_1 block. * * Adding children will coerce headings to toggle headings. * * @function * @param {string|string[]|Object} options - A string, an array of strings, or an options object representing the heading content. * @param {string|string[]|Array<Object>} [options.rich_text=[]] - The content as a string, an array of strings, or an array of rich text objects. * @param {string} [options.color="default"] - Color for the heading text. * @param {boolean} [options.is_toggleable=false] - Whether the heading is toggleable. * @param {Array<Object>} [options.children=[]] - An array of child block objects. * @returns {Object} A heading_1 block object compatible with Notion's API. * @example * // Use with a string * const simpleHeading = block.heading_1.createBlock("Simple Heading"); * * // Use with options object * const complexHeading = block.heading_1.createBlock({ * rich_text: "Complex Heading", * color: "red", * is_toggleable: true, * children: [ * // Child blocks would go here * ] * }); */ createBlock: (options) => { let rich_text, color, is_toggleable, children; if (typeof options === "string" || Array.isArray(options)) { rich_text = options; color = "default"; is_toggleable = false; children = []; } else { ({ rich_text = [], color = "default", is_toggleable = false, children = [], } = options); } return { type: "heading_1", heading_1: { rich_text: enforceRichText(rich_text), color: color, is_toggleable: is_toggleable, ...(children.length > 0 && { children }), }, }; }, }, /** * Methods for heading_2 blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ heading_2: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: true, /** * Creates a heading_2 block. * * Adding children will coerce headings to toggle headings. * * @function * @param {string|string[]|Object} options - A string, an array of strings, or an options object representing the heading content. * @param {string|string[]|Array<Object>} [options.rich_text=[]] - The content as a string, an array of strings, or an array of rich text objects. * @param {string} [options.color="default"] - Color for the heading text. * @param {boolean} [options.is_toggleable=false] - Whether the heading is toggleable. * @param {Array<Object>} [options.children=[]] - An array of child block objects. * @returns {Object} A heading_2 block object compatible with Notion's API. * @example * // Use with a string * const simpleHeading = block.heading_2.createBlock("Simple Heading"); * * // Use with options object * const complexHeading = block.heading_2.createBlock({ * rich_text: "Complex Heading", * color: "red", * is_toggleable: true, * children: [ * // Child blocks would go here * ] * }); */ createBlock: (options) => { let rich_text, color, is_toggleable, children; if (typeof options === "string" || Array.isArray(options)) { rich_text = options; color = "default"; is_toggleable = false; children = []; } else { ({ rich_text = [], color = "default", is_toggleable = false, children = [], } = options); } return { type: "heading_2", heading_2: { rich_text: enforceRichText(rich_text), color: color, is_toggleable: is_toggleable, ...(children.length > 0 && { children }), }, }; }, }, /** * Methods for heading_3 blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ heading_3: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: true, /** * Creates a heading_3 block. * * Adding children will coerce headings to toggle headings. * * @function * @param {string|string[]|Object} options - A string, an array of strings, or an options object representing the heading content. * @param {string|string[]|Array<Object>} [options.rich_text=[]] - The content as a string, an array of strings, or an array of rich text objects. * @param {string} [options.color="default"] - Color for the heading text. * @param {boolean} [options.is_toggleable=false] - Whether the heading is toggleable. * @param {Array<Object>} [options.children=[]] - An array of child block objects. * @returns {Object} A heading_3 block object compatible with Notion's API. * @example * // Use with a string * const simpleHeading = block.heading_3.createBlock("Simple Heading"); * * // Use with options object * const complexHeading = block.heading_3.createBlock({ * rich_text: "Complex Heading", * color: "red", * is_toggleable: true, * children: [ * // Child blocks would go here * ] * }); */ createBlock: (options) => { let rich_text, color, is_toggleable, children; if (typeof options === "string" || Array.isArray(options)) { rich_text = options; color = "default"; is_toggleable = false; children = []; } else { ({ rich_text = [], color = "default", is_toggleable = false, children = [], } = options); } return { type: "heading_3", heading_3: { rich_text: enforceRichText(rich_text), color: color, is_toggleable: is_toggleable, ...(children.length > 0 && { children }), }, }; }, }, /** * Methods for image blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ image: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: false, /** * Creates an image block. * * @function * @param {string|Object} options - A string representing the image URL, a file upload ID, or an options object. * @param {string} options.url - The URL for the image. * @param {string} options.id - The ID of the file upload. * @param {string|string[]|Array<Object>} [options.caption=[]] - The caption as a string, an array of strings, or an array of rich text objects. * @returns {Object|null} An image block object compatible with Notion's API, or null if the URL/ID is invalid. * @example * // Use with a string * const simpleImage = block.image.createBlock("https://i.imgur.com/5vSShIw.jpeg"); * * // Use with a file upload ID * const fileUploadImage = block.image.createBlock("123e4567-e89b-12d3-a456-426614174000"); * * // Use with options object for external image * const complexImage = block.image.createBlock({ * url: "https://i.imgur.com/5vSShIw.jpeg", * caption: "A beautiful landscape" * }); * * // Use with options object for file upload * const fileUploadImage = block.image.createBlock({ * id: "123e4567-e89b-12d3-a456-426614174000", * caption: "A beautiful landscape" * }); */ createBlock: (options) => { let url, id, caption; if (typeof options === "string") { url = options; caption = []; } else { ({ url, id, caption = [] } = options); } let urlOrId = url || id; const isValidImage = validateImageURL(urlOrId) || isValidUUID(urlOrId); const isFileUpload = isValidUUID(urlOrId); const isExternal = isValidURL(urlOrId); const imageType = isFileUpload ? "file_upload" : isExternal ? "external" : "file"; if (!isValidImage) { console.warn(`${urlOrId} is not a valid image URL or file upload ID.`) } return isValidImage ? { type: "image", image: { type: imageType, [imageType]: { [imageType === "file_upload" ? "id" : "url"]: urlOrId, }, caption: enforceRichText(caption), }, } : null; }, }, /** * Methods for numbered list item blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ numbered_list_item: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: true, /** * Creates a numbered list item block. * * @function * @param {string|string[]|Object} options - A string, an array of strings, or an options object representing the list item content. * @param {string|string[]|Array<Object>} [options.rich_text=[]] - The content as a string, an array of strings, or an array of rich text objects. * @param {Array<Object>} [options.children=[]] - An array of child block objects. * @param {string} [options.color="default"] - Color for the text. * @returns {Object} A numbered list item block object compatible with Notion's API. * @example * // Use with a string * const simpleItem = block.numbered_list_item.createBlock("Simple list item"); * * // Use with an array of strings * const multiLineItem = block.numbered_list_item.createBlock(["Line 1", "Line 2"]); * * // Use with options object * const complexItem = block.numbered_list_item.createBlock({ * rich_text: "Complex item", * color: "red", * children: [ * // Child blocks would go here * ] * }); */ createBlock: (options) => { let rich_text, children, color; if (typeof options === "string" || Array.isArray(options)) { rich_text = options; children = []; color = "default"; } else { ({ rich_text = [], children = [], color = "default", } = options); } return { type: "numbered_list_item", numbered_list_item: { rich_text: enforceRichText(rich_text), color: color, ...(children.length > 0 && { children }), }, }; }, }, /** * Methods for paragraph blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ paragraph: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: true, /** * Creates a paragraph block. * * @function * @param {string|string[]|Object} options - A string, an array of strings, or an options object representing the paragraph content. * @param {string|string[]|Array<Object>} [options.rich_text=[]] - The content as a string, an array of strings, or an array of rich text objects. * @param {Array<Object>} [options.children=[]] - An array of child block objects. * @param {string} [options.color="default"] - Color for the text. * @returns {Object} A paragraph block object compatible with Notion's API. * @example * // Direct use with a string * const paragraphBlock = block.paragraph.createBlock("Hello, World!"); * * // Direct use with an array of strings * const multiLineParagraph = block.paragraph.createBlock(["I'm a line", "I'm also a line!"]); * * // Usage with options object * const complexParagraph = block.paragraph.createBlock({ * rich_text: "Complex paragraph", * color: "red", * children: [ * // Child blocks would go here * ] * }); */ createBlock: (options) => { let rich_text, children, color; if (typeof options === "string" || Array.isArray(options)) { rich_text = options; children = []; color = "default"; } else { ({ rich_text = [], children = [], color = "default", } = options); } return { type: "paragraph", paragraph: { rich_text: rich_text === "" ? buildRichTextObj("") : enforceRichText(rich_text), color: color, ...(children.length > 0 && { children }), }, }; }, }, /** * Methods for PDF blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ pdf: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: false, /** * Creates a PDF block. * * @function * @param {string|Object} options - A string representing the PDF URL, a file upload ID, or an options object. * @param {string} options.url - The URL for the PDF. * @param {string} options.id - The ID of the file upload. * @param {string|string[]|Array<Object>} [options.caption=[]] - The caption as a string, an array of strings, or an array of rich text objects. * @returns {Object|null} A PDF block object compatible with Notion's API, or null if the URL/ID is invalid. * @example * // Use with a PDF URL * const externalPDF = block.pdf.createBlock("https://collegeinfogeek.com/wp-content/uploads/2015/01/10steps-reddit.pdf"); * * // Use with a file upload ID * const fileUploadPDF = block.pdf.createBlock("123e4567-e89b-12d3-a456-426614174000"); * * // Use with options object for external PDF * const externalPDF = block.pdf.createBlock({ * url: "https://collegeinfogeek.com/wp-content/uploads/2015/01/10steps-reddit.pdf", * caption: "The Reddit preview of the 10 Steps to Earning Awesome Grades book." * }); * * // Use with options object for file upload * const fileUploadPDF = block.pdf.createBlock({ * id: "123e4567-e89b-12d3-a456-426614174000", * caption: "The Reddit preview of the 10 Steps to Earning Awesome Grades book." * }); */ createBlock: (options) => { let url, id, caption; if (typeof options === "string") { url = options; caption = []; } else { ({ url, id, caption = [] } = options); } let urlOrId = url || id; const isValidPDF = validatePDFURL(urlOrId) || isValidUUID(urlOrId); const isFileUpload = isValidUUID(urlOrId); const isExternal = isValidURL(urlOrId); const pdfType = isFileUpload ? "file_upload" : isExternal ? "external" : "file"; if (!isValidPDF) { console.warn(`${urlOrId} is not a valid PDF URL or file upload ID.`) } return isValidPDF ? { type: "pdf", pdf: { type: pdfType, [pdfType]: { [pdfType === "file_upload" ? "id" : "url"]: urlOrId, }, caption: enforceRichText(caption), }, } : null; }, }, /** * Methods for quote blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ quote: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: true, /** * Creates a quote block. * * @function * @param {string|string[]|Object} options - A string, an array of strings, or an options object representing the quote content. * @param {string|string[]|Array<Object>} [options.rich_text=[]] - The content as a string, an array of strings, or an array of rich text objects. * @param {Array<Object>} [options.children=[]] - An array of child block objects. * @param {string} [options.color="default"] - Color for the text. * @returns {Object} A quote block object compatible with Notion's API. * @example * // Use with a string * const simpleQuote = block.quote.createBlock("Simple quote"); * * // Use with an array of strings * const multiLineQuote = block.quote.createBlock(["Line 1 of quote", "Line 2 of quote"]); * * // Use with options object * const complexQuote = block.quote.createBlock({ * rich_text: "Complex quote", * color: "gray", * children: [ * // Child blocks would go here * ] * }); */ createBlock: (options) => { let rich_text, children, color; if (typeof options === "string" || Array.isArray(options)) { rich_text = options; children = []; color = "default"; } else { ({ rich_text = [], children = [], color = "default", } = options); } return { type: "quote", quote: { rich_text: enforceRichText(rich_text), color: color, ...(children.length > 0 && { children }), }, }; }, }, /** * Methods for table blocks. * * @namespace * @property {boolean} supports_children - Indicates if the block supports child blocks. */ table: { /** * Indicates if the block supports child blocks. * @type {boolean} */ supports_children: true, /** * Creates a table block. * * @function * @param {Object} [options] - Options for creating the tab