Created
October 18, 2018 09:02
-
-
Save soasme/1a5271090250baed7936b5ac451e50c2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re, strutils, strformat, tables, sequtils, math | |
type | |
Header* = object | |
doc: string | |
level: int | |
MarkdownTokenType* {.pure.} = enum | |
Header | |
MarkdownTokenRef* = ref object | |
case type*: MarkdownTokenType | |
of MarkdownTokenType.Header: headerVal*: Header | |
MarkdownError* = object of Exception | |
let blockRules = { | |
MarkdownTokenType.Header: re"^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)", | |
}.toTable | |
proc findToken(doc: string, start: var int, ruleType: MarkdownTokenType): MarkdownTokenRef = | |
let regex = blockRules[ruleType] | |
var matches: array[5, string] | |
let size = doc[start .. doc.len - 1].matchLen(regex, matches=matches) | |
if size == -1: | |
return nil | |
case ruleType | |
of MarkdownTokenType.Header: | |
let val = Header(level: matches[0].len, doc: matches[1]) | |
result = MarkdownTokenRef(type: MarkdownTokenType.Header, headerVal: val) | |
start += size | |
iterator parseTokens(doc: string): MarkdownTokenRef = | |
var n = 0 | |
while n < len(doc): | |
var token: MarkdownTokenRef = nil | |
for type in [ | |
MarkdownTokenType.Header, | |
]: | |
token = findToken(doc, n, type) | |
if token != nil: | |
yield token | |
break | |
if token == nil: | |
raise newException(MarkdownError, fmt"unknown block rule at position {n}.") | |
proc renderToken(token: MarkdownTokenRef): string = | |
case token.type | |
of MarkdownTokenType.Header: | |
let header = token.headerVal | |
result = fmt"<h{header.level}>{header.doc}</h{header.level}>" | |
proc markdown*(doc: string): string = | |
for token in parseTokens(doc): | |
result &= renderToken(token) | |
when isMainModule: | |
stdout.write(markdown(stdin.readAll)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment