npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

red-agate

v0.5.0

Published

Static HTML|XML|SVG renderer using JSX, suitable for report output.

Downloads

79

Readme

RedAgate

Static HTML | XML | SVG renderer using JSX, suitable for report output.

RedAgate is static HTML | XML | SVG renderer.
You can start easily because we are using JSX and semantics similar to React.

npm GitHub release Travis GitHub forks GitHub stars

Advantages:

  • Easily to bundle resources (images, stylesheets, fonts, scripts, ...) .
    RedAgate.renderAsHtml() API and component lifecycle defer() method return promise objects.
    You can use standard Tag-Libs (e.g. Image, Style, Font, SingleFont, Script, Asset) to bundle them.

  • Many standard Tag-Libs (e.g. If, Repeat, ForEach, Template, Html5, Svg, SVG shapes, Barcodes (QR Code, Code39, Code128, EAN/UPC, ITF, NW7/Codabar, postal barcode) and complex objects) are bundled.

  • Html5 Canvas API is available in the sub tree of the Svg component.

  • Running on both server side (Node.js) and modern browsers (Chrome, Firefox, Safari, Edge).

RedAgate

Install

$ npm install red-agate --save

Note

To import this from your code, you need to use babel + webpack and import red-agate-*/modules/* paths.
(We have used the import statements for doing the tree-shaking. The import statements in the .js not the .mjs files cannot import from the vanilla node.js.)

You can also import from the .mjs file on a node with the --experimental-modules option enabled.

NOTICE:
Use with webpack >= 5

If you get the error:

Module not found: Error: Can't resolve '(importing/path/to/filename)'
in '(path/to/node_modules/path/to/dirname)'
Did you mean '(filename).js'?`

Add following setting to your webpack.config.js.

{
    test: /\.m?js/,
    resolve: {
        fullySpecified: false,
    },
},

On webpack >= 5, the extension in the request is mandatory for it to be fully specified if the origin is a '.mjs' file or a '.js' file where the package.json contains '"type": "module"'.

Usage

See live demo on browser (code) and Node.js example.

Hello, world:

/** @jsx RedAgate.createElement */
import * as RedAgate from 'red-agate/modules/red-agate';

interface HelloProps extends RedAgate.ComponentProps {
    name: string;
}

const Hello = (props: HelloProps) => {
    return (<div>Hello, {props.name}!</div>);
};

RedAgate.renderAsHtml(<Hello name={'😈RedAgate😈'}/>)
.then(html => console.log(html))
.catch(error => console.log(error))

Defining element by using lambda:

export interface IfProps extends RedAgate.ComponentProps {
    condition: boolean;
}

export const If = (props: IfProps) => {
    if (this.props.condition) return this.props.children;
    else return [];
};

Defining element by using component:

export interface IfProps extends RedAgate.ComponentProps {
    condition: boolean;
}

export class If extends RedAgate.RedAgateComponent<IfProps> {
    public constructor(props: IfProps) {
        super(props);
    }

    // Equivalent to React's render() .
    public transform() {
        if (this.props.condition) return this.props.children;
        else return [];
    }
}

Defining SVG element by using component:

import { SvgCanvas }          from 'red-agate-svg-canvas/modules/drawing/canvas/SvgCanvas';
import { Shape,
         CONTEXT_SVG_CANVAS } from 'red-agate/modules/red-agate/tags/Shape';

export interface RectProps extends ShapeProps {
    width: number;
    height: number;
}

export const rectPropsDefault: RectProps = Object.assign({}, shapePropsDefault, {
    width: 10,
    height: 10
});

export class Rect extends Shape<RectProps> {
    public constructor(props: RectProps) {
        super(Object.assign({}, rectPropsDefault, props));
    }

    public render(contexts: Map<string, any>, children: string) {
        const canvas: SvgCanvas = this.getContext(contexts, CONTEXT_SVG_CANVAS);
        canvas.rect(0, 0, this.props.width, this.props.height);
        return ``;
    }
}

Complete example:

