src/markdown

Search:
Group by:
Source   Edit  

nim-markdown

Most markdown parsers parse markdown documents in two steps, so does nim-markdown. The two-step consists of blocks parsing and inline parsing.

  • Block Parsing: One or more lines belongs to blocks, such as <p>, <h1>, etc.
  • Inline Parsing: Textual contents within the lines belongs to inlines, such as <a>, <em>, <strong>, etc.

When parsing block elements, nim-markdown follows this algorithm:

  • Step 1. Track current position pos in the document.
  • Step 2. If the document since pos matches one of our parsers, then apply it.
  • Step 3. After parsing, a new token is appended to the parent token, and then we advance pos.
  • Step 4. Go back to Step 1 until the end of file.

# Hello World\nWelcome to **nim-markdown**.\nLet's parse it.
^              ^                                            ^
0              14                                           EOF

^Document, pos=0

^Heading(level=1, doc="Hello World"), pos=14.
               
               ^Paragraph(doc="Wel..."), pos=EOF.
                                                            ^EOF, exit parsing.

After the block parsing step, a tree with only Block Tokens is constructed.

Document()
+-Heading(level=1, doc="Hello World")
+-Paragraph(doc="Wel...")

Then, we proceed to inline parsing. It walks the tree and expands more inline elements. The algorithm is the same, except we apply it to every Block Token. Eventually, we get something like this:

Document()
+-Heading(level=1)
  +-Text("H")
  +-Text("e")
  +-Text("l")
  +-Text("l")
  +-Text("o")
  ...
+-Paragraph()
  +-Text("W")
  +-Text("e")
  ...
  +-Em()
    +-Text("n")
    +-Text("i")
    +-Text("m")
    ...
  +-Text(".")
  ...

Finally, All Token types support conversion to HTML strings with the special $ proc,

Types

AtxHeadingParser = ref object of Parser
Source   Edit  
AutoLinkParser = ref object of Parser
Source   Edit  
BlanklineParser = ref object of Parser
Source   Edit  
Block = ref object of Token
Source   Edit  
Blockquote = ref object of Block
  chunks*: seq[Chunk]
Source   Edit  
BlockquoteParser = ref object of Parser
Source   Edit  
Chunk = ref object
  kind*: ChunkKind
  doc*: string
  pos*: int
Source   Edit  
ChunkKind = enum
  BlockChunk, LazyChunk, InlineChunk
Source   Edit  
CodeBlock = ref object of Block
  info*: string
Source   Edit  
CodeSpan = ref object of Inline
Source   Edit  
CodeSpanParser = ref object of Parser
Source   Edit  
Delimiter = ref object of Inline
  token*: Text
  kind*: string
  num*: int
  originalNum*: int
  isActive*: bool
  canOpen*: bool
  canClose*: bool
Source   Edit  
DelimiterParser = ref object of Parser
Source   Edit  
Document = ref object of Token
Source   Edit  
Em = ref object of Inline
Source   Edit  
Escape = ref object of Inline
Source   Edit  
EscapeParser = ref object of Parser
Source   Edit  
FencedCodeParser = ref object of Parser
Source   Edit  
HardBreak = ref object of Inline
Source   Edit  
HardBreakParser = ref object of Parser
Source   Edit  
Heading = ref object of Block
  level*: int
Source   Edit  
HtmlBlock = ref object of Block
Source   Edit  
HtmlBlockParser = ref object of Parser
Source   Edit  
HtmlEntity = ref object of Inline
Source   Edit  
HtmlEntityParser = ref object of Parser
Source   Edit  
HtmlTable = ref object of Block
Source   Edit  
HtmlTableParser = ref object of Parser
Source   Edit  
Image = ref object of Inline
  refId*: string
  allowNested*: bool
  url*: string
  alt*: string
  title*: string
Source   Edit  
ImageParser = ref object of Parser
Source   Edit  
IndentedCodeParser = ref object of Parser
Source   Edit  
Inline = ref object of Token
Source   Edit  
InlineHtml = ref object of Inline
Source   Edit  
InlineHtmlParser = ref object of Parser
Source   Edit  
Li = ref object of Block
  loose*: bool
  marker*: string
  verbatim*: string
Source   Edit  
LinkParser = ref object of Parser
Source   Edit  
MarkdownConfig = ref object
  escape*: bool              ## escape ``<``, ``>``, and ``&`` characters to be HTML-safe
  keepHtml*: bool            ## deprecated: preserve HTML tags rather than escape it
  blockParsers*: seq[Parser]
  inlineParsers*: seq[Parser]
Options for configuring parsing or rendering behavior. Source   Edit  
MarkdownError = object of ValueError
The error object for markdown parsing and rendering. Usually, you should not see MarkdownError raising in your application unless it's documented. Otherwise, please report it as an issue. Source   Edit  
Ol = ref object of Block
  start*: int
