diff --git a/index.ts b/index.ts index 5c1493e..e556774 100644 --- a/index.ts +++ b/index.ts @@ -1,18 +1,19 @@ import { readdir } from "node:fs/promises"; import { YAML } from "bun"; import metadata from "./metadata.json"; - -const templateRaw = await Bun.file("./template.html").text(); -const template = templateRaw - .replace("[[NAME]]", metadata.name) - .replace("[[YEAR]]", new Date().getFullYear().toString()); +import templateRaw from "./templates/post.html" with { type: "text" }; +const templateStr = templateRaw as unknown as string; +const template = templateStr + .replaceAll("[[SITE]]", metadata.title) + .replaceAll("[[NAME]]", metadata.name) + .replaceAll("[[TIMEZONE]]", metadata.timezone) + .replaceAll("[[YEAR]]", new Date().getFullYear().toString()); const posts = await readdir("./posts"); const defaultFrontmatter = { - thumb: "", title: "Untitled", desc: "", - date: "00-00-0000", // DD-MM-YYYY + date: "0000-00-00", // YYYY-MM-DD tags: [] as never[], draft: true, }; @@ -20,10 +21,11 @@ const defaultFrontmatter = { function fetchFrontmatter(raw?: string) { try { if (!raw) throw new Error("No frontmatter found."); - return { ...defaultFrontmatter, ...(YAML.parse(raw) as typeof defaultFrontmatter) }; + const parsed = { ...defaultFrontmatter, ...(YAML.parse(raw) as typeof defaultFrontmatter) }; + return { ...parsed, date: new Date(parsed.date) }; } catch { console.warn("Failed to parse frontmatter. Using default values."); - return { ...defaultFrontmatter }; + return { ...defaultFrontmatter, date: new Date(NaN) }; } } @@ -36,24 +38,18 @@ posts.forEach(async (post) => { const frontmatter = fetchFrontmatter(raw.at(0)); const html = Bun.markdown.html(content, { - tables: true, - strikethrough: true, - tasklists: true, autolinks: true, headings: true, - hardSoftBreaks: true, - wikiLinks: true, underline: true, latexMath: true, - collapseWhitespace: true, - permissiveAtxHeaders: true, - noIndentedCodeBlocks: true, - noHtmlBlocks: true, - noHtmlSpans: true, tagFilter: true, }); const render = template .replaceAll("[[TITLE]]", `${metadata.title} - ${frontmatter.title}`) + .replaceAll("[[POST_TITLE]]", frontmatter.title) + .replaceAll("[[DATE]]", frontmatter.date.toDateString()) + .replaceAll("[[REVISIONS]]", `https://git.satr14.my.id/satr14/ssg.md/commits/branch/main/posts/${post}`) + .replaceAll("[[DESC]]", frontmatter.desc) .replace("[[CONTENT]]", html); await Bun.write(`./dist/posts/${post.replace(".md", ".html")}`, render); diff --git a/package.json b/package.json index 24bf659..90aca3f 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,11 @@ "module": "index.ts", "type": "module", "private": true, + "scripts": { + "tw-dev": "bunx tailwindcss -i style.css -o dist/style.css --watch", + "prev": "bunx serve dist", + "bun-dev": "bun --watch index.ts" + }, "devDependencies": { "@types/bun": "latest" }, diff --git a/posts/test.md b/posts/test.md index 7dc584a..7fe722e 100644 --- a/posts/test.md +++ b/posts/test.md @@ -1,9 +1,8 @@ -thumb: https://raw.githubusercontent.com/satr14/ssg/master/assets/markdown.png title: Comprehensive Markdown & GFM Syntax Reference desc: A detailed guide to Markdown and GitHub Flavored Markdown (GFM) syntax, covering text formatting, lists, tables, code blocks, links, and footnotes. -date: 25-05-2026 +date: 2026-05-27 tags: [markdown, gfm, syntax, reference, guide] -draft: false +draft: true ^--- ## 1. Text Formatting & Structure @@ -57,18 +56,93 @@ draft: false ## 4. Code Blocks with Syntax Highlighting -```nix -{ config, pkgs, ... }: +```bash +#!/usr/bin/env bash +set -euo pipefail -{ - environment.systemPackages = with pkgs; [ - git - neovim - tmux - ]; - - nix.settings.experimental-features = [ "nix-command" "flakes" ]; +# Variables & string manipulation +NAME="world" +GREETING="Hello, ${NAME}!" +UPPER=${GREETING^^} +SLICE=${GREETING:0:5} +echo "$UPPER | $SLICE" + +# Arrays +FRUITS=(apple banana cherry) +FRUITS+=(mango) +echo "${FRUITS[@]}" # all elements +echo "${#FRUITS[@]}" # length +echo "${FRUITS[@]:1:2}" # slice + +# Associative array +declare -A CONFIG=([host]="localhost" [port]="8080") +echo "${CONFIG[host]}:${CONFIG[port]}" + +# Arithmetic +COUNT=0 +(( COUNT += 5 )) +RESULT=$(( COUNT ** 2 )) +echo "$RESULT" + +# Conditionals & test operators +FILE="/etc/hosts" +if [[ -f "$FILE" && -r "$FILE" ]]; then + echo "readable" +elif [[ -e "$FILE" ]]; then + echo "exists but not readable" +else + echo "not found" +fi + +# Case +case "$NAME" in + world|earth) echo "planet" ;; + *) echo "unknown" ;; +esac + +# Loops +for fruit in "${FRUITS[@]}"; do + echo "fruit: $fruit" +done + +for (( i=0; i<3; i++ )); do + echo "i=$i" +done + +WHILE=3 +while (( WHILE-- > 0 )); do + echo "while: $WHILE" +done + +# Functions with local vars & return codes +greet() { + local name=${1:-"stranger"} + local -r greeting="Hi, $name!" + echo "$greeting" + return 0 } +greet "$NAME" + +# Command substitution & process substitution +DATE=$(date +%Y-%m-%d) +DIFF=<(echo "foo") +echo "Today: $DATE" + +# Here-doc +cat < /dev/null 2>&1 + +# Parameter expansion: default, error, replace +echo "${UNSET:-default}" +echo "${GREETING/Hello/Hey}" +echo "${FILE##*/}" # basename +echo "${FILE%/*}" # dirname ``` --- @@ -78,11 +152,3 @@ draft: false * **Standard Link:** [Search Engine](https://www.google.com) * **Link with Tooltip:** [GitHub](https://github.com "Go to GitHub") * **Autolink (GFM):** https://nixos.org - ---- - -## 6. Footnotes (GFM) - -You can reference a footnote at the end of a sentence[^1]. - -[^1]: This is the text of the footnote, which typically renders at the bottom of the document. \ No newline at end of file diff --git a/style.css b/style.css index 899e500..3499a84 100644 --- a/style.css +++ b/style.css @@ -1,4 +1,105 @@ +@import url("https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400..700;1,400..700&display=swap"); + @import "tailwindcss"; @import "@catppuccin/tailwindcss/mocha.css"; -body { @apply bg-ctp-base text-ctp-text; } \ No newline at end of file +@theme { --font-custom: "Lora", serif; } +body { @apply bg-ctp-crust text-ctp-text; } + +h1 { @apply text-3xl; } +h2 { @apply text-2xl; } +h3 { @apply text-xl; } +h4 { @apply text-lg; } +h5 { @apply text-base; } +h6 { @apply text-sm; } +h1, h2, h3, h4, h5, h6 { @apply font-semibold my-2; } +h1 { @apply text-ctp-blue; } +h2, h3, h4, h5, h6 { @apply text-ctp-lavender; } +a:not(h1 a, h2 a, h3 a, h4 a, h5 a, h6 a) { @apply decoration-ctp-blue underline hover:no-underline; } + +p { @apply text-base; } +hr { @apply border-t border-ctp-surface1 my-6; } + +ul, ol { @apply list-inside my-4 pl-2; } +ol { @apply list-decimal; } +ul { @apply list-disc; } +ul ul, ul ol, ol ul, ol ol { @apply my-0 pl-6; } +input[type="checkbox"] { @apply mr-2 align-middle cursor-default accent-ctp-blue; } + +table { @apply block border-collapse overflow-x-auto my-4; } +table th, table td { @apply border border-ctp-surface1 px-4 py-2; } +table th { @apply bg-ctp-surface0 font-semibold; } + +blockquote { @apply border-l-4 border-ctp-surface1 pl-4 italic my-4; } +code { @apply text-ctp-text rounded px-1; } +pre { @apply bg-ctp-base text-ctp-text rounded p-4 overflow-x-auto; } + +/*pre code.hljs { + display: block; + overflow-x: auto; +} +.hljs-comment { + color: #697070; +} +.hljs-punctuation, +.hljs-tag { + color: #444a; +} +.hljs-tag .hljs-attr, +.hljs-tag .hljs-name { + color: #444; +} +.hljs-attribute, +.hljs-doctag, +.hljs-keyword, +.hljs-meta .hljs-keyword, +.hljs-name, +.hljs-selector-tag { + font-weight: 700; +} +.hljs-deletion, +.hljs-number, +.hljs-quote, +.hljs-selector-class, +.hljs-selector-id, +.hljs-string, +.hljs-template-tag, +.hljs-type { + color: #800; +} +.hljs-section, +.hljs-title { + color: #800; + font-weight: 700; +} +.hljs-link, +.hljs-operator, +.hljs-regexp, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-symbol, +.hljs-template-variable, +.hljs-variable { + color: #ab5656; +} +.hljs-literal { + color: #695; +} +.hljs-addition, +.hljs-built_in, +.hljs-bullet, +.hljs-code { + color: #397300; +} +.hljs-meta { + color: #1f7199; +} +.hljs-meta .hljs-string { + color: #38a; +} +.hljs-emphasis { + font-style: italic; +} +.hljs-strong { + font-weight: 700; +}*/ diff --git a/template.html b/template.html deleted file mode 100644 index 16309f1..0000000 --- a/template.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - [[TITLE]] - - - -
-

[[TITLE]]

-
-
- [[CONTENT]] -
- - - \ No newline at end of file diff --git a/templates/home.html b/templates/home.html new file mode 100644 index 0000000..dc02520 --- /dev/null +++ b/templates/home.html @@ -0,0 +1,43 @@ + + + + + + [[TITLE]] + + + + + + + + + + + + + + +
+ [[SITE]] +
+ + --:-- -- +
+
+
+

[[POST_TITLE]]

+ [[DATE]] - view revisions + [[CONTENT]] +
+ + + \ No newline at end of file diff --git a/templates/post.html b/templates/post.html new file mode 100644 index 0000000..dc02520 --- /dev/null +++ b/templates/post.html @@ -0,0 +1,43 @@ + + + + + + [[TITLE]] + + + + + + + + + + + + + + +
+ [[SITE]] +
+ + --:-- -- +
+
+
+

[[POST_TITLE]]

+ [[DATE]] - view revisions + [[CONTENT]] +
+ + + \ No newline at end of file