Search Shortcut cmd + k | ctrl + k
duck_block_utils

Build, transform, validate, and extract content from structured documents using the duck_block type

Maintainer(s): teaguesterling

Installing and Loading

INSTALL duck_block_utils FROM community;
LOAD duck_block_utils;

Example

-- Build a document programmatically
SELECT duck_blocks_assemble([
    duck_block_heading(1, 'Hello World'),
    duck_block_paragraph([
        duck_block_text('This is '),
        duck_block_bold('important'),
        duck_block_text(' content.')
    ]),
    duck_block_code('sql', 'SELECT * FROM documents')
]);

-- Render it as plain text
SELECT duck_blocks_to_text(duck_blocks_assemble([
    duck_block_heading(1, 'Hello World'),
    duck_block_paragraph('Some prose.')
]));

-- Works with the markdown extension for reading and writing files
LOAD markdown;
LOAD duck_block_utils;

-- Table of contents from a markdown file
SELECT * FROM duck_blocks_toc_rows(
    (SELECT list(b) FROM read_markdown_blocks('README.md') b)
);

-- Validate document structure
SELECT duck_blocks_validate(
    (SELECT list(b) FROM read_markdown_blocks('doc.md') b)
);

About duck_block_utils

The Duck Block Utils extension provides tools for building, transforming, validating, and extracting content from structured documents. All functions use the duck_block type - a unified representation for document elements that works across formats.

Documentation: duck-block-utils.readthedocs.io

2.0.0 is a breaking rename

Every db_* function was renamed to duck_block_* (builders) or duck_blocks_* (operations on a list). 54 names present in 1.6.1 are gone and there is no alias path, so 1.6.1 queries must be updated. The mapping is mechanical:

db_heading(1, 'Title')      ->  duck_block_heading(1, 'Title')
db_assemble(blocks)         ->  duck_blocks_assemble(blocks)
db_blocks_to_text(blocks)   ->  duck_blocks_to_text(blocks)
db_page                     ->  page_break

The duck_block Type

A unified struct for block-level, inline and metadata-value elements:

STRUCT(
    kind VARCHAR,                       -- 'block', 'inline' or 'value'
    element_type VARCHAR,               -- 'heading', 'paragraph', 'bold', 'link', etc.
    content VARCHAR,                    -- text, iff the element has a single text child
    level INTEGER,                      -- depth in a depth-first ordering; top is 1
    encoding VARCHAR,                   -- 'text', 'json', 'yaml', 'html', 'xml',
                                        --   'latex', 'markdown', 'toml'
    attributes MAP(VARCHAR, VARCHAR),   -- element-specific metadata
    element_order INTEGER               -- position in the document
)

level is structural depth, never a heading rank - a heading's rank lives in attributes['heading_level']. content is populated if and only if an element has a single text child; a heading additionally keeps a flattened title alongside its rich children.

Builders

All builder functions return LIST(duck_block) so they compose by nesting:

SELECT duck_block_paragraph([
    duck_block_text('Click '),
    duck_block_link('https://example.com', 'here'),
    duck_block_text(' for more.')
]);
Function Description
duck_block_heading(level, content) Heading (h1-h6)
duck_block_paragraph(content) Paragraph
duck_block_code(language, content) Fenced code block
duck_block_blockquote(content) Block quote
duck_block_list_block(ordered, items[]) Ordered or unordered list
duck_block_hr() Horizontal rule
duck_block_image(src, alt, title) Image
duck_block_metadata(content) Metadata blob (YAML frontmatter)
duck_block_raw(format, content) Raw content block
duck_block_text(content) Plain text
duck_block_bold(content) Bold
duck_block_italic(content) Italic
duck_block_link(href, content) Hyperlink
duck_block_inline_code(content) Inline code
duck_block_math(content) Math
duck_block_strikethrough(content) Strikethrough
duck_block_superscript(content) / duck_block_subscript(content) Super/subscript

Assembly

