mirror of
https://github.com/sbrow/thor.git
synced 2026-08-26 11:23:32 -04:00
refactor: Moved markdown code to a separate packge.
This commit is contained in:
@@ -46,16 +46,21 @@
|
|||||||
- [ ] Import/export packages. Hugo, jekyll, WordPress, etc.
|
- [ ] Import/export packages. Hugo, jekyll, WordPress, etc.
|
||||||
- [ ] Review every file in thor
|
- [ ] Review every file in thor
|
||||||
- [ ] Review assets.odin
|
- [ ] Review assets.odin
|
||||||
- [ ] Review alerts.odin
|
|
||||||
- [ ] Review content.odin
|
- [ ] Review content.odin
|
||||||
- [ ] Review emoji.odin
|
- [ ] Review defaults.odin
|
||||||
- [ ] Review feed.odin
|
- [ ] Review feed.odin
|
||||||
- [ ] Review footnotes.odin
|
|
||||||
- [ ] Review frontmatter.odin
|
- [ ] Review frontmatter.odin
|
||||||
- [ ] Review highlight.odin
|
|
||||||
- [ ] Review main.odin
|
- [ ] Review main.odin
|
||||||
- [ ] Review minifiy.odin
|
- [ ] Review minify.odin
|
||||||
- [ ] Review render.odin
|
- [ ] Review `markdown/`
|
||||||
|
- [ ] Review alerts.odin
|
||||||
|
- [ ] Review emoji.odin
|
||||||
|
- [ ] Review footnotes.odin
|
||||||
|
- [ ] Review footnotes_test.odin
|
||||||
|
- [ ] Review highlight.odin
|
||||||
|
- [ ] Review markdown.odin
|
||||||
- [ ] Review sectionate.odin
|
- [ ] Review sectionate.odin
|
||||||
|
- [ ] Review render.odin
|
||||||
- [x] Review site.odin
|
- [x] Review site.odin
|
||||||
- [ ] Review tree_sitter.odin
|
- [ ] Review treesitter/treesitter.odin
|
||||||
|
- [ ] Review vfs.odin
|
||||||
|
|||||||
+3
-25
@@ -1,6 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import cm "vendor:commonmark"
|
import md "markdown"
|
||||||
|
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:log"
|
import "core:log"
|
||||||
@@ -101,7 +101,7 @@ load_page :: proc(
|
|||||||
section: string,
|
section: string,
|
||||||
slug: string,
|
slug: string,
|
||||||
is_index: bool,
|
is_index: bool,
|
||||||
ext: bit_set[Markdown_Extension],
|
ext: bit_set[md.Extension],
|
||||||
) -> (
|
) -> (
|
||||||
page: Page,
|
page: Page,
|
||||||
ok: bool,
|
ok: bool,
|
||||||
@@ -132,29 +132,7 @@ load_page :: proc(
|
|||||||
if strings.has_suffix(file_path, ".html") {
|
if strings.has_suffix(file_path, ".html") {
|
||||||
page.body_html = strings.clone(body)
|
page.body_html = strings.clone(body)
|
||||||
} else {
|
} else {
|
||||||
sn_defs := make(map[string]string)
|
page.body_html = md.process(body, ext, file_path)
|
||||||
mn_defs := make(map[string]string)
|
|
||||||
clean_body := body
|
|
||||||
if .Sidenotes in ext {
|
|
||||||
clean_body, sn_defs, mn_defs = strip_definitions(body)
|
|
||||||
}
|
|
||||||
html := cm.markdown_to_html_from_string(clean_body, {.Unsafe})
|
|
||||||
if .Emoji in ext {
|
|
||||||
html = expand_emoji(html)
|
|
||||||
}
|
|
||||||
if .Sidenotes in ext {
|
|
||||||
html = inject_notes(html, sn_defs, mn_defs)
|
|
||||||
}
|
|
||||||
if .Alerts in ext {
|
|
||||||
html = inject_alerts(html)
|
|
||||||
}
|
|
||||||
if .Highlight in ext {
|
|
||||||
html = highlight_code(html, file_path)
|
|
||||||
}
|
|
||||||
if .Sections in ext {
|
|
||||||
html = wrap_sections(html)
|
|
||||||
}
|
|
||||||
page.body_html = html
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if section == "" && is_index {
|
if section == "" && is_index {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#+feature dynamic-literals
|
#+feature dynamic-literals
|
||||||
package main
|
package markdown
|
||||||
|
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#+feature dynamic-literals
|
#+feature dynamic-literals
|
||||||
package main
|
package markdown
|
||||||
|
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package markdown
|
||||||
|
|
||||||
import cm "vendor:commonmark"
|
import cm "vendor:commonmark"
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#+feature dynamic-literals
|
#+feature dynamic-literals
|
||||||
#+test
|
#+test
|
||||||
package main
|
package markdown
|
||||||
|
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:testing"
|
import "core:testing"
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package main
|
package markdown
|
||||||
|
|
||||||
import ts "treesitter"
|
import ts "../treesitter"
|
||||||
|
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:log"
|
import "core:log"
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package markdown
|
||||||
|
|
||||||
|
import cm "vendor:commonmark"
|
||||||
|
|
||||||
|
import "core:encoding/json"
|
||||||
|
import "core:strings"
|
||||||
|
|
||||||
|
Extension :: enum {
|
||||||
|
Emoji,
|
||||||
|
Sidenotes,
|
||||||
|
Alerts,
|
||||||
|
Highlight,
|
||||||
|
Sections,
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFAULT_EXTENSIONS :: bit_set[Extension]{.Emoji, .Sidenotes, .Alerts}
|
||||||
|
|
||||||
|
process :: proc(body: string, ext: bit_set[Extension], file_path: string) -> string {
|
||||||
|
side_notes := make(map[string]string)
|
||||||
|
margin_notes := make(map[string]string)
|
||||||
|
clean_body := body
|
||||||
|
if .Sidenotes in ext {
|
||||||
|
clean_body, side_notes, margin_notes = strip_definitions(body)
|
||||||
|
}
|
||||||
|
html := cm.markdown_to_html_from_string(clean_body, {.Unsafe})
|
||||||
|
if .Emoji in ext {
|
||||||
|
html = expand_emoji(html)
|
||||||
|
}
|
||||||
|
if .Sidenotes in ext {
|
||||||
|
html = inject_notes(html, side_notes, margin_notes)
|
||||||
|
}
|
||||||
|
if .Alerts in ext {
|
||||||
|
html = inject_alerts(html)
|
||||||
|
}
|
||||||
|
if .Highlight in ext {
|
||||||
|
html = highlight_code(html, file_path)
|
||||||
|
}
|
||||||
|
if .Sections in ext {
|
||||||
|
html = wrap_sections(html)
|
||||||
|
}
|
||||||
|
return html
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a ',' separated list of case-insensitive extension names to a bit set.
|
||||||
|
parse_extension_list :: proc(s: string) -> (result: bit_set[Extension]) {
|
||||||
|
for part in strings.split(s, ",", allocator = context.temp_allocator) {
|
||||||
|
name := strings.to_lower(strings.trim_space(part), allocator = context.temp_allocator)
|
||||||
|
switch name {
|
||||||
|
case "emoji":
|
||||||
|
result += {.Emoji}
|
||||||
|
case "sidenotes":
|
||||||
|
result += {.Sidenotes}
|
||||||
|
case "alerts":
|
||||||
|
result += {.Alerts}
|
||||||
|
case "highlight":
|
||||||
|
result += {.Highlight}
|
||||||
|
case "sections":
|
||||||
|
result += {.Sections}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a map[Extension]bool, apply it to ext.
|
||||||
|
apply_extension_config :: proc(ext: ^bit_set[Extension], config: json.Object) {
|
||||||
|
for name, val in config {
|
||||||
|
// TODO: Silently discards invalid values.
|
||||||
|
enabled := val.(json.Boolean) or_continue
|
||||||
|
switch name {
|
||||||
|
case "emoji":
|
||||||
|
if enabled {ext^ += {.Emoji}} else {ext^ -= {.Emoji}}
|
||||||
|
case "sidenotes":
|
||||||
|
if enabled {ext^ += {.Sidenotes}} else {ext^ -= {.Sidenotes}}
|
||||||
|
case "alerts":
|
||||||
|
if enabled {ext^ += {.Alerts}} else {ext^ -= {.Alerts}}
|
||||||
|
case "highlight":
|
||||||
|
if enabled {ext^ += {.Highlight}} else {ext^ -= {.Highlight}}
|
||||||
|
case "sections":
|
||||||
|
if enabled {ext^ += {.Sections}} else {ext^ -= {.Sections}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package markdown
|
||||||
|
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
|
||||||
@@ -8,6 +8,8 @@ import "core:mem"
|
|||||||
import "core:os"
|
import "core:os"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
|
||||||
|
import md "markdown"
|
||||||
|
|
||||||
|
|
||||||
// Site is the primary workhorse.
|
// Site is the primary workhorse.
|
||||||
Site :: struct {
|
Site :: struct {
|
||||||
@@ -26,7 +28,7 @@ Site :: struct {
|
|||||||
layouts_dir: string,
|
layouts_dir: string,
|
||||||
params: json.Object,
|
params: json.Object,
|
||||||
features: bit_set[Feature],
|
features: bit_set[Feature],
|
||||||
markdown_extensions: bit_set[Markdown_Extension],
|
markdown_extensions: bit_set[md.Extension],
|
||||||
}
|
}
|
||||||
|
|
||||||
Feature :: enum {
|
Feature :: enum {
|
||||||
@@ -35,22 +37,6 @@ Feature :: enum {
|
|||||||
Watch,
|
Watch,
|
||||||
}
|
}
|
||||||
|
|
||||||
Markdown_Extension :: enum {
|
|
||||||
Emoji,
|
|
||||||
Sidenotes,
|
|
||||||
Alerts,
|
|
||||||
Highlight,
|
|
||||||
Sections,
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFAULT_MARKDOWN_EXTENSIONS :: bit_set[Markdown_Extension] {
|
|
||||||
.Emoji,
|
|
||||||
.Sidenotes,
|
|
||||||
.Alerts,
|
|
||||||
// .Highlight,
|
|
||||||
// .Sections,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configuration loaded from `thor.json`. Gets folded in to Site before
|
// Configuration loaded from `thor.json`. Gets folded in to Site before
|
||||||
// Flags
|
// Flags
|
||||||
Config_File :: struct {
|
Config_File :: struct {
|
||||||
@@ -89,7 +75,7 @@ init_site :: proc(site: ^Site, args: []string) {
|
|||||||
|
|
||||||
// Set defaults
|
// Set defaults
|
||||||
site.base_url = "http://localhost:8080"
|
site.base_url = "http://localhost:8080"
|
||||||
site.markdown_extensions = DEFAULT_MARKDOWN_EXTENSIONS
|
site.markdown_extensions = md.DEFAULT_EXTENSIONS
|
||||||
|
|
||||||
_flags: Flags
|
_flags: Flags
|
||||||
flags.parse_or_exit(&_flags, args, .Odin, alloc)
|
flags.parse_or_exit(&_flags, args, .Odin, alloc)
|
||||||
@@ -163,7 +149,7 @@ site_apply_config :: proc(site: ^Site, config: Config_File, config_dir: string)
|
|||||||
|
|
||||||
// Apply markdown extensions from config
|
// Apply markdown extensions from config
|
||||||
if ext_obj, ok := config.markdown_extensions.(json.Object); ok {
|
if ext_obj, ok := config.markdown_extensions.(json.Object); ok {
|
||||||
apply_extension_config(&site.markdown_extensions, ext_obj)
|
md.apply_extension_config(&site.markdown_extensions, ext_obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
if modules_arr, ok := config.modules.(json.Array); ok {
|
if modules_arr, ok := config.modules.(json.Array); ok {
|
||||||
@@ -193,48 +179,8 @@ site_apply_cli_flags :: proc(site: ^Site, flags: Flags) {
|
|||||||
if flags.watch {site.features += {.Watch}}
|
if flags.watch {site.features += {.Watch}}
|
||||||
if flags.minify {site.features += {.Minify}}
|
if flags.minify {site.features += {.Minify}}
|
||||||
|
|
||||||
site.markdown_extensions += parse_extension_list(flags.md_enable)
|
site.markdown_extensions += md.parse_extension_list(flags.md_enable)
|
||||||
site.markdown_extensions -= parse_extension_list(flags.md_disable)
|
site.markdown_extensions -= md.parse_extension_list(flags.md_disable)
|
||||||
}
|
|
||||||
|
|
||||||
parse_extension_list :: proc(s: string) -> bit_set[Markdown_Extension] {
|
|
||||||
result: bit_set[Markdown_Extension]
|
|
||||||
if s == "" do return result
|
|
||||||
for part in strings.split(s, ",", allocator = context.temp_allocator) {
|
|
||||||
name := strings.to_lower(strings.trim_space(part), allocator = context.temp_allocator)
|
|
||||||
switch name {
|
|
||||||
case "emoji":
|
|
||||||
result += {.Emoji}
|
|
||||||
case "sidenotes":
|
|
||||||
result += {.Sidenotes}
|
|
||||||
case "alerts":
|
|
||||||
result += {.Alerts}
|
|
||||||
case "highlight":
|
|
||||||
result += {.Highlight}
|
|
||||||
case "sections":
|
|
||||||
result += {.Sections}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
apply_extension_config :: proc(ext: ^bit_set[Markdown_Extension], config: json.Object) {
|
|
||||||
for name, val in config {
|
|
||||||
enabled, is_bool := val.(json.Boolean)
|
|
||||||
if !is_bool do continue
|
|
||||||
switch name {
|
|
||||||
case "emoji":
|
|
||||||
if enabled {ext^ += {.Emoji}} else {ext^ -= {.Emoji}}
|
|
||||||
case "sidenotes":
|
|
||||||
if enabled {ext^ += {.Sidenotes}} else {ext^ -= {.Sidenotes}}
|
|
||||||
case "alerts":
|
|
||||||
if enabled {ext^ += {.Alerts}} else {ext^ -= {.Alerts}}
|
|
||||||
case "highlight":
|
|
||||||
if enabled {ext^ += {.Highlight}} else {ext^ -= {.Highlight}}
|
|
||||||
case "sections":
|
|
||||||
if enabled {ext^ += {.Sections}} else {ext^ -= {.Sections}}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
site_allocator :: proc(site: ^Site) -> mem.Allocator {
|
site_allocator :: proc(site: ^Site) -> mem.Allocator {
|
||||||
|
|||||||
Reference in New Issue
Block a user