Source   Edit  
OlParser = ref object of Parser
Source   Edit  
Paragraph = ref object of Block
  loose*: bool
  trailing*: string
Source   Edit  
ParagraphParser = ref object of Parser
Source   Edit  
Parser = ref object of RootObj
Source   Edit  
ParseResult = ref object
  token*: Token
  pos*: int
Source   Edit  
ReferenceParser = ref object of Parser
Source   Edit  
SetextHeadingParser = ref object of Parser
Source   Edit  
SoftBreak = ref object of Inline
Source   Edit  
SoftBreakParser = ref object of Parser
Source   Edit  
State = ref object
  references*: Table[string, Reference]
  config*: MarkdownConfig
Source   Edit  
Strikethrough = ref object of Inline
Source   Edit  
StrikethroughParser = ref object of Parser
Source   Edit  
Strong = ref object of Inline
Source   Edit  
TableRow = ref object of Block
Source   Edit  
TBody = ref object of Block
  size*: int
Source   Edit  
TBodyCell = ref object of Block
  align*: string
Source   Edit  
Text = ref object of Inline
  delimiter*: Delimiter
Source   Edit  
TextParser = ref object of Parser
Source   Edit  
THead = ref object of Block
Source   Edit  
THeadCell = ref object of Block
  align*: string
Source   Edit  
ThematicBreak = ref object of Block
Source   Edit  
ThematicBreakParser = ref object of Parser
Source   Edit  
Token = ref object of RootObj
  doc*: string
  pos*: int
  children*: DoublyLinkedList[Token]
Source   Edit  
Ul = ref object of Block
Source   Edit  
UlParser = ref object of Parser
Source   Edit  

Procs

proc `$`(chunk: Chunk): string {....raises: [ValueError], tags: [], forbids: [].}
Source   Edit  
proc appendChild(token: Token; child: Token) {....raises: [], tags: [], forbids: [].}
Source   Edit  
proc finalizeList(state: State; token: Token) {.
    ...raises: [Exception, KeyError, RegexError], tags: [RootEffect], forbids: [].}
