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.
|
# This file is auto-generated by lux pkg. Do not edit manually.
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "frontmatter"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "path:../../packages/frontmatter"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "markdown"
|
name = "markdown"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|||||||
1
lux.toml
1
lux.toml
@@ -5,3 +5,4 @@ description = "A Lux project"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
markdown = { version = "0.1.0", path = "../../packages/markdown" }
|
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 markdown
|
||||||
|
import frontmatter
|
||||||
|
|
||||||
type SiteConfig =
|
type SiteConfig =
|
||||||
| SiteConfig(String, String, String, String, String, String, String)
|
| SiteConfig(String, String, String, String, String, String, String)
|
||||||
|
|
||||||
type Frontmatter =
|
|
||||||
| Frontmatter(String, String, String, String)
|
|
||||||
|
|
||||||
type ParseResult =
|
|
||||||
| ParseResult(Frontmatter, String)
|
|
||||||
|
|
||||||
type Page =
|
type Page =
|
||||||
| Page(String, String, String, String, String)
|
| Page(String, String, String, String, String)
|
||||||
|
|
||||||
type FMState =
|
|
||||||
| FMState(Bool, Bool, String, String, String, String, String)
|
|
||||||
|
|
||||||
type TagEntry =
|
type TagEntry =
|
||||||
| TagEntry(String, String, String, String, String)
|
| TagEntry(String, String, String, String, String)
|
||||||
|
|
||||||
@@ -103,49 +95,6 @@ fn cfgStaticDir(c: SiteConfig): String =
|
|||||||
SiteConfig(_, _, _, _, _, _, sd) => sd,
|
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 =
|
fn pgDate(p: Page): String =
|
||||||
match p {
|
match p {
|
||||||
Page(d, _, _, _, _) => d,
|
Page(d, _, _, _, _) => d,
|
||||||
@@ -262,18 +211,15 @@ fn htmlTagPage(tagName: String, postsHtml: String): String = "<div class=\"page
|
|||||||
|
|
||||||
fn parseFile(path: String): Page with {File} = {
|
fn parseFile(path: String): Page with {File} = {
|
||||||
let raw = File.read(path)
|
let raw = File.read(path)
|
||||||
let parsed = parseFrontmatter(raw)
|
let doc = frontmatter.parse(raw)
|
||||||
match parsed {
|
let title = frontmatter.title(doc)
|
||||||
ParseResult(front, body) => {
|
let date = frontmatter.date(doc)
|
||||||
let title = fmTitle(front)
|
let tags = frontmatter.getOrDefault(doc, "tags", "")
|
||||||
let date = fmDate(front)
|
let body = frontmatter.body(doc)
|
||||||
let tags = fmTagsRaw(front)
|
|
||||||
let htmlContent = convertMd(body)
|
let htmlContent = convertMd(body)
|
||||||
let filename = basename(path)
|
let filename = basename(path)
|
||||||
let slug = slugFromFilename(filename)
|
let slug = slugFromFilename(filename)
|
||||||
Page(date, title, slug, tags, htmlContent)
|
Page(date, title, slug, tags, htmlContent)
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mapParseFiles(dir: String, files: List<String>): List<Page> with {File} =
|
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} = {
|
fn renderSnippetFile(snippetDir: String, filename: String): String with {File} = {
|
||||||
let raw = File.read(snippetDir + "/" + filename)
|
let raw = File.read(snippetDir + "/" + filename)
|
||||||
let parsed = parseFrontmatter(raw)
|
let doc = frontmatter.parse(raw)
|
||||||
match parsed {
|
htmlSnippetCard(convertMd(frontmatter.body(doc)))
|
||||||
ParseResult(_, body) => htmlSnippetCard(convertMd(body)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderSnippets(snippetDir: String, files: List<String>): List<String> with {File} =
|
fn renderSnippets(snippetDir: String, files: List<String>): List<String> with {File} =
|
||||||
|
|||||||
Reference in New Issue
Block a user