diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..7528e74 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,32 @@ +kind: pipeline +name: production +when: + event: [ push ] + branch: [ main ] + +clone: + git: + image: plugins/git + pull: true + +steps: + - name: build + image: node:latest + commands: + - npm i + - npx @11ty/eleventy + + - name: deploy + image: drillster/drone-rsync + settings: + hosts: + from_secret: deploy_host + target: /var/www/erratum.kazhnuz.space + source: _site/* + user: + from_secret: deploy_user + key: + from_secret: deploy_key + when: + branch: main + delete: true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a8fe7ae --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Generated files +package/generated* + +# Ignore installed npm modules +node_modules/ + +# Ignore build tool output, e.g. code coverage +.nyc_output/ +coverage/ + +# Ignore API documentation +api-docs/ + +# Ignore folders from source code editors +.vscode +.idea + +# Ignore eleventy output when doing manual tests +_site/ + +package-lock.json + +# Ignore test files +.cache +test/stubs-layout-cache/_includes/*.js \ No newline at end of file diff --git a/_data/metadata.js b/_data/metadata.js new file mode 100644 index 0000000..3a2f7c7 --- /dev/null +++ b/_data/metadata.js @@ -0,0 +1,11 @@ +module.exports = { + title: "Kobold Start", + url: "https://start.kobold.cafe/", + language: "fr", + description: "Un petit portail internet tout bête", + author: { + name: "Kazhnuz", + email: "kazhnuz@kobold.cafe", + url: "https://kazhnuz.space/" + } +} diff --git a/_includes/layouts/base.njk b/_includes/layouts/base.njk new file mode 100644 index 0000000..ba5a9ef --- /dev/null +++ b/_includes/layouts/base.njk @@ -0,0 +1,36 @@ +--- +layout: layouts/parent.njk +--- +
+
+
+ {{ content | safe }} +
+
+
+ + diff --git a/_includes/layouts/home.njk b/_includes/layouts/home.njk new file mode 100644 index 0000000..a66197f --- /dev/null +++ b/_includes/layouts/home.njk @@ -0,0 +1,36 @@ +--- +layout: layouts/parent.njk +--- +
+
+
+ {{ content | safe }} +
+
+
+ + diff --git a/_includes/layouts/index.njk b/_includes/layouts/index.njk new file mode 100644 index 0000000..98beaa4 --- /dev/null +++ b/_includes/layouts/index.njk @@ -0,0 +1,21 @@ + + + + + + + + Embarcadère + + + + + + + + + + + + + diff --git a/_includes/layouts/model.njk b/_includes/layouts/model.njk new file mode 100644 index 0000000..9ee583a --- /dev/null +++ b/_includes/layouts/model.njk @@ -0,0 +1,26 @@ +--- +layout: layouts/parent.njk +--- +
+
+ {{ content | safe }} +
+
+ + diff --git a/index.html b/_includes/layouts/parent.njk similarity index 80% rename from index.html rename to _includes/layouts/parent.njk index ca63dac..4e63223 100644 --- a/index.html +++ b/_includes/layouts/parent.njk @@ -1,26 +1,22 @@ + + + + + {{ title or metadata.title }} + + - - - - + {#- Uncomment this if you’d like folks to know that you used Eleventy to build your site! #} + - Embarcadère - - + {%- css %}{% include "public/css/index.css" %}{% endcss %} + - - - - - - - - - - + +
-

Bonjour

+

{{ metadata.title }}

diff --git a/_includes/layouts/post.njk b/_includes/layouts/post.njk new file mode 100644 index 0000000..ad83414 --- /dev/null +++ b/_includes/layouts/post.njk @@ -0,0 +1,28 @@ +--- +layout: layouts/parent.njk +--- +{# Only include the syntax highlighter CSS on blog posts #} +{%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %} +{%- css %}{% include "public/css/prism-diff.css" %}{%- endcss %} +

{{ title }}

+ + + +{{ content | safe }} + +{%- if collections.posts %} +{%- set previousPost = collections.posts | getPreviousCollectionItem %} +{%- set nextPost = collections.posts | getNextCollectionItem %} +{%- if nextPost or previousPost %} + +{%- endif %} +{%- endif %} diff --git a/_includes/postslist.njk b/_includes/postslist.njk new file mode 100644 index 0000000..99272c5 --- /dev/null +++ b/_includes/postslist.njk @@ -0,0 +1,9 @@ +{%- css %}.postlist { counter-reset: start-from {{ (postslistCounter or postslist.length) + 1 }} }{% endcss %} +
    +{% for post in postslist | reverse %} +
  1. + {% if post.data.title %}{{ post.data.title }}{% else %}{{ post.url }}{% endif %} + +
  2. +{% endfor %} +
diff --git a/content/index.md b/content/index.md new file mode 100644 index 0000000..4233b87 --- /dev/null +++ b/content/index.md @@ -0,0 +1,3 @@ +--- +layout: layouts/parent.njk +--- \ No newline at end of file diff --git a/eleventy.config.drafts.js b/eleventy.config.drafts.js new file mode 100644 index 0000000..8eb92dc --- /dev/null +++ b/eleventy.config.drafts.js @@ -0,0 +1,50 @@ +function eleventyComputedPermalink() { + // When using `addGlobalData` and you *want* to return a function, you must nest functions like this. + // `addGlobalData` acts like a global data file and runs the top level function it receives. + return (data) => { + // Always skip during non-watch/serve builds + if(data.draft && !process.env.BUILD_DRAFTS) { + return false; + } + + return data.permalink; + } +}; + +function eleventyComputedExcludeFromCollections() { + // When using `addGlobalData` and you *want* to return a function, you must nest functions like this. + // `addGlobalData` acts like a global data file and runs the top level function it receives. + return (data) => { + // Always exclude from non-watch/serve builds + if(data.draft && !process.env.BUILD_DRAFTS) { + return true; + } + + return data.eleventyExcludeFromCollections; + } +}; + +module.exports.eleventyComputedPermalink = eleventyComputedPermalink; +module.exports.eleventyComputedExcludeFromCollections = eleventyComputedExcludeFromCollections; + +module.exports = eleventyConfig => { + eleventyConfig.addGlobalData("eleventyComputed.permalink", eleventyComputedPermalink); + eleventyConfig.addGlobalData("eleventyComputed.eleventyExcludeFromCollections", eleventyComputedExcludeFromCollections); + + let logged = false; + eleventyConfig.on("eleventy.before", ({runMode}) => { + let text = "Excluding"; + // Only show drafts in serve/watch modes + if(runMode === "serve" || runMode === "watch") { + process.env.BUILD_DRAFTS = true; + text = "Including"; + } + + // Only log once. + if(!logged) { + console.log( `[11ty/eleventy-base-blog] ${text} drafts.` ); + } + + logged = true; + }); +} diff --git a/eleventy.config.images.js b/eleventy.config.images.js new file mode 100644 index 0000000..32a0269 --- /dev/null +++ b/eleventy.config.images.js @@ -0,0 +1,34 @@ +const path = require("path"); +const eleventyImage = require("@11ty/eleventy-img"); + +module.exports = eleventyConfig => { + function relativeToInputPath(inputPath, relativeFilePath) { + let split = inputPath.split("/"); + split.pop(); + + return path.resolve(split.join(path.sep), relativeFilePath); + } + + // Eleventy Image shortcode + // https://www.11ty.dev/docs/plugins/image/ + eleventyConfig.addAsyncShortcode("image", async function imageShortcode(src, alt, widths, sizes) { + // Full list of formats here: https://www.11ty.dev/docs/plugins/image/#output-formats + // Warning: Avif can be resource-intensive so take care! + let formats = ["avif", "webp", "auto"]; + let file = relativeToInputPath(this.page.inputPath, src); + let metadata = await eleventyImage(file, { + widths: widths || ["auto"], + formats, + outputDir: path.join(eleventyConfig.dir.output, "img"), // Advanced usage note: `eleventyConfig.dir` works here because we’re using addPlugin. + }); + + // TODO loading=eager and fetchpriority=high + let imageAttributes = { + alt, + sizes, + loading: "lazy", + decoding: "async", + }; + return eleventyImage.generateHTML(metadata, imageAttributes); + }); +}; diff --git a/eleventy.config.js b/eleventy.config.js new file mode 100644 index 0000000..5b88972 --- /dev/null +++ b/eleventy.config.js @@ -0,0 +1,144 @@ +const { DateTime } = require("luxon"); +const markdownItAnchor = require("markdown-it-anchor"); + +const pluginRss = require("@11ty/eleventy-plugin-rss"); +const pluginSyntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight"); +const pluginBundle = require("@11ty/eleventy-plugin-bundle"); +const pluginNavigation = require("@11ty/eleventy-navigation"); +const { EleventyHtmlBasePlugin } = require("@11ty/eleventy"); + +const pluginDrafts = require("./eleventy.config.drafts.js"); +const pluginImages = require("./eleventy.config.images.js"); +const pluginTOC = require('eleventy-plugin-toc'); + +module.exports = function(eleventyConfig) { + // Copy the contents of the `public` folder to the output folder + // For example, `./public/css/` ends up in `_site/css/` + eleventyConfig.addPassthroughCopy({ + "./public/": "/", + "./node_modules/prismjs/themes/prism-okaidia.css": "/css/prism-okaidia.css" + }); + + // Run Eleventy when these files change: + // https://www.11ty.dev/docs/watch-serve/#add-your-own-watch-targets + + // Watch content images for the image pipeline. + eleventyConfig.addWatchTarget("content/**/*.{svg,webp,png,jpeg}"); + + // App plugins + eleventyConfig.addPlugin(pluginDrafts); + eleventyConfig.addPlugin(pluginImages); + + // Official plugins + eleventyConfig.addPlugin(pluginRss); + eleventyConfig.addPlugin(pluginSyntaxHighlight, { + preAttributes: { tabindex: 0 } + }); + eleventyConfig.addPlugin(pluginNavigation); + eleventyConfig.addPlugin(EleventyHtmlBasePlugin); + eleventyConfig.addPlugin(pluginBundle); + eleventyConfig.addPlugin(pluginTOC, { + tags: ['h2'], + wrapper: 'div' + }); + + // Filters + eleventyConfig.addFilter("readableDate", (dateObj, format, zone) => { + // Formatting tokens for Luxon: https://moment.github.io/luxon/#/formatting?id=table-of-tokens + return DateTime.fromJSDate(dateObj, { zone: zone || "utc" }).toFormat(format || "dd LLLL yyyy"); + }); + + eleventyConfig.addFilter('htmlDateString', (dateObj) => { + // dateObj input: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string + return DateTime.fromJSDate(dateObj, {zone: 'utc'}).toFormat('yyyy-LL-dd'); + }); + + // Get the first `n` elements of a collection. + eleventyConfig.addFilter("head", (array, n) => { + if(!Array.isArray(array) || array.length === 0) { + return []; + } + if( n < 0 ) { + return array.slice(n); + } + + return array.slice(0, n); + }); + + // Return the smallest number argument + eleventyConfig.addFilter("min", (...numbers) => { + return Math.min.apply(null, numbers); + }); + + // Return all the tags used in a collection + eleventyConfig.addFilter("getAllTags", collection => { + let tagSet = new Set(); + for(let item of collection) { + (item.data.tags || []).forEach(tag => tagSet.add(tag)); + } + return Array.from(tagSet); + }); + + eleventyConfig.addFilter("filterTagList", function filterTagList(tags) { + return (tags || []).filter(tag => ["all", "nav", "post", "posts"].indexOf(tag) === -1); + }); + + // Customize Markdown library settings: + eleventyConfig.amendLibrary("md", mdLib => { + mdLib.use(markdownItAnchor, { + permalink: markdownItAnchor.permalink.ariaHidden({ + placement: "after", + class: "header-anchor", + symbol: "#", + ariaHidden: false, + }), + level: [1,2,3,4], + slugify: eleventyConfig.getFilter("slugify") + }); + }); + + // Features to make your build faster (when you need them) + + // If your passthrough copy gets heavy and cumbersome, add this line + // to emulate the file copy on the dev server. Learn more: + // https://www.11ty.dev/docs/copy/#emulate-passthrough-copy-during-serve + + // eleventyConfig.setServerPassthroughCopyBehavior("passthrough"); + + return { + // Control which files Eleventy will process + // e.g.: *.md, *.njk, *.html, *.liquid + templateFormats: [ + "md", + "njk", + "html", + "liquid", + ], + + // Pre-process *.md files with: (default: `liquid`) + markdownTemplateEngine: "njk", + + // Pre-process *.html files with: (default: `liquid`) + htmlTemplateEngine: "njk", + + // These are all optional: + dir: { + input: "content", // default: "." + includes: "../_includes", // default: "_includes" + data: "../_data", // default: "_data" + output: "_site" + }, + + // ----------------------------------------------------------------- + // Optional items: + // ----------------------------------------------------------------- + + // If your site deploys to a subdirectory, change `pathPrefix`. + // Read more: https://www.11ty.dev/docs/config/#deploy-to-a-subdirectory-with-a-path-prefix + + // When paired with the HTML plugin https://www.11ty.dev/docs/plugins/html-base/ + // it will transform any absolute URLs in your HTML to include this + // folder name and does **not** affect where things go in the output folder. + pathPrefix: "/", + }; +}; diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000..5a8db0f --- /dev/null +++ b/netlify.toml @@ -0,0 +1,24 @@ +[build] + publish = "_site" + command = "npm run build" + +[[plugins]] + + # Opt-in to the Netlify Lighthouse plugin (choose one): + + # 1. Go to your site on https://app.netlify.com and navigate to the Integrations tab, search for the `Lighthouse` plugin + # 2. Or via `npm install -D @netlify/plugin-lighthouse` + + # Read more: https://github.com/netlify/netlify-plugin-lighthouse + + package = "@netlify/plugin-lighthouse" + + # optional, fails build when a category is below a threshold + [plugins.inputs.thresholds] + performance = 1.0 + accessibility = 1.0 + best-practices = 1.0 + seo = 1.0 + + [plugins.inputs] + output_path = "reports/lighthouse/index.html" diff --git a/package.json b/package.json new file mode 100644 index 0000000..76c6525 --- /dev/null +++ b/package.json @@ -0,0 +1,47 @@ +{ + "name": "eleventy-base-blog", + "version": "8.0.0", + "description": "A starter repository for a blog web site using the Eleventy site generator.", + "scripts": { + "build": "npx @11ty/eleventy", + "build-ghpages": "npx @11ty/eleventy --pathprefix=/eleventy-base-blog/", + "start": "npx @11ty/eleventy --serve --quiet", + "debug": "DEBUG=Eleventy* npx @11ty/eleventy", + "debugstart": "DEBUG=Eleventy* npx @11ty/eleventy --serve --quiet", + "benchmark": "DEBUG=Eleventy:Benchmark* npx @11ty/eleventy" + }, + "repository": { + "type": "git", + "url": "git://github.com/11ty/eleventy-base-blog.git" + }, + "author": { + "name": "Zach Leatherman", + "email": "zachleatherman@gmail.com", + "url": "https://zachleat.com/" + }, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + }, + "bugs": { + "url": "https://github.com/11ty/eleventy-base-blog/issues" + }, + "homepage": "https://github.com/11ty/eleventy-base-blog#readme", + "devDependencies": { + "@11ty/eleventy": "^2.0.1", + "@11ty/eleventy-img": "^3.1.0", + "@11ty/eleventy-navigation": "^0.3.5", + "@11ty/eleventy-plugin-bundle": "^1.0.4", + "@11ty/eleventy-plugin-rss": "^1.2.0", + "@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0", + "luxon": "^3.3.0", + "markdown-it-anchor": "^8.6.7" + }, + "dependencies": { + "eleventy-plugin-toc": "^1.1.5" + } +} diff --git a/styles.css b/public/css/index.css similarity index 98% rename from styles.css rename to public/css/index.css index 8020c5b..b6352ef 100644 --- a/styles.css +++ b/public/css/index.css @@ -23,7 +23,7 @@ body { color: var(--color-text); /* Bacground by Ashim DSilva */ - background-image: url("./background.jpg"); + background-image: url("./img/background.jpg"); font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; diff --git a/dep/fork-awesome/css/fork-awesome.css b/public/dep/fork-awesome/css/fork-awesome.css similarity index 100% rename from dep/fork-awesome/css/fork-awesome.css rename to public/dep/fork-awesome/css/fork-awesome.css diff --git a/dep/fork-awesome/css/fork-awesome.min.css b/public/dep/fork-awesome/css/fork-awesome.min.css similarity index 100% rename from dep/fork-awesome/css/fork-awesome.min.css rename to public/dep/fork-awesome/css/fork-awesome.min.css diff --git a/dep/fork-awesome/css/fork-awesome.min.css.map b/public/dep/fork-awesome/css/fork-awesome.min.css.map similarity index 100% rename from dep/fork-awesome/css/fork-awesome.min.css.map rename to public/dep/fork-awesome/css/fork-awesome.min.css.map diff --git a/dep/fork-awesome/css/v5-compat.css b/public/dep/fork-awesome/css/v5-compat.css similarity index 100% rename from dep/fork-awesome/css/v5-compat.css rename to public/dep/fork-awesome/css/v5-compat.css diff --git a/dep/fork-awesome/css/v5-compat.min.css b/public/dep/fork-awesome/css/v5-compat.min.css similarity index 100% rename from dep/fork-awesome/css/v5-compat.min.css rename to public/dep/fork-awesome/css/v5-compat.min.css diff --git a/dep/fork-awesome/css/v5-compat.min.css.map b/public/dep/fork-awesome/css/v5-compat.min.css.map similarity index 100% rename from dep/fork-awesome/css/v5-compat.min.css.map rename to public/dep/fork-awesome/css/v5-compat.min.css.map diff --git a/dep/fork-awesome/fonts/forkawesome-webfont.eot b/public/dep/fork-awesome/fonts/forkawesome-webfont.eot similarity index 100% rename from dep/fork-awesome/fonts/forkawesome-webfont.eot rename to public/dep/fork-awesome/fonts/forkawesome-webfont.eot diff --git a/dep/fork-awesome/fonts/forkawesome-webfont.svg b/public/dep/fork-awesome/fonts/forkawesome-webfont.svg similarity index 100% rename from dep/fork-awesome/fonts/forkawesome-webfont.svg rename to public/dep/fork-awesome/fonts/forkawesome-webfont.svg diff --git a/dep/fork-awesome/fonts/forkawesome-webfont.ttf b/public/dep/fork-awesome/fonts/forkawesome-webfont.ttf similarity index 100% rename from dep/fork-awesome/fonts/forkawesome-webfont.ttf rename to public/dep/fork-awesome/fonts/forkawesome-webfont.ttf diff --git a/dep/fork-awesome/fonts/forkawesome-webfont.woff b/public/dep/fork-awesome/fonts/forkawesome-webfont.woff similarity index 100% rename from dep/fork-awesome/fonts/forkawesome-webfont.woff rename to public/dep/fork-awesome/fonts/forkawesome-webfont.woff diff --git a/dep/fork-awesome/fonts/forkawesome-webfont.woff2 b/public/dep/fork-awesome/fonts/forkawesome-webfont.woff2 similarity index 100% rename from dep/fork-awesome/fonts/forkawesome-webfont.woff2 rename to public/dep/fork-awesome/fonts/forkawesome-webfont.woff2 diff --git a/background.jpg b/public/img/background.jpg similarity index 100% rename from background.jpg rename to public/img/background.jpg