A simple, folder-driven static-site engine.
bun ssg fs
9
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor(templates): migrate Handlebars templates from .html to .hbs

Artwo ca4dbaab 7012485f

+309 -238
+20
.prettierrc.json
··· 1 + { 2 + "trailingComma": "all", 3 + "tabWidth": 2, 4 + "semi": false, 5 + "singleQuote": true, 6 + "printWidth": 100, 7 + "useTabs": false, 8 + "bracketSpacing": true, 9 + "endOfLine": "lf", 10 + "arrowParens": "always", 11 + 12 + "overrides": [ 13 + { 14 + "files": "**/*.hbs", 15 + "options": { 16 + "parser": "angular" 17 + } 18 + } 19 + ] 20 + }
+5
.vscode/extensions.json
··· 1 + { 2 + "recommendations": [ 3 + "mfeckies.handlebars-formatter" 4 + ] 5 + }
+1 -1
ToDo.md
··· 36 36 - ~~renomer le block index-list.webt en navigation.webt~~ 37 37 - ~~Ajouter gestion d'une ligne "name: mon nom" pour le block navigation~~ 38 38 - ~~Ajouter l'indentation des items dans le block navigation~~ 39 - - Pourquoi VSCode me remet les pages de templates en HTML pour le Language Mode alors que je spécifie Handlebars ? Comment forcer Handlebars 39 + - ~~Pourquoi VSCode me remet les pages de templates en HTML pour le Language Mode alors que je spécifie Handlebars ? Comment forcer Handlebars~~ 40 40 - Pouvoir spécifier un template pour une entrée 41 41 - **EN COURS** - commencer un site webette pour la documentation webette 42 42 - Plugin webette de TOC (sommaire, table des matières)
+1 -1
docs/helpers.md
··· 17 17 {{#if (in "posts" site.collections)}}...{{/if}} {{!-- enters block if "posts" exists --}} 18 18 {{first entry.blocks}} {{!-- first block object --}} 19 19 {{firstBlockOfType entry.blocks "image"}} {{!-- first image block or "" --}} 20 - {{renderLayout "layout/post.html"}} {{!-- renders the post layout with current context --}} 20 + {{renderLayout "post"}} {{!-- renders the post layout with current context --}} 21 21 ``` 22 22 23 23 ## Strings / text
+8 -8
docs/project-vision.md
··· 34 34 index.md 35 35 templates/ 36 36 wrapper/ 37 - wrapper.html 37 + wrapper.hbs 38 38 layout/ 39 - post.html 40 - page.html 39 + post.hbs 40 + page.hbs 41 41 partial/ 42 - header.html 43 - footer.html 42 + header.hbs 43 + footer.hbs 44 44 ``` 45 45 46 46 Webette must work immediately: ··· 84 84 85 85 collections: { 86 86 posts: { 87 - layout: "post.html", 88 - listLayout: "blog-index.html", 87 + layout: "post.hbs", 88 + listLayout: "blog-index.hbs", 89 89 }, 90 90 pages: { 91 - layout: "page.html", 91 + layout: "page.hbs", 92 92 routing: "root", // /pages/index -> / 93 93 }, 94 94 },
+3 -3
docs/site-config.md
··· 46 46 root: "_templates", 47 47 custom: { 48 48 index: { 49 - root: "layout/index-root.html", 50 - collections: "layout/index-collection.html", 49 + root: "layout/index-root.hbs", 50 + collections: "layout/index-collection.hbs", 51 51 collection: { 52 - posts: "layout/index-posts.html" 52 + posts: "layout/index-posts.hbs" 53 53 } 54 54 } 55 55 },
+10 -10
docs/templates.md
··· 6 6 7 7 - Tool defaults are configured in `webette.tool.ts` (`templates.root` and `templates.default.*`). 8 8 - The renderer looks first under the site root (`<site>/<templates.root>/...`), then falls back to the tool (`process.cwd()` + `templates.root`). 9 - - Folder structure: `wrapper/` for the wrapper, `layout/` for layouts (registered as partials), `partial/` for classic partials (e.g. `templates/partial/header.hbs` -> `{{> header}}`). `layout/index.html` is the default index layout used for root/collection listings when index generation is enabled. `layout/access-forbidden.html` is the default layout used to render forbidden placeholders in asset folders. `layout/not-found.html` is the default layout used to render the static `404.html`. 9 + - Folder structure: `wrapper/` for the wrapper, `layout/` for layouts (registered as partials), `partial/` for classic partials (e.g. `templates/partial/header.hbs` -> `{{> header}}`). `layout/index.hbs` is the default index layout used for root/collection listings when index generation is enabled. `layout/access-forbidden.hbs` is the default layout used to render forbidden placeholders in asset folders. `layout/not-found.hbs` is the default layout used to render the static `404.html`. 10 10 - Helper: the wrapper calls `{{{renderLayout layoutName}}}` which resolves the layout (partial) by name; `layoutName` defaults to `templates.default.layout`. 11 11 12 12 ## Template syntax ··· 34 34 35 35 ## Default wrapper + layout 36 36 37 - - The fallback wrapper (`templates/wrapper/wrapper.html`) envelopes the page and delegates the body to a layout via `renderLayout`. 38 - - The fallback layout (`templates/layout/post.html`) renders an entry (title, markdown/text/image/audio/video blocks) and shows a simple draft badge when `entry.isDraft` is `true`. 39 - - The fallback index layout (`templates/layout/index.html`) renders the root or collection listings (simple links + counters). 40 - - The fallback access-forbidden layout (`templates/layout/access-forbidden.html`) renders minimal "Access forbidden" pages in asset folders. 41 - - The fallback not-found layout (`templates/layout/not-found.html`) renders the static `404.html` page. 37 + - The fallback wrapper (`templates/wrapper/wrapper.hbs`) envelopes the page and delegates the body to a layout via `renderLayout`. 38 + - The fallback layout (`templates/layout/post.hbs`) renders an entry (title, markdown/text/image/audio/video blocks) and shows a simple draft badge when `entry.isDraft` is `true`. 39 + - The fallback index layout (`templates/layout/index.hbs`) renders the root or collection listings (simple links + counters). 40 + - The fallback access-forbidden layout (`templates/layout/access-forbidden.hbs`) renders minimal "Access forbidden" pages in asset folders. 41 + - The fallback not-found layout (`templates/layout/not-found.hbs`) renders the static `404.html` page. 42 42 43 43 Sites can override wrapper and layouts by dropping their files under `<site>/<templates.root>/wrapper/...` and `<site>/<templates.root>/layout/...`; resolution order is site > tool. 44 44 If the site config does not declare `templates.root`, or if the directory is missing, Webette logs a warning and falls back to tool templates. If a site omits any `templates.default.*` key, Webette logs a warning and falls back to the tool defaults for that key. ··· 51 51 templates: { 52 52 root: "_templates", 53 53 default: { 54 - index: "layout/index.html" 54 + index: "layout/index.hbs" 55 55 }, 56 56 custom: { 57 57 index: { 58 - root: "layout/index-root.html", 59 - collections: "layout/index-collection.html", 58 + root: "layout/index-root.hbs", 59 + collections: "layout/index-collection.hbs", 60 60 collection: { 61 - posts: "layout/index-posts.html" 61 + posts: "layout/index-posts.hbs" 62 62 } 63 63 } 64 64 }
+5 -5
docs/tool-config.md
··· 29 29 templates: { 30 30 root: "templates", 31 31 default: { 32 - wrapper: "wrapper/wrapper.html", 33 - layout: "layout/post.html", 34 - index: "layout/index.html", 35 - notFound: "layout/not-found.html", 36 - accessForbidden: "layout/access-forbidden.html", 32 + wrapper: "wrapper/wrapper.hbs", 33 + layout: "layout/post.hbs", 34 + index: "layout/index.hbs", 35 + notFound: "layout/not-found.hbs", 36 + accessForbidden: "layout/access-forbidden.hbs", 37 37 }, 38 38 }, 39 39 images: {
+5 -5
src/config/env.ts
··· 144 144 templates: { 145 145 root: "templates", 146 146 default: { 147 - wrapper: "wrapper/wrapper.html", 148 - layout: "layout/post.html", 149 - index: "layout/index.html", 150 - notFound: "layout/not-found.html", 151 - accessForbidden: "layout/access-forbidden.html", 147 + wrapper: "wrapper/wrapper.hbs", 148 + layout: "layout/post.hbs", 149 + index: "layout/index.hbs", 150 + notFound: "layout/not-found.hbs", 151 + accessForbidden: "layout/access-forbidden.hbs", 152 152 }, 153 153 }, 154 154 markdown: {
+2
src/core/template.ts
··· 90 90 const entries = await readdir(partialsDir, { withFileTypes: true }); 91 91 for (const entry of entries) { 92 92 if (!entry.isFile()) continue; 93 + if (path.extname(entry.name).toLowerCase() !== ".hbs") continue; 93 94 const name = path.parse(entry.name).name; 94 95 const partialPath = path.join(partialsDir, entry.name); 95 96 const source = await readFile(partialPath, "utf8"); ··· 112 113 const entries = await readdir(layoutsDir, { withFileTypes: true }); 113 114 for (const entry of entries) { 114 115 if (!entry.isFile()) continue; 116 + if (path.extname(entry.name).toLowerCase() !== ".hbs") continue; 115 117 const name = path.parse(entry.name).name; 116 118 const layoutPath = path.join(layoutsDir, entry.name); 117 119 const source = await readFile(layoutPath, "utf8");
+2 -2
templates/layout/access-forbidden.html templates/layout/access-forbidden.hbs
··· 1 1 <h1>Access forbidden</h1> 2 - <p>Sorry, you can't be here 🖤</p> 3 - <p><a href="/">← Back to site</a></p> 2 + <p>Sorry, you can't be here.</p> 3 + <p><a href="/">← Back to site</a></p>
+30
templates/layout/index.hbs
··· 1 + <h1>{{site.title}}</h1> 2 + 3 + {{#if collection}} 4 + <h2>Collection: {{collection.name}}</h2> 5 + <p>{{entries.length}} entries</p> 6 + <ul> 7 + <li><a href="/">← Back to root</a></li> 8 + {{#each entries}} 9 + <li> 10 + <a href="{{route}}">{{name}}</a> 11 + ({{blocks.length}} 12 + blocks) 13 + </li> 14 + {{/each}} 15 + </ul> 16 + {{else}} 17 + <h2>Collections</h2> 18 + <ul> 19 + {{#each collections}} 20 + <li> 21 + <a href="{{route}}">{{name}}</a> 22 + ({{entries.length}} 23 + entries) 24 + </li> 25 + {{/each}} 26 + </ul> 27 + {{/if}} 28 + 29 + <p>Last build: {{formatDate buildTime dateStyle="long"}}</p> 30 + <p>Last update: {{formatDate site.updatedAt dateStyle="long"}}</p>
-28
templates/layout/index.html
··· 1 - <h1>{{site.title}}</h1> 2 - 3 - {{#if collection}} 4 - <h2>Collection: {{collection.name}}</h2> 5 - <p>{{entries.length}} entries</p> 6 - <ul> 7 - <li><a href="/">← Back to root</a></li> 8 - {{#each entries}} 9 - <li> 10 - <a href="{{route}}">{{name}}</a> 11 - ({{blocks.length}} blocks) 12 - </li> 13 - {{/each}} 14 - </ul> 15 - {{else}} 16 - <h2>Collections</h2> 17 - <ul> 18 - {{#each collections}} 19 - <li> 20 - <a href="{{route}}">{{name}}</a> 21 - ({{entries.length}} entries) 22 - </li> 23 - {{/each}} 24 - </ul> 25 - {{/if}} 26 - 27 - <p>Last build: {{formatDate buildTime dateStyle="long"}}</p> 28 - <p>Last update: {{formatDate site.updatedAt dateStyle="long"}}</p>
+2 -4
templates/layout/not-found.html templates/layout/not-found.hbs
··· 7 7 8 8 <main> 9 9 <p>We could not find the page you requested.</p> 10 - <p> 11 - <a href="/">Go back to the homepage</a> 12 - </p> 13 - </main> 10 + <p><a href="/">Go back to the homepage</a></p> 11 + </main>
+37
templates/layout/post.hbs
··· 1 + {{> header}} 2 + 3 + <main> 4 + <article> 5 + <h2>{{entry.name}}</h2> 6 + 7 + {{#if entry.isDraft}} 8 + <p class="draft-badge">Brouillon (non publié)</p> 9 + {{/if}} 10 + 11 + {{#each entry.blocks}} 12 + {{#if (eq type "markdown")}} 13 + {{{safe content.html}}} 14 + {{else if (eq type "text")}} 15 + <pre>{{content.raw}}</pre> 16 + {{else if (eq type "image")}} 17 + {{#unless content.meta.renderedInline}} 18 + <figure> 19 + <img src="{{route}}" alt="{{name}}" /> 20 + <figcaption>{{name}}</figcaption> 21 + </figure> 22 + {{/unless}} 23 + {{else if (eq type "audio")}} 24 + <audio controls src="{{route}}"></audio> 25 + {{else if (eq type "video")}} 26 + <video controls src="{{route}}"></video> 27 + {{/if}} 28 + {{/each}} 29 + 30 + {{#if entry.pluginNote}} 31 + <p>Plugin: <em>{{entry.pluginNote}}</em></p> 32 + {{/if}} 33 + </article> 34 + </main> 35 + 36 + {{> footer}} 37 +
-26
templates/layout/post.html
··· 1 - {{> header}} 2 - 3 - <main> 4 - <article> 5 - <h2>{{entry.name}}</h2> 6 - {{#if entry.isDraft}} 7 - <p class="draft-badge">Brouillon (non publié)</p> 8 - {{/if}} {{#each entry.blocks}} {{#if (eq type "markdown")}} {{{safe 9 - content.html}}} {{else if (eq type "text")}} 10 - <pre>{{content.raw}}</pre> 11 - {{else if (eq type "image")}} {{#unless content.meta.renderedInline}} 12 - <figure> 13 - <img src="{{route}}" alt="{{name}}" /> 14 - <figcaption>{{name}}</figcaption> 15 - </figure> 16 - {{/unless}} {{else if (eq type "audio")}} 17 - <audio controls src="{{route}}"></audio> 18 - {{else if (eq type "video")}} 19 - <video controls src="{{route}}"></video> 20 - {{/if}} {{/each}} {{#if entry.pluginNote}} 21 - <p>Plugin: <em>{{entry.pluginNote}}</em></p> 22 - {{/if}} 23 - </article> 24 - </main> 25 - 26 - {{> footer}}
+1 -1
templates/partial/footer.html templates/partial/footer.hbs
··· 1 1 <footer> 2 2 <p>Site generated by Webette</p> 3 - </footer> 3 + </footer>
+3 -3
templates/partial/header.html templates/partial/header.hbs
··· 2 2 <h1>{{site.title}}</h1> 3 3 <nav> 4 4 {{#if collection.route}} 5 - <a href="{{collection.route}}">← Back to collection</a> 5 + <a href="{{collection.route}}">← Back to collection</a> 6 6 {{else}} 7 - <a href="/">← Back to index</a> 7 + <a href="/">← Back to index</a> 8 8 {{/if}} 9 9 </nav> 10 10 <h3>Collection: {{collection.name}}</h3> 11 - </header> 11 + </header>
+13
templates/wrapper/wrapper.hbs
··· 1 + <html lang="{{site.lang}}"> 2 + <head> 3 + <meta charset="utf-8" /> 4 + <title> 5 + {{#if entry}}{{entry.name}} - {{site.title}}{{else}}{{site.title}}{{/if}} 6 + </title> 7 + </head> 8 + <body> 9 + {{{renderLayout layoutName}}} 10 + 11 + {{{liveReloadScript}}} 12 + </body> 13 + </html>
-12
templates/wrapper/wrapper.html
··· 1 - <!DOCTYPE html> 2 - <html lang="{{site.lang}}"> 3 - <head> 4 - <meta charset="utf-8" /> 5 - <title>{{#if entry}}{{entry.name}} — {{site.title}}{{else}}{{site.title}}{{/if}}</title> 6 - </head> 7 - <body> 8 - {{{renderLayout layoutName}}} 9 - 10 - {{{liveReloadScript}}} 11 - </body> 12 - </html>
+5 -5
webette.tool.ts
··· 25 25 templates: { 26 26 root: "templates", // default templates folder 27 27 default: { 28 - wrapper: "wrapper/wrapper.html", // default wrapper 29 - layout: "layout/post.html", // default layout 30 - index: "layout/index.html", // default index layout 31 - notFound: "layout/not-found.html", // default 404 layout 32 - accessForbidden: "layout/access-forbidden.html", // default forbidden layout 28 + wrapper: "wrapper/wrapper.hbs", // default wrapper 29 + layout: "layout/post.hbs", // default layout 30 + index: "layout/index.hbs", // default index layout 31 + notFound: "layout/not-found.hbs", // default 404 layout 32 + accessForbidden: "layout/access-forbidden.hbs", // default forbidden layout 33 33 }, 34 34 }, 35 35 images: {
+2 -2
website-example/_templates/layout/access-forbidden.html website-example/_templates/layout/access-forbidden.hbs
··· 1 1 <h1>Access forbidden</h1> 2 - <p>Sorry, you can't be here 🖤</p> 3 - <p><a href="/">← Back to site</a></p> 2 + <p>Sorry, you can't be here.</p> 3 + <p><a href="/">← Back to site</a></p>
+1 -1
website-example/_templates/layout/index-collection.html website-example/_templates/layout/index-collection.hbs
··· 5 5 <p>{{collection.name}}</p> 6 6 <ul> 7 7 {{#each entries}} 8 - <li><a href="{{route}}">{{name}}</a></li> 8 + <li><a href="{{route}}">{{name}}</a></li> 9 9 {{/each}} 10 10 </ul> 11 11 </main>
+1 -1
website-example/_templates/layout/index-posts.html website-example/_templates/layout/index-posts.hbs
··· 5 5 <p>Specific layout for the posts collection.</p> 6 6 <ol> 7 7 {{#each entries}} 8 - <li><a href="{{route}}">{{name}}</a></li> 8 + <li><a href="{{route}}">{{name}}</a></li> 9 9 {{/each}} 10 10 </ol> 11 11 </main>
+1 -1
website-example/_templates/layout/index-root.html website-example/_templates/layout/index-root.hbs
··· 5 5 <p>Custom root index layout.</p> 6 6 <ul> 7 7 {{#each collections}} 8 - <li><a href="{{route}}">{{name}}</a> ({{entries.length}})</li> 8 + <li><a href="{{route}}">{{name}}</a> ({{entries.length}})</li> 9 9 {{/each}} 10 10 </ul> 11 11 </main>
+18
website-example/_templates/layout/index.hbs
··· 1 + {{> header}} 2 + 3 + <h2>Site index</h2> 4 + <p>You can browse all collections and entries of this demo site.</p> 5 + <ul> 6 + {{#each collections}} 7 + <li> 8 + <strong>{{name}}</strong> 9 + <ul> 10 + {{#each entries}} 11 + <li><a href="{{route}}">{{name}}</a></li> 12 + {{/each}} 13 + </ul> 14 + </li> 15 + {{/each}} 16 + </ul> 17 + 18 + {{> footer}}
-18
website-example/_templates/layout/index.html
··· 1 - {{> header}} 2 - 3 - <h2>Site index</h2> 4 - <p>You can browse all collections and entries of this demo site.</p> 5 - <ul> 6 - {{#each collections}} 7 - <li> 8 - <strong>{{name}}</strong> 9 - <ul> 10 - {{#each entries}} 11 - <li><a href="{{route}}">{{name}}</a></li> 12 - {{/each}} 13 - </ul> 14 - </li> 15 - {{/each}} 16 - </ul> 17 - 18 - {{> footer}}
website-example/_templates/layout/not-found.html website-example/_templates/layout/not-found.hbs
+43
website-example/_templates/layout/post.hbs
··· 1 + {{> header}} 2 + 3 + <main> 4 + <article> 5 + {{#if entry.isDraft}} 6 + <p class="draft-badge">Draft (unpublished)</p> 7 + {{/if}} 8 + 9 + {{#each entry.blocks}} 10 + {{#if (eq type "markdown")}} 11 + {{{safe content.html}}} 12 + {{else if (eq type "text")}} 13 + <pre>{{content.raw}}</pre> 14 + {{else if (eq type "image")}} 15 + {{#unless content.meta.renderedInline}} 16 + {{image this figure=true caption=name class="my-class"}} 17 + {{/unless}} 18 + {{else if (eq type "audio")}} 19 + <audio controls src="{{route}}"></audio> 20 + {{else if (eq type "video")}} 21 + <video controls src="{{route}}"></video>s 22 + {{else if (eq type "navigation")}} 23 + {{#if content.data.items}} 24 + <section class="navigation"> 25 + {{#if content.data.name}} 26 + <h2 class="navigation-title">{{content.data.name}}</h2> 27 + {{/if}} 28 + 29 + {{> navigation-items items=content.data.items}} 30 + </section> 31 + {{/if}} 32 + {{/if}} 33 + {{/each}} 34 + 35 + {{#if entry.pluginNote}} 36 + <p> 37 + Plugin: <em>{{entry.pluginNote}}</em> 38 + </p> 39 + {{/if}} 40 + </article> 41 + </main> 42 + 43 + {{> footer}}
-28
website-example/_templates/layout/post.html
··· 1 - {{> header}} 2 - 3 - <main> 4 - <article> 5 - {{#if entry.isDraft}} 6 - <p class="draft-badge">Draft (unpublished)</p> 7 - {{/if}} {{#each entry.blocks}} {{#if (eq type "markdown")}} {{{safe 8 - content.html}}} {{else if (eq type "text")}} 9 - <pre>{{content.raw}}</pre> 10 - {{else if (eq type "image")}} {{#unless content.meta.renderedInline}} 11 - {{image this figure=true caption=name class="my-class"}} {{/unless}} {{else 12 - if (eq type "audio")}} 13 - <audio controls src="{{route}}"></audio> 14 - {{else if (eq type "video")}} 15 - <video controls src="{{route}}"></video> 16 - {{else if (eq type "navigation")}} {{#if content.data.items}} 17 - <section class="navigation"> 18 - {{#if content.data.name}} 19 - <h2 class="navigation-title">{{content.data.name}}</h2> 20 - {{/if}} {{> navigation-items items=content.data.items}} 21 - </section> 22 - {{/if}} {{/if}} {{/each}} {{#if entry.pluginNote}} 23 - <p>Plugin: <em>{{entry.pluginNote}}</em></p> 24 - {{/if}} 25 - </article> 26 - </main> 27 - 28 - {{> footer}}
+1 -1
website-example/_templates/partial/footer.html website-example/_templates/partial/footer.hbs
··· 1 1 <footer> 2 2 <p>Site generated by webette</p> 3 - </footer> 3 + </footer>
+26
website-example/_templates/partial/header.hbs
··· 1 + <header class="site-header"> 2 + <div class="brand"> 3 + <img 4 + class="logo" 5 + src="{{asset 'images/bebette.svg'}}" 6 + alt="Bebette logo" 7 + width="48" 8 + height="48" 9 + /> 10 + <div class="brand-text"> 11 + <h1>{{site.title}}</h1> 12 + <p class="tagline">Some examples of webette capabilities</p> 13 + </div> 14 + </div> 15 + 16 + {{#if collection}} 17 + <nav class="site-nav"> 18 + <a href="/">← Back to index</a> 19 + </nav> 20 + 21 + <h3 class="collection-name">Collection: {{collection.name}}</h3> 22 + {{#if entry}} 23 + <h3 class="entry-name">Entry: {{entry.name}}</h3> 24 + {{/if}} 25 + {{/if}} 26 + </header>
-20
website-example/_templates/partial/header.html
··· 1 - <header class="site-header"> 2 - <div class="brand"> 3 - <img class="logo" src="{{asset "images/bebette.svg"}}" alt="Bebette logo" 4 - width="48" height="48" /> 5 - <div class="brand-text"> 6 - <h1>{{site.title}}</h1> 7 - <p class="tagline">Some examples of webette capabilities</p> 8 - </div> 9 - </div> 10 - {{#if collection}} 11 - <nav class="site-nav"> 12 - <a href="/">← Back to index</a> 13 - </nav> 14 - 15 - <h3 class="collection-name">Collection: {{collection.name}}</h3> 16 - {{#if entry}} 17 - <h3 class="entry-name">Entry: {{entry.name}}</h3> 18 - {{/if}} 19 - {{/if}} 20 - </header>
+41
website-example/_templates/partial/navigation-items.hbs
··· 1 + <ul class="navigation-list"> 2 + {{#each items}} 3 + <li class="navigation-item navigation-item--{{ kind }}"> 4 + {{#if (eq kind "title")}} 5 + <span class="navigation-heading">{{ title }}</span> 6 + {{else if (eq kind "collection")}} 7 + <a href="{{ collection.route }}"> 8 + {{#if title}}{{ title }}{{else}}{{ collection.name }}{{/if}} 9 + </a> 10 + 11 + {{#if collection.description}} 12 + <div class="collection-description">{{{nl2br collection.description}}}</div> 13 + {{/if}} 14 + 15 + {{#if collection.assets}} 16 + <div class="collection-assets"> 17 + {{#each collection.assets}} 18 + {{#if (eq type "image")}} 19 + {{image this class="collection-asset" variant="small"}} 20 + {{else if (eq type "audio")}} 21 + <audio controls src="{{ route }}"></audio> 22 + {{else if (eq type "video")}} 23 + <video controls src="{{ route }}"></video> 24 + {{/if}} 25 + {{/each}} 26 + </div> 27 + {{/if}} 28 + {{else if (eq kind "entry")}} 29 + <a href="{{ entry.route }}"> 30 + {{#if title}}{{ title }}{{else}}{{ entry.name }}{{/if}} 31 + {{#if (match entry.route "#([^#]+)$")}}, #{{match entry.route "#([^#]+)$"}}{{/if}} 32 + </a> 33 + <span class="navigation-entry-meta">(collection: {{ collection.name }})</span> 34 + {{/if}} 35 + 36 + {{#if children}} 37 + {{> navigation-items items=children}} 38 + {{/if}} 39 + </li> 40 + {{/each}} 41 + </ul>
-30
website-example/_templates/partial/navigation-items.html
··· 1 - <ul class="navigation-list"> 2 - {{#each items}} 3 - <li class="navigation-item navigation-item--{{kind}}"> 4 - {{#if (eq kind "title")}} 5 - <span class="navigation-heading">{{title}}</span> 6 - {{else if (eq kind "collection")}} 7 - <a href="{{collection.route}}">{{#if title}}{{title}}{{else}}{{collection.name}}{{/if}}</a> 8 - {{#if collection.description}} 9 - <div class="collection-description"> 10 - {{{nl2br collection.description}}} 11 - </div> 12 - {{/if}} {{#if collection.assets}} 13 - <div class="collection-assets"> 14 - {{#each collection.assets}} {{#if (eq type "image")}} {{image this 15 - class="collection-asset" variant="small"}} {{else if (eq type "audio")}} 16 - <audio controls src="{{route}}"></audio> 17 - {{else if (eq type "video")}} 18 - <video controls src="{{route}}"></video> 19 - {{/if}} {{/each}} 20 - </div> 21 - {{/if}} 22 - {{else if (eq kind "entry")}} 23 - <a href="{{entry.route}}">{{#if title}}{{title}}{{else}}{{entry.name}}{{/if}}{{#if 24 - (match entry.route "#([^#]+)$")}}, #{{match entry.route 25 - "#([^#]+)$"}}{{/if}}</a> 26 - <span class="navigation-entry-meta">(collection: {{collection.name}})</span> 27 - {{/if}} {{#if children}} {{> navigation-items items=children}} {{/if}} 28 - </li> 29 - {{/each}} 30 - </ul>
+14
website-example/_templates/wrapper/wrapper.hbs
··· 1 + <html lang="{{site.lang}}"> 2 + <head> 3 + <meta charset="utf-8" /> 4 + <link rel="stylesheet" href="{{asset 'css/init.css'}}" /> 5 + <link rel="stylesheet" href="{{asset 'css/style.css'}}" /> 6 + <title> 7 + {{#if entry}}{{entry.name}} - {{site.title}}{{else}}{{site.title}}{{/if}} 8 + </title> 9 + </head> 10 + <body> 11 + {{{renderLayout layoutName}}} 12 + {{{liveReloadScript}}} 13 + </body> 14 + </html>
-14
website-example/_templates/wrapper/wrapper.html
··· 1 - <!DOCTYPE html> 2 - <html lang="{{site.lang}}"> 3 - <head> 4 - <meta charset="utf-8" /> 5 - <link rel="stylesheet" href="{{asset "css/init.css"}}" /> <link 6 - rel="stylesheet" href="{{asset "css/style.css"}}" /> 7 - <title> 8 - {{#if entry}}{{entry.name}} — {{site.title}}{{else}}{{site.title}}{{/if}} 9 - </title> 10 - </head> 11 - <body> 12 - {{{renderLayout layoutName}}} {{{liveReloadScript}}} 13 - </body> 14 - </html>
+8 -8
website-example/webette.config.ts
··· 31 31 publicBase: "/assets", 32 32 }, 33 33 default: { 34 - wrapper: "wrapper/wrapper.html", 35 - layout: "layout/post.html", 36 - index: "layout/index.html", 37 - notFound: "layout/not-found.html", 38 - accessForbidden: "layout/access-forbidden.html", 34 + wrapper: "wrapper/wrapper.hbs", 35 + layout: "layout/post.hbs", 36 + index: "layout/index.hbs", 37 + notFound: "layout/not-found.hbs", 38 + accessForbidden: "layout/access-forbidden.hbs", 39 39 }, 40 40 custom: { 41 41 index: { 42 - root: "layout/index-root.html", 43 - collections: "layout/index-collection.html", 42 + root: "layout/index-root.hbs", 43 + collections: "layout/index-collection.hbs", 44 44 collection: { 45 - posts: "layout/index-posts.html", 45 + posts: "layout/index-posts.hbs", 46 46 }, 47 47 }, 48 48 },