/** @jsx RedAgate.createElement */
import * as RedAgate     from 'red-agate/modules/red-agate';
import { ForEach,
         If,
         Template }      from 'red-agate/modules/red-agate/taglib';
import { Html5 }         from 'red-agate/modules/red-agate/html';
import { Svg,
         Group,
         Rect,
         Text,
         GridLine,
         SvgImposition } from 'red-agate/modules/red-agate/svg';
import { Font,
         Image,
         Style }         from 'red-agate/modules/red-agate/bundler';
import { query }         from 'red-agate/modules/red-agate/data';
import { Lambda }        from 'red-agate/modules/red-agate/app';
import { HtmlRenderer }  from 'red-agate/modules/red-agate/renderer';

interface FbaDetail {
    id: string;
    name: string;
    condition: string;
}
interface PrintJob {
    details: FbaDetail[];
}

const designerMode = true;
const font = "'Noto Sans', sans-serif";
const Fba = (props: {leaf: FbaDetail}) =>
    <Template>
        <Group x={0} y={0}>
            <Text x={27} y={11.5}
                textAlign="center" font={`11.5px 'Libre Barcode 128 Text', cursive`} fill
                text={leaf.id} />
            <Text x={4} y={18 + 3.5}
                font={`3.5px ${font}`} fill
                text={leaf.name} />
            <Text x={4} y={22 + 3.5}
                font={`3.5px ${font}`} fill
                text={leaf.condition} />
        </Group>
    </Template>;

export const fbaA4ReportHandler: Lambda = (event: PrintJob, context, callback) => RedAgate.renderOnAwsLambda(
<Html5>
    <head>
        <title>FBA</title>
        <link href="https://fonts.googleapis.com/css?family=Noto+Sans" rel="stylesheet"/>
        <link href="https://fonts.googleapis.com/css?family=Libre+Barcode+128+Text" rel="stylesheet"/>
        <Style src="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.css"/>
        <Style src="https://cdnjs.cloudflare.com/ajax/libs/paper-css/0.3.0/paper.css"/>
        <style dangerouslySetInnerHTML={{ __html: require('./fba-a4.style.css') }}/>
    </head>

    <body class="A4">
        <ForEach items={query(event.details).groupEvery(40).select()}> { (items: FbaDetail[]) =>
            <section class="sheet" style="position: relative; top: 0mm; left: 0mm;">
                <Svg width={210 - 1} height={297 - 2} unit='mm'>
                    <SvgImposition items={items} paperWidth={210} paperHeight={297} cols={4} rows={10}> { (item: FbaDetail) =>
                        <Template>
                            <If condition={designerMode}>
                                <Rect x={0} y={0} width={210 / 4} height={297 / 10} lineWidth={0.5} stroke/>
                                <GridLine startX={0} startY={0} endX={210 / 4} endY={297 / 10} gridSize={5} bleed={0} lineWidth={0.1}/>
                            </If>

                            <Fba leaf={item} />
                        </Template> }
                    </SvgImposition>
                </Svg>
            </section> }
        </ForEach>
    </body>
</Html5>, callback);
const event = {
    details: [{
        // ...
    }]
};

fbaA4ReportHandler(event /* PrintJob */, {} as any /* Context */, (error, result) => {
    if (error) {
        console.log(error);
    } else {
        console.log(result);
    }
});

Render html into PDF:

/** @jsx RedAgate.createElement */
import * as RedAgate    from 'red-agate/modules/red-agate';
import { Html5 }        from 'red-agate/modules/red-agate/html';
import { Lambda }       from 'red-agate/modules/red-agate/app';
import { HtmlRenderer } from 'red-agate/modules/red-agate/renderer';

interface PrintJob { /*  */ }

export const reportHandler: Lambda = (event: PrintJob, context, callback) => RedAgate.renderOnAwsLambda(
<Html5>
    hello, { event.name }!
</Html5>, callback);

export const pdfHandler = HtmlRenderer.toPdfHandler(reportHandler, {}, {
    width: '210mm',
    height: '297mm',
    printBackground: true,
});

pdfHandler(event /* PrintJob */, {} as any /* Context */, (error, result) => {
    if (error) {
        console.log(error);
    } else {
        console.log(result);
    }
});

Call from another process:

/** @jsx RedAgate.createElement */
import * as RedAgate     from 'red-agate/modules/red-agate';
import { Html5 }         from 'red-agate/modules/red-agate/html';
import { App }           from 'red-agate/modules/red-agate/app';

export const billngReportHandler = (event: BillingPrintJob, context, callback) => RedAgate.renderOnAwsLambda(
<Html5>billng</Html5>, callback);

export const kanbanReportHandler = (event: KanbanPrintJob, context, callback) => RedAgate.renderOnAwsLambda(
<Html5>kanban</Html5>, callback);

App.route('/', (evt, ctx, cb) => cb(null, 'Hello, Node!'))
   .route('/billing', billngReportHandler)
   .route('/kanban', kanbanReportHandler)
   .run({});
#!/usr/bin/env python3

import json
import os
import sys

sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/node_modules/red-agate/')
from redagate_lambda import call, LambdaInternalErrorException


if __name__ == '__main__':
    from flask import Flask, abort
    app = Flask(__name__)

    @app.errorhandler(LambdaInternalErrorException)
    def internal_error_handler(e):
        return 'Internal Server Error', 500

    @app.route('/billing')
    def run_billing_report():
        with open('./src/reports/billing.data.json') as f:
            event = json.loads(f.read())
            event['eventName'] = '/billing'
            return call(command=["node", "dist/app.js"], event=event)

    @app.route('/kanban')
    def run_barcode_test_report():
        with open('./src/reports/kanban.data.json') as f:
            event = json.loads(f.read())
            event['eventName'] = '/kanban'
            return call(command=["node", "dist/app.js"], event=event)

    port = int(os.environ['PORT']) if os.environ.get('PORT') is not None else None
    app.run(debug=True, port=port)

Mix react elements:

/** @jsx react.createElement */
import * as react from 'react';

interface ReactHelloProps {
    name: string;
}

export const ReactHello: React.SFC<ReactHelloProps> = (props) => {
    return (<span>Hello, {props.name}!</span>);
};
/** @jsx RedAgate.createElement */
import * as RedAgate          from 'red-agate/modules/red-agate';
import { Html5 }              from 'red-agate/modules/red-agate/html';

import { ReactHost }          from 'red-agate-react-host/modules/react-host';
import { ReactHello }         from './hello';
import { createElement as $ } from 'react';

RedAgate.renderAsHtml(
<Html5>
    <ReactHost element={$(ReactHello, {name: '😎React😎'})} />
</Html5>)
.then(html => console.log(html))
.catch(error => console.log(error))

We provide ES6 module files under red-agate*/modules/* path.
You can get the benefits of tree shaking when using webpack.
Instead, you can also import the whole by simply specifying red-agate* as the import path.

Component Lifecycle

| call order | method | description | |------:|--------|-------------| | 0 | earlyConstruct(): void | This method is marker and it will be NEVER called.If it defined, constructor will be called in createElement().Otherwise constructor will be called in render???() APIs. | | 1 | constructor(props) /lambda(props) | Construct a component.If it is lambda, transform myself and children DOM tree. | | 2 | transform(): RedAgateNode | Transform myself and children DOM tree.This method is equivalent to render() of React method. | | 3 | defer(): Promise<any> | Wait for asynchronous resources. | | 4 | beforeRender(    contexts: Map<string, any>): void| Get contexts provided by parent elements.Preparing something for child elements. | | 5 | render(    contexts: Map<string, any>,    children: string): string| Return rendering result as string. | | 6 | afterRender(    contexts: Map<string, any>): void| Clean up contexts, graphic states, ... |

APIs

/** @jsx RedAgate.createElement */import * as RedAgate from 'red-agate/modules/red-agate'

