neh

nehan

Dynamic html layout engine for paged-media written by Typescript

Showing:

Popularity

Downloads/wk

54

GitHub Stars

17

Maintenance

Last Commit

3d ago

Contributors

1

Package

Dependencies

0

License

MIT

Type Definitions

Built-In

Tree-Shakeable

No?

Categories

Readme

nehan

Introduction

Dynamic html layout engine for paged-media written by Typescript.

Install

npm install nehan

Demo

See Nehan Reader at Chrome Web Store.

Or nehan-player demo

How to use Nehan Reader

  1. Install Nehan Reader.
  2. Goto any site you want to read as paged-media.
  3. Click the browser action button
  4. Then you'll see paged site.

Example

See example directory.

Usage

simple usage with no styling

import { PagedNehanDocument } from 'nehan';

const $result = document.querySelector("#result");

new PagedNehanDocument("<h1>hello, nehan!</h1>", {}).render({
  onPage: (ctx) => {
    const evaluatedPage = ctx.caller.getPage(ctx.page.index);
    $result.appendChild(evaluatedPage.dom);
    $result.appendChild(document.createElement("hr"));
  },
  onComplete: (ctx) => {
    console.log(`finished! ${ctx.time}msec`);
  }
});

render with style

import { PagedNehanDocument, CssStyleSheet } from 'nehan';

const $result = document.querySelector("#result");

new PagedNehanDocument("<h1>hello, nehan!</h1>", {
  styleSheets:[
    new CssStyleSheet({
      "body":{
        writihgMode:"horizontal-tb", // or "vertical-rl"
        fontSize:"16px",
        padding: "1em",
        measure: "640px", // means 'width' in horizontal-tb, 'height' in vertical-rl.
        extent: "480px"   // means 'height' in horizontal-tb, 'width' in vertical-rl.
      },
      "h1":{
        marginAfter: "1em",   // means 'margin-bottom' in horizontal-tb, 'margin-left' in vertical-rl
        paddingStart: "0.5em" // means 'padding-left' in horizontal-tb, 'padding-top' in vertical-rl
      }
    }
  ]
}).render({
  onPage: (ctx) => {
    const evaluatedPage = ctx.caller.getPage(ctx.page.index);
    $result.appendChild(evaluatedPage.dom);
    $result.appendChild(document.createElement("hr"));
  },
  onComplete: (ctx) => {
    console.log(`finished! ${ctx.time}msec`);
  }
});

About logical size

To handle documents that are independent of the character direction, we use the logical size.

  • measure means the size in the inline direction.
  • extent means the size in the block direction.

logical-size - physical-size table

logical-size\writing-modehorizontal-tbvertical-rlvertical-lr
measurewidthheightheight
extentheightwidthwidth

About logical direction

To handle documents that are independent of the character direction, we use the logical direction.

  • start means inline level heading direction.
  • end means inline level trailing direction.
  • before measn block level heading direction.
  • after means block level trailing direction.

Example1 (logical-margin - physical-margin table)

logical-direction\writing-modehorizontal-tbvertical-rlvertical-lr
margin-startmargin-leftmargin-topmargin-top
margin-endmargin-rightmargin-bottommargin-bottom
margin-beforemargin-topmargin-rightmargin-left
margin-aftermargin-bottommargin-leftmargin-right

The same is true for padding and border(border-xxx-width, border-xxx-color, border-xxx-style).

Example2 (logical-border-radius - physical-border-radius table)

logical-direction\writing-modehorizontal-tbvertical-rlvertical-lr
border-before-start-radiusborder-top-left-radiusborder-top-right-radiusborder-top-left-radius
border-before-end-radiusborder-top-right-radiusborder-bottom-right-radiusborder-bottom-left-radius
border-after-end-radiusborder-bottom-right-radiusborder-bottom-left-radiusborder-bottom-right-radius
border-after-start-radiusborder-bottom-left-radiusborder-top-left-radiusborder-top-right-radius

Shothanded logical property

If you set margin like margin:1em 2em 3em 4em, then it means margin-before:1em, margin-end:2em, margin-after:3em, margin-start:4em.

If you set margin like margin:1em 2em 3em, then it means margin-before:1em, margin-end:2em, margin-after:3em, margin-start:2em.

If you set margin like margin:1em 2em, then it means margin-before:1em, margin-end:2em, margin-after:1em, margin-start:2em.

If you set margin like margin:1em, then it means margin-before:1em, margin-end:1em, margin-after:1em, margin-start:1em.

The same is true for padding and border(border-xxx-width, border-xxx-color, border-xxx-style).

Dynamic Style

You can define functional value for each selector(css property name is !xxx).

In following example, all elements that matches .require-xx will cause page-break if rest block size(restExtent) is smaller than xxpx.

import { CssStyleSheet, DynamicStyleContext, CssDeclarationBlock } from 'nehan';

function requiredExtent(requiredSize: number) {
  return (ctx: DynamicStyleContext): CssDeclarationBlock | undefined => {
    if (!ctx.parentContext) {
      return undefined;
    }
    const restExtent = ctx.parentContext.restExtent;
    if (restExtent >= requiredSize) {
      return undefined; // enough block size is left!
    }
    // restExtent < requiredSize(not enough block size left)
    return { "page-break-before": "always" };
  };
}

const myStyleSheet = new CssStyleSheet({
  ".require-60": {
    "!dynamic": requiredExtent(60)
  }
});

DOM generation hook

You can define dom generation hook for each selector element like this(css property name is @xxx).

import { CssStyleSheet, DomCallbackContext } from 'nehan';

const myStyleSheet = new CssStyleSheet({
  ".foo": {
    "@create": (ctx: DomCallbackContext) => {
      ctx.dom.onclick = (e) => {
        alert(`${ctx.selector} is clicked!`); // .foo is clicked!
      };
    }
  }
});

Plugins

Development

npm run build and library is generated in dist directory.

License

MIT

Rate & Review

Great Documentation0
Easy to Use0
Performant0
Highly Customizable0
Bleeding Edge0
Responsive Maintainers0
Poor Documentation0
Hard to Use0
Slow0
Buggy0
Abandoned0
Unwelcoming Community0
100