@apleasantview/eleventy-plugin-baseline 0.1.0-next.33 → 0.1.0-next.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -23
- package/core/content-map-store.js +51 -0
- package/core/filters/index.js +4 -0
- package/core/filters/isString.js +1 -1
- package/core/filters/related-posts.js +1 -1
- package/core/global-functions/index.js +6 -0
- package/core/logging.js +25 -25
- package/core/page-context.js +310 -0
- package/core/registry.js +110 -0
- package/core/schema.js +37 -0
- package/core/shortcodes/image.js +8 -3
- package/core/shortcodes/index.js +2 -0
- package/core/slug-index.js +61 -0
- package/core/translation-map-store.js +46 -0
- package/core/types.js +73 -0
- package/core/utils/helpers.js +75 -0
- package/core/utils/pick.js +7 -0
- package/core/virtual-dir.js +111 -0
- package/core/wikilinks.js +152 -0
- package/index.js +364 -0
- package/modules/assets/index.js +162 -0
- package/modules/{assets-esbuild/process.js → assets/processors/esbuild-process.js} +3 -1
- package/modules/{assets-postcss/process.js → assets/processors/postcss-process.js} +5 -2
- package/modules/assets/schema.js +14 -0
- package/modules/head/drivers/capo-adapter.js +72 -0
- package/modules/head/drivers/posthtml-head-elements.js +140 -0
- package/modules/head/index.js +106 -0
- package/modules/head/schema.js +42 -0
- package/modules/head/utils/alternates.js +11 -0
- package/modules/head/utils/dedupe.js +47 -0
- package/modules/multilang/index.js +149 -0
- package/modules/navigator/index.js +140 -0
- package/modules/navigator/schema.js +13 -0
- package/modules/{navigator-core → navigator}/templates/navigator-core.html +10 -4
- package/{core → modules/navigator/utils}/debug.js +7 -1
- package/modules/sitemap/index.js +121 -0
- package/modules/{sitemap-core → sitemap}/templates/sitemap-core.html +2 -2
- package/modules/{sitemap-core → sitemap}/templates/sitemap-index.html +2 -2
- package/modules.js +6 -0
- package/package.json +15 -6
- package/core/filters.js +0 -9
- package/core/globals.js +0 -6
- package/core/helpers.js +0 -36
- package/core/modules.js +0 -18
- package/core/shortcodes.js +0 -3
- package/eleventy.config.js +0 -169
- package/modules/assets-core/plugins/assets-core.js +0 -197
- package/modules/head-core/drivers/posthtml-head-elements.js +0 -127
- package/modules/head-core/plugins/head-core.js +0 -75
- package/modules/head-core/utils/head-utils.js +0 -249
- package/modules/multilang-core/plugins/multilang-core.js +0 -118
- package/modules/navigator-core/plugins/navigator-core.js +0 -57
- package/modules/sitemap-core/plugins/sitemap-core.js +0 -88
- /package/core/{globals → global-functions}/date.js +0 -0
- /package/modules/{assets-postcss/fallback → assets/configs}/postcss.config.js +0 -0
- /package/modules/{multilang-core → multilang}/filters/i18n-default-translation.js +0 -0
- /package/modules/{multilang-core → multilang}/filters/i18n-translation-in.js +0 -0
- /package/modules/{multilang-core → multilang}/filters/i18n-translations-for.js +0 -0
|
@@ -10,7 +10,13 @@ const debugOptions = { space: 0 };
|
|
|
10
10
|
* @returns {string}
|
|
11
11
|
*/
|
|
12
12
|
function inspect(obj, options = {}) {
|
|
13
|
-
return utilInspect(obj,
|
|
13
|
+
return utilInspect(obj, {
|
|
14
|
+
depth: 4,
|
|
15
|
+
maxArrayLength: 10,
|
|
16
|
+
breakLength: 80,
|
|
17
|
+
compact: true,
|
|
18
|
+
...options
|
|
19
|
+
});
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
/**
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { normalizeLanguages } from '../../core/utils/helpers.js';
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Sitemap (module)
|
|
11
|
+
*
|
|
12
|
+
* Sitemap generation and per-page sitemap metadata. Layers on Eleventy
|
|
13
|
+
* collections rather than rendering independently. In multilingual mode it
|
|
14
|
+
* partitions per-language sitemaps and emits a sitemap index; otherwise it
|
|
15
|
+
* emits a single flat sitemap.
|
|
16
|
+
*
|
|
17
|
+
* Architecture layer:
|
|
18
|
+
* module
|
|
19
|
+
*
|
|
20
|
+
* System role:
|
|
21
|
+
* Reads the same normalised language map as multilang (via
|
|
22
|
+
* core/utils/helpers.js) and emits virtual templates that Eleventy
|
|
23
|
+
* renders to XML. Pages opt out via `noindex` in the cascade.
|
|
24
|
+
*
|
|
25
|
+
* Lifecycle:
|
|
26
|
+
* build-time → register virtual sitemap templates (single, per-lang,
|
|
27
|
+
* or index)
|
|
28
|
+
* cascade-time → eleventyComputed `page.sitemap` resolves ignore /
|
|
29
|
+
* changefreq / priority on each page
|
|
30
|
+
*
|
|
31
|
+
* Why this exists:
|
|
32
|
+
* Eleventy has no built-in sitemap. Multilingual sites also need
|
|
33
|
+
* partitioning plus an index, which only makes sense once language config
|
|
34
|
+
* is normalised the same way multilang sees it.
|
|
35
|
+
*
|
|
36
|
+
* Scope:
|
|
37
|
+
* Owns computed page.sitemap and the virtual sitemap templates
|
|
38
|
+
* (single-language /sitemap.xml, or per-lang /{lang}/sitemap.xml plus a
|
|
39
|
+
* /sitemap.xml index).
|
|
40
|
+
* Does not own language normalisation (core/utils/helpers.js) or noindex
|
|
41
|
+
* propagation through the cascade.
|
|
42
|
+
*
|
|
43
|
+
* Data flow:
|
|
44
|
+
* settings.languages + page data → computed page.sitemap + virtual
|
|
45
|
+
* templates → /sitemap.xml or per-language + index
|
|
46
|
+
*
|
|
47
|
+
* @param {import("@11ty/eleventy").UserConfig} eleventyConfig
|
|
48
|
+
* @param {Object} moduleContext
|
|
49
|
+
*/
|
|
50
|
+
export function sitemapCore(eleventyConfig, moduleContext) {
|
|
51
|
+
const { state, log } = moduleContext;
|
|
52
|
+
const { settings, options } = state;
|
|
53
|
+
|
|
54
|
+
// --- Language normalization ---
|
|
55
|
+
// Accept languages as array or object; normalize to object map.
|
|
56
|
+
// Drives collection building, locale data, and sitemap-core language config.
|
|
57
|
+
const normalizeLanguageCode = (lang) => (lang || '').toLowerCase().trim();
|
|
58
|
+
const defaultLanguage = normalizeLanguageCode(settings.defaultLanguage);
|
|
59
|
+
const languages = normalizeLanguages(settings, log);
|
|
60
|
+
const hasLanguages = languages && Object.keys(languages).length > 0;
|
|
61
|
+
const isMultilingual = options.multilang === true && defaultLanguage && hasLanguages;
|
|
62
|
+
|
|
63
|
+
// Computed sitemap data: every page gets a page.sitemap object.
|
|
64
|
+
// Pages set noindex in frontmatter or site data to be excluded.
|
|
65
|
+
eleventyConfig.addGlobalData('eleventyComputed.page.sitemap', () => {
|
|
66
|
+
return (data) => ({
|
|
67
|
+
ignore: data.noindex ?? data.page?.noindex ?? data.settings?.noindex ?? false,
|
|
68
|
+
changefreq: '',
|
|
69
|
+
priority: -1
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// --- Virtual sitemap templates ---
|
|
74
|
+
// Read template sources synchronously (same constraint as navigator-core).
|
|
75
|
+
// In multilingual mode: one sitemap per language + a sitemap index.
|
|
76
|
+
// In single-language mode: one flat sitemap at /sitemap.xml.
|
|
77
|
+
// Activation gate lives in the composition root via features.sitemap;
|
|
78
|
+
// the module is only registered when enabled.
|
|
79
|
+
const templatePath = path.join(__dirname, './templates/sitemap-core.html');
|
|
80
|
+
const indexTemplatePath = path.join(__dirname, './templates/sitemap-index.html');
|
|
81
|
+
const baseContent = fs.readFileSync(templatePath, 'utf-8');
|
|
82
|
+
const indexContent = fs.readFileSync(indexTemplatePath, 'utf-8');
|
|
83
|
+
|
|
84
|
+
const langKeys = Object.keys(languages || {});
|
|
85
|
+
const multilingual = isMultilingual;
|
|
86
|
+
|
|
87
|
+
if (multilingual && langKeys.length > 1) {
|
|
88
|
+
for (const lang of langKeys) {
|
|
89
|
+
eleventyConfig.addTemplate(`_baseline/sitemap-core-${lang}.html`, baseContent, {
|
|
90
|
+
permalink: `${lang}/sitemap.xml`,
|
|
91
|
+
title: '',
|
|
92
|
+
description: '',
|
|
93
|
+
layout: null,
|
|
94
|
+
eleventyExcludeFromCollections: true,
|
|
95
|
+
isMultilingual: multilingual,
|
|
96
|
+
sitemapLang: lang,
|
|
97
|
+
_internal: true
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
eleventyConfig.addTemplate('_baseline/sitemap-index.html', indexContent, {
|
|
102
|
+
permalink: '/sitemap.xml',
|
|
103
|
+
title: '',
|
|
104
|
+
description: '',
|
|
105
|
+
layout: null,
|
|
106
|
+
eleventyExcludeFromCollections: true,
|
|
107
|
+
isMultilingual: multilingual,
|
|
108
|
+
languages: languages,
|
|
109
|
+
_internal: true
|
|
110
|
+
});
|
|
111
|
+
} else {
|
|
112
|
+
eleventyConfig.addTemplate('_baseline/sitemap-core.html', baseContent, {
|
|
113
|
+
permalink: '/sitemap.xml',
|
|
114
|
+
title: '',
|
|
115
|
+
description: '',
|
|
116
|
+
layout: null,
|
|
117
|
+
eleventyExcludeFromCollections: true,
|
|
118
|
+
_internal: true
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
|
2
2
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
|
3
|
-
{%- if not
|
|
3
|
+
{%- if not settings.noindex %}
|
|
4
4
|
{%- for item in collections.all %}
|
|
5
5
|
{%- if not item.data.eleventyExcludeFromCollections and (not item.data.sitemap or item.data.sitemap.ignore != true) and item.data.noindex != true %}
|
|
6
|
-
{%- set pageLang = item.data.lang or
|
|
6
|
+
{%- set pageLang = item.data.lang or settings.defaultLanguage %}
|
|
7
7
|
{%- if (not isMultilingual) or (not sitemapLang) or (pageLang == sitemapLang) %}
|
|
8
8
|
{%- set absoluteUrl = item.url | htmlBaseUrl %}
|
|
9
9
|
{%- set lastmod = item.data.sitemap and item.data.sitemap.lastmod or item.date %}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
|
2
2
|
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
3
|
-
{%- if not
|
|
4
|
-
{%- set langs =
|
|
3
|
+
{%- if not settings.noindex %}
|
|
4
|
+
{%- set langs = languages %}
|
|
5
5
|
{%- if langs %}
|
|
6
6
|
{%- for lang, cfg in langs %}
|
|
7
7
|
<sitemap>
|
package/modules.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Modules barrel.
|
|
2
|
+
export { assetsCore } from './modules/assets/index.js';
|
|
3
|
+
export { headCore } from './modules/head/index.js';
|
|
4
|
+
export { multilangCore } from './modules/multilang/index.js';
|
|
5
|
+
export { navigatorCore } from './modules/navigator/index.js';
|
|
6
|
+
export { sitemapCore } from './modules/sitemap/index.js';
|
package/package.json
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apleasantview/eleventy-plugin-baseline",
|
|
3
|
-
"version": "0.1.0-next.
|
|
3
|
+
"version": "0.1.0-next.39",
|
|
4
4
|
"description": "An experimental Swiss army knife toolkit for Eleventy",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "eleventy.config.js",
|
|
7
6
|
"exports": {
|
|
8
|
-
".": "./
|
|
7
|
+
".": "./index.js",
|
|
9
8
|
"./package.json": "./package.json"
|
|
10
9
|
},
|
|
11
10
|
"files": [
|
|
12
|
-
"
|
|
11
|
+
"index.js",
|
|
12
|
+
"modules.js",
|
|
13
13
|
"core/**",
|
|
14
14
|
"modules/**",
|
|
15
15
|
"README.md",
|
|
16
|
-
"LICENSE"
|
|
16
|
+
"LICENSE",
|
|
17
|
+
"!**/__tests__/**",
|
|
18
|
+
"!**/*.test.js"
|
|
17
19
|
],
|
|
18
20
|
"engines": {
|
|
19
21
|
"node": ">=20"
|
|
@@ -38,14 +40,21 @@
|
|
|
38
40
|
"@11ty/eleventy-img": "^6.0.4"
|
|
39
41
|
},
|
|
40
42
|
"dependencies": {
|
|
43
|
+
"@11ty/eleventy-utils": "^2.0.7",
|
|
44
|
+
"@rviscomi/capo.js": "^2.1.0",
|
|
41
45
|
"cssnano": "^7.1.2",
|
|
42
46
|
"dotenv": "^17.2.3",
|
|
43
47
|
"esbuild": "0.27.0",
|
|
48
|
+
"kleur": "^4.1.5",
|
|
49
|
+
"luxon": "^3.7.2",
|
|
50
|
+
"markdown-it": "^14.1.1",
|
|
44
51
|
"postcss": "^8.5.6",
|
|
45
52
|
"postcss-import": "^16.1.1",
|
|
46
53
|
"postcss-import-ext-glob": "^2.1.1",
|
|
47
54
|
"postcss-load-config": "^6.0.1",
|
|
48
|
-
"postcss-preset-env": "^10.4.0"
|
|
55
|
+
"postcss-preset-env": "^10.4.0",
|
|
56
|
+
"slugify": "^1.6.6",
|
|
57
|
+
"zod": "^4.3.6"
|
|
49
58
|
},
|
|
50
59
|
"sideEffects": false
|
|
51
60
|
}
|
package/core/filters.js
DELETED
package/core/globals.js
DELETED
package/core/helpers.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { TemplatePath } from '@11ty/eleventy-utils';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Helper function to add trailing slash to a path
|
|
5
|
-
* @param {string} path
|
|
6
|
-
* @returns {string}
|
|
7
|
-
*/
|
|
8
|
-
export function addTrailingSlash(path) {
|
|
9
|
-
if (path.slice(-1) === '/') {
|
|
10
|
-
return path;
|
|
11
|
-
}
|
|
12
|
-
return path + '/';
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Resolves the assets directory paths from config.
|
|
17
|
-
* Joins inputDir/outputDir with rawDir, normalizes, and adds trailing slashes.
|
|
18
|
-
* @param {string} inputDir - The input directory (e.g., "./src/").
|
|
19
|
-
* @param {string} outputDir - The output directory (e.g., "./dist/").
|
|
20
|
-
* @param {string} rawDir - Raw directory value from config (e.g., "assets").
|
|
21
|
-
* @returns {{assetsDir: string, assetsOutputDir: string}}
|
|
22
|
-
*/
|
|
23
|
-
export function resolveAssetsDir(inputDir, outputDir, rawDir) {
|
|
24
|
-
// Join input/output with assets subdir and normalize
|
|
25
|
-
const joinedInput = TemplatePath.join(inputDir, rawDir || '');
|
|
26
|
-
const joinedOutput = TemplatePath.join(outputDir, rawDir || '');
|
|
27
|
-
|
|
28
|
-
const assetsDir = addTrailingSlash(TemplatePath.standardizeFilePath(joinedInput));
|
|
29
|
-
const assetsOutputDir = addTrailingSlash(TemplatePath.standardizeFilePath(joinedOutput));
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
assetsDir,
|
|
33
|
-
assetsOutputDir
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
package/core/modules.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
// Eleventy plugins
|
|
2
|
-
import { EleventyHtmlBasePlugin } from '@11ty/eleventy';
|
|
3
|
-
|
|
4
|
-
// Custom plugins
|
|
5
|
-
import multilangCore from '../modules/multilang-core/plugins/multilang-core.js';
|
|
6
|
-
import navigatorCore from '../modules/navigator-core/plugins/navigator-core.js';
|
|
7
|
-
import assetsCore from '../modules/assets-core/plugins/assets-core.js';
|
|
8
|
-
import headCore from '../modules/head-core/plugins/head-core.js';
|
|
9
|
-
import sitemapCore from '../modules/sitemap-core/plugins/sitemap-core.js';
|
|
10
|
-
|
|
11
|
-
export default {
|
|
12
|
-
EleventyHtmlBasePlugin,
|
|
13
|
-
multilangCore,
|
|
14
|
-
navigatorCore,
|
|
15
|
-
assetsCore,
|
|
16
|
-
headCore,
|
|
17
|
-
sitemapCore
|
|
18
|
-
};
|
package/core/shortcodes.js
DELETED
package/eleventy.config.js
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
|
-
import globals from './core/globals.js';
|
|
3
|
-
import debug from './core/debug.js';
|
|
4
|
-
import filters from './core/filters.js';
|
|
5
|
-
import modules from './core/modules.js';
|
|
6
|
-
import shortcodes from './core/shortcodes.js';
|
|
7
|
-
import { eleventyImageOnRequestDuringServePlugin } from '@11ty/eleventy-img';
|
|
8
|
-
|
|
9
|
-
import { createRequire } from 'node:module';
|
|
10
|
-
const __require = createRequire(import.meta.url);
|
|
11
|
-
|
|
12
|
-
const { name, version } = __require('./package.json');
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Eleventy Plugin Baseline.
|
|
16
|
-
*
|
|
17
|
-
* @typedef {Object} BaselineOptions
|
|
18
|
-
* @property {boolean} [verbose=false] Enable extra logging from the plugin.
|
|
19
|
-
* @property {boolean} [enableNavigatorTemplate=false] Register navigator template/routes.
|
|
20
|
-
* @property {boolean} [enableSitemapTemplate=true] Register sitemap template/routes.
|
|
21
|
-
* @property {boolean} [multilingual=false] Enable multilang core (requires defaultLanguage + languages).
|
|
22
|
-
* @property {string} [defaultLanguage] IETF/BCP47 default language code (used when multilingual=true).
|
|
23
|
-
* @property {Record<string, unknown>} [languages={}] Language definition map (shape not enforced; only presence/keys checked).
|
|
24
|
-
* @property {Object} [assetsESBuild] Options forwarded to assets-esbuild (minify/target).
|
|
25
|
-
*
|
|
26
|
-
* @param {BaselineOptions} [options={}] Custom options for the plugin.
|
|
27
|
-
* @returns {(eleventyConfig: import("@11ty/eleventy").UserConfig) => Promise<void>}
|
|
28
|
-
*/
|
|
29
|
-
export default function baseline(options = {}) {
|
|
30
|
-
/** @param {import("@11ty/eleventy").UserConfig} eleventyConfig */
|
|
31
|
-
const plugin = async function (eleventyConfig) {
|
|
32
|
-
try {
|
|
33
|
-
eleventyConfig.versionCheck('>=3.0');
|
|
34
|
-
} catch (e) {
|
|
35
|
-
console.log(`[eleventy-plugin-baseline] WARN Eleventy plugin compatibility: ${e.message}`);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// --- Options ---
|
|
39
|
-
// Merge user options with defaults, detect environment capabilities,
|
|
40
|
-
// and expose everything as _baseline global data for templates.
|
|
41
|
-
const hasImageTransformPlugin = eleventyConfig.hasPlugin('eleventyImageTransformPlugin');
|
|
42
|
-
|
|
43
|
-
const userOptions = {
|
|
44
|
-
version,
|
|
45
|
-
name,
|
|
46
|
-
verbose: options.verbose ?? false,
|
|
47
|
-
hasImageTransformPlugin,
|
|
48
|
-
enableNavigatorTemplate: options.enableNavigatorTemplate ?? false,
|
|
49
|
-
enableSitemapTemplate: options.enableSitemapTemplate ?? true,
|
|
50
|
-
filterAllCollection: options.filterAllCollection ?? true,
|
|
51
|
-
assets: {
|
|
52
|
-
esbuild: options.assetsESBuild ?? {}
|
|
53
|
-
},
|
|
54
|
-
multilingual: options.multilingual ?? false,
|
|
55
|
-
...options
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// --- Language normalization ---
|
|
59
|
-
// Accept languages as array or object; normalize to object map.
|
|
60
|
-
// Drives multilang-core registration and sitemap-core language config.
|
|
61
|
-
const normalizedLanguages = Array.isArray(userOptions.languages)
|
|
62
|
-
? Object.fromEntries(
|
|
63
|
-
userOptions.languages
|
|
64
|
-
.filter((lang) => typeof lang === 'string' && lang.trim())
|
|
65
|
-
.map((lang) => [lang.trim(), {}])
|
|
66
|
-
)
|
|
67
|
-
: userOptions.languages && typeof userOptions.languages === 'object'
|
|
68
|
-
? userOptions.languages
|
|
69
|
-
: null;
|
|
70
|
-
|
|
71
|
-
if (userOptions.verbose && Array.isArray(userOptions.languages)) {
|
|
72
|
-
const normalizedCount = normalizedLanguages ? Object.keys(normalizedLanguages).length : 0;
|
|
73
|
-
if (normalizedCount !== userOptions.languages.length) {
|
|
74
|
-
console.warn('[baseline] Some languages entries were invalid and were dropped.');
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
userOptions.languages = normalizedLanguages;
|
|
79
|
-
const languages = normalizedLanguages;
|
|
80
|
-
const hasLanguages = languages && Object.keys(languages).length > 0;
|
|
81
|
-
const isMultilingual = userOptions.multilingual === true && userOptions.defaultLanguage && hasLanguages;
|
|
82
|
-
|
|
83
|
-
// --- Core setup ---
|
|
84
|
-
// Global data, globals registration, static passthrough, drafts preprocessor.
|
|
85
|
-
eleventyConfig.addGlobalData('_baseline', userOptions);
|
|
86
|
-
globals(eleventyConfig);
|
|
87
|
-
eleventyConfig.addPassthroughCopy({ './src/static': '/' });
|
|
88
|
-
|
|
89
|
-
// Drafts preprocessor — skip draft pages during production builds.
|
|
90
|
-
// Guarded against double-registration; user config wins if already set.
|
|
91
|
-
if (!eleventyConfig.preprocessors.drafts) {
|
|
92
|
-
eleventyConfig.addPreprocessor('drafts', '*', (data) => {
|
|
93
|
-
if (data.draft && process.env.ELEVENTY_RUN_MODE === 'build') {
|
|
94
|
-
return false;
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// --- Modules ---
|
|
100
|
-
// Registration order matters: multilang first (sets up locale data),
|
|
101
|
-
// then assets, head, sitemap. Navigator is last (debug only).
|
|
102
|
-
|
|
103
|
-
if (isMultilingual) {
|
|
104
|
-
eleventyConfig.addPlugin(modules.multilangCore, {
|
|
105
|
-
defaultLanguage: userOptions.defaultLanguage,
|
|
106
|
-
languages
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
eleventyConfig.addPlugin(modules.EleventyHtmlBasePlugin, {
|
|
111
|
-
baseHref: process.env.URL || eleventyConfig.pathPrefix
|
|
112
|
-
});
|
|
113
|
-
eleventyConfig.addPlugin(modules.assetsCore, { esbuild: userOptions.assets.esbuild });
|
|
114
|
-
|
|
115
|
-
eleventyConfig.addPlugin(modules.headCore);
|
|
116
|
-
eleventyConfig.addPlugin(modules.sitemapCore, {
|
|
117
|
-
enableSitemapTemplate: userOptions.enableSitemapTemplate,
|
|
118
|
-
multilingual: isMultilingual,
|
|
119
|
-
languages
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
// --- Filters ---
|
|
123
|
-
eleventyConfig.addFilter('markdownify', filters.markdownFilter);
|
|
124
|
-
eleventyConfig.addFilter('relatedPosts', filters.relatedPostsFilter);
|
|
125
|
-
eleventyConfig.addFilter('isString', filters.isStringFilter);
|
|
126
|
-
|
|
127
|
-
// --- Shortcodes ---
|
|
128
|
-
eleventyConfig.addShortcode('image', shortcodes.imageShortcode);
|
|
129
|
-
|
|
130
|
-
// --- Image dev server ---
|
|
131
|
-
// Serves on-demand image transforms during `--serve` without writing to disk.
|
|
132
|
-
eleventyConfig.addPlugin(eleventyImageOnRequestDuringServePlugin);
|
|
133
|
-
|
|
134
|
-
// --- Debug ---
|
|
135
|
-
// Underscore-prefixed filters and navigator template for inspecting
|
|
136
|
-
// data at render time. Not part of the public API surface.
|
|
137
|
-
eleventyConfig.addFilter('_inspect', debug.inspect);
|
|
138
|
-
eleventyConfig.addFilter('_json', debug.json);
|
|
139
|
-
eleventyConfig.addFilter('_keys', debug.keys);
|
|
140
|
-
eleventyConfig.addPlugin(modules.navigatorCore, { enableNavigatorTemplate: userOptions.enableNavigatorTemplate });
|
|
141
|
-
|
|
142
|
-
// Temporary content map debug listener.
|
|
143
|
-
eleventyConfig.on('eleventy.contentMap', async ({ inputPathToUrl, urlToInputPath }) => {
|
|
144
|
-
let debuginput = inputPathToUrl;
|
|
145
|
-
let debugurl = urlToInputPath;
|
|
146
|
-
|
|
147
|
-
return (debuginput, debugurl);
|
|
148
|
-
});
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
// Set a named function identity so eleventyConfig.hasPlugin() can detect this plugin.
|
|
152
|
-
Object.defineProperty(plugin, 'name', { value: `${name}` });
|
|
153
|
-
return plugin;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// --- Eleventy directory and template config ---
|
|
157
|
-
// Exported separately so consuming sites can re-export without duplicating values.
|
|
158
|
-
export const config = {
|
|
159
|
-
dir: {
|
|
160
|
-
input: 'src',
|
|
161
|
-
output: 'dist',
|
|
162
|
-
data: '_data',
|
|
163
|
-
includes: '_includes',
|
|
164
|
-
assets: 'assets'
|
|
165
|
-
},
|
|
166
|
-
htmlTemplateEngine: 'njk',
|
|
167
|
-
markdownTemplateEngine: 'njk',
|
|
168
|
-
templateFormats: ['html', 'njk', 'md']
|
|
169
|
-
};
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { TemplatePath } from '@11ty/eleventy-utils';
|
|
3
|
-
import { addTrailingSlash, resolveAssetsDir } from '../../../core/helpers.js';
|
|
4
|
-
import { warnIfVerbose, getVerbose } from '../../../core/logging.js';
|
|
5
|
-
|
|
6
|
-
import assetsESbuild from '../../assets-esbuild/process.js';
|
|
7
|
-
import assetsPostCSS from '../../assets-postcss/process.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Sync the cache object with resolved directory paths.
|
|
11
|
-
* Called once at registration time and again on the eleventy.directories event
|
|
12
|
-
* when Eleventy finalizes its directory config.
|
|
13
|
-
*/
|
|
14
|
-
const syncCacheFromDirectories = (cache, dirs, rawDir) => {
|
|
15
|
-
const inputDir = TemplatePath.addLeadingDotSlash(dirs.input || './');
|
|
16
|
-
const outputDir = TemplatePath.addLeadingDotSlash(dirs.output || './');
|
|
17
|
-
const { assetsDir, assetsOutputDir } = resolveAssetsDir(inputDir, outputDir, rawDir);
|
|
18
|
-
|
|
19
|
-
cache.input = addTrailingSlash(inputDir);
|
|
20
|
-
cache.output = addTrailingSlash(outputDir);
|
|
21
|
-
cache.assetsInput = assetsDir;
|
|
22
|
-
cache.assetsOutput = assetsOutputDir;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Guard: resolve directories from eleventyConfig.dir if the eleventy.directories
|
|
27
|
-
* event hasn't fired yet (e.g. when global data or watch targets are read early).
|
|
28
|
-
*/
|
|
29
|
-
const ensureCache = (cache, eleventyConfig, rawDir, verbose) => {
|
|
30
|
-
if (cache.assetsInput) return;
|
|
31
|
-
syncCacheFromDirectories(cache, eleventyConfig.dir || {}, rawDir);
|
|
32
|
-
warnIfVerbose(verbose, 'Fallback directory resolution');
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* eleventy-plugin-assets-core
|
|
37
|
-
*
|
|
38
|
-
* The single assets plugin. Owns all Eleventy wiring for JS and CSS processing:
|
|
39
|
-
* directory resolution, template formats, extensions, compile guards, inline
|
|
40
|
-
* filters, watch targets, and global data. Processing logic lives in the
|
|
41
|
-
* pure functions imported from assets-esbuild and assets-postcss.
|
|
42
|
-
*
|
|
43
|
-
* Options:
|
|
44
|
-
* - verbose (boolean, default global baseline verbose): enable verbose logs.
|
|
45
|
-
* - esbuild (object): options forwarded to esbuild (minify, target).
|
|
46
|
-
* Defaults live in assets-esbuild/process.js — pass only overrides.
|
|
47
|
-
*/
|
|
48
|
-
/** @param {import("@11ty/eleventy").UserConfig} eleventyConfig */
|
|
49
|
-
export default function assetsCore(eleventyConfig, options = {}) {
|
|
50
|
-
const verbose = getVerbose(eleventyConfig) || options.verbose || false;
|
|
51
|
-
const userKey = 'assets';
|
|
52
|
-
|
|
53
|
-
// Extract raw directory value from config (can be done early).
|
|
54
|
-
const rawDir = eleventyConfig.dir?.[userKey] || userKey;
|
|
55
|
-
|
|
56
|
-
// Cache holds resolved paths. Initialized as nulls, populated immediately
|
|
57
|
-
// by syncCacheFromDirectories, then updated when eleventy.directories fires.
|
|
58
|
-
const cache = {
|
|
59
|
-
input: null,
|
|
60
|
-
output: null,
|
|
61
|
-
assetsInput: null,
|
|
62
|
-
assetsOutput: null
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
syncCacheFromDirectories(cache, eleventyConfig.dir || {}, rawDir);
|
|
66
|
-
|
|
67
|
-
// Update cache when Eleventy finalizes directories, and register a virtual
|
|
68
|
-
// `directories.assets` key so other code can read the resolved assets path.
|
|
69
|
-
eleventyConfig.on('eleventy.directories', (directories) => {
|
|
70
|
-
syncCacheFromDirectories(cache, directories, rawDir);
|
|
71
|
-
|
|
72
|
-
// Add a virtual directory key only if not already defined/configurable.
|
|
73
|
-
const existing = Object.getOwnPropertyDescriptor(eleventyConfig.directories, userKey);
|
|
74
|
-
if (existing && existing.configurable === false) {
|
|
75
|
-
warnIfVerbose(verbose, `directories[${userKey}] already defined; skipping`);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
Object.defineProperty(eleventyConfig.directories, userKey, {
|
|
80
|
-
get() {
|
|
81
|
-
return cache.assetsInput;
|
|
82
|
-
},
|
|
83
|
-
enumerable: true,
|
|
84
|
-
configurable: false
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
// Expose resolved assets paths as global data for templates.
|
|
89
|
-
// Templates use _baseline.assets.input to build paths for inline filters.
|
|
90
|
-
eleventyConfig.addGlobalData('_baseline.assets', () => {
|
|
91
|
-
ensureCache(cache, eleventyConfig, rawDir, verbose);
|
|
92
|
-
return {
|
|
93
|
-
input: cache.assetsInput,
|
|
94
|
-
output: cache.assetsOutput
|
|
95
|
-
};
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
// Watch common asset formats so edits trigger reloads during --serve.
|
|
99
|
-
ensureCache(cache, eleventyConfig, rawDir, verbose);
|
|
100
|
-
const watchGlob = TemplatePath.join(cache.assetsInput, '**/*.{css,js,svg,png,jpeg,jpg,webp,gif,avif}');
|
|
101
|
-
eleventyConfig.addWatchTarget(watchGlob);
|
|
102
|
-
|
|
103
|
-
// --- JS (esbuild) ---
|
|
104
|
-
// Register js as a template format. Only index.js files under assets/js/
|
|
105
|
-
// are compiled; everything else (11tydata.js, non-entry scripts) is skipped
|
|
106
|
-
// by the compile guard. The inline filter wraps the same process function.
|
|
107
|
-
// Defaults (minify, target) live in assets-esbuild/process.js.
|
|
108
|
-
|
|
109
|
-
const esbuildOptions = options.esbuild || {};
|
|
110
|
-
const jsDir = `${cache.assetsInput}js/`;
|
|
111
|
-
|
|
112
|
-
eleventyConfig.addTemplateFormats('js');
|
|
113
|
-
|
|
114
|
-
// Prevent Eleventy from processing 11tydata.js files as templates.
|
|
115
|
-
// The compile guard below also filters these, but without this ignore
|
|
116
|
-
// Eleventy still enters them into the template graph (data cascade,
|
|
117
|
-
// permalink computation) before compile gets a chance to reject them.
|
|
118
|
-
eleventyConfig.ignores.add(`${cache.input}**/*.11tydata.js`);
|
|
119
|
-
|
|
120
|
-
eleventyConfig.addExtension('js', {
|
|
121
|
-
outputFileExtension: 'js',
|
|
122
|
-
useLayouts: false,
|
|
123
|
-
read: false,
|
|
124
|
-
compileOptions: {
|
|
125
|
-
permalink: true,
|
|
126
|
-
cache: true
|
|
127
|
-
},
|
|
128
|
-
// Compile guard: only process index.js files under the assets js directory.
|
|
129
|
-
// Returning undefined skips the file without error.
|
|
130
|
-
compile: async function (_inputContent, inputPath) {
|
|
131
|
-
if (
|
|
132
|
-
inputPath.includes('11tydata.js') ||
|
|
133
|
-
!inputPath.startsWith(jsDir) ||
|
|
134
|
-
path.basename(inputPath) !== 'index.js'
|
|
135
|
-
) {
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return async () => assetsESbuild(inputPath, esbuildOptions);
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// Inline filter: bundle a JS file and wrap in <script> tags.
|
|
144
|
-
// Accepts per-call esbuild options (merged with defaults in process.js).
|
|
145
|
-
// Eleventy's addAsyncFilter handles the Nunjucks callback bridge,
|
|
146
|
-
// so this is a plain async function.
|
|
147
|
-
eleventyConfig.addAsyncFilter('inlineESbuild', async function (inputPath, opts = {}) {
|
|
148
|
-
try {
|
|
149
|
-
const js = await assetsESbuild(inputPath, opts);
|
|
150
|
-
return `<script>${js}</script>`;
|
|
151
|
-
} catch {
|
|
152
|
-
// Non-fatal: return an error comment so the build doesn't break.
|
|
153
|
-
return `<script>/* Error processing JS */</script>`;
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
// --- CSS (PostCSS) ---
|
|
158
|
-
// Register css as a template format. Only index.css files under assets/css/
|
|
159
|
-
// are compiled; non-entry CSS is skipped. Reads from disk (read: false) —
|
|
160
|
-
// the process function owns its own I/O. Config loading and caching live
|
|
161
|
-
// in assets-postcss/process.js.
|
|
162
|
-
|
|
163
|
-
const cssDir = `${cache.assetsInput}css/`;
|
|
164
|
-
|
|
165
|
-
eleventyConfig.addTemplateFormats('css');
|
|
166
|
-
|
|
167
|
-
eleventyConfig.addExtension('css', {
|
|
168
|
-
outputFileExtension: 'css',
|
|
169
|
-
useLayouts: false,
|
|
170
|
-
read: false,
|
|
171
|
-
compileOptions: {
|
|
172
|
-
permalink: true,
|
|
173
|
-
cache: true
|
|
174
|
-
},
|
|
175
|
-
// Compile guard: only process index.css files under the assets css directory.
|
|
176
|
-
compile: async function (_inputContent, inputPath) {
|
|
177
|
-
if (!inputPath.startsWith(cssDir) || path.basename(inputPath) !== 'index.css') {
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return async () => assetsPostCSS(inputPath);
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
// Inline filter: process a CSS file through PostCSS and wrap in <style> tags.
|
|
186
|
-
// Eleventy's addAsyncFilter handles the Nunjucks callback bridge,
|
|
187
|
-
// so this is a plain async function.
|
|
188
|
-
eleventyConfig.addAsyncFilter('inlinePostCSS', async function (inputPath) {
|
|
189
|
-
try {
|
|
190
|
-
const css = await assetsPostCSS(inputPath);
|
|
191
|
-
return `<style>${css}</style>`;
|
|
192
|
-
} catch {
|
|
193
|
-
// Non-fatal: return an error comment so the build doesn't break.
|
|
194
|
-
return `<style>/* Error processing CSS */</style>`;
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
}
|