├── .env-sample ├── .github └── dependabot.yml ├── .gitignore ├── LICENSE ├── README.md ├── config ├── collections.js ├── cssFormat.js ├── filters.js ├── jsFormat.js ├── markdown.js ├── passthroughCopy.js ├── transforms.js └── utils │ └── format-date.js ├── eleventy.config.js ├── netlify.toml ├── package-lock.json ├── package.json ├── process ├── generate-favicons.js └── new-post.js └── src ├── 404.webc ├── _components ├── article-footer.webc ├── article-meta.webc ├── author-picture.webc ├── auto-toc.webc ├── back-to-top.webc ├── block-quote.webc ├── copy-right.webc ├── date-time.webc ├── image-md.webc ├── main-nav.webc ├── page-footer.webc ├── page-header.webc ├── pagination-navigation.webc ├── posts-list.webc ├── previous-next.webc ├── series-listing.webc └── social-contact.webc ├── _data └── meta.js ├── _layouts ├── article.webc ├── base.webc └── page.webc ├── assets ├── images │ ├── TV.jpg │ ├── _favicons-source │ │ └── favicon.jpg │ ├── bird.jpg │ └── favicons │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon-180x180.png │ │ ├── favicon-32x32.png │ │ └── favicon.ico ├── js │ └── index.js └── style │ ├── blocks │ ├── auto-toc.css │ ├── buttons.css │ ├── card.css │ ├── home-author-section.css │ ├── image.css │ ├── main-nav.css │ ├── page-footer.css │ ├── page-header.css │ ├── post-list.css │ ├── prism-okaidia.css │ ├── series-listing.css │ └── top-button.css │ ├── global.css │ ├── index.css │ ├── reset.css │ └── utilities │ ├── anchors.css │ ├── flex.css │ ├── flow.css │ ├── utils.css │ └── wrapper.css ├── feed.njk ├── manifest.webc ├── pages ├── about.webc ├── awesome.webc ├── blog.11tydata.js ├── blog.webc ├── home.webc └── pages.11tydata.js ├── posts ├── loving-care.md ├── peace-in-the-city.md ├── post-one.md ├── posts.11tydata.js └── war-in-the-world.md ├── robots.webc ├── sitemap.webc ├── tags.11tydata.js └── tags.webc /.env-sample: -------------------------------------------------------------------------------- 1 | SITE_URL=https://www.domain.com -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 2 | 3 | version: 2 4 | updates: 5 | - package-ecosystem: "npm" 6 | directory: "/" 7 | schedule: 8 | interval: "weekly" 9 | ignore: 10 | - dependency-name: "markdown-it" 11 | versioning-strategy: increase 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | # Eleventy 107 | _site/ 108 | 109 | # Eleventy serverless 110 | netlify/functions/dynamic/** 111 | !netlify/functions/dynamic/index.js 112 | 113 | # Local Netlify folder 114 | .netlify -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webc-starter-kit 2 | A starter project for [Eleventy](https://www.11ty.dev/) (11ty) using [WebC](https://www.11ty.dev/docs/languages/webc/) as a main template langage. Also includes opiniated assets processing and a few more bells and whistles. 3 | 4 | This is really a blog stater project, but can be adapted to other means. I entend to use this as a base for my futur projects. 5 | 6 | ## How to use 7 | Webc starter kit is a template repository. The "Use this template" button can be used to create a new repo with the same structure (recommended). [More details](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template). When this is done: 8 | 9 | 1. Clone the newly created repo. 10 | 2. Navigate to the directory. 11 | 3. Install dependencies. 12 | 4. Run one of these command. 13 | * Local developpment: `npm start`. 14 | * [Netlify cli](https://www.netlify.com/products/cli/): `npm run dev`. 15 | * Build for production: `npm run build`. 16 | * Remove *_site* and start fresh: `npm run clean`. 17 | * Debug: `npm run debug`. 18 | * Generate favicons from an image: `npm run generate-favicons`. 19 | * Create a new post template: `npm run new-post "My Title"`. 20 | 21 | ## Features 22 | * RSS feed through Atom. 23 | * Sitemap with *robot.txt* pointing to it. 24 | * Site manifest. 25 | * Tags pages. 26 | * Series for posts. 27 | * Table of contents for posts. 28 | * Back to top button. 29 | * UNSTABLE: draft feature for posts. This feature prevents production build to complete. See [#59](https://github.com/11ty/eleventy-plugin-webc/issues/59). 30 | * JS pipeline with [esbuild](https://esbuild.github.io/). 31 | * CSS pipeline with [Lightning CSS](https://lightningcss.dev/). 32 | * Image optimization with [eleventy-img](https://www.11ty.dev/docs/plugins/image/). 33 | * [Serverless](https://www.11ty.dev/docs/plugins/serverless/): uncomment in config file to use. 34 | * Custom 404 page at the root. May require specific integration depending on your hosting setup/platform. 35 | * Already setup for [Netlify dev](https://www.netlify.com/products/cli/) and specific configuration through *netlify.toml*. 36 | * Automation for favicons and new post generation. 37 | * Minifying HTML, CSS and JavaScript in production. 38 | * Comprehensive meta data file to configure site's parameters in one place. 39 | 40 | ## Site's meta data 41 | Located in *src/_data/meta.js*. Exports an object used to set defaults and configure functional templates (sitemap, RSS, etc.). 42 | 43 | ## Components 44 | Most components live in the *src/_components* directory. These are authored components and are globally available. There are a few external components as well which are also made globally available through *eleventy.config.js*. 45 | ### author-picture.webc 46 | * Output: `` or `` 47 | * Attributes: any compatible with `` (public) 48 | * Details: uses <[eleventy-image](https://github.com/11ty/eleventy-img/blob/main/eleventy-image.webc)> to process `src`. Any public attributes will be added to the output. `width`, `sizes`, `class="image"` and `decoding="async"` are preset. Outputs `avif`, `webp` and `jpeg` formats to *_site/images*. Used in article. 49 | * Usage: 50 | ```html 51 | 56 | 57 | ``` 58 | 59 | ### image-md.webc 60 | * Output: `` or `` 61 | * Attributes: any compatible with `` (public) 62 | * Details: same as *author-picture.webc*, but with different configuration `width` and `sizes`. Generally used troughout the site. 63 | * Usage: 64 | ```html 65 | 66 | ``` 67 | ### auto-toc.webc 68 | * ouput: 69 | ```html 70 |
71 | Contents 72 | 82 |
83 | ``` 84 | * Attributes: 85 | * `open`: used with a thruty value, it will set the boolean `open` attribute on the `details` element. [Read more about the open attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details#attributes). 86 | * Details: uses [markdown-it-toc-done-right](https://github.com/nagaozen/markdown-it-toc-done-right#readme) under the hood. Works only in markdown files. 87 | * Usage: 88 | ```html 89 | 90 | ``` 91 | ### copy-right.webc 92 | 93 | 94 | ## Pages 95 | Pages are located in the *pages* directory. Excepting the "Home" page, all pages are remapped to project's root and inherit from the *page.webc* layout. The *home.webc* page is remapped to project's root index. The following properties may be defined in front matter: 96 | * `title` -> document title and first heading (`

