Lume 2.5.0 - Pedro Días and Muño Vandilaz
6 min read
Feliz aninovo 🎄!
New year and new Lume version! This time, I'd like to dedicate it to Pedro Días and Muño Vandilaz, who married on April 16, 1061, almost a thousand years ago. This is the first same-sex marriage documented in Galicia (and the rest of Spain).
The wedding took place in a small Catholic chapel. It's surprising to see how homophobic prejudices have changed since then. If you want to read more about this event take a look at this Qnews article (English) or gCiencia post (Galician).
New plugin json_ld
JSON-LD (JSON for Linking Data) is a way to provide
structured data to web pages using JSON format, which
is easier to parse and doesn't require to modify the HTML code. It's defined
with a <script type="application/ld+json">
element containing the JSON code.
For example:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"url": "https://oscarotero.com/",
"headline": "Óscar Otero - Web designer and developer",
"name": "Óscar Otero",
"description": "I’m just a designer and web developer",
"author": {
"@type": "Person",
"name": "Óscar Otero"
}
}
</script>
The json_ld
plugin, created by Shuaixr, makes
easier to work with this structured data. Edit your _config
file to install
it:
import lume from "lume/mod.ts";
import jsonLd from "lume/plugins/json_ld.ts";
const site = lume();
site.use(jsonLd());
export default site;
Then, you can create the jsonLd
variable in your pages. For example:
jsonLd:
"@type": WebSite
url: /
headline: Óscar Otero - Web designer and developer
name: Óscar Otero
description: I’m just a designer and web developer
author:
"@type": Person
name: Óscar Otero
Note the following:
- The plugin automatically adds the
@context
property if it's missing - URLs can omit the protocol and host. The plugin automatically resolves all
URLs based on the
location
of the site.
Like with other similar plugins like metas, you can use field aliases:
title: Óscar Otero - Web designer and developer
header:
title: Óscar Otero
description: I’m just a designer and web developer
jsonLd:
"@type": WebSite
url: /
headline: =title
name: =header.title
description: =header.description
author:
"@type": Person
name: =header.title
TypeScript
If you want to use TypeScript, there's the Lume.Data["jsonLd"]
type (powered
by schema-dts package):
export const jsonLd: Lume.Data["jsonLd"] = {
"@type": "WebSite",
url: "/",
headline: "Óscar Otero - Web designer and developer",
description: "I’m just a designer and web developer",
name: "Óscar Otero",
author: {
"@type": "Person",
name: "Óscar Otero",
},
};
More info in the plugin documentation page.
New plugin purgecss
PurgeCSS is a utility to remove unused CSS code, making your CSS files smaller to improve the site performance. The tool provides a Postcss plugin so, in theory, it can also be used in Lume. Now it has its own plugin (big thanks to into-the-v0id) which has some advantages:
- Scan generated HTML pages by Lume
- Scan bundled JS dependencies (bootstrap, etc)
- Only include CSS that is necessary (don't include drafts or conditional HTML that does not make it into the build)
import lume from "lume/mod.ts";
import purgecss from "lume/plugins/purgecss.ts";
const site = lume();
site.use(purgecss());
export default site;
Go to the plugin documentation page for more info.
New router
middleware
Lume is a static site generator (and always will be). But sometimes you need some server-side logic to handle small things. For example, to handle the data a user sends from an HTML form, or maybe you need a small API to provide dynamic data.
For sites requiring front and back, you have great options like
Fresh, Astro or
Hono. But if you only need a couple of entry points, you
may consider using something simpler like router
middleware, which is a
minimal router that works great with Lume's server.
import Server from "lume/core/server.ts";
import Router from "lume/middlewares/router.ts";
// Create the router
const router = new Router();
router.get("/hello/:name", ({ name }) => {
return new Response(`Hello ${name}`);
});
// Create the server:
const server = new Server();
server.use(router.middleware());
server.start();
That's all. Now the /hello/laura
request will return a Hello laura
response!
The router uses the standard URLPattern under the hood that creates an object with all variables captured in the path and passes it as the first argument of the route handler.
In addition to the captured variables, you have the request
property with the
Request instance:
router.get("/search", ({ request }) => {
const { searchParams } = new URL(request.url);
const query = searchParams.get("query");
return new Response(`Searching by ${query}`);
});
Note that to use this middleware in production, you need a hosting service running Deno like Deno Deploy or similar.
New plaintext
plugin
Sometimes you have your content in Markdown or HTML, but also need a plain text version. Let's see the following example:
---
title: Welcome to **my site**
---
<!doctype html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ title |> md(true) }}</h1>
</body>
</html>
The title
variable uses Markdown syntax to render
Welcome to <strong>my site</strong>
. But this also affects the <title>
element of the page which contains the asterisks.
The new plaintext
plugin registers the plaintext
filter, that not only
removes any Markdown and HTML syntax but also linebreaks and extra spaces:
---
title: Welcome to **my site**
---
<!doctype html>
<html>
<head>
<title>{{ title |> plaintext }}</title>
</head>
<body>
<h1>{{ title |> md(true) }}</h1>
</body>
</html>
The plugin is disabled by default so you need to import it to your _config.ts file:
import lume from "lume/mod.ts";
import plaintext from "lume/plugins/plaintext.ts";
const site = lume();
site.use(plaintext());
export default site;
More info in the plugin documentation page.
Better control of the generated CSS code
Some plugins like google_fonts
,
prism
or
code_highlight
can generate CSS
code. The way this code is generated is different for each plugin.
Google Fonts plugin has the cssFile
option to configure the filename to output
the CSS code. If the css file doesn't exist, it's created. If it already exists,
the code is appended at the end. You can use the placeholder
option to insert
the code at some point in the middle of the file.
site.use(googleFonts({
cssFile: "styles.css",
placeholder: "/* insert-google-fonts-here */",
// ...more options
}));
Prism and Code Highlight plugins output the theme's CSS code differently. The
theme
option has the path
property but it's not the output css file but
the source file:
site.use(prism({
theme: {
name: "funky",
path: "/_includes/css/code_theme.css",
},
}));
This means that if you set the path as /_includes/css/code_theme.css
, this
file must be imported somewhere in your CSS code in order to be visible:
@import "css/code_theme.css";
The problem with this approach is it requires two steps: first, configure the
source file name in the plugin, and then import the file in your CSS file (or
copy it with site.copy()
).
The Google fonts approach is more straightforward.
In order to make Lume more consistent across all plugins, I want to unify the
way the CSS code is generated everywhere. That's why the theme.path
option of
Prism and Code Highlight plugins are now deprecated and the new theme.cssFile
and theme.placeholder
options were added.
site.use(prism({
theme: {
name: "funky",
cssFile: "styles.css",
placeholder: "/* prism-theme-here */",
},
}));
This change is also aligned with the
components.placeholder
option
introduced in Lume 2.4.
Other changes
- Added
subset
options to Google fonts plugin. - Added
ui.globalVariable
option to Pagefind plugin to store the pagefind instance in a global variable for future manipulation. - Hot reload inline script includes the integrity hash, to avoid CSP issues.
- Files with extension
.d.ts
are ignored by Lume, to avoid generating empty files. - Updated the default browser versions supported by LightningCSS plugin.
See the CHANGELOG.md file to see a list of all changes with more detail.