Function Description
duck_blocks_assemble(blocks[]) Combine blocks into a document
duck_blocks_document(blocks[]) Alias for assemble
duck_block_section(level, title, children[]) Section with a heading
duck_blocks_concat(a, b) Concatenate block lists
duck_blocks_rebase_levels(blocks, offset) Shift heading levels

Query and extraction

Function Description
duck_blocks_to_text(blocks) Plain text
duck_blocks_headings(blocks) Heading hierarchy
duck_blocks_toc_rows(blocks) Table of contents, one row per entry
duck_blocks_get_section(blocks, pattern) One section by title or id
duck_blocks_sections_like(blocks, term) Sections whose text matches
duck_blocks_page_rows(blocks) Page boundaries, separate from the outline
duck_blocks_get_pages(blocks, first, last) A page range
duck_blocks_links(blocks) Every link
duck_blocks_stats(blocks) / duck_blocks_structure(blocks) Document shape
duck_blocks_diff(before, after) ADDED / REMOVED / MOVED between two versions

Validation

Function Description
duck_blocks_validate(blocks) Spec conformance: valid, plus errors
duck_blocks_lint(blocks) Advisory conformance warnings
duck_blocks_quality(blocks) Document quality, which is NOT conformance
duck_block_spec_version() The spec version this build implements

Rendering

Function Description
duck_blocks_render_ansi(blocks, width) Terminal rendering with themes

Pandoc integration

Convert between Pandoc's JSON AST and duck_block without invoking Pandoc:

Function Description
pandoc_ast_to_blocks(json) Parse a Pandoc AST
duck_blocks_to_pandoc_ast(blocks) Emit a full Pandoc document
duck_blocks_to_pandoc_blocks(blocks) Emit just the block list
read_pandoc_ast(path) / write_pandoc_ast(path, blocks) Read and write AST files

Ecosystem

  • duckdb_markdown - read_markdown_blocks(), and COPY ... TO ... (FORMAT markdown, MARKDOWN_MODE duck_block)
  • duckdb_webbed - HTML parsing and generation
-- Read markdown, append to it, write it back
LOAD markdown;
LOAD duck_block_utils;

COPY (
    SELECT unnest(duck_blocks_concat(
        (SELECT list(b) FROM read_markdown_blocks('doc.md') b),
        duck_blocks_assemble([
            duck_block_hr(),
            duck_block_paragraph('Generated by DuckDB')
        ])
    )) AS block
) TO 'output.md' (FORMAT markdown, MARKDOWN_MODE duck_block);

Added Functions

function_name function_type description comment examples
duck_block scalar NULL NULL  
duck_block_aliases pragma NULL NULL  
duck_block_attr scalar NULL NULL  
duck_block_blockquote scalar NULL NULL  
duck_block_bold scalar NULL NULL  
duck_block_cite scalar NULL NULL  
duck_block_code scalar NULL NULL  
duck_block_content scalar NULL NULL  
duck_block_div scalar NULL NULL  
duck_block_doc_macros pragma NULL NULL  
duck_block_encoding scalar NULL NULL  
duck_block_encoding_names scalar NULL NULL  
duck_block_ensure_extension scalar NULL NULL  
duck_block_heading scalar NULL NULL  
duck_block_hr scalar NULL NULL  
duck_block_image scalar NULL NULL  
duck_block_inline_code scalar NULL NULL  
duck_block_inline_image scalar NULL NULL  
duck_block_italic scalar NULL NULL  
duck_block_kind_names scalar NULL NULL  
duck_block_level scalar NULL NULL  
duck_block_linebreak scalar NULL NULL  
duck_block_link scalar NULL NULL  
duck_block_list scalar NULL NULL  
duck_block_list_block scalar NULL NULL  
duck_block_list_item scalar NULL NULL  
duck_block_math scalar NULL NULL  
duck_block_metadata scalar NULL NULL  
duck_block_note scalar NULL NULL  
duck_block_order scalar NULL NULL  
duck_block_paragraph scalar NULL NULL  
duck_block_plain scalar NULL NULL  
duck_block_quoted scalar NULL NULL  
duck_block_raw scalar NULL NULL  
duck_block_raw_inline scalar NULL NULL  
duck_block_render pragma NULL NULL  
duck_block_section scalar NULL NULL  
duck_block_set_content scalar NULL NULL  
duck_block_set_level scalar NULL NULL  
duck_block_set_order scalar NULL NULL  
duck_block_smallcaps scalar NULL NULL  
duck_block_softbreak scalar NULL NULL  
duck_block_space scalar NULL NULL  
duck_block_span scalar NULL NULL  
duck_block_spec_version scalar NULL NULL  
duck_block_strikethrough scalar NULL NULL  
duck_block_subscript scalar NULL NULL  
duck_block_superscript scalar NULL NULL  
duck_block_terminal_width scalar NULL NULL  
duck_block_text scalar NULL NULL  
duck_block_type scalar NULL NULL  
duck_block_type_names scalar NULL NULL  
duck_block_underline scalar NULL NULL  
duck_block_valid scalar NULL NULL  
duck_blocks_assemble scalar NULL NULL  
duck_blocks_code_blocks scalar NULL NULL  
duck_blocks_code_blocks_structs scalar NULL NULL  
duck_blocks_concat scalar NULL NULL  
duck_blocks_diff table_macro NULL NULL  
duck_blocks_document scalar NULL NULL  
duck_blocks_exclude scalar NULL NULL  
duck_blocks_filter scalar NULL NULL  
duck_blocks_get_pages macro NULL NULL  
duck_blocks_get_pages_text macro NULL NULL  
duck_blocks_get_section macro NULL NULL  
duck_blocks_get_section_text macro NULL NULL  
duck_blocks_headings scalar NULL NULL  
duck_blocks_headings_structs scalar NULL NULL  
duck_blocks_inlines_to_pandoc scalar NULL NULL  
duck_blocks_links scalar NULL NULL  
duck_blocks_links_structs scalar NULL NULL  
duck_blocks_lint scalar NULL NULL  
duck_blocks_merge scalar NULL NULL  
duck_blocks_normalize scalar NULL NULL  
duck_blocks_page_rows table_macro NULL NULL  
duck_blocks_quality table_macro NULL NULL  
duck_blocks_rebase_levels scalar NULL NULL  
duck_blocks_render_ansi scalar NULL NULL  
duck_blocks_reorder scalar NULL NULL  
duck_blocks_sections_like table_macro NULL NULL  
duck_blocks_sections_like_text table_macro NULL NULL  
duck_blocks_slice scalar NULL NULL  
duck_blocks_stamp scalar NULL NULL  
duck_blocks_stats scalar NULL NULL  
duck_blocks_structure scalar NULL NULL  
duck_blocks_to_match_text macro NULL NULL  
duck_blocks_to_pandoc_ast scalar NULL NULL  
duck_blocks_to_pandoc_blocks scalar NULL NULL  
duck_blocks_to_text scalar NULL NULL  
duck_blocks_toc scalar NULL NULL  
duck_blocks_toc_rows table_macro NULL NULL  
duck_blocks_toc_structs scalar NULL NULL  
duck_blocks_validate scalar NULL NULL  
duck_blocks_version scalar NULL NULL  
pandoc_ast table NULL NULL  
pandoc_ast_to_blocks scalar NULL NULL  
pandoc_inlines_to_db_inlines scalar NULL NULL  
pandoc_inlines_to_text scalar NULL NULL  
read_pandoc_ast scalar NULL NULL  
to_duck_block scalar NULL NULL  
write_pandoc_ast scalar NULL NULL  

Overloaded Functions

This extension does not add any function overloads.

Added Types

type_name type_size logical_type type_category internal
duck_block 0 STRUCT COMPOSITE true
duck_block_ext 0 STRUCT COMPOSITE true

Added Settings

This extension does not add any settings.