Codeblocks
This commit is contained in:
@@ -41,5 +41,11 @@ Text under a blockquote [#named]
|
|||||||
| table | row | with |
|
| table | row | with |
|
||||||
| some | ***content*** | in |
|
| some | ***content*** | in |
|
||||||
|
|
||||||
|
```odin
|
||||||
|
main :: proc() {
|
||||||
|
fmt.println("Hello, World!")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
[&1] Ordered list item 2 not included
|
[&1] Ordered list item 2 not included
|
||||||
[&named] This is the definition for a named footnote
|
[&named] This is the definition for a named footnote
|
||||||
|
|||||||
@@ -187,6 +187,29 @@ print_html :: proc(token: ^Token) {
|
|||||||
fmt.print("</div>\n")
|
fmt.print("</div>\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case TokenType.CodeBlock:
|
||||||
|
lang := ""
|
||||||
|
if v, ok := token.value.(string); ok && v != "" {
|
||||||
|
lang = v
|
||||||
|
}
|
||||||
|
if lang != "" {
|
||||||
|
fmt.printf("<pre><code class=\"lang-%s\">", lang)
|
||||||
|
} else {
|
||||||
|
fmt.print("<pre><code>")
|
||||||
|
}
|
||||||
|
for i := 0; i < len(token.children); i += 1 {
|
||||||
|
print_html(token.children[i])
|
||||||
|
if i + 1 < len(token.children) {
|
||||||
|
fmt.print("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.print("\n</code></pre>\n")
|
||||||
|
|
||||||
|
case TokenType.InlineCode:
|
||||||
|
if code, ok := token.value.(string); ok {
|
||||||
|
fmt.printf("<code>%s</code>", code)
|
||||||
|
}
|
||||||
|
|
||||||
case TokenType.BreakLine:
|
case TokenType.BreakLine:
|
||||||
fmt.print("<br>\n")
|
fmt.print("<br>\n")
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ print_token :: proc(token: ^Token, depth: int = 0) {
|
|||||||
type_str = "FootnoteDef"
|
type_str = "FootnoteDef"
|
||||||
case TokenType.FootnoteRef:
|
case TokenType.FootnoteRef:
|
||||||
type_str = "FootnoteRef"
|
type_str = "FootnoteRef"
|
||||||
|
case TokenType.CodeBlock:
|
||||||
|
type_str = "CodeBlock"
|
||||||
|
case TokenType.InlineCode:
|
||||||
|
type_str = "InlineCode"
|
||||||
}
|
}
|
||||||
|
|
||||||
value_str := ""
|
value_str := ""
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ TokenType :: enum {
|
|||||||
Middle,
|
Middle,
|
||||||
FootnoteDef,
|
FootnoteDef,
|
||||||
FootnoteRef,
|
FootnoteRef,
|
||||||
|
CodeBlock,
|
||||||
|
InlineCode,
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenValue :: union {
|
TokenValue :: union {
|
||||||
@@ -249,12 +251,61 @@ parse_inline_style :: proc(token: ^Token, symbol: byte, toggles: []StyleToggle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pass_through_children :: proc(token: ^Token) {
|
pass_through_children :: proc(token: ^Token) {
|
||||||
|
if token.type == .CodeBlock || token.type == .InlineCode {
|
||||||
|
return
|
||||||
|
}
|
||||||
parse_inline_style(token, '*', []StyleToggle{{2, .Bold}, {1, .Italics}})
|
parse_inline_style(token, '*', []StyleToggle{{2, .Bold}, {1, .Italics}})
|
||||||
parse_inline_style(token, '~', []StyleToggle{{2, .Strikethrough}})
|
parse_inline_style(token, '~', []StyleToggle{{2, .Strikethrough}})
|
||||||
parse_inline_style(token, '-', []StyleToggle{{2, .Strikethrough}})
|
parse_inline_style(token, '-', []StyleToggle{{2, .Strikethrough}})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse_inline_code :: proc(token: ^Token) {
|
||||||
|
if token.type == .CodeBlock || token.type == .InlineCode {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if token.children != nil {
|
||||||
|
for i := 0; i < len(token.children); i += 1 {
|
||||||
|
parse_inline_code(token.children[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if token.type == .Text {
|
||||||
|
str, ok := token.value.(string)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
start_idx := strings.index_byte(str, '`')
|
||||||
|
if start_idx == -1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
end_idx := strings.index_byte(str[start_idx + 1:], '`')
|
||||||
|
if end_idx == -1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
end_idx += start_idx + 1
|
||||||
|
|
||||||
|
code := str[start_idx + 1:end_idx]
|
||||||
|
|
||||||
|
token.value = nil
|
||||||
|
|
||||||
|
if start_idx > 0 {
|
||||||
|
push_token(token, .Text, str[:start_idx])
|
||||||
|
}
|
||||||
|
push_token(token, .InlineCode, code)
|
||||||
|
|
||||||
|
if end_idx + 1 < len(str) {
|
||||||
|
rem := push_token(token, .Text, str[end_idx + 1:])
|
||||||
|
parse_inline_code(rem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
parse_inline_footnotes :: proc(token: ^Token) {
|
parse_inline_footnotes :: proc(token: ^Token) {
|
||||||
|
if token.type == .CodeBlock || token.type == .InlineCode {
|
||||||
|
return
|
||||||
|
}
|
||||||
if token.children != nil {
|
if token.children != nil {
|
||||||
for i := 0; i < len(token.children); i += 1 {
|
for i := 0; i < len(token.children); i += 1 {
|
||||||
parse_inline_footnotes(token.children[i])
|
parse_inline_footnotes(token.children[i])
|
||||||
@@ -295,6 +346,9 @@ parse_inline_footnotes :: proc(token: ^Token) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
add_breaklines :: proc(token: ^Token) {
|
add_breaklines :: proc(token: ^Token) {
|
||||||
|
if token.type == .CodeBlock {
|
||||||
|
return
|
||||||
|
}
|
||||||
if token.children == nil {
|
if token.children == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -331,9 +385,28 @@ parse :: proc(lines: []string, allocator := context.allocator) -> Token {
|
|||||||
|
|
||||||
// FIRST PASS
|
// FIRST PASS
|
||||||
|
|
||||||
|
in_code_block := false
|
||||||
|
|
||||||
for untrimmed_line, line_index in lines {
|
for untrimmed_line, line_index in lines {
|
||||||
line := strings.trim_space(untrimmed_line)
|
line := strings.trim_space(untrimmed_line)
|
||||||
|
|
||||||
|
if in_code_block {
|
||||||
|
if strings.has_prefix(line, "```") {
|
||||||
|
in_code_block = false
|
||||||
|
current_token = &root
|
||||||
|
} else {
|
||||||
|
push_token(current_token, TokenType.Text, untrimmed_line)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.has_prefix(line, "```") {
|
||||||
|
lang := strings.trim_space(line[3:])
|
||||||
|
current_token = push_token(&root, TokenType.CodeBlock, lang)
|
||||||
|
in_code_block = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
current_token = &root
|
current_token = &root
|
||||||
continue
|
continue
|
||||||
@@ -441,6 +514,7 @@ parse :: proc(lines: []string, allocator := context.allocator) -> Token {
|
|||||||
// THIRD PASS
|
// THIRD PASS
|
||||||
|
|
||||||
for token in root.children {
|
for token in root.children {
|
||||||
|
parse_inline_code(token)
|
||||||
pass_through_children(token)
|
pass_through_children(token)
|
||||||
parse_inline_footnotes(token)
|
parse_inline_footnotes(token)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user