New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@lit-labs/eleventy-plugin-lit

Package Overview
Dependencies
Maintainers
9
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lit-labs/eleventy-plugin-lit - npm Package Compare versions

Comparing version 0.1.1 to 0.2.0

worker/worker.d.ts

7

index.d.ts

@@ -6,8 +6,3 @@ /**

*/
/// <reference types="node" />
declare const path: import("path").PlatformPath;
declare type LitPluginOptions = {
componentModules?: string[];
};
declare const iterableToString: (iterable: Iterable<string>) => string;
export {};
//# sourceMappingURL=index.d.ts.map

@@ -7,27 +7,96 @@ "use strict";

*/
// Note this file must be CommonJS for compatibility with Eleventy, but we can't
// rely on TypeScript's CommonJS output mode, because that will also convert
// dynamic import() calls to require() calls. That would be bad, because we need
// to import ES modules from @lit-labs/ssr, which requires preserved import()
// calls.
//
// So instead we use TypeScript's ESM output mode, but explicitly write
// require() calls for the CommonJS modules we import.
//
// See https://github.com/microsoft/TypeScript/issues/43329 and
// https://github.com/microsoft/TypeScript#22321 for more details.
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require('path');
module.exports = {
configFunction: function (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
eleventyConfig, { componentModules } = {}) {
if (require('vm').Module === undefined) {
// Show a more friendly error message if the --experimental-vm-modules
// flag is missing.
// TODO(aomarks) Rendering in a worker would remove the need for this flag.
const red = '\u001b[31m';
const yellow = '\u001b[33m';
const reset = '\u001b[0m';
console.error(`${yellow}
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const path = __importStar(require("path"));
const worker_threads_1 = require("worker_threads");
function configureWorker(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
eleventyConfig, resolvedComponentModules) {
let worker;
const requestIdResolveMap = new Map();
let requestId = 0;
eleventyConfig.on('eleventy.before', async () => {
worker = new worker_threads_1.Worker(path.resolve(__dirname, './worker/worker.js'));
worker.on('error', (err) => {
console.error('Unexpected error while rendering lit component in worker thread', err);
throw err;
});
let requestResolve;
const requestPromise = new Promise((resolve) => {
requestResolve = resolve;
});
worker.on('message', (message) => {
switch (message.type) {
case 'initialize-response': {
requestResolve();
break;
}
case 'render-response': {
const { id, rendered } = message;
const resolve = requestIdResolveMap.get(id);
if (resolve === undefined) {
throw new Error('@lit-labs/eleventy-plugin-lit received invalid render-response message');
}
resolve(rendered);
requestIdResolveMap.delete(id);
break;
}
}
});
const message = {
type: 'initialize-request',
imports: resolvedComponentModules,
};
worker.postMessage(message);
await requestPromise;
});
eleventyConfig.on('eleventy.after', async () => {
await worker.terminate();
});
eleventyConfig.addTransform('render-lit', async (content, outputPath) => {
if (!outputPath.endsWith('.html')) {
return content;
}
const renderedContent = await new Promise((resolve) => {
requestIdResolveMap.set(requestId, resolve);
const message = {
type: 'render-request',
id: requestId++,
content,
};
worker.postMessage(message);
});
const outerMarkersTrimmed = trimOuterMarkers(renderedContent);
return outerMarkersTrimmed;
});
}
function configureVm(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
eleventyConfig, resolvedComponentModules) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
if (require('vm').Module === undefined) {
// Show a more friendly error message if the --experimental-vm-modules
// flag is missing.
const red = '\u001b[31m';
const yellow = '\u001b[33m';
const reset = '\u001b[0m';
console.error(`${yellow}
┌─────────────────────${red} ERROR ${yellow}─────────────────────┐

@@ -44,5 +113,53 @@ │${reset} ${yellow}│

${reset}`);
throw new Error('@lit-labs/eleventy-plugin-lit requires that eleventy be launched ' +
'with NODE_OPTIONS=--experimental-vm-modules');
throw new Error('@lit-labs/eleventy-plugin-lit requires that eleventy be launched ' +
'with NODE_OPTIONS=--experimental-vm-modules');
}
const renderModulePath = path.join(process.cwd(), 'arbitrary.js');
let contextifiedRender;
let contextifiedUnsafeHTML;
// Create a fresh context before each build, so that our module cache resets
// on every --watch mode build.
// TODO(aomarks) For better performance, we could re-use contexts between
// build, but selectively invalidate its cache so that only the user's
// modules are reloaded.
eleventyConfig.on('eleventy.before', async () => {
// Note this file must be CommonJS for compatibility with Eleventy, but
// TypeScript's CommonJS output mode will also convert dynamic import()
// calls to require() calls. That would be bad, because we need
// to import ES modules from @lit-labs/ssr, which requires preserved
// import() calls.
// So we use eval(`import()`) instead
//
// See https://github.com/microsoft/TypeScript/issues/43329 for details
const { getWindow } = (await eval(`import('@lit-labs/ssr/lib/dom-shim.js')`));
const { ModuleLoader } = (await eval(`import('@lit-labs/ssr/lib/module-loader.js')`));
const window = getWindow({ includeJSBuiltIns: true });
const loader = new ModuleLoader({ global: window });
// TODO(aomarks) Replace with concurrent Promise.all version once
// https://github.com/lit/lit/issues/2549 has been addressed.
for (const module of resolvedComponentModules) {
await loader.importModule(module, renderModulePath);
}
contextifiedRender = (await loader.importModule('@lit-labs/ssr/lib/render-lit-html.js', renderModulePath)).module.namespace.render;
// TOOD(aomarks) We could also directly synthesize an html TemplateResult
// instead of doing so via the the unsafeHTML directive. The directive is
// performing some extra validation that doesn't really apply to us.
contextifiedUnsafeHTML = (await loader.importModule('lit/directives/unsafe-html.js', renderModulePath)).module.namespace.unsafeHTML;
});
eleventyConfig.addTransform('render-lit', async (content, outputPath) => {
if (!outputPath.endsWith('.html')) {
return content;
}
// TODO(aomarks) Maybe we should provide a `renderUnsafeHtml` function
// directly from SSR which does this.
const iterator = contextifiedRender(contextifiedUnsafeHTML(content));
const concatenated = iterableToString(iterator);
const outerMarkersTrimmed = trimOuterMarkers(concatenated);
return outerMarkersTrimmed;
});
}
module.exports = {
configFunction: function (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
eleventyConfig, { componentModules, mode = 'worker' } = {}) {
if (componentModules === undefined || componentModules.length === 0) {

@@ -53,48 +170,29 @@ // If there are no component modules, we could never have anything to

}
const renderModulePath = path.join(process.cwd(), 'arbitrary.js');
const resolvedComponentModules = componentModules.map((module) => path.resolve(process.cwd(), module));
let contextifiedRender;
let contextifiedUnsafeHTML;
// Create a fresh context before each build, so that our module cache resets
// on every --watch mode build.
// TODO(aomarks) For better performance, we could re-use contexts between
// build, but selectively invalidate its cache so that only the user's
// modules are reloaded.
eleventyConfig.on('eleventy.before', async () => {
const { getWindow } = await import('@lit-labs/ssr/lib/dom-shim.js');
const { ModuleLoader } = await import('@lit-labs/ssr/lib/module-loader.js');
const window = getWindow({ includeJSBuiltIns: true });
const loader = new ModuleLoader({ global: window });
// TODO(aomarks) Replace with concurrent Promise.all version once
// https://github.com/lit/lit/issues/2549 has been addressed.
for (const module of resolvedComponentModules) {
await loader.importModule(module, renderModulePath);
switch (mode) {
case 'worker': {
configureWorker(eleventyConfig, resolvedComponentModules);
break;
}
contextifiedRender = (await loader.importModule('@lit-labs/ssr/lib/render-lit-html.js', renderModulePath)).module.namespace.render;
// TOOD(aomarks) We could also directly synthesize an html TemplateResult
// instead of doing so via the the unsafeHTML directive. The directive is
// performing some extra validation that doesn't really apply to us.
contextifiedUnsafeHTML = (await loader.importModule('lit/directives/unsafe-html.js', renderModulePath)).module.namespace.unsafeHTML;
});
eleventyConfig.addTransform('render-lit', async (content, outputPath) => {
if (!outputPath.endsWith('.html')) {
return content;
case 'vm': {
configureVm(eleventyConfig, resolvedComponentModules);
break;
}
// TODO(aomarks) Maybe we should provide a `renderUnsafeHtml` function
// directly from SSR which does this.
const iterator = contextifiedRender(contextifiedUnsafeHTML(content));
const concatenated = iterableToString(iterator);
// Lit SSR includes comment markers to track the outer template from
// the template we've generated here, but it's not possible for this
// outer template to be hydrated, so they serve no purpose.
// TODO(aomarks) Maybe we should provide an option to SSR option to skip
// outer markers (though note there are 2 layers of markers due to the
// use of the unsafeHTML directive).
const outerMarkersTrimmed = concatenated
.replace(/^((<!--[^<>]*-->)|(<\?>)|\s)+/, '')
.replace(/((<!--[^<>]*-->)|(<\?>)|\s)+$/, '');
return outerMarkersTrimmed;
});
default: {
throw new Error('Invalid mode provided for @lit-labs/eleventy-plugin-lit');
}
}
},
};
// Lit SSR includes comment markers to track the outer template from
// the template we've generated here, but it's not possible for this
// outer template to be hydrated, so they serve no purpose.
// TODO(aomarks) Maybe we should provide an option to SSR option to skip
// outer markers (though note there are 2 layers of markers due to the
// use of the unsafeHTML directive).
function trimOuterMarkers(renderedContent) {
return renderedContent
.replace(/^((<!--[^<>]*-->)|(<\?>)|\s)+/, '')
.replace(/((<!--[^<>]*-->)|(<\?>)|\s)+$/, '');
}
// Assuming this is faster than Array.from(iter).join();

@@ -101,0 +199,0 @@ // TODO: perf test

{
"name": "@lit-labs/eleventy-plugin-lit",
"version": "0.1.1",
"version": "0.2.0",
"description": "Eleventy plugin for rendering Lit components.",

@@ -24,3 +24,4 @@ "author": "Google LLC",

"files": [
"/index.{d.ts,d.ts.map,js,js.map}"
"/index.{d.ts,d.ts.map,js,js.map}",
"/worker/worker.{d.ts,d.ts.map,js,js.map}"
],

@@ -36,3 +37,3 @@ "engines": {

"build:demo:watch": "cd demo && NODE_OPTIONS=--experimental-vm-modules eleventy --watch",
"clean": "rimraf \"index.{js,js.map,d.ts,d.ts.map}\" \"test/**/*.{js,js.map,d.ts,d.ts.map}\" demo/_site .tsbuildinfo",
"clean": "rimraf \"index.{js,js.map,d.ts,d.ts.map}\" \"test/**/*.{js,js.map,d.ts,d.ts.map}\" \"worker/**/*.{js,js.map,d.ts,d.ts.map}\" demo/_site *.tsbuildinfo",
"serve:demo": "wds --watch --node-resolve --open demo/_site/test",

@@ -39,0 +40,0 @@ "test": "uvu test/ \".*-test.js$\""

@@ -57,2 +57,3 @@ # @lit-labs/eleventy-plugin-lit

eleventyConfig.addPlugin(litPlugin, {
mode: 'worker',
componentModules: [

@@ -67,2 +68,20 @@ 'js/demo-greeter.js',

### Configure mode
Use the `mode` setting to tell the plugin which mode to use for rendering.
The plugin currently supports either `'worker'` or `'vm'`.
`'worker'` mode (default) utilizes
[worker threads](https://nodejs.org/api/worker_threads.html#worker-threads)
to render components in isolation.
`'vm'` mode utilizes [`vm.Module`](https://nodejs.org/api/vm.html#class-vmmodule)
for context isolation and therefore eleventy _must_ be executed with the
`--experimental-vm-modules` Node flag enabled. This flag is available in
Node versions `12.16.0` and above.
```sh
NODE_OPTIONS=--experimental-vm-modules eleventy
```
### Configure component modules

@@ -84,18 +103,20 @@

### Enable experimental VM modules
Note that in `'worker'` mode, Node determines the module system
[accordingly](https://nodejs.org/api/packages.html#determining-module-system),
and as such care must be taken to ensure Node reads them as ESM files
while still reading the eleventy config file as CommonJS.
> 🚧 Note: Removing this requirement is on the [roadmap](#roadmap). Follow
> [#2494](https://github.com/lit/lit/issues/2484) for progress and discussion.
> 🚧
Some options are:
Eleventy _must_ be executed with the
[`--experimental-vm-modules`](https://nodejs.org/api/vm.html#class-vmmodule)
Node flag enabled. This flag is available in Node versions `12.16.0` and above.
This flag allows the lit plugin to render components without modifying any
global state, and enables compatibility with Eleventy's `--watch` mode.
1. Add `{"type": "module"}` to your base `package.json`, make sure the
eleventy config file ends with the `.cjs` extension, and supply it as
a command line argument to `eleventy`.
```sh
NODE_OPTIONS=--experimental-vm-modules eleventy
```
```sh
eleventy --config=.eleventy.cjs
```
1. Put all component `.js` files in a subdirectory with a nested `package.json` with
`{"type": "module"}`.
### Watch mode

@@ -406,7 +427,2 @@

- [[#2484](https://github.com/lit/lit/issues/2484)] Use [worker
threads](https://nodejs.org/api/worker_threads.html) instead of [isolated VM
modules](https://nodejs.org/api/vm.html#class-vmmodule) so that the
`--experimental-vm-modules` flag is no longer required.
- [[#2485](https://github.com/lit/lit/issues/2485)] Provide a mechanism for

@@ -435,1 +451,5 @@ passing [Eleventy data](https://www.11ty.dev/docs/data/) to components as

Please see [CONTRIBUTING.md](../../../CONTRIBUTING.md).
### Testing environment variables:
- `SHOW_TEST_OUTPUT`: Set to show all `stdout` and `stderr` from spawned eleventy invocations in test cases.

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc