Dynamic html layout engine for paged-media written by Typescript.
npm install nehan
See Nehan Reader at Chrome Web Store.
- Install Nehan Reader.
- Goto any site you want to read as paged-media.
- Click the browser action button
- Then you'll see paged site.
See example directory.
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`);
}
});
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`);
}
});
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\writing-mode | horizontal-tb | vertical-rl | vertical-lr |
---|---|---|---|
measure | width | height | height |
extent | height | width | width |
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.
logical-direction\writing-mode | horizontal-tb | vertical-rl | vertical-lr |
---|---|---|---|
margin-start | margin-left | margin-top | margin-top |
margin-end | margin-right | margin-bottom | margin-bottom |
margin-before | margin-top | margin-right | margin-left |
margin-after | margin-bottom | margin-left | margin-right |
The same is true for padding
and border
(border-xxx-width
, border-xxx-color
, border-xxx-style
).
logical-direction\writing-mode | horizontal-tb | vertical-rl | vertical-lr |
---|---|---|---|
border-before-start-radius | border-top-left-radius | border-top-right-radius | border-top-left-radius |
border-before-end-radius | border-top-right-radius | border-bottom-right-radius | border-bottom-left-radius |
border-after-end-radius | border-bottom-right-radius | border-bottom-left-radius | border-bottom-right-radius |
border-after-start-radius | border-bottom-left-radius | border-top-left-radius | border-top-right-radius |
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
).
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 xx
px.
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)
}
});
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!
};
}
}
});
npm run build
and library is generated in dist
directory.
MIT