Source   Edit  
proc getAtxHeading(s: string; start: int = 0): tuple[level: int, doc: string,
    size: int] {....raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc getDelimiterStack(token: Token): DoublyLinkedList[Delimiter] {....raises: [],
    tags: [], forbids: [].}
Source   Edit  
proc getFence(doc: string; start: int = 0): tuple[indent: int, fence: string,
    size: int] {....raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc getIndentedCodeFirstLine(doc: string; start: int = 0): tuple[code: string,
    size: int] {....raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc getIndentedCodeRestLines(doc: string; start: int = 0): tuple[code: string,
    size: int] {....raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc getLinkDestination(doc: string; start: int): tuple[slice: Slice[int],
    size: int] {....raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc getLinkLabel(doc: string; start: int): tuple[label: string, size: int] {.
    ...raises: [MarkdownError, KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc getLinkText(doc: string; start: int; allowNested: bool = false): tuple[
    slice: Slice[int], size: int] {....raises: [MarkdownError, ValueError,
    KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc getLinkTitle(doc: string; start: int): tuple[slice: Slice[int], size: int] {.
    ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc getSetextHeading(doc: string; start = 0): tuple[level: int, doc: string,
    size: int] {....raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc isBlockquote(s: string; start: int = 0): bool {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc isContinuationText(doc: string; start: int = 0; stop: int = 0): bool {.
    ...raises: [KeyError, RegexError, Exception, ValueError], tags: [RootEffect],
    forbids: [].}
Source   Edit  
proc isOlNo1ListItem(doc: string; start: int = 0; stop: int = 0): bool {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc isUlEmptyListItem(doc: string; start: int = 0; stop: int = 0): bool {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc markdown(doc: string; config: MarkdownConfig = nil;
              root: Token = Document()): string {.
    ...raises: [KeyError, RegexError, Exception, MarkdownError],
    tags: [RootEffect], forbids: [].}

Convert a markdown document into a HTML document.

config:

  • You can set config=initCommonmarkConfig() to apply commonmark syntax (default).
  • Or, set config=initGfmConfig() to apply GFM syntax.

root:

  • You can set root=Document() (default).
  • Or, set root to any other token types, such as root=Blockquote(), or even your customized Token types, such as root=Div().
Source   Edit  
proc matchHtmlStart(doc: string; start: int = 0; bufsize: int = 0): tuple[
    startRe: Regex, endRe: Regex, endMatch: bool, continuation: bool] {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc normalizeLabel(label: string): string {....raises: [KeyError, RegexError],
    tags: [], forbids: [].}
Source   Edit  
proc parse(state: State; token: Token) {.
    ...raises: [KeyError, RegexError, Exception, MarkdownError],
    tags: [RootEffect], forbids: [].}
Source   Edit  
proc parseBlankLine(doc: string; start: int): ParseResult {....raises: [Exception],
    tags: [RootEffect], forbids: [].}
Source   Edit  
proc parseCodeContent(doc: string; indent: int; fence: string): tuple[
    code: string, size: int] {....raises: [KeyError, RegexError, ValueError],
                               tags: [], forbids: [].}
Source   Edit  
proc parseCodeInfo(doc: string; start: int = 0): tuple[info: string, size: int] {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc parseHTMLBlockContent(doc: string; startPattern: string;
                           endPattern: string; ignoreCase = false): tuple[
    html: string, size: int] {....raises: [KeyError, RegexError], tags: [],
                               forbids: [].}
Source   Edit  
proc parseIndentedCode(doc: string; start: int): ParseResult {.
    ...raises: [Exception], tags: [RootEffect], forbids: [].}
Source   Edit  
proc parseOrderedListItem(doc: string; start = 0; marker: var string;
                          listItemDoc: var string; index: var int = 1): int {.
    ...raises: [KeyError, RegexError, ValueError, Exception], tags: [RootEffect],
    forbids: [].}
Source   Edit  
proc parseTableAligns(doc: string): tuple[aligns: seq[string], matched: bool] {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc parseTableRow(doc: string): seq[string] {....raises: [], tags: [], forbids: [].}
Source   Edit  
proc parseTildeBlockCodeInfo(doc: string; start: int = 0): tuple[info: string,
    size: int] {....raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc parseUnorderedListItem(doc: string; start = 0; marker: var string;
                            listItemDoc: var string): int {.
    ...raises: [KeyError, RegexError, Exception], tags: [RootEffect], forbids: [].}
Source   Edit  
proc processEmphasis(state: State; token: Token) {....raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc readCLIOptions(): MarkdownConfig {....raises: [], tags: [], forbids: [].}

Read options from command line. If no option passed, the corresponding option will be the default.

Available options:

  • -e / --escape
  • --no-escape
  • -k / --keep-html
  • '--no-keep-html`
Source   Edit  
proc removeDelimiter(delimiter: var DoublyLinkedNode[Delimiter]) {....raises: [],
    tags: [], forbids: [].}
Source   Edit  
proc render(token: Token; sep = "\n"): string {....raises: [Exception],
    tags: [RootEffect], forbids: [].}
Source   Edit  
proc replaceInitialTabs(doc: string): string {....raises: [], tags: [], forbids: [].}
Source   Edit  
proc scanInlineDelimiters(doc: string; start: int; delimiter: var Delimiter) {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
proc tipToken(token: Token): Token {....raises: [], tags: [], forbids: [].}
Source   Edit  
proc toAlt(token: Token): string {....raises: [Exception], tags: [RootEffect],
                                   forbids: [].}
Source   Edit  

Methods

method `$`(token: Blockquote): string {....raises: [Exception], tags: [RootEffect],
                                        forbids: [].}
Source   Edit  
method `$`(token: CodeBlock): string {....raises: [KeyError, RegexError, ValueError],
                                       tags: [], forbids: [].}
Source   Edit  
method `$`(token: CodeSpan): string {....raises: [], tags: [], forbids: [].}
Source   Edit  
method `$`(token: Em): string {....raises: [Exception], tags: [RootEffect],
                                forbids: [].}
Source   Edit  
method `$`(token: Escape): string {....raises: [], tags: [], forbids: [].}
Source   Edit  
method `$`(token: HardBreak): string {....raises: [], tags: [], forbids: [].}
Source   Edit  
method `$`(token: Heading): string {....raises: [Exception, ValueError],
                                     tags: [RootEffect], forbids: [].}
Source   Edit  
method `$`(token: HtmlBlock): string {....raises: [], tags: [], forbids: [].}
Source   Edit  
method `$`(token: HtmlEntity): string {....raises: [KeyError, RegexError],
                                        tags: [], forbids: [].}
Source   Edit  
method `$`(token: HtmlTable): string {....raises: [Exception], tags: [RootEffect],
                                       forbids: [].}
Source   Edit  
method `$`(token: Image): string {....raises: [KeyError, RegexError, ValueError,
    Exception], tags: [RootEffect], forbids: [].}
Source   Edit  
method `$`(token: InlineHtml): string {....raises: [ValueError, KeyError,
    RegexError], tags: [], forbids: [].}
Source   Edit  
method `$`(token: Li): string {....raises: [Exception], tags: [RootEffect],
                                forbids: [].}
Source   Edit  
method `$`(token: Ol): string {....raises: [Exception], tags: [RootEffect],
                                forbids: [].}
Source   Edit  
method `$`(token: Paragraph): string {....raises: [Exception], tags: [RootEffect],
                                       forbids: [].}
Source   Edit  
method `$`(token: SoftBreak): string {....raises: [], tags: [], forbids: [].}
Source   Edit  
method `$`(token: Strikethrough): string {....raises: [], tags: [], forbids: [].}
Source   Edit  
method `$`(token: Strong): string {....raises: [Exception], tags: [RootEffect],
                                    forbids: [].}
Source   Edit  
method `$`(token: TableRow): string {....raises: [Exception], tags: [RootEffect],
                                      forbids: [].}
Source   Edit  
method `$`(token: TBody): string {....raises: [Exception], tags: [RootEffect],
                                   forbids: [].}
Source   Edit  
method `$`(token: TBodyCell): string {....raises: [Exception, ValueError],
                                       tags: [RootEffect], forbids: [].}
Source   Edit  
method `$`(token: Text): string {....raises: [], tags: [], forbids: [].}
Source   Edit  
method `$`(token: THead): string {....raises: [Exception], tags: [RootEffect],
                                   forbids: [].}
Source   Edit  
method `$`(token: THeadCell): string {....raises: [Exception, ValueError],
                                       tags: [RootEffect], forbids: [].}
Source   Edit  
method `$`(token: ThematicBreak): string {....raises: [], tags: [], forbids: [].}
Source   Edit  
method `$`(token: Token): string {.base, ...raises: [], tags: [], forbids: [].}
Source   Edit  
method `$`(token: Ul): string {....raises: [Exception], tags: [RootEffect],
                                forbids: [].}
Source   Edit  
method apply(this: Blockquote; state: State; res: ParseResult): ParseResult {.
    ...raises: [Exception], tags: [RootEffect], forbids: [].}
Source   Edit  
method apply(this: Image; state: State; res: ParseResult): ParseResult {.
    ...raises: [KeyError, Exception], tags: [RootEffect], forbids: [].}
Source   Edit  
method apply(this: Link; state: State; res: ParseResult): ParseResult {.
    ...raises: [KeyError, Exception], tags: [RootEffect], forbids: [].}
Source   Edit  
method apply(this: Ol; state: State; res: ParseResult): ParseResult {.
    ...raises: [Exception, KeyError, RegexError], tags: [RootEffect], forbids: [].}
Source   Edit  
method apply(this: Reference; state: State; res: ParseResult): ParseResult {.
    ...raises: [], tags: [], forbids: [].}
Source   Edit  
method apply(this: Token; state: State; res: ParseResult): ParseResult {.base,
    ...raises: [], tags: [], forbids: [].}
Source   Edit  
method apply(this: Ul; state: State; res: ParseResult): ParseResult {.
    ...raises: [Exception, KeyError, RegexError], tags: [RootEffect], forbids: [].}
Source   Edit  
method parse(this: AutoLinkParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError, ValueError], tags: [], forbids: [].}
Source   Edit  
method parse(this: BlanklineParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
method parse(this: BlockquoteParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError, ValueError, Exception], tags: [RootEffect],
    forbids: [].}
Source   Edit  
method parse(this: CodeSpanParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
method parse(this: DelimiterParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
method parse(this: EscapeParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
method parse(this: FencedCodeParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError, ValueError], tags: [], forbids: [].}
Source   Edit  
method parse(this: HardBreakParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
method parse(this: HtmlBlockParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
method parse(this: HtmlEntityParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
method parse(this: HtmlTableParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
method parse(this: ImageParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError, MarkdownError, ValueError], tags: [],
    forbids: [].}
Source   Edit  
method parse(this: IndentedCodeParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
method parse(this: InlineHtmlParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
method parse(this: LinkParser; doc: string; start: int): ParseResult {.
    ...raises: [MarkdownError, ValueError, KeyError, RegexError], tags: [],
    forbids: [].}
Source   Edit  
method parse(this: OlParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError, ValueError, Exception], tags: [RootEffect],
    forbids: [].}
Source   Edit  
method parse(this: ParagraphParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError, Exception, ValueError], tags: [RootEffect],
    forbids: [].}
Source   Edit  
method parse(this: Parser; doc: string; start: int): ParseResult {.base,
    ...raises: [], tags: [], forbids: [].}
Source   Edit  
method parse(this: ReferenceParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError, Exception], tags: [RootEffect], forbids: [].}
Source   Edit  
method parse(this: SoftBreakParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
method parse(this: StrikethroughParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
method parse(this: TextParser; doc: string; start: int): ParseResult {.
    ...raises: [], tags: [], forbids: [].}
Source   Edit  
method parse(this: ThematicBreakParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError], tags: [], forbids: [].}
Source   Edit  
method parse(this: UlParser; doc: string; start: int): ParseResult {.
    ...raises: [KeyError, RegexError, Exception], tags: [RootEffect], forbids: [].}
Source   Edit