Sign in

    #cmark_base

    This package provides fundamental CommonMark parsing utilities and data structures for parsing various CommonMark elements.

    #Text Location Tracking

    The package includes utilities for tracking text locations in source files:

    ///|
    test "text location handling" {
    let loc = @cmark_base.TextLoc::{
    file: "test.md",
    first_ccode: 0,
    last_ccode: 10,
    first_line: LinePos(1, 0),
    last_line: LinePos(1, 10),
    }
    let after_loc = loc.after()
    debug_inspect(
    after_loc,
    content=(
    #|{
    #| file: "test.md",
    #| first_ccode: 1,
    #| last_ccode: -1,
    #| first_line: LinePos(1, 10),
    #| last_line: LinePos(-1, -1),
    #|}
    ),
    )
    let none_loc = @cmark_base.TextLoc::none()
    debug_inspect(none_loc.is_none(), content="true")
    }

    The package provides functions for parsing links, URIs and email addresses:

    ///|
    test "link parsing" {
    let txt = "Visit <https://mooncakes.io/>!"
    debug_inspect(@cmark_base.autolink_uri(txt, start=6), content="Some(28)")
    let email = "Contact <user@example.com> today!"
    debug_inspect(@cmark_base.autolink_email(email, start=8), content="Some(25)")
    }

    #String Analysis Utilities

    The package provides various string analysis functions:

    ///|
    test "string analysis" {
    let start = 0

    // Find first non-blank character
    debug_inspect(
    @cmark_base.first_non_blank(" hello", last=7, start~),
    content="2",
    )

    // Count repeated characters
    debug_inspect(
    @cmark_base.run_of(char='-', "---hello", last=8, start~),
    content="2",
    )
    }

    #Line Types and Parsing Utilities

    The package provides comprehensive line type detection for different CommonMark elements:

    ///|
    test "line type detection" {
    let start = 0

    // ATX Heading
    debug_inspect(
    @cmark_base.LineType::atx_heading("# Heading", last=8, start~),
    content="AtxHeadingLine(1, 1, 2, 8)",
    )

    // Thematic Break
    debug_inspect(
    @cmark_base.LineType::thematic_break("---", last=2, start~),
    content="ThematicBreakLine(2)",
    )

    // List Items
    debug_inspect(
    @cmark_base.LineType::list_marker("- Item", last=5, start~),
    content="ListMarkerLine(Unordered('-'), 0)",
    )
    debug_inspect(
    @cmark_base.LineType::list_marker("1. Item", last=6, start~),
    content="ListMarkerLine(Ordered(1, '.'), 1)",
    )
    }

    #List Types

    The package provides support for different types of lists:

    ///|
    test "list types" {
    let unordered = @cmark_base.ListType::Unordered('-')
    let ordered = @cmark_base.ListType::Ordered(1, '.')

    // Check if lists are of same type
    debug_inspect(unordered.is_same_type(unordered), content="true")
    debug_inspect(unordered.is_same_type(ordered), content="false")
    }

    #HTML Block Parsing

    Support for detecting and parsing HTML blocks:

    ///|
    test "html blocks" {
    let start = 0
    debug_inspect(
    @cmark_base.LineType::html_block_start("<div>", last=5, start~),
    content="HtmlBlockLine(EndBlank)",
    )
    debug_inspect(
    @cmark_base.LineType::html_block_end(
    "</div></br>",
    end_cond=EndStr("</div>"),
    start~,
    last=6,
    ),
    content="true",
    )
    }

    #Metadata Handling

    The package includes structures for tracking metadata:

    ///|
    test "metadata handling" {
    let loc = @cmark_base.TextLoc::{
    file: "test.md",
    first_ccode: 0,
    last_ccode: 10,
    first_line: LinePos(1, 0),
    last_line: LinePos(1, 10),
    }
    let meta = @cmark_base.Meta::new(loc~)
    debug_inspect(meta.is_none(), content="false")
    let none_meta = @cmark_base.Meta::none()
    debug_inspect(none_meta.is_none(), content="true")
    }

    CharCodePos

    type CharCodePos = Int

    FilePath

    type FilePath = String

    First

    type First = Int

    The type for the first first byte position of a parsed construct.

    HeadingLevel

    type HeadingLevel = Int

    The type for heading levels.

    Indent

    type Indent = Int

    The type for indentation magnitude.

    Last

    type Last = Int

    The type for the last byte position of a parsed construct.

    LineNum

    type LineNum = Int

    type Next = Int

    The type for a byte position after a parsed construct. The byte position may be invalid (end of input range) or on the newline.

    ContextState

    pub extenum ContextState {
    }

    Extensible enum for renderer context state.

    Concrete renderers extend this type with their own state variants (e.g. extenum ContextState += { MyState(...) }) so the generic @cmark_renderer.Context can carry renderer-specific state without relying on Error? as an untyped container.

    FencedCodeBlockContinue

    pub(all) enum FencedCodeBlockContinue {
    Close(Int, Int)
    Code
    } derive(
    Debug
    )

    FencedCodeBlockContinue::new

    fn FencedCodeBlockContinue::new(s : String, fence~ : (Char, Int), last~ : Int, start~ : Int) -> FencedCodeBlockContinue

    fenced_code_block_continue(fence, s, last, start) indicates whether the fence code continues or closes in the the range [start;last] given the opening open which indicates the indent, fence char and number of fence chars.

    HtmlBlockEndCond

    pub(all) enum HtmlBlockEndCond {
    EndStr(String)
    EndCond1
    EndBlank
    EndBlank7
    } derive(Eq,
    Debug
    )

    LineSpan

    pub(all) struct LineSpan {
    pos : LinePos
    first : Int
    last : Int
    } derive(Compare, Eq,
    Debug
    )

    LineType

    pub(all) enum LineType {
    AtxHeadingLine(Int, Int, Int, Int)
    BlankLine
    BlockQuoteLine
    FencedCodeBlockLine(Int, Int, (Int, Int)?)
    HtmlBlockLine(HtmlBlockEndCond)
    IndentedCodeBlockLine
    ListMarkerLine(ListType, Int)
    ParagraphLine
    SetextUnderlineLine(Int, Int)
    ThematicBreakLine(Int)
    ExtTableRow(Int)
    ExtFootnoteLabel(Array[Span], Int, String)
    Nomatch
    } derive(Eq,
    Debug
    )

    LineType::atx_heading

    fn LineType::atx_heading(s : String, last~ : Int, start~ : Int) -> LineType

    https://spec.commonmark.org/current/#atx-headings

    LineType::ext_footnote_label

    fn LineType::ext_footnote_label(buf : StringBuilder, s : String, line_pos~ : LinePos, last~ : Int, start~ : Int) -> LineType

    LineType::ext_table_row

    fn LineType::ext_table_row(s : String, last~ : Int, start~ : Int) -> LineType

    LineType::fenced_code_block_start

    fn LineType::fenced_code_block_start(s : String, last~ : Int, start~ : Int) -> LineType

    LineType::html_block_end

    fn LineType::html_block_end(s : String, end_cond~ : HtmlBlockEndCond, last~ : Int, start~ : Int) -> Bool

    LineType::html_block_start

    fn LineType::html_block_start(s : String, last~ : Int, start~ : Int) -> LineType

    https://spec.commonmark.org/current/#html-blocks

    LineType::list_marker

    fn LineType::list_marker(s : String, last~ : Int, start~ : Int) -> LineType

    https://spec.commonmark.org/current/#list-marker

    LineType::setext_heading_underline

    fn LineType::setext_heading_underline(s : String, last~ : Int, start~ : Int) -> LineType

    https://spec.commonmark.org/current/#setext-heading

    LineType::thematic_break

    fn LineType::thematic_break(s : String, last~ : Int, start~ : Int) -> LineType

    https://spec.commonmark.org/current/#thematic-breaks

    ListType

    pub(all) enum ListType {
    Unordered(Char)
    Ordered(Int, Char)
    } derive(Eq, ToJson,
    Debug
    ,
    FromJson
    )

    ListType::is_same_type

    fn ListType::is_same_type(self : ListType, other : ListType) -> Bool

    Meta

    pub(all) struct Meta {
    id : Int
    loc : TextLoc
    extra : Error?
    } derive(
    Debug
    )

    impl Eq for Meta

    Meta::compare

    fn Meta::compare(self : Meta, other : Meta) -> Int

    Meta::is_none

    fn Meta::is_none(self : Meta) -> Bool

    Meta::new

    fn Meta::new(loc? : TextLoc) -> Meta

    Meta::none

    fn Meta::none() -> Meta

    NextLineFn

    pub(all) struct NextLineFn[A]((A) -> LineSpan?)

    NextLineResult

    pub(all) enum NextLineResult {
    ThisLine(Int)
    NextLine(LineSpan, Int)
    } derive(
    Debug
    )

    Span

    pub(all) struct Span {
    start : Int
    span : LineSpan
    } derive(Compare, Eq,
    Debug
    )

    A line span with the byte position on where the line starts (inside a CommonMark container). The [line_start] is the start of line in the container, the [line_span] has the actual data. The characters in the [[line_start];[line_span.first - 1]] are blanks.

    TextLoc

    pub(all) struct TextLoc {
    file : String
    first_ccode : Int
    last_ccode : Int
    first_line : LinePos
    last_line : LinePos
    } derive(Compare, Eq, ToJson,
    Debug
    ,
    FromJson
    )

    TextLoc::after

    fn TextLoc::after(self : TextLoc) -> TextLoc

    TextLoc::is_empty

    fn TextLoc::is_empty(self : TextLoc) -> Bool

    TextLoc::is_none

    fn TextLoc::is_none(self : TextLoc) -> Bool

    TextLoc::none

    fn TextLoc::none() -> TextLoc

    TextLoc::reloc

    fn TextLoc::reloc(self : TextLoc, other : TextLoc) -> TextLoc

    TextLoc::span

    fn TextLoc::span(self : TextLoc, other : TextLoc) -> TextLoc

    TextLoc::to_first

    fn TextLoc::to_first(self : TextLoc) -> TextLoc

    TextLoc::to_last

    fn TextLoc::to_last(self : TextLoc) -> TextLoc

    fn autolink_email(s : String, last? : Int, start? : Int) -> Int?

    autolink_email(s, last, start) matches an email autolink starting at start in the range [start;last] (assumed on the same line).
    fn autolink_uri(s : String, last? : Int, start? : Int) -> Int?

    autolink_uri(s, last, start) matches an URI autolink starting at start in the range [start;last] (assumed on the same line).

    char_code_pos_none

    let char_code_pos_none : Int

    fn could_be_link_ref_definition(s : String, last~ : Int, start~ : Int) -> Bool

    https://spec.commonmark.org/current/#link-reference-definition

    ext_task_marker

    fn ext_task_marker(s : String, last~ : Int, start~ : Int) -> (Char, Int)?

    file_path_none

    let file_path_none : String

    first_non_blank

    fn first_non_blank(s : String, last~ : Int, start~ : Int) -> Int

    first_non_blank(s, last, start) is the first position in the range [start, last] that is not blank and last + 1 if there is none.

    first_non_blank_in_span

    fn first_non_blank_in_span(s : String, span : LineSpan) -> Int

    first_non_blank_in_span(s, span) is first_non_blank(s, last=span.last, start=span.first).

    first_non_blank_over_nl

    fn[A] first_non_blank_over_nl(next_line~ : NextLineFn[A], s : String, lines : A, line~ : LineSpan, start~ : Int) -> NextLineResult?

    first_non_blank_over_nl(next_line, s, lines, line, start) is the first byte position starting with start that is not blank in line or on the next line as determined by next_line. Returns None if there is no such position.

    first_non_escaped_char

    fn first_non_escaped_char(c : Char, s : String, last~ : Int, start~ : Int) -> Int

    first_non_escaped_char(c, s, last, start) is the first CharCodePos in the range [start, last] that has c unescaped and last + 1 if there is none.

    last_non_blank

    fn last_non_blank(s : String, first~ : Int, start~ : Int) -> Int

    last_non_blank(s, first, start) is the last position in the range [first, start] that is not blank and first - 1 if there is none.

    line_num_none

    let line_num_none : Int

    line_pos_none

    let line_pos_none : LinePos

    fn link_destination(s : String, last~ : Int, start~ : Int) -> (Bool, Int, Int)?

    link_destination(s, last, start) matches a link destination starting at start in the range start..=last (assumed on the same line). This is Some((delimited, first, last)) with the data in [first..=last] the destination data. delimited is true if first-1 is '<' and last + 1 is '>'.

    See: https://spec.commonmark.org/current/#link-destination
    fn[A] link_label(buf : StringBuilder, next_line~ : NextLineFn[A], s : String, lines : A, line~ : LineSpan, start~ : Int) -> (LineSpan, Array[Span], Int, String)?

    Matches a link label on line starting at start. The byte ranges have the label's content, the string is the normalized label (blanks collapsed, Unicode case folded). buf is used as scratch space.

    See: https://spec.commonmark.org/current/#link-label
    fn[A] link_title(next_line~ : NextLineFn[A], s : String, lines : A, line~ : LineSpan, start~ : Int) -> (LineSpan, Array[Span], Int)?

    link_title(next_line, s, lines, line, last) is a link title on line line starting at start. Returns Some((lines, last_line, spans, last)) with lines the lines after consuming the title, last_line the line where it stops, spans the byte ranges of s that make up the title in reverse order, last is on the closing delimiter and guaranteed to be on last_line.

    See: https://spec.commonmark.org/current/#link-title

    raw_html

    fn[A] raw_html(next_line~ : NextLineFn[A], s : String, lines : A, line~ : LineSpan, start~ : Int) -> (LineSpan, Array[Span], Int)?

    https://spec.commonmark.org/current/#html-tag

    rev_drop_spaces

    fn rev_drop_spaces(s : String, first~ : Int, start~ : Int) -> Int

    rev_drop_spaces(s, first, start) is the last position in the range [first, start] that is not U+0020 and first - 1 if there is none.

    run_of

    fn run_of(char~ : Char, s : String, last~ : Int, start~ : Int) -> Int

    run_of(char, s, last, start) is the last position of a consecutive run of char in the range [start, last] or start - 1 if start is not char.

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io