| method | description | |--------|-------------| | RedAgate.createElement(    type: ComponentFactory<P>,    props: P or null or undefined,    ...children: RedAgateNode[]): RedAgateElement<P> | Create a element.This function is called from JSX compiled code. | | RedAgate.renderAsHtml(    element: RedAgateNode): Promise<string> | Render elements to string. | | RedAgate.render(    element: RedAgateNode,    container: HTMLElement,    callback?: (        html: string or null,        error: any or null    ) => void): void | Render elements and apply to DOM. | | RedAgate.renderOnAwsLambda(    element: RedAgateNode,    callback: (        error: any or null,        result: any or null    ) => void): void | Render elements to string.Return result via AWS lambda callback. | | RedAgate.renderOnExpress(    element: RedAgateNode,    req: any,    res: any): void | Render elements to string.Return result via Express web server callback. |

import { query } from 'red-agate/modules/red-agate/data'

| method | description | |--------|-------------| | query(    data: T[]): Query<T> | Transform an array. | | Query<T>#orderBy(    condition: Array<string or    string[        /* colName: string,        ('asc' or 'desc') */    ]> or        ((a: T, b: T) =>        number)): Query<T> | Sort an array. | | Query<T>#groupBy(    condition: string[        /* colName: string */    ] or        ((a: T, b: T,        index: number, array: T[]) =>        boolean)): Query<T[]> | Grouping and transform an array. | | Query<T>#groupEvery(    n: number or    {        single: number,        first?: number,        intermediate: number,        last?: number    }): Query<T[]> | Grouping and transform an array. | | Query<T>#where(    fn: (        value: T,        index: number,        array: T[]    ) => boolean): Query<T> | Filter an array. | | Query<T>#select<R>(    fn?: (        value: T,        index: number,        array: T[]    ) => R): Array<R or T> | Map an array. |

import { App } from 'red-agate/modules/red-agate/app'

| method | description | |--------|-------------| | App.cli(    options: string[]    handler: (        opts: Map<string, string>        ) => void): App | Add CLI routing.If options[i] starts with ? it is a optional parameter.If options[i] ends with * it is a wildcard. | | App.route(    name: string    lambda: Lambda): App | Add routing to lambda.name parameter is used as routing path.When request event is received call the lambda that name equals to event.eventName. | | App.run(    context: any    lambda?: Lambda): App | Run routing.event is received from stdin as JSON and send response to stdout.Exit process by calling exit() when response is ended.If lambda is specified, ignore route() and call lambda. |

import { Lambdas } from 'red-agate/modules/red-agate/app'

| method | description | |--------|-------------| | Lambdas.pipe(    handler1: Lambda,    handler2: Lambda): Lambda | Pipe 2 lambdas.Return a composite function that piping 2 lambdas.2nd lambda's event is 1st lambda's callback result. |

import { HtmlRenderer } from 'red-agate/modules/red-agate/renderer'

$ npm install puppeteer --save

| method | description | |--------|-------------| | HtmlRenderer.toPdf(    html: string or Promise<string>,    navigateOptions: any,    pdfOptions: any): Promise<Buffer> | Render HTML into PDF using puppeteer.See puppeteer#page.goto about navigateOptions.See puppeteer#page.pdf about pdfOptions. | | HtmlRenderer.toImage(    html: string or Promise<string>,    navigateOptions: any,    imageOptions: any): Promise<Buffer> | Render HTML into image using puppeteer.See puppeteer#page.goto about navigateOptions.See puppeteer#page.screenshot about imageOptions. | | HtmlRenderer.toPdfHandler(    handler: Lambda,    navigateOptions: any,    pdfOptions: any): Lambda | Create composite function returning pdf as callback result. | | HtmlRenderer.toImageHandler(    handler: Lambda,    navigateOptions: any,    imageOptions: any): Lambda | Create composite function returning image as callback result. |

Standard Tag-Libs

red-agate/modules/red-agate/taglib

| tag | description | |-----|-------------| | Repeat | Loop N times. | | ForEach | Iterate an array. | | If | Conditional branch. | | Do | Call a lambda function when createElement . | | Facet | Grouping child elements.Give a name to group. | | Template | Synonym for Facet . |

