Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 46 additions & 39 deletions src/helpers/setup-css.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import postcss from 'postcss';
import autoprefixer from 'autoprefixer';
import postCssImport from 'postcss-import';
import postCssNesting from 'postcss-nesting';
import postCssCsso from 'postcss-csso';
import { promises as fs } from 'node:fs';
import path from 'node:path';
import postcss from 'postcss';
import postCssCsso from 'postcss-csso';
import postCssImport from 'postcss-import';
import postCssNesting from 'postcss-nesting';

/**
* Registers CSS build and watch logic for Eleventy using PostCSS pipeline.
* @param {import('@11ty/eleventy').EleventyConfig} eleventyConfig - Eleventy config object
*/
export function setupCSS(eleventyConfig) {
const sourceFile = './src/styles/index.css';
const compiledFile = './dist/style.css';
const sourceFile = './src/styles/index.css';
const compiledFile = './dist/style.css';

// Process CSS before the build starts
eleventyConfig.on('beforeBuild', async () => {
await processCSS(sourceFile, compiledFile, false);
});

// Watch CSS source files for changes to trigger rebuild
eleventyConfig.addWatchTarget(sourceFile);
eleventyConfig.addWatchTarget('src/components/**/*.css');
// Process CSS before the build starts
eleventyConfig.on('beforeBuild', async () => {
await processCSS(sourceFile, compiledFile, false);
});

// Watch CSS source files for changes to trigger rebuild
eleventyConfig.addWatchTarget(sourceFile);
eleventyConfig.addWatchTarget('src/styles/**/*.css');
eleventyConfig.addWatchTarget('src/components/**/*.css');
}

/**
Expand All @@ -32,34 +32,41 @@ export function setupCSS(eleventyConfig) {
* @param {boolean} [debug=false] - Enable debug logging
*/
async function processCSS(sourceFile, compiledFile, debug = false) {
try {
// Remove old file if it exists
await fs.unlink(compiledFile).then(() => {
if (debug) console.log(`💥 Removed old CSS file: ${compiledFile}`);
}).catch((err) => {
if (err.code !== 'ENOENT') throw err;
});
try {
// Remove old file if it exists
await fs
.unlink(compiledFile)
.then(() => {
if (debug)
console.log(`💥 Removed old CSS file: ${compiledFile}`);
})
.catch((err) => {
if (err.code !== 'ENOENT') throw err;
});

// Ensure the output directory exists
const compiledDir = path.dirname(compiledFile);
await fs.mkdir(compiledDir, { recursive: true });

// Ensure the output directory exists
const compiledDir = path.dirname(compiledFile);
await fs.mkdir(compiledDir, { recursive: true });
// Read the source CSS
const css = await fs.readFile(sourceFile, 'utf8');

// Read the source CSS
const css = await fs.readFile(sourceFile, 'utf8');
// Process CSS with PostCSS plugins. Run the minifier only in production
const plugins = [postCssImport, postCssNesting, autoprefixer];
if (process.env.NODE_ENV === 'production') {
plugins.push(postCssCsso);
}

// Process CSS with PostCSS plugins
const result = await postcss([
postCssImport,
postCssNesting,
autoprefixer,
postCssCsso,
]).process(css, { from: sourceFile, to: compiledFile });
const result = await postcss(plugins).process(css, {
from: sourceFile,
to: compiledFile
});

// Write processed CSS to compiledFile
await fs.writeFile(compiledFile, result.css);
// Write processed CSS to compiledFile
await fs.writeFile(compiledFile, result.css);

if (debug) console.log(`🎉 Compiled new CSS file: ${compiledFile}`);
} catch (error) {
console.error('⛔️ CSS processing error:', error);
}
if (debug) console.log(`🎉 Compiled new CSS file: ${compiledFile}`);
} catch (error) {
console.error('⛔️ CSS processing error:', error);
}
}
6 changes: 0 additions & 6 deletions src/layouts/post.njk
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,10 @@
{% extends "main.njk" %}
{% block content %}
<article role="article" aria-labelledby="post-title">
<header>
<h2 id="post-title">{{ title }}</h2>
<time datetime="{{ date.toISOString() }}">{{ date.toLocaleDateString('en-GB', { day: "numeric", month: "long", year: "numeric" }) }}</time>
</header>

<section>{{ content | safe }}</section>

<nav aria-label="Post navigation">
<p><a href="/notes" rel="up">&larrhk; Back to notes</a></p>
</nav>

</article>
{% endblock %}
102 changes: 102 additions & 0 deletions src/styles/base.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
:root {
--colour-light: #efefef;
--colour-dark: #222222;
--colour-link: darkcyan;
--colour-link-alt: yellow;
--line-height: 1.9;
--character-width: 72ch;
}

body {
box-sizing: border-box;
background-color: var(--colour-light);
color: var(--colour-dark);
font-family: var(--type-stack);
max-width: var(--character-width);
margin: auto;
padding: 20px;
width: 100%;
}

h1 {
line-height: var(--line-height);
}

a {
color: var(--colour-link);
font-weight: 600;
}

img {
height: auto;
width: 100%;
}

footer {
padding: 2rem 0;
}

footer svg {
height: 1rem;
width: auto;
}

footer a svg path {
fill: var(--colour-link);
}

footer ul {
list-style: none;
text-align: right;
}

footer li {
display: inline-block;
padding: 0 5px;
}

@media (prefers-color-scheme: dark) {
body {
background-color: var(--colour-dark);
color: var(--colour-light);
}

a {
color: var(--colour-link-alt);
}

footer a svg path {
fill: var(--colour-link-alt);
}
}

/* Accessible skip-to-content link (classless) */
/* Target the page anchor used in templates: href="#main-content" */
a[href='#main-content'] {
position: absolute;
left: -999px;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px); /* legacy */
white-space: nowrap;
border: 0;
padding: 0;
}

a[href='#main-content']:focus,
a[href='#main-content']:focus-visible {
position: fixed;
top: 1rem;
left: 1rem;
width: auto;
height: auto;
overflow: visible;
clip: auto;
background: var(--colour-dark);
color: var(--colour-light);
padding: 0.25rem 0.5rem;
border-radius: 4px;
z-index: 1000;
text-decoration: none;
}
126 changes: 3 additions & 123 deletions src/styles/index.css
Original file line number Diff line number Diff line change
@@ -1,124 +1,4 @@
@layer reset, base;

@layer reset {
@import "reset.css";
}
@import 'reset.css' layer(reset);
@import 'base.css' layer(base);

@layer base {
:root {
--colour-light: #EFEFEF;
--colour-dark: #222222;
--colour-link: darkcyan;
--colour-link-alt: yellow;
--type-size: 100%;
--type-stack: 'system', sans-serif;
--line-height: 1.9;
--character-width: 72ch;
}

@font-face {
font-family: system;
font-style: normal;
font-weight: 300;
src: local('.SFNSText-Light'),
local('.HelveticaNeueDeskInterface-Light'),
local('.LucidaGrandeUI'),
local('Ubuntu Light'),
local('Segoe UI Light'),
local('Roboto-Light'),
local('DroidSans'),
local('Tahoma');
}

body {
box-sizing: border-box;
background-color: var(--colour-light);
color: var(--colour-dark);
font-family: var(--type-stack);
font-size: var(--type-size);
line-height: var(--line-height);
max-width: var(--character-width);
margin: auto;
padding: 20px;
width: 100%;
}

a {
color: var(--colour-link);
font-weight: 600;
}

img {
height: auto;
width: 100%;
}

footer {
padding: 2rem 0;
}

footer svg {
height: 1rem;
width: auto;
}

footer a svg path {
fill: var(--colour-link);
}

footer ul {
list-style: none;
text-align: right;
}

footer li {
display: inline-block;
padding: 0 5px;
}

@media (prefers-color-scheme: dark) {
body {
background-color: var(--colour-dark);
color: var(--colour-light);
}

a {
color: var(--colour-link-alt);
}

footer a svg path {
fill: var(--colour-link-alt);
}
}

/* Accessible skip-to-content link (classless) */
/* Target the page anchor used in templates: href="#main-content" */
a[href="#main-content"] {
position: absolute;
left: -999px;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px); /* legacy */
white-space: nowrap;
border: 0;
padding: 0;
}

a[href="#main-content"]:focus,
a[href="#main-content"]:focus-visible {
position: fixed;
top: 1rem;
left: 1rem;
width: auto;
height: auto;
overflow: visible;
clip: auto;
background: var(--colour-dark);
color: var(--colour-light);
padding: 0.25rem 0.5rem;
border-radius: 4px;
z-index: 1000;
text-decoration: none;
}
}
@layer reset, base;
Loading