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

@popeindustries/lit-html-server

Package Overview
Dependencies
Maintainers
2
Versions
58
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@popeindustries/lit-html-server - npm Package Compare versions

Comparing version 4.0.1 to 4.0.2

71

package.json
{
"name": "@popeindustries/lit-html-server",
"version": "4.0.1",
"version": "4.0.2",
"description": "Render lit-html templates on the server",

@@ -32,3 +32,4 @@ "author": "Alexander Pope <alex@pope-industries.com>",

"import": "./index.mjs",
"require": "./index.js"
"require": "./index.js",
"types": "./index.d.ts"
},

@@ -38,3 +39,4 @@ "./directives/async-append.js": {

"import": "./directives/async-append.mjs",
"require": "./directives/async-append.js"
"require": "./directives/async-append.js",
"types": "./directives/async-append.d.ts"
},

@@ -44,3 +46,4 @@ "./directives/async-replace.js": {

"import": "./directives/async-replace.mjs",
"require": "./directives/async-replace.js"
"require": "./directives/async-append.js",
"types": "./directives/async-append.d.ts"
},

@@ -50,3 +53,4 @@ "./directives/cache.js": {

"import": "./directives/cache.mjs",
"require": "./directives/cache.js"
"require": "./directives/cache.js",
"types": "./directives/cache.d.ts"
},

@@ -56,3 +60,4 @@ "./directives/class-map.js": {

"import": "./directives/class-map.mjs",
"require": "./directives/class-map.js"
"require": "./directives/class-map.js",
"types": "./directives/class-map.d.ts"
},

@@ -62,3 +67,4 @@ "./directives/guard.js": {

"import": "./directives/guard.mjs",
"require": "./directives/guard.js"
"require": "./directives/guard.js",
"types": "./directives/guard.d.ts"
},

@@ -68,3 +74,4 @@ "./directives/if-defined.js": {

"import": "./directives/if-defined.mjs",
"require": "./directives/if-defined.js"
"require": "./directives/if-defined.js",
"types": "./directives/if-defined.d.ts"
},

@@ -74,3 +81,4 @@ "./directives/repeat.js": {

"import": "./directives/repeat.mjs",
"require": "./directives/repeat.js"
"require": "./directives/repeat.js",
"types": "./directives/repeat.d.ts"
},

@@ -80,3 +88,4 @@ "./directives/style-map.js": {

"import": "./directives/style-map.mjs",
"require": "./directives/style-map.js"
"require": "./directives/style-map.js",
"types": "./directives/style-map.d.ts"
},

@@ -86,3 +95,4 @@ "./directives/unsafe-html.js": {

"import": "./directives/unsafe-html.mjs",
"require": "./directives/unsafe-html.js"
"require": "./directives/unsafe-html.js",
"types": "./directives/unsafe-html.d.ts"
},

@@ -92,3 +102,4 @@ "./directives/until.js": {

"import": "./directives/until.mjs",
"require": "./directives/until.js"
"require": "./directives/until.js",
"types": "./directives/until.d.ts"
}

@@ -101,23 +112,22 @@ },

},
"dependencies": {},
"devDependencies": {
"@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-node-resolve": "^13.0.6",
"@types/node": "^16.11.12",
"autocannon": "^7.5.0",
"chai": "^4.3.4",
"chalk": "^5.0.0",
"eslint": "^8.4.1",
"eslint-config-prettier": "^8.3.0",
"@rollup/plugin-commonjs": "^22.0.0",
"@rollup/plugin-node-resolve": "^13.3.0",
"@types/node": "^18.0.0",
"autocannon": "^7.9.0",
"chai": "^4.3.6",
"chalk": "^5.0.1",
"eslint": "^8.17.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0",
"get-stream": "^6.0.1",
"husky": "^7.0.4",
"lint-staged": "^12.1.2",
"husky": "^8.0.1",
"lint-staged": "^13.0.1",
"lit-html": "^1.4.1",
"mocha": "^9.1.3",
"prettier": "^2.5.1",
"puppeteer": "^13.0.0",
"rollup": "^2.61.1",
"send": "^0.17.2",
"typescript": "^4.5.3"
"mocha": "^10.0.0",
"prettier": "^2.7.1",
"puppeteer": "^14.4.0",
"rollup": "^2.75.6",
"send": "^0.18.0",
"typescript": "^4.7.3"
},