red-agate/modules/red-agate/bundler

| tag | description | |-----|-------------| | Asset | Fetch a external resource.Fetched resource is referred from other tags. | | Image | Fetch a external image resource. | | Script | Fetch a external script resource. | | Style | Fetch a external stylesheet resource. | | Font | Synonym for Style . | | SingleFont | Fetch a external single font-family font resource. |

red-agate/modules/red-agate/html

| tag | description | |-----|-------------| | Html4_01_Strict | Output doctype declaration and html tag. | | Html4_01_Transitional | Output doctype declaration and html tag. | | Html4_01_Frameset | Output doctype declaration and html tag. | | Xhtml1_0_Strict | Output doctype declaration and html tag. | | Xhtml1_0_Transitional | Output doctype declaration and html tag. | | Xhtml1_0_Frameset | Output doctype declaration and html tag. | | Html5 | Output doctype declaration and html tag. | | Xml | Output xml declaration. | | HtmlImposition | Impose pages in a physical page. |

red-agate/modules/red-agate/svg

| tag | description | |-----|-------------| | Svg | Output svg tag.Children can use a Canvas context. | | Ambient | Change current graphic state properties. | | Arc | Draw an arc. | | Canvas | Call a lambda function and draw by using Canvas context object. | | Circle | Draw a circle. | | Curve | Draw bezier curve(s). | | GridLine | Draw grid lines for design time. | | Group | Group children.Output g tag. | | Line | Draw line(s). | | Path | Group path fragments (e.g. Arc, Circle, Curve, Line, Rect, ...) . | | Pie | Draw a pie. | | Polygon | Draw a polygon. | | Rect | Draw a rectangle. | | RoundRect | Draw a rounded rectangle. | | SvgAssetFragment | Append raw SVG tags into defs. | | SvgFragment | Append raw SVG tags. | | Text | Draw text line(s). | | SvgImposition | Impose pages in a physical page. |

red-agate/modules/red-agate/printing

| tag | description | |-----|-------------| | PrinterMarksProps | Draw printer marks (crop mark, bleed mark, center mark, fold mark). |

red-agate-barcode/modules/barcode/(Code39|Code128|Ean|Itf|JapanPostal|Nw7|Qr)

$ npm install red-agate-barcode --save

| tag | description | |-----|-------------| | Code39 | Draw a CODE39 barcode. | | Code128 | Draw a CODE128 barcode. (GS1-128 is available) | | Ean13 | Draw a EAN-13 (GTIN-13 / JAN-13) barcode. | | Ean8 | Draw a EAN-8 (GTIN-8 / JAN-8) barcode. | | Ean5 | Draw a EAN-5 (JAN-5) barcode. | | Ean2 | Draw a EAN-2 (JAN-2) barcode. | | UpcA | Draw a UPC-A (GTIN-12) barcode. | | UpcE | Draw a UPC-E barcode. | | Itf | Draw a ITF barcode. (GTIN-14 is available) | | JapanPostal | Draw a Japan Post Customer barcode. | | Nw7 | Draw a NW7 (Codabar) barcode. | | Qr | Draw a QR Code (model 2) barcode. |

red-agate-react-host/modules/react-host

$ npm install react --save
$ npm install react-dom --save
$ npm install red-agate-react-host --save

| tag | description | |-----|-------------| | ReactHost | Host a react element and render as static markup. |

Configurations for building application

If you want to use red-agate w/o jsx pragma comment (/** @jsx RedAgate.createElement */),
You should configure tsconfig or .babelrc for building JSX.
Prease see typescript docs , babel docs or example.

FAQ

  • Can I receive element events (e.g. onclick) ?
    • No. RedAgate is static renderer. Please use React, Vue, Riot, Angular, knockout, ...
  • Can I change DOM via API after rendered to real DOM?
    • No. Please use React, Vue, Riot, Angular, knockout, ...
  • Can I build print preview window by using RedAgate?
    • paper-css may help you to build print previews.

License

ISC
Copyright (c) 2017, Shellyl_N and Authors.