Code Monkey home page Code Monkey logo

lit-ntml's Introduction

lit-ntml

Inspired by lit-html but for Node.js.


Version Node version MIT License

Downloads Total downloads Packagephobia Bundlephobia

Build Status CircleCI Dependency Status codecov Coverage Status

codebeat badge Codacy Badge Code of Conduct

Lightweight and modern templating for SSR in Node.js, inspired by lit-html.

This module also gets featured in web-padawan/awesome-lit-html. Make sure to check the repo out for awesome things inspired by lit-html. ๐Ÿ‘๐Ÿ’ฏ

Table of contents

Features

  • await all tasks including Functions, Promises, and whatnot.
  • minify: true to minify rendered HTML string.
  • parse: 'html'|'fragment'|true|false to parse content as HTML fragment string (default) or HTML string.
  • pretty: { ocd: boolean } to prettify content with ocd set to true (default) or false.
  • Compatible for ES Modules (import ntml from 'ntml') and CommonJS (const { ntml } = require('ntml');).
  • Parses PromiseList or List by default, without explicit joining. See demo.
  • Uses htmlMinifier to minify HTML string.
  • Uses parse5 to parse HTML string by default.
  • Uses pretty to prettify HTML string by default.
  • Support HTML syntax highlighting + autocompletion with vscode-lit-html in JavaScript's template string.
  • Support native ES Module via .mjs

Pre-requisite

How to use

Install

# Install via NPM
$ npm install lit-ntml

Enable syntax highlighting when writing HTML with template literal

Visual Studio Code

  1. Install vscode-lit-html extension.
  2. If the extension does not provide that syntax highlighting and autocompletion, try writing your templates in .jsx file (or .tsx file if you're TypeScript user) . That should work.

Code examples

ES Modules or TypeScript

Await all tasks (Promises, Functions, strings, etc)
/** Import project dependencies */
import ntml from 'lit-ntml';

/** Setting up */
const html = ntml();
const header = text => () => new Promise(yay => setTimeout(() => yay(`<div class="header">${text}</div>`), 3e3));
const content = text => async () => `<div class="content">${text}</div>`;
const someLoremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';

const rendered = await html`
  <html lang="en">
    <body>
      <style>
        body {
          padding: 0;
          margin: 0;
          font-size: 16px;
          font-family: 'sans-serif';
          box-sizing: border-box;
        }

        .header {
          background: #0070fb;
          color: #fff;
        }

        .content {
          background: #f5f5f5;
          color: #000;
        }
      </style>

      <main>
        <div>Hello, world! ${header('Hello, world!')} ${content('lorem ipsum')}</div>
        <div>${someLoremIpsum}</div>
      </main>
    </body>
  </html>
`;

console.log('#', rendered); /** <html lang="en>...</html> */
Minify rendered HTML string
/** Import project dependencies */
import ntml from 'lit-ntml';

/** Setting up */
const html = ntml({
  minify: true,
  // options: { minify: {...} }, // Optional htmlMinifier.Options
});

const minifyAfterRendered = await html`
  <html lang="en">
    <body>
      <style>
        body {
          padding: 0;
          margin: 0;
          font-size: 16px;
          font-family: 'sans-serif';
          box-sizing: border-box;
        }

        .header {
          background: #0070fb;
          color: #fff;
        }

        .content {
          background: #f5f5f5;
          color: #000;
        }
      </style>

      <main>
        <div>Hello, world!</div>
        <div>This content will be minified!</div>
      </main>
    </body>
  </html>
`;

console.log('#', minifyAfterRendered); /** <html lang="en"><body><style>...</style><main>...</main></body></html> */
Parse PromiseList or List
/** Import project dependencies */
import assert from 'assert';
import ntml from 'lit-ntml';

/** Setting up */
const html = ntml();
const nameList = [
  'John Doe',
  'Michael CEO',
  'Cash Black',
  'Vict Fisherman',
];
const expected = `<h1>Hello, World!</h1>
<ul>
  <li>John Doe</li>
  <li>Michael CEO</li>
  <li>Cash Black</li>
  <li>Vict Fisherman</li>
</ul>`;

const listRendered = await html`<h1>Hello, World!</h1>
<ul>${
  nameList.map(n => html`<li>${n}</li>`)
}</ul>`;
const asyncListRendered = await html`<h1>Hello, World!</h1>
<ul>${
  nameList.map(async n => html`<li>${n}</li>`)
}</ul>`;

assert.strictEqual(listRendered, expected); // OK
assert.strictEqual(asyncListRendered, expected); // OK

Node.js

const { ntml } = require('ntml');

(async () => {
  const html = ntml();

  const rendered = await html`<div>haha</div>`;

  console.log('#', rendered);
  /**
   * <div>haha</div>
   */
})();

API Reference

DEFAULT_MINIFY_OPTIONS

{
  collapseBooleanAttributes: true,
  collapseWhitespace: true,
  minifyCSS: true,
  minifyJS: true,
  processConditionalComments: true,
  quoteCharacter: '"',
  removeComments: true,
  removeOptionalTags: true,
  removeRedundantAttributes: true,
  removeScriptTypeAttributes: true,
  removeStyleLinkTypeAttributes: true,
  sortAttributes: true,
  sortClassName: true,
  trimCustomFragments: true,
}

NtmlOpts

  • minify <?boolean> Optional minification flag. If true, minify rendered HTML string. Defaults to false.
  • options <?Object> Optional settings.

ntml([options])

  • options <?NtmlOpts> Optional configuration for the templating.
  • returns: <Promise<string>> Promise which resolves with rendered HTML string.

Caveat

Writing CSS styles outside of HTMLStyleElement can lead to unexpected parsing behavior, such as:

CSS styles outside of <style>

import ntml from 'lit-ntml';

const html = ntml();
const style = () => html`
  body {}

  div {}
`;

const main = () => html`
  <style>${style()}</style>
`;

/**
 * <!DOCTYPE>
 * <html> 
 *   <head>
 *     <style>
 *       <!DOCTYPE html>
 *       <html>
 *         <head>
 *           <style>
 *             body {}
 *
 *             div {}
 *           </style>
 *         </head>
 *       </html>
 *     </style>
 *   </head>
 * </html>
 * 
 */

It's clearly that the style tag element has been wrapped inside another html tag element. This is an unexpected behavior. However, it kind of makes sense as from the above scenario each of the new content is rendered separately with lit-ntml and the lit-ntml has no knowledge about what will be rendered next and before. To avoid such behavior, do one of the following:

  1. Wrap with any valid HTML element tag

    const style = () => html`
    <style>
      body {}
    
      main {}
    </style>`;
  2. Make sure options[parse] is set to false or fragment

    const { ntml } = require('lit-ntml');
    const html = ntml({
      options: {
        parse: 'fragment', // or parse: false,
      },
    });
    const style = () => html`
    body {}
    main {}
    `;
    const main = () => html`<style>${style}</style>`;

License

MIT License ยฉ Rong Sen Ng

lit-ntml's People

Contributors

motss avatar

Watchers

James Cloos avatar Chad Compton avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.