@@ -147,3 +157,4 @@ "prettier": {

"typecheck": "tsc --noEmit"
}
},
"readme": "[![NPM Version](https://img.shields.io/npm/v/@popeindustries/lit-html-server.svg?style=flat)](https://npmjs.org/package/@popeindustries/lit-html-server)\n[![Build Status](https://img.shields.io/github/workflow/status/popeindustries/lit-html-server/test/master)](https://github.com/popeindustries/lit-html-server/actions)\n\n# lit-html-server\n\nRender [**lit-html**](https://github.com/polymer/lit-html) templates on the server as strings or streams (and in the browser too!). Supports all **lit-html** types, special attribute expressions, and many of the standard directives.\n\n> Although based on **lit-html** semantics, **lit-html-server** is a great general purpose HTML template streaming library. Tagged template literals are a native JavaScript feature, and the HTML rendered is 100% standard markup, with no special syntax or runtime required!\n\n## Usage\n\nInstall with `npm/yarn`:\n\n```bash\n$ npm install --save @popeindustries/lit-html-server\n```\n\n...write your **lit-html** template:\n\n```js\nconst { html } = require('@popeindustries/lit-html-server');\nconst { classMap } = require('@popeindustries/lit-html-server/directives/class-map.js');\nconst { until } = require('@popeindustries/lit-html-server/directives/until.js');\n\nfunction Layout(data) {\n return html`\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <title>${data.title}</title>\n </head>\n <body>\n ${until(Body(data.api))}\n </body>\n </html>\n `;\n}\n\nasync function Body(api) {\n // Some Promise-based request method\n const data = await fetchRemoteData(api);\n\n return html`\n <h1>${data.title}</h1>\n <x-widget ?enabled=\"${data.hasWidget}\"></x-widget>\n <p class=\"${classMap({ negative: data.invertedText })}\">${data.text}</p>\n `;\n}\n```\n\n...and render (plain HTTP server example, though similar for Express/Fastify/etc):\n\n```js\nconst http = require('http');\nconst { renderToStream } = require('@popeindustries/lit-html-server');\n\nhttp.createServer((request, response) => {\n const data = { title: 'Home', api: '/api/home' };\n\n response.writeHead(200);\n // Returns a Node.js Readable stream which can be piped to \"response\"\n renderToStream(Layout(data)).pipe(response);\n});\n```\n\n## Universal Templates\n\nWith **lit-html-server** and **lit-html** it's possible to write a single template and render it on the server, in a ServiceWorker, and in the browser. In order to be able to render the same template in three different runtime environments, it's necessary to change the version of `html` and `directives` used to process the template. It would certainly be possible to alias imports using a build process (so that `import { html } from 'lit-html'` points to `@popeindustries/lit-html-server` for bundles run in server/ServiceWorker), but a more flexible approach would be to pass references directly to the templates (dependency injection):\n\n```js\n/**\n * layout.js\n */\nimport Body from './body.js';\n\nexport function Layout(context, data) {\n const {\n html,\n directives: { until }\n } = context;\n\n return html`\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <title>${data.title}</title>\n </head>\n <body>\n ${until(Body(context, data.api))}\n </body>\n </html>\n `;\n}\n\n/**\n * server.js\n * (transpiler or experimental modules required)\n */\nimport { html, renderToStream } from '@popeindustries/lit-html-server';\nimport { Layout } from './layout.js';\nimport { until } from '@popeindustries/lit-html-server/directives/until.js';\n\nconst context = {\n html,\n directives: {\n until\n }\n};\n\nhttp\n .createServer((request, response) => {\n response.writeHead(200);\n renderToStream(Layout(context, data)).pipe(response);\n }\n\n/**\n * service-worker.js\n * (bundler required)\n */\nimport { html, renderToStream } from '@popeindustries/lit-html-server/browser/index.js';\nimport { Layout } from './layout.js';\nimport { until } from '@popeindustries/lit-html-server/browser/directives/until.js';\n\nconst context = {\n html,\n directives: {\n until\n }\n};\n\nself.addEventListener('fetch', (event) => {\n const stream = renderToStream(Layout(context, data));\n const response = new Response(stream, {\n headers: {\n 'content-type': 'text/html'\n }\n });\n\n event.respondWith(response);\n});\n\n/**\n * browser.js\n */\nimport { html, render } from 'lit-html';\nimport { Layout } from './layout.js';\nimport { until } from 'lit-html/directives/until.js';\n\nconst context = {\n html,\n directives: {\n until\n }\n};\n\nrender(Layout(context, data), document.body);\n```\n\n## API (Node.js)\n\n### `html`\n\nThe tag function to apply to HTML template literals (also aliased as `svg`):\n\n```js\nconst { html } = require('@popeindustries/lit-html-server');\n\nconst name = 'Bob';\nhtml`\n <h1>Hello ${name}!</h1>\n`;\n```\n\nAll template expressions (values interpolated with `${value}`) are escaped for securely including in HTML by default. An `unsafe-html` [directive](#directives) is available to disable escaping:\n\n```js\nconst { html } = require('@popeindustries/lit-html-server');\nconst { unsafeHTML } = require('@popeindustries/lit-html-server/directives/unsafe-html.js');\n\nhtml`\n <div>${unsafeHTML('<span>danger!</span>')}</div>\n`;\n```\n\n> The following render methods accept an `options` object with the following properties:\n>\n> - **`serializePropertyAttributes: boolean`** - enable `JSON.stringify` of property attribute values (default: `false`)\n\n### `renderToStream(result: TemplateResult, options: RenderOptions): Readable`\n\nReturns the result of the template tagged by `html` as a Node.js `Readable` stream of markup:\n\n```js\nconst { html, renderToStream } = require('@popeindustries/lit-html-server');\n\nconst name = 'Bob';\nrenderToStream(\n html`\n <h1>Hello ${name}!</h1>\n `\n).pipe(response);\n```\n\n### `renderToString(result: TemplateResult, options: RenderOptions): Promise<string>`\n\nReturns the result of the template tagged by `html` as a Promise which resolves to a string of markup:\n\n```js\nconst { html, renderToString } = require('@popeindustries/lit-html-server');\n\nconst name = 'Bob';\nconst markup = await renderToString(\n html`\n <h1>Hello ${name}!</h1>\n `\n);\nresponse.end(markup);\n```\n\n### `renderToBuffer(result: TemplateResult, options: RenderOptions): Promise<Buffer>`\n\nReturns the result of the template tagged by `html` as a Promise which resolves to a Buffer of markup:\n\n```js\nconst { html, renderToBuffer } = require('@popeindustries/lit-html-server');\n\nconst name = 'Bob';\nconst markup = await renderToBuffer(\n html`\n <h1>Hello ${name}!</h1>\n `\n);\nresponse.end(markup);\n```\n\n## API (Browser)\n\n**lit-html-server** may also be used in the browser to render strings of markup, or in a Service Worker script to render streams of markup.\n\n### `html`\n\nThe tag function to apply to HTML template literals (also aliased as `svg`):\n\n```js\nimport { html } from '@popeindustries/lit-html-server/browser.mjs';\n\nconst name = 'Bob';\nhtml`\n <h1>Hello ${name}!</h1>\n`;\n```\n\n### `renderToStream(TemplateResult): ReadableStream`\n\nReturns the result of the template tagged by `html` as a `ReadableStream` stream of markup. This may be used in a Service Worker script to stream an html response to the browser:\n\n```js\nimport { html, renderToStream } from '@popeindustries/lit-html-server/browser.mjs';\n\nself.addEventListener('fetch', (event) => {\n const name = 'Bob';\n const stream = renderToStream(\n html`\n <h1>Hello ${name}!</h1>\n `\n );\n const response = new Response(stream, {\n headers: {\n 'content-type': 'text/html'\n }\n });\n\n event.respondWith(response);\n});\n```\n\n> _NOTE: a bundler is required to package modules for use in a Service Worker_\n\n### `renderToString(TemplateResult): Promise<string>`\n\nReturns the result of the template tagged by `html` as a Promise which resolves to a string of markup:\n\n```js\nimport { html, renderToString } from '@popeindustries/lit-html-server/browser.mjs';\nconst name = 'Bob';\nconst markup = await renderToString(\n html`\n <h1>Hello ${name}!</h1>\n `\n);\ndocument.body.innerHtml = markup;\n```\n\n## Writing templates\n\nIn general, all of the standard **lit-html** rules and semantics apply when rendering templates on the server with **lit-html-server** (read more about [**lit-html**](https://polymer.github.io/lit-html/guide/) and writing templates [here](https://polymer.github.io/lit-html/guide/writing-templates.html)).\n\n### Template structure\n\nAlthough there are no technical restrictions for doing so, if you plan on writing templates for use on both the server and client, you should abide by the same rules:\n\n- templates should be well-formed when all expressions are replaced with empty values\n- expressions should only occur in attribute-value and text-content positions\n- expressions should not appear where tag or attribute names would appear\n- templates can have multiple top-level elements and text\n- templates should not contain unclosed elements\n\n### Expressions\n\nAll of the **lit-html** [expression syntax](https://polymer.github.io/lit-html/guide/writing-templates.html#binding-types) is supported:\n\n- text:\n\n```js\nhtml`\n <h1>Hello ${name}</h1>\n`;\n//=> <h1>Hello Bob</h1>\n```\n\n- attribute:\n\n```js\nhtml`\n <div id=\"${id}\"></div>\n`;\n//=> <div id=\"main\"></div>\n```\n\n- boolean attribute (attribute markup removed with falsey expression values):\n\n```js\nhtml`\n <input type=\"checkbox\" ?checked=\"${checked}\" />\n`;\n//=> <input type=\"checkbox\" checked> if truthy\n//=> <input type=\"checkbox\" > if falsey\n```\n\n- property (attribute markup removed unless `RenderOptions.serializePropertyAttributes = true` ):\n\n```js\nconst value = { some: 'text' };\nhtml`\n <input .value=\"${value}\" />\n`;\n//=> <input />\nhtml`\n <input .value=\"${value}\" />\n`;\n//=> <input .value=\"{&quot;some&quot;:&quot;text&quot;}\"/>\n// (when render options.serializePropertyAttributes = true)\n```\n\n- event handler (attribute markup removed):\n\n```js\nconst fn = (e) => console.log('clicked');\nhtml`\n <button @click=\"${fn}\">Click Me</button>\n`;\n//=> <button >Click Me</button>\n```\n\n### Types\n\nMost of the **lit-html** [value types](https://polymer.github.io/lit-html/guide/writing-templates.html#supported-types) are supported:\n\n- primitives: `String`, `Number`, `Boolean`, `null`, and `undefined`\n\n > Note that `undefined` handling is the same as in **lit-html**: stringified when used as an attribute value, and ignored when used as a node value\n\n- nested templates:\n\n```js\nconst header = html`\n <h1>Header</h1>\n`;\nconst page = html`\n ${header}\n <p>This is some text</p>\n`;\n```\n\n- Arrays / iterables (sync):\n\n```js\nconst items = [1, 2, 3];\nhtml`\n <ul>\n ${items.map(\n (item) =>\n html`\n <li>${item}</li>\n `\n )}\n </ul>\n`;\nhtml`\n <p>total = ${new Set(items)}</p>\n`;\n```\n\n- Promises:\n\n```js\nconst promise = fetch('sample.txt').then((r) => r.text());\nhtml`\n <p>The response is ${promise}.</p>\n`;\n```\n\n> Note that **lit-html** no longer supports Promise values. Though **lit-html-server** does, it's recommended to use the `until` directive instead when authoring templates to be used in both environments.\n\n### Directives\n\nMost of the built-in **lit-html** [directives](https://lit-html.polymer-project.org/guide/template-reference#built-in-directives) are also included for compatibility when using templates on the server and in the browser (even though some directives are no-ops in a server rendered context):\n\n- `asyncAppend(value)`: Renders the items of an AsyncIterable, appending new values after previous values:\n\n```js\nconst { asyncAppend } = require('@popeindustries/lit-html-server/directives/async-append.js');\n\nhtml`\n <ul>\n ${asyncAppend(someListIterator)}\n </ul>\n`;\n```\n\n- `cache(value)`: Enables fast switching between multiple templates by caching previous results. Since it's generally not desireable to cache between requests, this is a no-op:\n\n```js\nconst { cache } = require('@popeindustries/lit-html-server/directives/cache.js');\n\ncache(\n loggedIn\n ? html`\n You are logged in\n `\n : html`\n Please log in\n `\n);\n```\n\n- `classMap(classInfo)`: applies css classes to the `class` attribute. 'classInfo' keys are added as class names if values are truthy:\n\n```js\nconst { classMap } = require('@popeindustries/lit-html-server/directives/class-map.js');\n\nhtml`\n <div class=\"${classMap({ red: true })}\"></div>\n`;\n```\n\n- `guard(value, fn)`: no-op since re-rendering does not apply (renders result of `fn`):\n\n```js\nconst { guard } = require('@popeindustries/lit-html-server/directives/guard.js');\n\nhtml`\n <div>\n ${guard(items, () =>\n items.map(\n (item) =>\n html`\n ${item}\n `\n )\n )}\n </div>\n`;\n```\n\n- `ifDefined(value)`: sets the attribute if the value is defined and removes the attribute if the value is undefined:\n\n```js\nconst { ifDefined } = require('@popeindustries/lit-html-server/directives/if-defined.js');\n\nhtml`\n <div class=\"${ifDefined(className)}\"></div>\n`;\n```\n\n- `repeat(items, keyfnOrTemplate, template))`: no-op since re-rendering does not apply (maps `items` over `template`)\n\n```js\nconst { repeat } = require('@popeindustries/lit-html-server/directives/repeat.js');\n\nhtml`\n <ul>\n ${repeat(\n items,\n (i) => i.id,\n (i, index) =>\n html`\n <li>${index}: ${i.name}</li>\n `\n )}\n </ul>\n`;\n```\n\n- `styleMap(styleInfo)`: applies css properties to the `style` attribute. 'styleInfo' keys and values are added as style properties:\n\n```js\nconst { styleMap } = require('@popeindustries/lit-html-server/directives/style-map.js');\n\nhtml`\n <div style=\"${styleMap({ color: 'red' })}\"></div>\n`;\n```\n\n- `unsafeHTML(value)`: render `value` without HTML escaping:\n\n```js\nconst { unsafeHTML } = require('@popeindustries/lit-html-server/directives/unsafe-html.js');\n\nhtml`\n <div>${unsafeHTML(\"hey! it's dangerous! <script>boom!</script>\")}</div>\n`;\n```\n\n- `until(...args)`: renders one of a series of values, including Promises, in priority order. Since it's not possible to render more than once in a server context, primitive synchronous values are prioritized over asynchronous Promises. If no synchronous values are passed, the last value is rendered regardless of type:\n\n```js\nconst { until } = require('@popeindustries/lit-html-server/directives/until.js');\n\nhtml`\n <p>\n ${until(\n fetch('content.json').then((r) => r.json()),\n html`\n <span>Loading...</span>\n `\n )}\n </p>\n`;\n// => renders <p><span>Loading...</span></p>\n\nhtml`\n <p>\n ${until(\n fetch('content.json').then((r) => r.json()),\n isBrowser\n ? html`\n <span>Loading...</span>\n `\n : undefined\n )}\n </p>\n`;\n// => renders fetch result\n```\n\n## Thanks!\n\nThanks to [Thomas Parslow](https://github.com/almost) for the [stream-template](https://github.com/almost/stream-template) library that was the inspiration for this streaming implementation, and thanks to [Justin Fagnani](https://github.com/justinfagnani) and the [team](https://github.com/Polymer/lit-html/graphs/contributors) behind the **lit-html** project!\n"
}
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