CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-notion-utils

Useful utilities for working with Notion data structures and operations in both Node.js and browser environments.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

page-analysis.mddocs/

Page Analysis & Metadata

Core functionality for analyzing Notion pages and extracting metadata including titles, reading time estimates, content statistics, and breadcrumb navigation.

Capabilities

Get Page Title

Extracts the title of the root page from a record map.

/**
 * Gets the title of the root page in a recordMap
 * @param recordMap - Extended record map containing page data
 * @returns Page title or null if no title found
 */
function getPageTitle(recordMap: ExtendedRecordMap): string | null;

Usage Example:

import { getPageTitle } from "notion-utils";

const title = getPageTitle(recordMap);
if (title) {
  console.log(`Page title: ${title}`);
}

Estimate Page Read Time

Estimates the time it would take to read a Notion page using Medium's reading time algorithm.

/**
 * Returns an estimate for the time it would take for a person to read the content in the given Notion page
 * @param block - The page block to analyze
 * @param recordMap - Extended record map containing all blocks
 * @param options - Configuration options for read time calculation
 * @returns Detailed reading time estimate with word/image counts
 */
function estimatePageReadTime(
  block: Block,
  recordMap: ExtendedRecordMap,
  options?: EstimatePageReadTimeOptions
): PageReadTimeEstimate;

/**
 * Same as estimatePageReadTime but returns a human-readable string
 * @param block - The page block to analyze
 * @param recordMap - Extended record map containing all blocks
 * @param opts - Configuration options for read time calculation
 * @returns Human-readable time estimate (e.g., "5 minutes", "less than a minute")
 */
function estimatePageReadTimeAsHumanizedString(
  block: Block,
  recordMap: ExtendedRecordMap,
  opts: EstimatePageReadTimeOptions
): string;

interface EstimatePageReadTimeOptions {
  /** Words per minute reading speed (default: 275) */
  wordsPerMinute?: number;
  /** Time in seconds to "read" an image (default: 12) */
  imageReadTimeInSeconds?: number;
}

interface PageReadTimeEstimate {
  /** Total number of words found */
  numWords: number;
  /** Total number of images found */
  numImages: number;
  /** Time to read words in minutes */
  totalWordsReadTimeInMinutes: number;
  /** Time to view images in minutes */
  totalImageReadTimeInMinutes: number;
  /** Combined total reading time in minutes */
  totalReadTimeInMinutes: number;
}

Usage Examples:

import { estimatePageReadTime, estimatePageReadTimeAsHumanizedString } from "notion-utils";

// Get detailed reading time data
const readTimeData = estimatePageReadTime(pageBlock, recordMap);
console.log(`Words: ${readTimeData.numWords}, Images: ${readTimeData.numImages}`);
console.log(`Total read time: ${readTimeData.totalReadTimeInMinutes} minutes`);

// Get human-readable string
const readTimeString = estimatePageReadTimeAsHumanizedString(pageBlock, recordMap, {
  wordsPerMinute: 250, // Slower reading speed
  imageReadTimeInSeconds: 15 // More time per image
});
console.log(`Estimated read time: ${readTimeString}`);

Get Page Breadcrumbs

Generates breadcrumb navigation by traversing up to parent pages.

/**
 * Gets the breadcrumb trail for a page by traversing up to parent pages
 * @param recordMap - Extended record map containing page data
 * @param activePageId - ID of the current/active page
 * @returns Array of breadcrumb objects or null if none can be generated
 */
function getPageBreadcrumbs(
  recordMap: ExtendedRecordMap,
  activePageId: string
): Array<BreadcrumbItem> | null;

interface BreadcrumbItem {
  /** The block representing this breadcrumb level */
  block: Block;
  /** Whether this is the active/current page */
  active: boolean;
  /** Page ID for this breadcrumb level */
  pageId: string;
  /** Display title for this breadcrumb level */
  title: string;
  /** Icon for this breadcrumb level (if any) */
  icon: string | null;
}

Usage Example:

import { getPageBreadcrumbs } from "notion-utils";

const breadcrumbs = getPageBreadcrumbs(recordMap, currentPageId);
if (breadcrumbs) {
  breadcrumbs.forEach((crumb, index) => {
    const separator = index > 0 ? " > " : "";
    console.log(`${separator}${crumb.title}${crumb.active ? " (current)" : ""}`);
  });
}

Types

// Re-exported from notion-types
interface ExtendedRecordMap {
  block: Record<string, Block>;
  collection?: Record<string, Collection>;
  collection_view?: Record<string, CollectionView>;
  notion_user?: Record<string, NotionUser>;
  collection_query?: Record<string, any>;
  signed_urls?: Record<string, string>;
  preview_images?: Record<string, string>;
}

interface Block {
  id: string;
  type: BlockType;
  properties?: Record<string, any>;
  format?: Record<string, any>;
  content?: string[];
  parent_id: string;
  parent_table: string;
  alive: boolean;
  created_time: number;
  last_edited_time: number;
}

Install with Tessl CLI

npx tessl i tessl/npm-notion-utils

docs

block-property-utilities.md

content-extraction.md

data-operations.md

id-url-management.md

index.md

navigation-structure.md

page-analysis.md

text-processing.md

tile.json