`). 97 | * `description` -> document description. 98 | * `lang` -> ``'s `lang` attribute value. 99 | * `navigation` -> Object. Takes an `order` (number) and a `label` (string) properties which defines ordering and text display in site's main navigation. 100 | 101 | ## Config: `eleventy.config.js` 102 | The *eleventy.config.js* config file is located at the project's root. The config file uses the `addPlugin` method to import the different parts of configuration which all lives in the *config* folder (except for external plugins). Here's a sample of the config object. 103 | ```js 104 | return { 105 | dir: { 106 | input: "src", 107 | output: "_site", 108 | includes: "_includes", 109 | layouts: "_layouts", 110 | data: "_data" 111 | }, 112 | pathPrefix: "/", 113 | htmlTemplateEngine: "webc", 114 | markdownTemplateEngine: "webc", 115 | templateFormats: ["njk", "liquid", "html", "md", "11ty.js", "webc"] 116 | }; 117 | ``` 118 | ## Plugins 119 | Webc starter kit uses several plugins. 120 | ### Official plugins 121 | * [eleventy-plugin-rss](https://www.11ty.dev/docs/plugins/rss/) 122 | * [eleventy-plugin-syntaxhighlight](https://www.11ty.dev/docs/plugins/syntaxhighlight/) 123 | * [eleventy-plugin-webc](https://www.11ty.dev/docs/languages/webc/) 124 | * [eleventy-img](https://www.11ty.dev/docs/plugins/image/) 125 | * [eleventy-serverless](https://www.11ty.dev/docs/plugins/serverless/) 126 | ### Markdown plugins 127 | * [markdown-it-anchor](https://www.npmjs.com/package/markdown-it-anchor) 128 | * [markdown-it-toc-done-right](https://www.npmjs.com/package/markdown-it-toc-done-right) 129 | * [markdown-it-attrs](https://www.npmjs.com/package/markdown-it-attrs) 130 | * [markdown-it-eleventy-img](https://www.npmjs.com/package/markdown-it-eleventy-img) 131 | ## Collections 132 | Collections included in Webc starter kit. 133 | ### `posts` collection 134 | Contains every `.md` files living in the *posts* directory. Reversed order. Intended for blog posts. 135 | ### `pages` collection 136 | Contains every `.webc` files living in the *pages* directory. Ordered ascending by the `navigation.order` property. These represents the pages of the site. 137 | ### `series` collection 138 | Consist of an object containing all series grouped by name. Only markdown file inside of the *posts* directory and containig a `series` property with a string value (the name of the series). Falsy values will be exluded. 139 | ### `tags` collection 140 | A deduplicated list of all posts tags. Used to generate tags pages. 141 | ## Generator scripts 142 | Located in the *process* directory. These are utility node scripts 143 | 144 | Work in progress... -------------------------------------------------------------------------------- /config/collections.js: -------------------------------------------------------------------------------- 1 | /** @param {import("@11ty/eleventy").UserConfig} config */ 2 | 3 | module.exports = function(config) { 4 | config.addCollection("posts", (collection) => { 5 | const posts = collection.getFilteredByGlob("./src/posts/*.md"); 6 | return posts.reverse(); 7 | }); 8 | config.addCollection("pages", (collection) => { 9 | const pages = collection.getFilteredByGlob("./src/pages/*.webc"); 10 | return pages.sort((a, b) => a.data.navigation.order - b.data.navigation.order); 11 | }); 12 | config.addCollection("series", (collection) => { 13 | const posts = collection.getFilteredByGlob("./src/posts/*.md"); 14 | return posts.reduce((obj, post) => { 15 | if(!post.data.series) return obj; 16 | if(!obj[post.data.series]) obj[post.data.series] = []; 17 | 18 | obj[post.data.series].push(post); 19 | return obj; 20 | }, {}); 21 | }); 22 | config.addCollection("tags", (collection) => { 23 | const posts = collection.getFilteredByGlob("./src/posts/*.md"); 24 | const tagSet = posts.reduce((set, template) => { 25 | if(template.data.tags) { 26 | template.data.tags.forEach((tag) => set.add(tag)); 27 | } 28 | return set; 29 | }, new Set()); 30 | return [...tagSet]; 31 | }); 32 | }; -------------------------------------------------------------------------------- /config/cssFormat.js: -------------------------------------------------------------------------------- 1 | const browserslist = require("browserslist"); 2 | const { bundle, browserslistToTargets } = require("lightningcss"); 3 | const cssIndex = "./src/assets/style/index.css"; 4 | 5 | module.exports = function(config) { 6 | config.addTemplateFormats("css"); 7 | 8 | config.addExtension("css", { 9 | outputFileExtension: "css", 10 | compile(inputContent, inputPath) { 11 | 12 | if(inputPath !== cssIndex) return; 13 | 14 | return (data) => bundle({ 15 | filename: inputPath, 16 | minify: data.meta.isProduction, 17 | targets: browserslistToTargets(browserslist(data.pkg.browserslist)), 18 | drafts: { 19 | nesting: true 20 | } 21 | }).code; 22 | } 23 | }); 24 | }; -------------------------------------------------------------------------------- /config/filters.js: -------------------------------------------------------------------------------- 1 | const { formatDateUtc } = require("./utils/format-date"); 2 | 3 | function normalize(value, defaultValue) { 4 | // Taken from: https://github.com/mozilla/nunjucks/blob/master/nunjucks/src/filters.js#L8 5 | if(value === null || value === undefined || value === false) { 6 | return defaultValue; 7 | } 8 | return value; 9 | }; 10 | 11 | module.exports = function(config) { 12 | config.addFilter("readableDate", function(date, format = "YYYY-MM-DD") { 13 | return formatDateUtc(format, date); 14 | }); 15 | 16 | config.addFilter("truncate", function(input, length, killwords, end) { 17 | // Taken from (slightly modified): https://github.com/mozilla/nunjucks/blob/master/nunjucks/src/filters.js#L522 18 | input = normalize(input, ""); 19 | length = length || 60; 20 | 21 | if(input.length <= length) { 22 | return input; 23 | } 24 | 25 | if(killwords) { 26 | input = input.substring(0, length); 27 | } else { 28 | let idx = input.lastIndexOf(" ", length); 29 | if (idx === -1) { 30 | idx = length; 31 | } 32 | 33 | input = input.substring(0, idx); 34 | } 35 | 36 | input += (end !== undefined && end !== null) ? end : "..."; 37 | return input; 38 | }); 39 | 40 | config.addFilter("wordcount", function(str) { 41 | // Taken from (slightly modified): https://github.com/mozilla/nunjucks/blob/master/nunjucks/src/filters.js#L620 42 | str = normalize(str, ""); 43 | const words = str ? str.match(/\w+/g) : null; 44 | return words ? words.length : 0; 45 | }); 46 | 47 | config.addFilter("striptags", function(input, preserveLinebreaks) { 48 | // Taken from (slightly modified): https://github.com/mozilla/nunjucks/blob/master/nunjucks/src/filters.js#L489 49 | input = normalize(input, ""); 50 | let tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>|/gi; 51 | let trimmedInput = input.replace(tags, '').trim(); 52 | let res = ""; 53 | if (preserveLinebreaks) { 54 | res = trimmedInput 55 | .replace(/^ +| +$/gm, '') // remove leading and trailing spaces 56 | .replace(/ +/g, ' ') // squash adjacent spaces 57 | .replace(/(\r\n)/g, '\n') // normalize linebreaks (CRLF -> LF) 58 | .replace(/\n\n\n+/g, '\n\n'); // squash abnormal adjacent linebreaks 59 | } else { 60 | res = trimmedInput.replace(/\s+/gi, " "); 61 | } 62 | return res; 63 | }); 64 | }; -------------------------------------------------------------------------------- /config/jsFormat.js: -------------------------------------------------------------------------------- 1 | const esbuild = require("esbuild"); 2 | const jsIndex = "./src/assets/js/index.js"; 3 | 4 | module.exports = function(config) { 5 | config.addTemplateFormats("js"); 6 | 7 | config.addExtension("js", { 8 | outputFileExtension: "js", 9 | compile(inputContent, inputPath) { 10 | 11 | if(inputPath !== jsIndex) return; 12 | 13 | return async (data) => { 14 | const output = await esbuild.build({ 15 | entryPoints: [inputPath], 16 | bundle: true, 17 | format: "esm", 18 | target: "es6", 19 | minify: data.meta.isProduction, 20 | write: false 21 | }); 22 | 23 | return output.outputFiles[0].text; 24 | }; 25 | } 26 | }); 27 | }; -------------------------------------------------------------------------------- /config/markdown.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const markdownIt = require("markdown-it"); 3 | const markdownItAnchor = require("markdown-it-anchor"); 4 | const markdownItTocDoneRight = require("markdown-it-toc-done-right"); 5 | const markdownItAttrs = require("markdown-it-attrs"); 6 | const markdownItEleventyImg = require("markdown-it-eleventy-img"); 7 | const uslugify = require("uslug"); 8 | 9 | module.exports = function(config) { 10 | config.setLibrary("md", markdownIt ({ 11 | html: true, 12 | breaks: true, 13 | linkify: true 14 | }) 15 | .use(markdownItAnchor, { 16 | slugify: uslugify, 17 | permalink: markdownItAnchor.permalink.headerLink({ 18 | safariReaderFix: true, 19 | class: "reset-anchor" 20 | }), 21 | level: [2, 3] 22 | }) 23 | .use(markdownItTocDoneRight, { 24 | slugify: uslugify, 25 | listType: "ul", 26 | level: [2, 3], 27 | containerClass: "auto-toc" 28 | }) 29 | .use(markdownItAttrs) 30 | .use(markdownItEleventyImg, { 31 | imgOptions: { 32 | widths: [600, 450, 300], 33 | urlPath: "/images/", 34 | outputDir: path.join("_site", "images"), 35 | formats: ["avif", "webp", "jpeg"] 36 | }, 37 | globalAttributes: { 38 | class: "image markdown-image", 39 | decoding: "async", 40 | sizes: "(max-width: 48rem) 300px, (max-width: 62rem) 450px, 600px" 41 | } 42 | })); 43 | }; -------------------------------------------------------------------------------- /config/passthroughCopy.js: -------------------------------------------------------------------------------- 1 | const meta = require("../src/_data/meta"); 2 | 3 | module.exports = function(config) { 4 | config.setServerPassthroughCopyBehavior("passthrough"); 5 | 6 | config.addPassthroughCopy({ [meta.favicon.temp]: meta.favicon.dest }); 7 | }; -------------------------------------------------------------------------------- /config/transforms.js: -------------------------------------------------------------------------------- 1 | const { isProduction } = require("../src/_data/meta"); 2 | const htmlmin = require("html-minifier-terser"); 3 | 4 | module.exports = function(config) { 5 | config.addTransform("htmlmin", function(content) { 6 | if(this.page.outputPath && this.page.outputPath.endsWith(".html") && isProduction) { 7 | return htmlmin.minify(content, { 8 | collapseBooleanAttributes: true, 9 | collapseWhitespace: true, 10 | decodeEntities: true, 11 | includeAutoGeneratedTags: false, 12 | removeComments: true, 13 | minifyCSS: true, 14 | minifyJS: true 15 | }); 16 | } 17 | 18 | return content; 19 | }); 20 | }; -------------------------------------------------------------------------------- /config/utils/format-date.js: -------------------------------------------------------------------------------- 1 | const dayjs = require("dayjs"); 2 | const utc = require("dayjs/plugin/utc"); 3 | dayjs.extend(utc); 4 | 5 | function formatDateUtc(format, date) { 6 | return dayjs.utc(date).format(format); 7 | }; 8 | 9 | function formatDateLocal(format, date) { 10 | return dayjs(date).format(format); 11 | }; 12 | 13 | module.exports = { 14 | formatDateUtc, 15 | formatDateLocal 16 | }; -------------------------------------------------------------------------------- /eleventy.config.js: -------------------------------------------------------------------------------- 1 | /** @param {import("@11ty/eleventy").UserConfig} config */ 2 | 3 | const { EleventyRenderPlugin, EleventyServerlessBundlerPlugin } = require("@11ty/eleventy"); 4 | 5 | module.exports = function(config) { 6 | config.addPlugin(EleventyRenderPlugin); 7 | /* 8 | config.addPlugin(EleventyServerlessBundlerPlugin, { 9 | name: "dynamic", 10 | functionsDir: "./netlify/functions/", 11 | }); 12 | */ 13 | config.addPlugin(require("@11ty/eleventy-plugin-rss")); 14 | config.addPlugin(require("@11ty/eleventy-plugin-syntaxhighlight")); 15 | config.addPlugin(require("@11ty/eleventy-plugin-webc"), { 16 | components: [ 17 | "src/_components/**/*.webc", 18 | "./node_modules/@11ty/eleventy-plugin-syntaxhighlight/syntax-highlight.webc", 19 | "npm:@11ty/eleventy-img/*.webc" 20 | ] 21 | }); 22 | config.addPlugin(require("@11ty/eleventy-img").eleventyImagePlugin, { 23 | urlPath: "/images/", 24 | outputDir: "_site/images", 25 | formats: ["avif", "webp", "jpeg"], 26 | defaultAttributes: { 27 | decoding: "async" 28 | } 29 | }); 30 | config.addPlugin(require("./config/markdown")); 31 | config.addPlugin(require("./config/collections")); 32 | config.addPlugin(require("./config/filters")); 33 | config.addPlugin(require("./config/transforms")); 34 | config.addPlugin(require("./config/cssFormat")); 35 | config.addPlugin(require("./config/jsFormat")); 36 | config.addPlugin(require("./config/passthroughCopy")); 37 | 38 | config.setWatchJavaScriptDependencies(false); 39 | 40 | return { 41 | dir: { 42 | input: "src", 43 | output: "_site", 44 | includes: "_includes", 45 | layouts: "_layouts", 46 | data: "_data" 47 | }, 48 | pathPrefix: "/", 49 | htmlTemplateEngine: "webc", 50 | markdownTemplateEngine: "webc", 51 | templateFormats: ["njk", "liquid", "html", "md", "11ty.js", "webc"] 52 | }; 53 | }; -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | publish = "_site" 3 | command = "npm run build" 4 | 5 | [dev] 6 | command = "npm start" 7 | 8 | [functions] 9 | node_bundler = "esbuild" 10 | 11 | [[headers]] 12 | for = "/*" 13 | 14 | [headers.values] 15 | Content-Security-Policy = "default-src 'self'; frame-ancestors 'self'; form-action 'self'; style-src 'self' 'unsafe-inline'" 16 | Strict-Transport-Security = "max-age=63072000; includeSubDomains; preload" 17 | X-Frame-Options = "SAMEORIGIN" 18 | X-XSS-Protection = "1; mode=block" 19 | X-Content-Type-Options = "nosniff" 20 | Referrer-Policy = "no-referrer" 21 | Permissions-Policy = "autoplay=(), camera=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), publickey-credentials-get=()" 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webc-starter-kit", 3 | "description": "A starter project for Eleventy (11ty) using WebC as a main template langage. Also includes opiniated assets processing and a few more bells and whistles.", 4 | "version": "0.1.0", 5 | "main": "eleventy.config.js", 6 | "scripts": { 7 | "start": "npx @11ty/eleventy --serve", 8 | "dev": "npx netlify dev", 9 | "clean": "rm -rf _site", 10 | "generate-favicons": "node process/generate-favicons.js", 11 | "new-post": "node process/new-post.js", 12 | "debug": "DEBUG=Eleventy* npx @11ty/eleventy", 13 | "build": "PRODUCTION=true npx @11ty/eleventy" 14 | }, 15 | "browserslist": [ 16 | "defaults" 17 | ], 18 | "dependencies": { 19 | "@11ty/eleventy": "^2.0.1", 20 | "@11ty/eleventy-fetch": "^4.0.0", 21 | "@11ty/eleventy-img": "^3.1.0", 22 | "@11ty/eleventy-plugin-rss": "^1.2.0", 23 | "@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0", 24 | "@11ty/eleventy-plugin-webc": "^0.11.1", 25 | "@11ty/is-land": "^4.0.0", 26 | "@toycode/markdown-it-class": "^1.2.4", 27 | "browserslist": "^4.21.5", 28 | "dayjs": "^1.11.7", 29 | "esbuild": "^0.17.18", 30 | "favicons": "^7.1.2", 31 | "html-minifier-terser": "^7.2.0", 32 | "lightningcss": "^1.20.0", 33 | "markdown-it": "^13.0.1", 34 | "markdown-it-anchor": "^8.6.7", 35 | "markdown-it-attrs": "^4.1.6", 36 | "markdown-it-eleventy-img": "^0.10.1", 37 | "markdown-it-toc-done-right": "^4.2.0", 38 | "netlify-cli": "^14.3.1", 39 | "uslug": "^1.0.4" 40 | }, 41 | "repository": { 42 | "type": "git", 43 | "url": "git+https://github.com/solution-loisir/webc-starter-kit.git" 44 | }, 45 | "keywords": [ 46 | "Eleventy", 47 | "11ty", 48 | "WebC", 49 | "ssg" 50 | ], 51 | "author": "Mathieu Huot", 52 | "license": "Apache-2.0", 53 | "bugs": { 54 | "url": "https://github.com/solution-loisir/webc-starter-kit/issues" 55 | }, 56 | "homepage": "https://github.com/solution-loisir/webc-starter-kit#readme" 57 | } 58 | -------------------------------------------------------------------------------- /process/generate-favicons.js: -------------------------------------------------------------------------------- 1 | const { favicons } = require("favicons"); 2 | const fs = require("fs/promises"); 3 | const path = require("path"); 4 | const meta = require("../src/_data/meta"); 5 | 6 | const source = meta.favicon.source; 7 | 8 | const configuration = { 9 | path: meta.favicon.temp 10 | }; 11 | 12 | (async function generateFavicons() { 13 | const response = await favicons(source, configuration); 14 | await fs.mkdir(configuration.path, { recursive: true }); 15 | 16 | await Promise.all( 17 | response.images.map(async (image) => { 18 | switch(image.name) { 19 | case "favicon.ico": 20 | case "favicon-32x32.png": 21 | case "android-chrome-192x192.png": 22 | case "android-chrome-512x512.png": 23 | case "apple-touch-icon-180x180.png": 24 | await fs.writeFile(path.join(configuration.path, image.name), image.contents); 25 | } 26 | }) 27 | ); 28 | console.log(`Favicons have been generated to ${configuration.path}!`); 29 | })(); -------------------------------------------------------------------------------- /process/new-post.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | const slug = require("../node_modules/@11ty/eleventy/src/Filters/Slug"); 4 | const title = process.argv[2]; 5 | const fileName = slug(title); 6 | const filePath = path.join("./src/posts/", fileName + ".md"); 7 | const { formatDateLocal } = require("../config/utils/format-date"); 8 | const data = `--- 9 | title: ${title} 10 | description: "" 11 | date: ${formatDateLocal("YYYY-MM-DD")} 12 | updated: false 13 | lang: en 14 | published: false 15 | series: "" 16 | toc: false 17 | top_button: false 18 | og_image: "" 19 | og_image_alt: "" 20 | og_image_width: "" 21 | og_image_height: "" 22 | tags: "" 23 | --- 24 | 25 | 26 | `; 27 | 28 | try { 29 | fs.accessSync(filePath); 30 | } catch(error) { 31 | fs.writeFileSync(filePath, data); 32 | console.log(`Created ${fileName} post!`); 33 | return; 34 | }; 35 | 36 | console.log(`${filePath} already exist.`); -------------------------------------------------------------------------------- /src/404.webc: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page.webc 3 | title: 404 not found 4 | dynamicPermalink: false 5 | permalink: "404.html" 6 | --- -------------------------------------------------------------------------------- /src/_components/article-footer.webc: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
-------------------------------------------------------------------------------- /src/_components/article-meta.webc: -------------------------------------------------------------------------------- 1 |
    2 |
  • Published on:
  • 3 |
  • Updated on:
  • 4 | 5 |
  • 6 |
  • 7 |
-------------------------------------------------------------------------------- /src/_components/author-picture.webc: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

Author:

5 |

6 | 9 |
10 |
-------------------------------------------------------------------------------- /src/_components/auto-toc.webc: -------------------------------------------------------------------------------- 1 |
2 | Contents 3 | 4 | [toc] 5 |
-------------------------------------------------------------------------------- /src/_components/back-to-top.webc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/_components/block-quote.webc: -------------------------------------------------------------------------------- 1 |
2 | 3 |

Source :

4 |
-------------------------------------------------------------------------------- /src/_components/copy-right.webc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/_components/date-time.webc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/_components/image-md.webc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/_components/main-nav.webc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/_components/page-footer.webc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/_components/page-header.webc: -------------------------------------------------------------------------------- 1 |
2 | WebC 🎈 3 | 4 |
-------------------------------------------------------------------------------- /src/_components/pagination-navigation.webc: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/_components/posts-list.webc: -------------------------------------------------------------------------------- 1 |
    2 | 41 |
-------------------------------------------------------------------------------- /src/_components/previous-next.webc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/_components/series-listing.webc: -------------------------------------------------------------------------------- 1 |
2 |

series!

3 | 8 |
-------------------------------------------------------------------------------- /src/_components/social-contact.webc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/_data/meta.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | module.exports = { 4 | url: process.env.SITE_URL || "http://localhost:8080", 5 | canonical(pathBase) { 6 | return path.join(this.url, pathBase); 7 | }, 8 | isProduction: Boolean(process.env.PRODUCTION), 9 | title: "WebC starter kit", 10 | subtitle: "A kit to start with WebC!", 11 | description: "A starter project for Eleventy (11ty) using WebC as a main template langage. Also includes opiniated assets processing and a few more bells and whistles.", 12 | display: "fullscreen", 13 | tagsLimit: 4, 14 | author: { 15 | name: "My Name", 16 | image: { 17 | src: "./src/assets/images/bird.jpg", 18 | alt: "Eagle as profile picture" 19 | }, 20 | description: "A brief description of me as an author.", 21 | contact: { 22 | email: { 23 | label: "Email", 24 | icon: '', 25 | link: "mailto:my@email.com" 26 | }, 27 | twitter: { 28 | label: "Twitter", 29 | icon: '', 30 | link: "https://twitter.com/@my_twitter_handle" 31 | }, 32 | mastodon: { 33 | label: "Mastodon", 34 | icon: '', 35 | link: "https://mastodon.social/@mymastodonhandle" 36 | }, 37 | github: { 38 | label: "GitHub", 39 | icon: '', 40 | link: "https://github.com/my-user-name-5599" 41 | } 42 | } 43 | }, 44 | favicon: { 45 | source: "src/assets/images/_favicons-source/favicon.jpg", 46 | temp: "src/assets/images/favicons/", 47 | dest: "/" 48 | }, 49 | color: { 50 | theme: "#000", 51 | background: "#fff" 52 | }, 53 | og: { 54 | type: "website", 55 | image: { 56 | src: "", 57 | alt: "", 58 | width: "1200", 59 | height: "600" 60 | } 61 | }, 62 | rss: { 63 | label: "RSS feed", 64 | icon: '', 65 | link: "/feed.xml" 66 | }, 67 | top: { 68 | label: "Back to top", 69 | icon: '', 70 | link: "#top" 71 | } 72 | }; -------------------------------------------------------------------------------- /src/_layouts/article.webc: -------------------------------------------------------------------------------- 1 | --- 2 | layout: base.webc 3 | --- 4 |
5 |
6 |
7 |

8 | 15 | 16 |
17 | 18 |
19 | 20 |
21 |
-------------------------------------------------------------------------------- /src/_layouts/base.webc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/_layouts/page.webc: -------------------------------------------------------------------------------- 1 | --- 2 | layout: base.webc 3 | --- 4 |
5 |

6 |

7 |
8 |
-------------------------------------------------------------------------------- /src/assets/images/TV.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solution-loisir/webc-starter-kit/efc5170a336e65425ec9a32a81277d1bfaeca69f/src/assets/images/TV.jpg -------------------------------------------------------------------------------- /src/assets/images/_favicons-source/favicon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solution-loisir/webc-starter-kit/efc5170a336e65425ec9a32a81277d1bfaeca69f/src/assets/images/_favicons-source/favicon.jpg -------------------------------------------------------------------------------- /src/assets/images/bird.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solution-loisir/webc-starter-kit/efc5170a336e65425ec9a32a81277d1bfaeca69f/src/assets/images/bird.jpg -------------------------------------------------------------------------------- /src/assets/images/favicons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solution-loisir/webc-starter-kit/efc5170a336e65425ec9a32a81277d1bfaeca69f/src/assets/images/favicons/android-chrome-192x192.png -------------------------------------------------------------------------------- /src/assets/images/favicons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solution-loisir/webc-starter-kit/efc5170a336e65425ec9a32a81277d1bfaeca69f/src/assets/images/favicons/android-chrome-512x512.png -------------------------------------------------------------------------------- /src/assets/images/favicons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solution-loisir/webc-starter-kit/efc5170a336e65425ec9a32a81277d1bfaeca69f/src/assets/images/favicons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /src/assets/images/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solution-loisir/webc-starter-kit/efc5170a336e65425ec9a32a81277d1bfaeca69f/src/assets/images/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /src/assets/images/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solution-loisir/webc-starter-kit/efc5170a336e65425ec9a32a81277d1bfaeca69f/src/assets/images/favicons/favicon.ico -------------------------------------------------------------------------------- /src/assets/js/index.js: -------------------------------------------------------------------------------- 1 | /* Add global JavaSript below! */ -------------------------------------------------------------------------------- /src/assets/style/blocks/auto-toc.css: -------------------------------------------------------------------------------- 1 | .contents { 2 | background-color: var(--color-light-blue); 3 | margin-block-end: var(--size-400); 4 | padding-inline: var(--padding-sm); 5 | padding-block: var(--size-200); 6 | border-radius: var(--radius); 7 | } 8 | 9 | .contents ul { 10 | margin-block: 0; 11 | padding-inline-start: var(--padding-sm); 12 | } -------------------------------------------------------------------------------- /src/assets/style/blocks/buttons.css: -------------------------------------------------------------------------------- 1 | .button { 2 | padding-block: var(--size-100); 3 | padding-inline: var(--size-300); 4 | background-color: var(--color-primary-transparent); 5 | border: 2px solid var(--color-primary-darker); 6 | border-radius: var(--radius-pill); 7 | text-decoration: none; 8 | color: var(--color-light); 9 | min-width: 15ch; 10 | text-align: center; 11 | } 12 | 13 | .button:active { 14 | background-color: var(--color-primary-darker); 15 | } 16 | 17 | .button.button-primary { 18 | background-color: var(--color-primary-transparent); 19 | border: 2px solid var(--color-primary-darker); 20 | color: var(--color-light); 21 | } 22 | 23 | .button.button-primary:active { 24 | background-color: var(--color-primary-darker); 25 | } 26 | 27 | .button.button-accent { 28 | background-color: var(--color-accent-transparent); 29 | border: 2px solid var(--color-accent-darker); 30 | color: var(--color-dark); 31 | } 32 | 33 | .button.button-accent:active { 34 | background-color: var( --color-accent-darker); 35 | } -------------------------------------------------------------------------------- /src/assets/style/blocks/card.css: -------------------------------------------------------------------------------- 1 | .card { 2 | padding-block: var(--size-300); 3 | padding-inline: var(--size-400); 4 | background-color: var(--color-light-accent); 5 | outline: 2.5px dashed var(--color-accent); 6 | border-radius: var(--radius-pill); 7 | max-width: 30ch; 8 | } 9 | 10 | .card img { 11 | border-radius: var(--radius); 12 | } -------------------------------------------------------------------------------- /src/assets/style/blocks/home-author-section.css: -------------------------------------------------------------------------------- 1 | .home-author-section { 2 | background: #0052cc; 3 | background: var(--gradient-primary); 4 | margin-block-end: -3.9rem; 5 | min-height: 450px; 6 | color: var(--color-light); 7 | } 8 | 9 | .home-author-section img { 10 | border-radius: var(--radius-round); 11 | } 12 | 13 | .home-author-section a { 14 | color: var(--color-light); 15 | } -------------------------------------------------------------------------------- /src/assets/style/blocks/image.css: -------------------------------------------------------------------------------- 1 | .image { 2 | border-radius: var(--radius); 3 | box-shadow: 2px 2px 6px -2px hwb(216 5% 85%); 4 | } -------------------------------------------------------------------------------- /src/assets/style/blocks/main-nav.css: -------------------------------------------------------------------------------- 1 | .main-nav a[aria-current="page"] { 2 | text-decoration: underline; 3 | } -------------------------------------------------------------------------------- /src/assets/style/blocks/page-footer.css: -------------------------------------------------------------------------------- 1 | .page-footer { 2 | background-color: var(--color-gray); 3 | } -------------------------------------------------------------------------------- /src/assets/style/blocks/page-header.css: -------------------------------------------------------------------------------- 1 | .page-header { 2 | display: flex; 3 | flex-wrap: wrap; 4 | justify-content: space-around; 5 | align-items: center; 6 | row-gap: var(--size-300); 7 | column-gap: var(--size-900); 8 | padding-block: var(--padding-sm); 9 | padding-inline: var(--padding-md); 10 | box-shadow: 3px 3px 10px -3px #d3d8de; 11 | } -------------------------------------------------------------------------------- /src/assets/style/blocks/post-list.css: -------------------------------------------------------------------------------- 1 | .post-list > li { 2 | padding-inline: var(--padding-sm); 3 | padding-block: var(--padding-md); 4 | flex: 1 1 25ch; 5 | outline: 2.5px dashed var(--color-primary); 6 | border-radius: var(--radius-pill); 7 | background-color: var(--color-light-blue); 8 | display: flex; 9 | flex-direction: column; 10 | justify-content: space-between; 11 | gap: var(--size-400); 12 | } 13 | 14 | .post-list__tags ul { 15 | row-gap: var(--size-100); 16 | column-gap: var(--size-200); 17 | } -------------------------------------------------------------------------------- /src/assets/style/blocks/prism-okaidia.css: -------------------------------------------------------------------------------- 1 | /** 2 | * okaidia theme for JavaScript, CSS and HTML 3 | * Loosely based on Monokai textmate theme by http://www.monokai.nl/ 4 | * @author ocodia 5 | */ 6 | 7 | code[class*="language-"], 8 | pre[class*="language-"] { 9 | color: #f8f8f2; 10 | background: none; 11 | text-shadow: 0 1px rgba(0, 0, 0, 0.3); 12 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 13 | font-size: 1em; 14 | text-align: left; 15 | white-space: pre; 16 | word-spacing: normal; 17 | word-break: normal; 18 | word-wrap: normal; 19 | line-height: 1.5; 20 | 21 | -moz-tab-size: 2; 22 | -o-tab-size: 2; 23 | tab-size: 2; 24 | 25 | -webkit-hyphens: none; 26 | -moz-hyphens: none; 27 | -ms-hyphens: none; 28 | hyphens: none; 29 | } 30 | 31 | /* Code blocks */ 32 | pre[class*="language-"] { 33 | padding: 1em; 34 | /*margin: .5em 0;*/ 35 | overflow: auto; 36 | /*border-radius: 0.3em;*/ 37 | border-radius: var(--radius); 38 | } 39 | 40 | @media(max-width: 64ch) { 41 | pre[class*="language-"] { 42 | margin-inline: -7.5vw; 43 | border-radius: 0; 44 | padding-inline: 2em; 45 | } 46 | } 47 | 48 | :not(pre) > code[class*="language-"], 49 | pre[class*="language-"] { 50 | background: #272822; 51 | } 52 | 53 | /* Inline code */ 54 | :not(pre) > code[class*="language-"] { 55 | padding: .1em; 56 | border-radius: .3em; 57 | white-space: normal; 58 | } 59 | 60 | .token.comment, 61 | .token.prolog, 62 | .token.doctype, 63 | .token.cdata { 64 | color: slategray; 65 | } 66 | 67 | .token.punctuation { 68 | color: #f8f8f2; 69 | } 70 | 71 | .token.namespace { 72 | opacity: .7; 73 | } 74 | 75 | .token.property, 76 | .token.tag, 77 | .token.constant, 78 | .token.symbol, 79 | .token.deleted { 80 | color: #f92672; 81 | } 82 | 83 | .token.boolean, 84 | .token.number { 85 | color: #ae81ff; 86 | } 87 | 88 | .token.selector, 89 | .token.attr-name, 90 | .token.string, 91 | .token.char, 92 | .token.builtin, 93 | .token.inserted { 94 | color: #a6e22e; 95 | } 96 | 97 | .token.operator, 98 | .token.entity, 99 | .token.url, 100 | .language-css .token.string, 101 | .style .token.string, 102 | .token.variable { 103 | color: #f8f8f2; 104 | } 105 | 106 | .token.atrule, 107 | .token.attr-value, 108 | .token.function, 109 | .token.class-name { 110 | color: #e6db74; 111 | } 112 | 113 | .token.keyword { 114 | color: #66d9ef; 115 | } 116 | 117 | .token.regex, 118 | .token.important { 119 | color: #fd971f; 120 | } 121 | 122 | .token.important, 123 | .token.bold { 124 | font-weight: bold; 125 | } 126 | .token.italic { 127 | font-style: italic; 128 | } 129 | 130 | .token.entity { 131 | cursor: help; 132 | } -------------------------------------------------------------------------------- /src/assets/style/blocks/series-listing.css: -------------------------------------------------------------------------------- 1 | .series-listing > p { 2 | font-size: var(--size-700); 3 | background: var(--webkit-gradient-primary); 4 | background-clip: text; 5 | -webkit-background-clip: text; 6 | -webkit-text-fill-color: transparent; 7 | } 8 | 9 | .series-listing a[aria-current="page"] { 10 | background-color: #fbcbcf; 11 | border-radius: var(--radius); 12 | } -------------------------------------------------------------------------------- /src/assets/style/blocks/top-button.css: -------------------------------------------------------------------------------- 1 | .top-button { 2 | display: block; 3 | position: fixed; 4 | right: var(--size-500); 5 | bottom: var(--size-400); 6 | z-index: 999; 7 | opacity: 0; 8 | } 9 | 10 | @media(max-width: 64ch) { 11 | .top-button { 12 | right: 0; 13 | } 14 | } 15 | 16 | .opacity-increase { 17 | animation-name: opacity-increase; 18 | animation-duration: 0.5s; 19 | animation-timing-function: linear; 20 | animation-delay: 0; 21 | animation-fill-mode: forwards; 22 | animation-direction: alternate; 23 | animation-iteration-count: 1; 24 | } 25 | 26 | .opacity-decrease { 27 | animation-name: opacity-decrease; 28 | animation-duration: 0.5s; 29 | animation-timing-function: linear; 30 | animation-delay: 0; 31 | animation-fill-mode: forwards; 32 | animation-direction: alternate; 33 | animation-iteration-count: 1; 34 | } 35 | 36 | @keyframes opacity-increase { 37 | 0% {opacity: 0;} 38 | 20% {opacity: 0.3;} 39 | 40% {opacity: 0.5;} 40 | 60% {opacity: 0.7;} 41 | 80% {opacity: 0.9;} 42 | 100% {opacity: 1;} 43 | } 44 | 45 | @keyframes opacity-decrease { 46 | 0% {opacity: 1;} 47 | 20% {opacity: 0.9;} 48 | 40% {opacity: 0.7;} 49 | 60% {opacity: 0.5;} 50 | 80% {opacity: 0.3;} 51 | 100% {opacity: 0;} 52 | } -------------------------------------------------------------------------------- /src/assets/style/global.css: -------------------------------------------------------------------------------- 1 | /* 2 | Breakpoints 3 | xs: 25rem -> ~400px 4 | sm: 36rem -> ~576px 5 | md: 48rem -> ~768px 6 | lg: 62rem -> ~992px 7 | xl: 80rem -> ~1280px 8 | */ 9 | 10 | :root { 11 | /* Colors */ 12 | --color-primary: hwb(216 0% 20%); 13 | --color-primary-darker: hwb(216 0% 30%); 14 | --color-primary-transparent: hwb(216 0% 20% / 0.8); 15 | --color-accent: hwb(357 35% 1%); 16 | --color-accent-darker: hwb(357 35% 31%); 17 | --color-accent-transparent: hwb(357 35% 1% / 0.8); 18 | --color-light-accent: hwb(357 90% 0%); 19 | --color-dark: hwb(216 0% 98%); 20 | --color-light: hwb(216 98% 0%); 21 | --color-light-blue: hwb(216 90% 0%); 22 | --color-gray: hwb(216 83% 13%); 23 | --color-white: #fff; 24 | --gradient-primary: linear-gradient(180deg, hwb(216 0% 20%) 0%, hwb(216 0% 25%) 12.5%, hwb(216 0% 29%) 25%, hwb(216 0% 35%) 37.5%, hwb(216 0% 39%) 50%, hwb(216 0% 44%) 62.5%, hwb(216 0% 44%) 75%, hwb(216 0% 39%) 87.5%, hwb(216 0% 35%) 100%); 25 | --webkit-gradient-primary: -webkit-linear-gradient(180deg, hwb(216 0% 20%) 0%, hwb(216 0% 25%) 12.5%, hwb(216 0% 29%) 25%, hwb(357 35% 35%) 37.5%, hwb(216 0% 39%) 50%, hwb(357 35% 44%) 62.5%, hwb(357 35% 44%) 75%, hwb(357 35% 39%) 87.5%, hwb(216 0% 35%) 100%); 26 | /* Sizes */ 27 | --size-font-base: 112.5%; 28 | --size-100: 0.2rem; 29 | --size-200: 0.5rem; 30 | --size-300: 0.8rem; 31 | --size-400: 1rem; 32 | --size-500: 1.2rem; 33 | --size-600: 1.4rem; 34 | --size-700: 1.7rem; 35 | --size-800: 2rem; 36 | --size-900: 2.4rem; 37 | --size-1200: 3.9rem; 38 | /* Padding */ 39 | --padding-sm: var(--size-500); 40 | --padding-md: var(--size-600); 41 | --padding-lg: var(--size-700); 42 | --padding-xl: var(--size-900); 43 | --padding-xxl: var(--size-1200); 44 | /* Measures */ 45 | --width-md: min(65ch, 85vw); 46 | /* Border radius */ 47 | --radius: 7px; 48 | --radius-pill: 1em; 49 | --radius-round: 50%; 50 | } 51 | 52 | html { 53 | font-size: var(--size-font-base); 54 | } 55 | 56 | body { 57 | font-family: Helvetica, Arial, sans-serif; 58 | color: var(--color-dark); 59 | background-color: var(--color-light); 60 | overflow-x: hidden; 61 | } 62 | 63 | p + p { 64 | margin-block-start: var(--size-300); 65 | } 66 | 67 | h1 { 68 | font-size: var(--size-1200); 69 | } 70 | 71 | h2 { 72 | font-size: var(--size-900); 73 | } 74 | 75 | h3 { 76 | font-size: var(--size-700); 77 | } 78 | 79 | h4 { 80 | font-size: var(--size-500); 81 | } 82 | 83 | h1, 84 | h2, 85 | h3, 86 | h4 { 87 | font-family: Helvetica, Arial, sans-serif; 88 | line-height: 1.2; 89 | margin-block-start: var(--size-700); 90 | } 91 | 92 | :target { 93 | scroll-margin-top: var(--size-300); 94 | } 95 | 96 | main { 97 | display: block; 98 | min-height: 100vh; 99 | } 100 | 101 | a { 102 | display: inline-block; 103 | } 104 | 105 | [role="list"] { 106 | margin-block: 0; 107 | padding-inline-start: 0; 108 | } 109 | 110 | hr { 111 | border: 0; 112 | border-bottom: 2.5px dashed var(--color-primary); 113 | } 114 | 115 | article blockquote { 116 | margin-block: 1em; 117 | padding-block: 1em; 118 | padding-inline: 2em; 119 | border-inline-start: 20px solid var(--color-primary); 120 | border-start-end-radius: 1em; 121 | border-end-end-radius: 1em; 122 | background-color: var(--color-light-blue); 123 | } 124 | 125 | @media(max-width: 64ch) { 126 | article blockquote { 127 | margin-inline: -7.5vw; 128 | border-start-end-radius: 0; 129 | border-end-end-radius: 0; 130 | } 131 | } -------------------------------------------------------------------------------- /src/assets/style/index.css: -------------------------------------------------------------------------------- 1 | @import "reset.css"; 2 | @import "global.css"; 3 | @import "blocks/page-header.css"; 4 | @import "blocks/image.css"; 5 | @import "blocks/auto-toc.css"; 6 | @import "blocks/prism-okaidia.css"; 7 | @import "blocks/post-list.css"; 8 | @import "blocks/main-nav.css"; 9 | @import "blocks/series-listing.css"; 10 | @import "blocks/page-footer.css"; 11 | @import "blocks/card.css"; 12 | @import "blocks/home-author-section.css"; 13 | @import "blocks/top-button.css"; 14 | @import "blocks/buttons.css"; 15 | @import "utilities/wrapper.css"; 16 | @import "utilities/flow.css"; 17 | @import "utilities/utils.css"; 18 | @import "utilities/flex.css"; 19 | @import "utilities/anchors.css"; -------------------------------------------------------------------------------- /src/assets/style/reset.css: -------------------------------------------------------------------------------- 1 | /* [Modified version] hankchizljaw modern-css-reset https://github.com/hankchizljaw/modern-css-reset/blob/master/src/reset.css */ 2 | 3 | /* Box sizing rules */ 4 | *, 5 | *::before, 6 | *::after { 7 | box-sizing: border-box; 8 | } 9 | 10 | /* Remove default margin */ 11 | body, 12 | h1, 13 | h2, 14 | h3, 15 | h4, 16 | p, 17 | figure, 18 | blockquote, 19 | dl, 20 | dd { 21 | margin: 0; 22 | } 23 | 24 | /* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */ 25 | ul[role="list"], 26 | ol[role="list"] { 27 | list-style: none; 28 | } 29 | 30 | /* Set core root defaults */ 31 | html:focus-within { 32 | scroll-behavior: smooth; 33 | } 34 | 35 | /* Set core body defaults */ 36 | body { 37 | min-height: 100vh; 38 | text-rendering: optimizeSpeed; 39 | line-height: 1.5; 40 | } 41 | 42 | /* A elements that don't have a class get default styles */ 43 | a:not([class]) { 44 | text-decoration-skip-ink: auto; 45 | } 46 | 47 | /* Make images easier to work with */ 48 | img, 49 | picture { 50 | max-width: 100%; 51 | display: block; 52 | height: auto; 53 | } 54 | 55 | /* Inherit fonts for inputs and buttons */ 56 | input, 57 | button, 58 | textarea, 59 | select { 60 | font: inherit; 61 | } 62 | 63 | /* Remove all animations and transitions for people that prefer not to see them */ 64 | @media (prefers-reduced-motion: reduce) { 65 | html:focus-within { 66 | scroll-behavior: auto; 67 | } 68 | *, 69 | *::before, 70 | *::after { 71 | animation-duration: 0.01ms !important; 72 | animation-iteration-count: 1 !important; 73 | transition-duration: 0.01ms !important; 74 | scroll-behavior: auto !important; 75 | } 76 | } -------------------------------------------------------------------------------- /src/assets/style/utilities/anchors.css: -------------------------------------------------------------------------------- 1 | .reset-anchor { 2 | color: inherit; 3 | text-decoration: none; 4 | } -------------------------------------------------------------------------------- /src/assets/style/utilities/flex.css: -------------------------------------------------------------------------------- 1 | .flex { 2 | display: flex; 3 | flex-wrap: wrap; 4 | } 5 | 6 | .justify-center { 7 | justify-content: center; 8 | } 9 | 10 | .justify-self-center { 11 | justify-self: center; 12 | } 13 | 14 | .justify-space-around { 15 | justify-content: space-around; 16 | } 17 | 18 | .align-center { 19 | align-items: center; 20 | } 21 | 22 | .align-self-center { 23 | align-self: center; 24 | } 25 | 26 | .flex-column { 27 | flex-direction: column; 28 | } -------------------------------------------------------------------------------- /src/assets/style/utilities/flow.css: -------------------------------------------------------------------------------- 1 | .flow.flow-xs > * + *, 2 | .flow > .flow-xs > * + * { 3 | margin-block-start: var(--size-100); 4 | } 5 | 6 | .flow.flow-sm > * + *, 7 | .flow > .flow-sm > * + * { 8 | margin-block-start: var(--size-200); 9 | } 10 | 11 | .flow > * + *, 12 | .flow > .flow > * + * { 13 | margin-block-start: var(--size-400); 14 | } 15 | 16 | .flow.flow-lg > * + *, 17 | .flow > .flow-lg > * + * { 18 | margin-block-start: var(--size-700); 19 | } 20 | 21 | .flow.flow-xl > * + *, 22 | .flow > .flow-xl > * + * { 23 | margin-block-start: var(--size-900); 24 | } -------------------------------------------------------------------------------- /src/assets/style/utilities/utils.css: -------------------------------------------------------------------------------- 1 | .gap-100 { 2 | gap: var(--size-100); 3 | } 4 | 5 | .gap-200 { 6 | gap: var(--size-200); 7 | } 8 | 9 | .gap-300 { 10 | gap: var(--size-300); 11 | } 12 | 13 | .gap-400 { 14 | gap: var(--size-400); 15 | } 16 | 17 | .bold { 18 | font-weight: 700; 19 | } 20 | 21 | .line-height-xs { 22 | line-height: 0.5; 23 | } 24 | 25 | .line-height-sm { 26 | line-height: 1; 27 | } 28 | 29 | .line-height-md { 30 | line-height: 1.2; 31 | } 32 | 33 | .big { 34 | font-size: var(--size-600); 35 | } 36 | 37 | .small { 38 | font-size: var(--size-300); 39 | } 40 | 41 | .margin-block-0 { 42 | margin-block: 0; 43 | } 44 | 45 | .margin-block-600 { 46 | margin-block: var(--size-600); 47 | } 48 | 49 | .margin-block-1200 { 50 | margin-block: var(--size-1200); 51 | } 52 | 53 | .margin-inline-auto { 54 | margin-inline: auto; 55 | } 56 | 57 | .padding-block-200 { 58 | padding-block: var(--size-200); 59 | } 60 | 61 | .text-center { 62 | text-align: center; 63 | } -------------------------------------------------------------------------------- /src/assets/style/utilities/wrapper.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | margin-inline: auto; 3 | width: var(--width-md); 4 | } 5 | 6 | .wrapper.padding-block-md { 7 | padding-block: var(--padding-md); 8 | } 9 | 10 | .wrapper.padding-block-xxl { 11 | padding-block: var(--padding-xxl); 12 | } 13 | 14 | .wrapper .full-width { 15 | /* https://css-tricks.com/full-width-containers-limited-width-parents/ */ 16 | width: 100vw; 17 | position: relative; 18 | left: 50%; 19 | right: 50%; 20 | margin-left: -50vw; 21 | margin-right: -50vw; 22 | } -------------------------------------------------------------------------------- /src/feed.njk: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyExcludeFromCollections: true 3 | dynamicPermalink: false 4 | permalink: feed.xml 5 | --- 6 | 7 | 8 | {{ meta.title }} 9 | {{ meta.subtitle }} 10 | 11 | 12 | {{ collections.posts | getNewestCollectionItemDate | dateToRfc3339 }} 13 | {{ meta.url }} 14 | 15 | {{ meta.author.name }} 16 | {{ meta.author.contact.email.link }} 17 | 18 | {%- for post in collections.posts %} 19 | {%- if post.url %} 20 | {%- set absolutePostUrl = post.url | absoluteUrl(meta.url) %} 21 | 22 | {{ post.data.title }} 23 | 24 | {{ post.date | dateToRfc3339 }} 25 | {{ absolutePostUrl }} 26 | {{ post.templateContent | htmlToAbsoluteUrls(absolutePostUrl) }} 27 | 28 | {%- endif %} 29 | {%- endfor %} 30 | -------------------------------------------------------------------------------- /src/manifest.webc: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyExcludeFromCollections: true 3 | dynamicPermalink: false 4 | permalink: manifest.json 5 | --- 6 | -------------------------------------------------------------------------------- /src/pages/about.webc: -------------------------------------------------------------------------------- 1 | --- 2 | title: "About" 3 | description: "This page explains what WebC is all about!" 4 | lang: "en" 5 | navigation: 6 | order: 4 7 | label: About 8 | --- -------------------------------------------------------------------------------- /src/pages/awesome.webc: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Awesome List" 3 | description: "The Awesome list." 4 | lang: "en" 5 | navigation: 6 | order: 2 7 | label: Awesome 8 | --- -------------------------------------------------------------------------------- /src/pages/blog.11tydata.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | permalink(data) { 3 | return `blog/${data.pagination.pageNumber ? `page-${data.pagination.pageNumber + 1}/` : ""}`; 4 | } 5 | }; -------------------------------------------------------------------------------- /src/pages/blog.webc: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Blog" 3 | description: "The blog of Webc Starter Kit" 4 | lang: "en" 5 | navigation: 6 | order: 3 7 | label: "Blog" 8 | pagination: 9 | data: collections.posts 10 | size: 8 11 | alias: posts 12 | --- 13 | 14 | -------------------------------------------------------------------------------- /src/pages/home.webc: -------------------------------------------------------------------------------- 1 | --- 2 | description: "The home page of WebC starter kit a starter project for Eleventy (11ty) using WebC as a main template langage. Also includes opiniated assets processing and a few more bells and whistles." 3 | lang: "en" 4 | dynamicPermalink: false 5 | permalink: "/" 6 | navigation: 7 | order: 1 8 | label: Home 9 | --- 10 |
11 |

Most recent posts

12 | 13 |
14 |
15 | View all posts 16 |
17 |
18 |
19 | 20 |

21 | Learn more about the author 22 |
23 |
-------------------------------------------------------------------------------- /src/pages/pages.11tydata.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | layout: "page.webc", 3 | permalink: (data) => `/${data.page.fileSlug}/` 4 | }; -------------------------------------------------------------------------------- /src/posts/loving-care.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Loving Care 3 | description: How to care for others. 4 | date: 2023-03-09 5 | lang: en 6 | published: true 7 | series: political thinking! 8 | og_image: "" 9 | og_image_alt: "" 10 | og_image_width: "" 11 | og_image_height: "" 12 | tags: 13 | - mental health 14 | - love 15 | - care 16 | - society 17 | - the world 18 | --- 19 | -------------------------------------------------------------------------------- /src/posts/peace-in-the-city.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Peace in the city 3 | description: This is an essay on peace and how to live toghether. 4 | date: 2023-03-08 5 | lang: en 6 | published: true 7 | series: political thinking! 8 | og_image: "" 9 | og_image_alt: "" 10 | og_image_width: "" 11 | og_image_height: "" 12 | tags: 13 | - peace 14 | - love 15 | - care 16 | --- 17 | Lets be friends. -------------------------------------------------------------------------------- /src/posts/post-one.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Post one 3 | description: "Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts." 4 | date: 2023-04-13 5 | updated: 2023-04-15 6 | lang: en 7 | published: true 8 | series: "Post one, two, three" 9 | toc: false 10 | og_image: "" 11 | og_image_alt: "" 12 | og_image_width: "" 13 | og_image_height: "" 14 | tags: 15 | - dummy 16 | - text 17 | - commas 18 | --- 19 | 20 | 21 | ## Heading H2 22 | Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. 23 | 1. List item 1 24 | 2. List item 2 25 | 3. List item 3 26 | 27 | Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean. 28 | 29 | ### Heading H3 30 | A small river named Duden flows by their place and supplies it with the necessary regelialia. 31 | 32 | It is a paradisematic country, in which roasted parts of sentences fly into your mouth. 33 | * List item 1 34 | * List item 2 35 | * List item 3 36 | 37 | #### Heading H4 38 | Even the all-powerful Pointing has no control about the blind texts it is an almost unorthographic life One day however a small line of blind text by the name of Lorem Ipsum decided to leave for the far World of Grammar. 39 | 40 | 41 | "This is a blockquote. He thought. It wasn't a dream. His room, a proper human room although a little too small, lay peacefully between its four familiar walls." 42 | 43 | 44 | The Big Oxmox advised her not to do so, because there were thousands of bad Commas, wild Question Marks and devious Semikoli, but the Little Blind Text didn’t listen. She packed her seven versalia, put her initial into the belt and made herself. -------------------------------------------------------------------------------- /src/posts/posts.11tydata.js: -------------------------------------------------------------------------------- 1 | const meta = require("../_data/meta"); 2 | 3 | module.exports = { 4 | layout: "article.webc", 5 | eleventyComputed: { 6 | eleventyExcludeFromCollections(data) { 7 | return meta.isProduction && data.published === false ? true : false; 8 | } 9 | }, 10 | permalink(data) { 11 | return meta.isProduction && data.published === false ? false : `blog/posts/${data.page.fileSlug}/`; 12 | }, 13 | og_type: "article", 14 | og_author: meta.canonical("/about/"), 15 | author: meta.author.name, 16 | author_image: meta.author.image.src, 17 | author_image_alt: meta.author.image.alt 18 | }; -------------------------------------------------------------------------------- /src/posts/war-in-the-world.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: War in the world 3 | description: This is an essay on war and the end of the world. 4 | date: 2023-02-24 5 | lang: en 6 | published: true 7 | series: political thinking! 8 | toc: true 9 | top_button: true 10 | og_image: "" 11 | og_image_alt: "" 12 | og_image_width: "" 13 | og_image_height: "" 14 | tags: love 15 | --- 16 | 17 | 18 | ## Our futur 19 | There is war in this world. Maybe, some day, it will end. I'm writing this as we speak. 20 | 21 | Other paragraph. 22 | 23 | ### How we see things 24 | It is not always obvious to see things clearly. 25 | 26 | 27 | function test() { 28 | return true; 29 | } 30 | 31 | 32 | ![A television on a small table with a retro wallpaper background.](./src/assets/images/TV.jpg) -------------------------------------------------------------------------------- /src/robots.webc: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyExcludeFromCollections: true 3 | dynamicPermalink: false 4 | permalink: robots.txt 5 | --- 6 | -------------------------------------------------------------------------------- /src/sitemap.webc: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyExcludeFromCollections: true 3 | dynamicPermalink: false 4 | permalink: sitemap.xml 5 | --- 6 | 7 | 8 | 16 | -------------------------------------------------------------------------------- /src/tags.11tydata.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | eleventyComputed: { 3 | title(data) { 4 | return `#${data.pagination.items[0]}`; 5 | }, 6 | description(data) { 7 | return `Listing posts related to ${data.pagination.items[0]}.`; 8 | } 9 | }, 10 | permalink(data) { 11 | return `tags/${this.slugify(data.pagination.items[0])}/`; 12 | } 13 | }; -------------------------------------------------------------------------------- /src/tags.webc: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page.webc 3 | pagination: 4 | data: collections.tags 5 | size: 1 6 | alias: tag 7 | --- 8 |

Here, you will find posts related to the tag.

9 | --------------------------------------------------------------------------------