-module(tale@templates). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/tale/templates.gleam"). -export([write_site/1, default_post_archetype/0, write_default_theme/1]). -export_type([template_file/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC(" Embedded templates for Tale's generators\n"). -type template_file() :: {text, binary(), binary()}. -file("src/tale/templates.gleam", 53). -spec describe_write_error(binary(), simplifile:file_error()) -> binary(). describe_write_error(Path, Err) -> <<<<<<"Unable to write "/utf8, Path/binary>>/binary, ": "/utf8>>/binary, (simplifile:describe_error(Err))/binary>>. -file("src/tale/templates.gleam", 57). -spec join_path(binary(), binary()) -> binary(). join_path(Root, Path) -> case Path of <<""/utf8>> -> Root; _ -> <<<>/binary, Path/binary>> end. -file("src/tale/templates.gleam", 38). -spec write_template(binary(), template_file()) -> {ok, nil} | {error, binary()}. write_template(Root, Template) -> Path = case Template of {text, P, _} -> P end, Full_path = join_path(Root, Path), gleam@result:'try'( tale@paths:ensure_parent_dirs(Full_path), fun(_) -> case Template of {text, _, Contents} -> _pipe = simplifile:write(Full_path, Contents), gleam@result:map_error( _pipe, fun(Err) -> describe_write_error(Full_path, Err) end ) end end ). -file("src/tale/templates.gleam", 34). -spec write_files(binary(), list(template_file())) -> {ok, nil} | {error, binary()}. write_files(Root, Files) -> gleam@list:try_each(Files, fun(File) -> write_template(Root, File) end). -file("src/tale/templates.gleam", 12). -spec write_site(binary()) -> {ok, nil} | {error, binary()}. write_site(To) -> write_files( To, [{text, <<"archetypes/default.md"/utf8>>, <<"---\ntitle = \"New Article\"\ndescription = \"Short summary of the page\"\ndate = \"2025-01-01\"\ndraft = true\n---\n\n# Title Goes Here\n\nWrite your Markdown content here. Use code fences, blockquotes, headings, and\nlists to structure your article. All frontmatter values accept standard TOML.\n"/utf8>>}, {text, <<"assets/.gitkeep"/utf8>>, <<""/utf8>>}, {text, <<"config.toml"/utf8>>, <<"# Site/Blog Configuration\n\n# Title of the Site/Blog\ntitle = \"Tale\"\n\n# Description of the Site/Blog\ndescription = \"A Gleam static site generator\"\n\n# Author of the Site/Blog\n# Will be set as post author if not define in the post metadata\nauthor = \"Tale Team\"\n\n# Base URL of the Site/Blog\nbaseUrl = \"/\"\n\n# The Directory where static files will be generated for deployment\n# Default: \"public\" if not defined\npublishDir = \"public\"\n\n# The Directory where content files are located\n# Default: \"content\" if not defined\ncontentDir = \"content\"\n\n# The Theme to use for the Site/Blog\n# Default: \"default\" if not defined\ntheme = \"default\"\n\n# The Number of posts to display per page\n# pagination = 5\n\n# Navigation menu (order matters)\n[menus]\n [[menus.main]]\n name = \"Home\"\n pageRef = \"/\"\n weight = 10\n\n [[menus.main]]\n name = \"About\"\n pageRef = \"/about\"\n weight = 20\n\n [[menus.main]]\n name = \"Tags\"\n pageRef = \"/tags/\"\n weight = 30\n"/utf8>>}, {text, <<"content/_index.md"/utf8>>, <<"---\ntitle = \"Home\"\ndescription = \"Welcome to the Tale static site/blog generator\"\n---\n\n# Welcome to Tale\n\nCreate Markdown files inside `content/` to publish pages and posts. The default\nsite ships with a documentation-friendly theme, paginated home page, and tag\nlistings. Edit `content/posts/markdown-tour.md` to see how different Markdown\nconstructs render in the UI.\n"/utf8>>}, {text, <<"content/about.md"/utf8>>, <<"---\ntitle = \"About\"\ndescription = \"Learn more about this prototype\"\n---\n\n## About This Site\n\nThis site demonstrates:\n\n- TOML frontmatter parsing via `tom`\n- Markdown to HTML rendering through `mork`\n- Handles templates with partials and pagination helpers\n"/utf8>>}, {text, <<"content/posts/markdown-tour.md"/utf8>>, <<"---\ntitle = \"Markdown Syntax Tour\"\ndescription = \"A mega-post demonstrating Markdown and GFM output\"\ndate = \"2025-11-21\"\ntags = [\"docs\", \"markdown\", \"syntax\"]\n---\n\n# Markdown syntax tour\n\nThis document mirrors the Markdown reference at so we can see how\ncommon constructs are rendered inside the theme.\n\n## Inline formatting\n\n*Italic*, **strong**, ***strong italic***, `inline code`, ~~strikethrough~~, and\ninserted text using raw HTML. Escape sequence: `\\*` literally shows\nan asterisk.\n\n## Links & images\n\nLink styles: [inline link](https://commonmark.org) or reference-style [docs][docs].\n\n![Markdown logo](https://commonmark.org/help/images/favicon.png)\n\n[docs]: https://commonmark.org/help/\n\n## Lists\n\n- Bullet one\n- Bullet two\n - Nested bullet\n 1. Ordered inside\n 2. Still works\n- [ ] Task unchecked\n- [x] Task checked\n\n1. Ordered list entry\n2. Another entry\n3. And a third\n\n## Blockquotes\n\n> Block quotes can contain paragraphs, **inline styles**, and nested lists.\n>\n> > A nested quote feels nice too.\n\n## Footnotes\n\nMarkdown handles footnotes[^note] inline, great for references.[^ref]\n\n[^note]: Rendered at the bottom with backlinks.\n[^ref]: This one proves multiple notes work.\n\n## Code blocks\n\n```gleam\npub fn main() {\n io.println(\"Hello from Markdown fenced code!\")\n}\n```\n\nIndented code works too:\n\n touch src/app.gleam\n gleam test\n\n## Tables\n\n| Feature | Status | Notes |\n|--------------|--------|------------------------------|\n| Inline code | ✅ | Backticks everywhere. |\n| Task lists | ✅ | Syntax uses `[ ]` and `[x]`. |\n| Footnotes | ✅ | Great for citations. |\n\n## Thematic breaks\n\n---\n\n## Final paragraph\n\nIf something renders oddly, tweak the theme knowing every major Markdown feature is\nrepresented here.\n"/utf8>>}, {text, <<"content/tags/_index.md"/utf8>>, <<"---\ntitle = \"Tags overview\"\ndescription = \"Browse all tags\"\n---\n\n# Tags\n\nAll tags are listed below. Use these links to explore topics.\n"/utf8>>}, {text, <<"layouts/.gitkeep"/utf8>>, <<""/utf8>>}, {text, <<"static/.gitkeep"/utf8>>, <<""/utf8>>}] ). -file("src/tale/templates.gleam", 20). -spec default_post_archetype() -> binary(). default_post_archetype() -> case gleam@list:find_map( [{text, <<"archetypes/default.md"/utf8>>, <<"---\ntitle = \"New Article\"\ndescription = \"Short summary of the page\"\ndate = \"2025-01-01\"\ndraft = true\n---\n\n# Title Goes Here\n\nWrite your Markdown content here. Use code fences, blockquotes, headings, and\nlists to structure your article. All frontmatter values accept standard TOML.\n"/utf8>>}, {text, <<"assets/.gitkeep"/utf8>>, <<""/utf8>>}, {text, <<"config.toml"/utf8>>, <<"# Site/Blog Configuration\n\n# Title of the Site/Blog\ntitle = \"Tale\"\n\n# Description of the Site/Blog\ndescription = \"A Gleam static site generator\"\n\n# Author of the Site/Blog\n# Will be set as post author if not define in the post metadata\nauthor = \"Tale Team\"\n\n# Base URL of the Site/Blog\nbaseUrl = \"/\"\n\n# The Directory where static files will be generated for deployment\n# Default: \"public\" if not defined\npublishDir = \"public\"\n\n# The Directory where content files are located\n# Default: \"content\" if not defined\ncontentDir = \"content\"\n\n# The Theme to use for the Site/Blog\n# Default: \"default\" if not defined\ntheme = \"default\"\n\n# The Number of posts to display per page\n# pagination = 5\n\n# Navigation menu (order matters)\n[menus]\n [[menus.main]]\n name = \"Home\"\n pageRef = \"/\"\n weight = 10\n\n [[menus.main]]\n name = \"About\"\n pageRef = \"/about\"\n weight = 20\n\n [[menus.main]]\n name = \"Tags\"\n pageRef = \"/tags/\"\n weight = 30\n"/utf8>>}, {text, <<"content/_index.md"/utf8>>, <<"---\ntitle = \"Home\"\ndescription = \"Welcome to the Tale static site/blog generator\"\n---\n\n# Welcome to Tale\n\nCreate Markdown files inside `content/` to publish pages and posts. The default\nsite ships with a documentation-friendly theme, paginated home page, and tag\nlistings. Edit `content/posts/markdown-tour.md` to see how different Markdown\nconstructs render in the UI.\n"/utf8>>}, {text, <<"content/about.md"/utf8>>, <<"---\ntitle = \"About\"\ndescription = \"Learn more about this prototype\"\n---\n\n## About This Site\n\nThis site demonstrates:\n\n- TOML frontmatter parsing via `tom`\n- Markdown to HTML rendering through `mork`\n- Handles templates with partials and pagination helpers\n"/utf8>>}, {text, <<"content/posts/markdown-tour.md"/utf8>>, <<"---\ntitle = \"Markdown Syntax Tour\"\ndescription = \"A mega-post demonstrating Markdown and GFM output\"\ndate = \"2025-11-21\"\ntags = [\"docs\", \"markdown\", \"syntax\"]\n---\n\n# Markdown syntax tour\n\nThis document mirrors the Markdown reference at so we can see how\ncommon constructs are rendered inside the theme.\n\n## Inline formatting\n\n*Italic*, **strong**, ***strong italic***, `inline code`, ~~strikethrough~~, and\ninserted text using raw HTML. Escape sequence: `\\*` literally shows\nan asterisk.\n\n## Links & images\n\nLink styles: [inline link](https://commonmark.org) or reference-style [docs][docs].\n\n![Markdown logo](https://commonmark.org/help/images/favicon.png)\n\n[docs]: https://commonmark.org/help/\n\n## Lists\n\n- Bullet one\n- Bullet two\n - Nested bullet\n 1. Ordered inside\n 2. Still works\n- [ ] Task unchecked\n- [x] Task checked\n\n1. Ordered list entry\n2. Another entry\n3. And a third\n\n## Blockquotes\n\n> Block quotes can contain paragraphs, **inline styles**, and nested lists.\n>\n> > A nested quote feels nice too.\n\n## Footnotes\n\nMarkdown handles footnotes[^note] inline, great for references.[^ref]\n\n[^note]: Rendered at the bottom with backlinks.\n[^ref]: This one proves multiple notes work.\n\n## Code blocks\n\n```gleam\npub fn main() {\n io.println(\"Hello from Markdown fenced code!\")\n}\n```\n\nIndented code works too:\n\n touch src/app.gleam\n gleam test\n\n## Tables\n\n| Feature | Status | Notes |\n|--------------|--------|------------------------------|\n| Inline code | ✅ | Backticks everywhere. |\n| Task lists | ✅ | Syntax uses `[ ]` and `[x]`. |\n| Footnotes | ✅ | Great for citations. |\n\n## Thematic breaks\n\n---\n\n## Final paragraph\n\nIf something renders oddly, tweak the theme knowing every major Markdown feature is\nrepresented here.\n"/utf8>>}, {text, <<"content/tags/_index.md"/utf8>>, <<"---\ntitle = \"Tags overview\"\ndescription = \"Browse all tags\"\n---\n\n# Tags\n\nAll tags are listed below. Use these links to explore topics.\n"/utf8>>}, {text, <<"layouts/.gitkeep"/utf8>>, <<""/utf8>>}, {text, <<"static/.gitkeep"/utf8>>, <<""/utf8>>}], fun(File) -> case File of {text, <<"archetypes/default.md"/utf8>>, Contents} -> {ok, Contents}; _ -> {error, nil} end end ) of {ok, Contents@1} -> Contents@1; {error, _} -> <<""/utf8>> end. -file("src/tale/templates.gleam", 16). -spec write_default_theme(binary()) -> {ok, nil} | {error, binary()}. write_default_theme(To) -> write_files( To, [{text, <<"assets/css/style.css"/utf8>>, <<":root {\n color: #111;\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n sans-serif;\n}\n\n* {\n box-sizing: border-box;\n}\n\nbody {\n margin: 0 auto;\n max-width: 68ch;\n padding: 2rem 1.25rem 4rem;\n line-height: 1.4;\n color: inherit;\n background: #fff;\n}\n\na {\n color: inherit;\n text-decoration: none;\n}\n\nh1,\nh2,\nh3 {\n margin: 0 0 0.4rem;\n font-weight: 600;\n}\n\np {\n margin: 0 0 0.8rem;\n}\n\nhgroup {\n margin: 0 0 1rem;\n}\n\n.site-header {\n margin-bottom: 1.5rem;\n}\n\n.site-header h1 {\n font-size: 1.9rem;\n}\n\n.site-header hgroup p {\n color: #666;\n}\n\n.site-menu {\n display: flex;\n flex-wrap: wrap;\n gap: 0.75rem;\n margin-top: 0.75rem;\n font-size: 0.95rem;\n}\n\n.site-menu a:hover {\n color: #666;\n}\n\n.layout main,\n.layout {\n display: block;\n}\n\n.post-list {\n margin-top: 1.5rem;\n}\n\n.post-card {\n margin-bottom: 1.6rem;\n}\n\n.post-card h2 {\n font-size: 1.35rem;\n margin-bottom: 0.25rem;\n}\n\n.post-meta {\n font-size: 0.85rem;\n color: #555;\n margin-bottom: 0.25rem;\n}\n\n.tag-list {\n display: flex;\n flex-wrap: wrap;\n gap: 0.4rem;\n margin: 0.4rem 0;\n}\n\n.tag-list a {\n display: inline-block;\n padding: 0.1rem 0.6rem;\n border: 1px solid #222;\n border-radius: 999px;\n font-size: 0.8rem;\n}\n\n.pagination {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 1.5rem;\n margin-top: 2rem;\n font-size: 0.9rem;\n text-align: center;\n}\n\nfooter {\n margin-top: 3rem;\n font-size: 0.85rem;\n color: #555;\n}\n\n/* Minimal Markdown styles */\npre,\ncode {\n font-family:\n ui-monospace,\n SFMono-Regular,\n SF Mono,\n Menlo,\n Consolas,\n \"Liberation Mono\",\n monospace;\n}\n\npre {\n background: #f5f5f5;\n padding: 0.75rem;\n border-radius: 6px;\n overflow: auto;\n border: 1px solid #e0e0e0;\n margin: 0 0 1rem;\n}\n\ncode {\n background: #f5f5f5;\n padding: 0.1rem 0.35rem;\n border-radius: 4px;\n border: 1px solid #e0e0e0;\n}\n\ntable {\n width: 100%;\n border-collapse: collapse;\n margin: 1rem 0;\n font-size: 0.95rem;\n}\n\nth,\ntd {\n padding: 0.5rem 0.75rem;\n border: 1px solid #ddd;\n text-align: left;\n}\n\nthead th {\n background: #fafafa;\n font-weight: 600;\n}\n"/utf8>>}, {text, <<"assets/js/app.js"/utf8>>, <<"(() => {\n const el = document.querySelector('[data-build-info]')\n if (!el) return\n const time = new Date().toLocaleString()\n el.textContent = `Built at ${time}`\n})()\n"/utf8>>}, {text, <<"layouts/_partials/footer.html"/utf8>>, <<"
\n

\n © {{current_year}} {{metadata.site_title}} ·\n {{metadata.site_author}}\n

\n
\n"/utf8>>}, {text, <<"layouts/_partials/head/css.html"/utf8>>, <<"\n"/utf8>>}, {text, <<"layouts/_partials/head/js.html"/utf8>>, <<"\n"/utf8>>}, {text, <<"layouts/_partials/head.html"/utf8>>, <<"\n \n \n \n {{#if is_home}}\n {{metadata.site_title}}\n {{/if}}\n {{#if is_subpage}}\n {{metadata.title}} | {{metadata.site_title}}\n {{/if}}\n \n \n \n {{>_partials/head_css metadata}}\n {{>_partials/head_js metadata}}\n\n"/utf8>>}, {text, <<"layouts/_partials/header.html"/utf8>>, <<"
\n
\n

{{metadata.site_title}}

\n

{{metadata.site_description}}

\n
\n {{>_partials/menu metadata}}\n
\n"/utf8>>}, {text, <<"layouts/_partials/menu.html"/utf8>>, <<"{{#if has_site_menu}}\n\n{{/if}}\n"/utf8>>}, {text, <<"layouts/_partials/post_card.html"/utf8>>, <<"
\n

{{date}} · {{author}}

\n

{{title}}

\n

{{description}}

\n {{#if has_tags}}\n
\n {{#each tags}}\n {{name}}\n {{/each}}\n
\n {{/if}}\n
\n"/utf8>>}, {text, <<"layouts/baseof.html"/utf8>>, <<"\n\n {{>_partials/head .}}\n \n {{>_partials/header .}} {{main}} {{>_partials/footer .}}\n \n\n"/utf8>>}, {text, <<"layouts/home.html"/utf8>>, <<"
\n
\n
\n

{{metadata.title}}

\n

{{metadata.description}}

\n
\n
\n\n {{#if has_body}}\n
{{body}}
\n {{/if}}\n\n
\n {{#each pages}} {{>_partials/post_card .}} {{/each}}\n
\n\n {{#if pagination.has_pages}}\n \n {{/if}}\n
\n"/utf8>>}, {text, <<"layouts/page.html"/utf8>>, <<"
\n
\n
\n
\n

{{metadata.title}}

\n

{{metadata.description}}

\n
\n
\n {{body}}\n
\n
\n"/utf8>>}, {text, <<"layouts/section.html"/utf8>>, <<"
\n
\n
\n

{{metadata.date}} · {{metadata.author}}

\n

{{metadata.title}}

\n

{{metadata.description}}

\n
\n {{body}} {{#if metadata.has_tags}}\n
\n
\n {{#each metadata.tags}}\n {{name}}\n {{/each}}\n
\n
\n {{/if}}\n
\n
\n"/utf8>>}, {text, <<"layouts/taxonomy.html"/utf8>>, <<"
\n
\n
\n

{{metadata.title}}

\n

{{metadata.description}}

\n
\n
\n
\n
\n {{#each site_tags}}\n {{name}} ({{count}})\n {{/each}}\n
\n
\n
\n"/utf8>>}, {text, <<"layouts/term.html"/utf8>>, <<"
\n
\n
\n

{{current_tag.name}}

\n

{{current_tag.count}} posts

\n
\n
\n\n
\n {{#each pages}} {{>_partials/post_card .}} {{/each}}\n
\n\n {{#if pagination.has_pages}}\n \n {{/if}}\n
\n"/utf8>>}, {text, <<"static/robots.txt"/utf8>>, <<"User-agent: *\nAllow: /\n"/utf8>>}, {text, <<"theme.toml"/utf8>>, <<"# Theme name\nname = \"default\"\n# License\nlicense = \"MIT\"\n\n# Description\ndescription = \"Starter theme for the Tale SSG with docs-friendly layouts\"\n\n# Version\nversion = \"0.1.0\"\n\n# Theme Link\nsrc = \"https://example.com/themes/default\"\n\n# Theme tags\ntags = [\"blog\", \"docs\", \"tags\", \"responsive\"]\n\n# Theme features\nfeatures = [\"pagination\", \"tags\", \"documentation\", \"partials\"]\n\n# Theme author\n[author]\n name = \"Tale SSG Team\"\n homepage = \"https://example.com\"\n email = \"hello@example.com\"\n"/utf8>>}] ).