Skip to content

Commit

Permalink
Adds support for arbitrary JavaScript front matter on top of existing…
Browse files Browse the repository at this point in the history
… `js` engine. Also works with `javascript` #2819
  • Loading branch information
zachleat committed Jul 3, 2024
1 parent 8a39fa9 commit 6623330
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 25 deletions.
34 changes: 34 additions & 0 deletions src/Engines/FrontMatter/JavaScript.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { RetrieveGlobals } from "node-retrieve-globals";

// `javascript` Front Matter Type
export default function (frontMatterCode, context = {}) {
let { filePath } = context;

// context.language would be nice as a guard, but was unreliable
if (frontMatterCode.trimStart().startsWith("{")) {
return context.engines.jsLegacy.parse(frontMatterCode, context);
}

let vm = new RetrieveGlobals(frontMatterCode, {
filePath,
// ignored if vm.Module is stable (or --experimental-vm-modules)
transformEsmImports: true,
});

// Future warning until vm.Module is stable:
// If the frontMatterCode uses `import` this uses the `experimentalModuleApi`
// option in node-retrieve-globals to workaround https://github.com/zachleat/node-retrieve-globals/issues/2
let data = {
page: {
// Theoretically fileSlug and filePathStem could be added here but require extensionMap
inputPath: filePath,
},
};

// this is async, but it’s handled in Eleventy upstream.
return vm.getGlobalContext(data, {
reuseGlobal: true,
dynamicImport: true,
// addRequire: true,
});
}
36 changes: 11 additions & 25 deletions src/UserConfig.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import chalk from "kleur";
import { DateTime } from "luxon";
import yaml from "js-yaml";
import matter from "gray-matter";

import debugUtil from "debug";
import { RetrieveGlobals } from "node-retrieve-globals";
import { DeepCopy, TemplatePath } from "@11ty/eleventy-utils";

import HtmlBasePlugin from "./Plugins/HtmlBasePlugin.js";
Expand All @@ -15,6 +15,7 @@ import EventEmitter from "./Util/AsyncEventEmitter.js";
import EleventyCompatibility from "./Util/Compatibility.js";
import EleventyBaseError from "./Errors/EleventyBaseError.js";
import BenchmarkManager from "./Benchmark/BenchmarkManager.js";
import JavaScriptFrontMatter from "./Engines/FrontMatter/JavaScript.js";

const debug = debugUtil("Eleventy:UserConfig");

Expand Down Expand Up @@ -148,30 +149,15 @@ class UserConfig {
engines: {
yaml: yaml.load.bind(yaml),

node: (frontMatterCode, { filePath }) => {
let vm = new RetrieveGlobals(frontMatterCode, {
filePath,
// ignored if vm.Module is stable (or --experimental-vm-modules)
transformEsmImports: true,
});

// Future warning until vm.Module is stable:
// If the frontMatterCode uses `import` this uses the `experimentalModuleApi`
// option in node-retrieve-globals to workaround https://github.com/zachleat/node-retrieve-globals/issues/2
let data = {
page: {
// Theoretically fileSlug and filePathStem could be added here but require extensionMap
inputPath: filePath,
},
};

// this is async, but it’s handled in Eleventy upstream.
return vm.getGlobalContext(data, {
reuseGlobal: true,
dynamicImport: true,
// addRequire: true,
});
},
// Backwards compatible with `js` object front matter
// https://github.com/11ty/eleventy/issues/2819
javascript: JavaScriptFrontMatter,

// Needed for fallback behavior in the new `javascript` engine
jsLegacy: matter.engines.javascript,

// for compatibility
node: JavaScriptFrontMatter,
},
};

Expand Down
11 changes: 11 additions & 0 deletions test/JavaScriptFrontMatterTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,14 @@ test("Custom Front Matter Parsing Options (using JavaScript node-retrieve-global

t.is(result[0]?.content, `<div>Hi</div><div>Bye</div>`);
});

test("Custom Front Matter Parsing Options (using backwards-compatible `js` instead of node-retrieve-globals)", async (t) => {
let elev = new Eleventy("./test/stubs/script-frontmatter/test-js.njk", "./_site");
elev.disableLogger();

let result = await elev.toJSON();

t.deepEqual(result.length, 1);

t.is(result[0]?.content, `<div>HELLO!</div>`);
});
8 changes: 8 additions & 0 deletions test/stubs/script-frontmatter/test-js.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---javascript
{
myFunction: function() {
return "HELLO!";
}
}
---
<div>{{ myFunction() }}</div>

0 comments on commit 6623330

Please sign in to comment.