refactor: replace inline frontmatter code with frontmatter package
Removed ~60 lines of inline frontmatter parsing (FMState, Frontmatter, ParseResult types, fmFoldLine, parseFrontmatter, and accessor functions). Now uses the frontmatter package via import. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,79 +0,0 @@
|
||||
// YAML-like frontmatter parser
|
||||
// Parses the --- delimited frontmatter block from markdown files
|
||||
|
||||
pub type Frontmatter =
|
||||
| Frontmatter(String, String, String, String)
|
||||
// title date desc tagsRaw
|
||||
|
||||
pub type ParseResult =
|
||||
| ParseResult(Frontmatter, String)
|
||||
// front body
|
||||
|
||||
pub fn parse(content: String): ParseResult = {
|
||||
let lines = String.lines(content);
|
||||
// Skip first --- line, collect key: value pairs until next ---
|
||||
let result = List.fold(lines, (false, false, "", "", "", "", ""), fn(acc: (Bool, Bool, String, String, String, String, String), line: String): (Bool, Bool, String, String, String, String, String) => {
|
||||
let inFront = acc.0;
|
||||
let pastFront = acc.1;
|
||||
let title = acc.2;
|
||||
let date = acc.3;
|
||||
let desc = acc.4;
|
||||
let tags = acc.5;
|
||||
let body = acc.6;
|
||||
if pastFront then
|
||||
(inFront, pastFront, title, date, desc, tags, body + line + "\n")
|
||||
else if String.trim(line) == "---" then
|
||||
if inFront then
|
||||
// End of frontmatter
|
||||
(false, true, title, date, desc, tags, body)
|
||||
else
|
||||
// Start of frontmatter
|
||||
(true, false, title, date, desc, tags, body)
|
||||
else if inFront then {
|
||||
// Parse key: value
|
||||
match String.indexOf(line, ": ") {
|
||||
Some(idx) => {
|
||||
let key = String.trim(String.substring(line, 0, idx));
|
||||
let rawVal = String.trim(String.substring(line, idx + 2, String.length(line)));
|
||||
// Strip surrounding quotes if present
|
||||
let val = if String.startsWith(rawVal, "\"") then
|
||||
String.substring(rawVal, 1, String.length(rawVal) - 1)
|
||||
else
|
||||
rawVal;
|
||||
if key == "title" then
|
||||
(inFront, pastFront, val, date, desc, tags, body)
|
||||
else if key == "date" then
|
||||
(inFront, pastFront, title, val, desc, tags, body)
|
||||
else if key == "description" then
|
||||
(inFront, pastFront, title, date, val, tags, body)
|
||||
else if key == "tags" then
|
||||
(inFront, pastFront, title, date, desc, val, body)
|
||||
else
|
||||
(inFront, pastFront, title, date, desc, tags, body)
|
||||
},
|
||||
None => (inFront, pastFront, title, date, desc, tags, body)
|
||||
}
|
||||
} else
|
||||
(inFront, pastFront, title, date, desc, tags, body)
|
||||
});
|
||||
let front = Frontmatter(result.2, result.3, result.4, result.5);
|
||||
ParseResult(front, result.6)
|
||||
}
|
||||
|
||||
pub fn getTitle(f: Frontmatter): String =
|
||||
match f { Frontmatter(t, _, _, _) => t }
|
||||
|
||||
pub fn getDate(f: Frontmatter): String =
|
||||
match f { Frontmatter(_, d, _, _) => d }
|
||||
|
||||
pub fn getDesc(f: Frontmatter): String =
|
||||
match f { Frontmatter(_, _, d, _) => d }
|
||||
|
||||
pub fn getTagsRaw(f: Frontmatter): String =
|
||||
match f { Frontmatter(_, _, _, t) => t }
|
||||
|
||||
pub fn getTags(f: Frontmatter): List<String> =
|
||||
match f { Frontmatter(_, _, _, t) =>
|
||||
if t == "" then []
|
||||
else String.split(t, " ")
|
||||
}
|
||||
5
lux.lock
5
lux.lock
@@ -1,5 +1,10 @@
|
||||
# This file is auto-generated by lux pkg. Do not edit manually.
|
||||
|
||||
[[package]]
|
||||
name = "frontmatter"
|
||||
version = "0.1.0"
|
||||
source = "path:../../packages/frontmatter"
|
||||
|
||||
[[package]]
|
||||
name = "markdown"
|
||||
version = "0.1.0"
|
||||
|
||||
1
lux.toml
1
lux.toml
@@ -5,3 +5,4 @@ description = "A Lux project"
|
||||
|
||||
[dependencies]
|
||||
markdown = { version = "0.1.0", path = "../../packages/markdown" }
|
||||
frontmatter = { version = "0.1.0", path = "../../packages/frontmatter" }
|
||||
|
||||
72
main.lux
72
main.lux
@@ -1,20 +1,12 @@
|
||||
import markdown
|
||||
import frontmatter
|
||||
|
||||
type SiteConfig =
|
||||
| SiteConfig(String, String, String, String, String, String, String)
|
||||
|
||||
type Frontmatter =
|
||||
| Frontmatter(String, String, String, String)
|
||||
|
||||
type ParseResult =
|
||||
| ParseResult(Frontmatter, String)
|
||||
|
||||
type Page =
|
||||
| Page(String, String, String, String, String)
|
||||
|
||||
type FMState =
|
||||
| FMState(Bool, Bool, String, String, String, String, String)
|
||||
|
||||
type TagEntry =
|
||||
| TagEntry(String, String, String, String, String)
|
||||
|
||||
@@ -103,49 +95,6 @@ fn cfgStaticDir(c: SiteConfig): String =
|
||||
SiteConfig(_, _, _, _, _, _, sd) => sd,
|
||||
}
|
||||
|
||||
fn fmFoldLine(acc: FMState, line: String): FMState =
|
||||
match acc {
|
||||
FMState(inFront, pastFront, title, date, desc, tags, body) => if pastFront then FMState(inFront, pastFront, title, date, desc, tags, body + line + "
|
||||
") else if String.trim(line) == "---" then if inFront then FMState(false, true, title, date, desc, tags, body) else FMState(true, false, title, date, desc, tags, body) else if inFront then match String.indexOf(line, ": ") {
|
||||
Some(idx) => {
|
||||
let key = String.trim(String.substring(line, 0, idx))
|
||||
let rawVal = String.trim(String.substring(line, idx + 2, String.length(line)))
|
||||
let val = if String.startsWith(rawVal, "\"") then String.substring(rawVal, 1, String.length(rawVal) - 1) else rawVal
|
||||
if key == "title" then FMState(inFront, pastFront, val, date, desc, tags, body) else if key == "date" then FMState(inFront, pastFront, title, val, desc, tags, body) else if key == "description" then FMState(inFront, pastFront, title, date, val, tags, body) else if key == "tags" then FMState(inFront, pastFront, title, date, desc, val, body) else acc
|
||||
},
|
||||
None => acc,
|
||||
} else acc,
|
||||
}
|
||||
|
||||
fn parseFrontmatter(content: String): ParseResult = {
|
||||
let lines = String.lines(content)
|
||||
let init = FMState(false, false, "", "", "", "", "")
|
||||
let result = List.fold(lines, init, fmFoldLine)
|
||||
match result {
|
||||
FMState(_, _, title, date, desc, tags, body) => ParseResult(Frontmatter(title, date, desc, tags), body),
|
||||
}
|
||||
}
|
||||
|
||||
fn fmTitle(f: Frontmatter): String =
|
||||
match f {
|
||||
Frontmatter(t, _, _, _) => t,
|
||||
}
|
||||
|
||||
fn fmDate(f: Frontmatter): String =
|
||||
match f {
|
||||
Frontmatter(_, d, _, _) => d,
|
||||
}
|
||||
|
||||
fn fmTagsRaw(f: Frontmatter): String =
|
||||
match f {
|
||||
Frontmatter(_, _, _, t) => t,
|
||||
}
|
||||
|
||||
fn fmTags(f: Frontmatter): List<String> =
|
||||
match f {
|
||||
Frontmatter(_, _, _, t) => if t == "" then [] else String.split(t, " "),
|
||||
}
|
||||
|
||||
fn pgDate(p: Page): String =
|
||||
match p {
|
||||
Page(d, _, _, _, _) => d,
|
||||
@@ -262,18 +211,15 @@ fn htmlTagPage(tagName: String, postsHtml: String): String = "<div class=\"page
|
||||
|
||||
fn parseFile(path: String): Page with {File} = {
|
||||
let raw = File.read(path)
|
||||
let parsed = parseFrontmatter(raw)
|
||||
match parsed {
|
||||
ParseResult(front, body) => {
|
||||
let title = fmTitle(front)
|
||||
let date = fmDate(front)
|
||||
let tags = fmTagsRaw(front)
|
||||
let doc = frontmatter.parse(raw)
|
||||
let title = frontmatter.title(doc)
|
||||
let date = frontmatter.date(doc)
|
||||
let tags = frontmatter.getOrDefault(doc, "tags", "")
|
||||
let body = frontmatter.body(doc)
|
||||
let htmlContent = convertMd(body)
|
||||
let filename = basename(path)
|
||||
let slug = slugFromFilename(filename)
|
||||
Page(date, title, slug, tags, htmlContent)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn mapParseFiles(dir: String, files: List<String>): List<Page> with {File} =
|
||||
@@ -384,10 +330,8 @@ fn writeTagPages(outputDir: String, allTagEntries: List<TagEntry>, siteTitle: St
|
||||
|
||||
fn renderSnippetFile(snippetDir: String, filename: String): String with {File} = {
|
||||
let raw = File.read(snippetDir + "/" + filename)
|
||||
let parsed = parseFrontmatter(raw)
|
||||
match parsed {
|
||||
ParseResult(_, body) => htmlSnippetCard(convertMd(body)),
|
||||
}
|
||||
let doc = frontmatter.parse(raw)
|
||||
htmlSnippetCard(convertMd(frontmatter.body(doc)))
|
||||
}
|
||||
|
||||
fn renderSnippets(snippetDir: String, files: List<String>): List<String> with {File} =
|
||||
|
||||
Reference in New Issue
Block a user