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

@hiveio/content-renderer

v2.3.1

Published

Content renderer for Hive posts and comments. Markdown + HTML

Downloads

625

Readme

@hiveio/content-renderer

npm License PRs Welcome

👉 Online demo

Portable library that renders Hive posts and comments to string. It supports markdown and html and mimics the behaviour of condenser frontend.

Features:

  • supports markdown and html
  • sanitizes html and protects from XSS
  • embeds images, videos, and other assets via links or iframes
  • ensures links are safe to display and begins with https:// protocol
  • linkify #tags and @username mentions
  • proxify images if needed and appropriate function is provided
  • synchronous execution with no external calls

Credit: this library is based on the code from condenser. It's aim is to allow other projects display Hive content the right way without porting the same code over and over.

Server side usage

Installation:

$ npm install --save @hiveio/content-renderer

Typescript:

import { DefaultRenderer } from "@hiveio/content-renderer";

const renderer = new DefaultRenderer({
    baseUrl: "https://hive.blog/",
    breaks: true,
    skipSanitization: false,
    allowInsecureScriptTags: false,
    addNofollowToLinks: true,
    doNotShowImages: false,
    assetsWidth: 640,
    assetsHeight: 480,
    imageProxyFn: (url: string) => url,
    usertagUrlFn: (account: string) => "/@" + account,
    hashtagUrlFn: (hashtag: string) => "/trending/" + hashtag,
    isLinkSafeFn: (url: string) => true,
    addExternalCssClassToMatchingLinksFn: (url: string) => true,
    ipfsPrefix: "https://ipfs.io/ipfs/" // IPFS gateway to display ipfs images
});

const safeHtmlStr = renderer.render(postContent);

Browser usage:

See demo and its source.


<script src="https://unpkg.com/@hiveio/content-renderer"></script>
<script>
    const renderer = new HiveContentRenderer.DefaultRenderer({
        baseUrl: "https://hive.blog/",
        breaks: true,
        skipSanitization: false,
        allowInsecureScriptTags: false,
        addNofollowToLinks: true,
        doNotShowImages: false,
        cssClassForInternalLinks: "link",
        cssClassForExternalLinks: "external",
        assetsWidth: 640,
        assetsHeight: 480,
        imageProxyFn: (url) => url,
        usertagUrlFn: (account) => "/@" + account,
        hashtagUrlFn: (hashtag) => "/trending/" + hashtag,
        isLinkSafeFn: (url) => true,
        addExternalCssClassToMatchingLinksFn: (url: string) => true,
        ipfsPrefix: "https://ipfs.io/ipfs/"
    });

    $(document).ready(() => {
        const renderMarkdownBtnElem = $("#render-button");
        const inputElem = $("#input");
        const outputElem = $("#output");
        const outputMarkupElem = $("#output-markup");

        renderMarkdownBtnElem.on("click", () => {
            const input = inputElem.val();
            const output = renderer.render(input);

            console.log("Rendered", output);
            outputElem.html(output);
            outputMarkupElem.text(output);
        });
    });
</script>
</body>
</html>

Renderer options

You can pass options to the renderer to customize its behaviour. Here is the list of available

export interface RendererOptions {
    baseUrl: string;
    breaks: boolean;
    skipSanitization: boolean;
    allowInsecureScriptTags: boolean;
    addNofollowToLinks: boolean;
    doNotShowImages: boolean;
    assetsWidth: number;
    assetsHeight: number;
    imageProxyFn: (url: string) => string;
    hashtagUrlFn: (hashtag: string) => string;
    usertagUrlFn: (account: string) => string;
    isLinkSafeFn: (url: string) => boolean;
    addExternalCssClassToMatchingLinksFn: (url: string) => boolean;
    addTargetBlankToLinks?: boolean;
    cssClassForInternalLinks?: string;
    cssClassForExternalLinks?: string;
    ipfsPrefix?: string;
}

Options explained

  • baseUrl - base url of the website. It's used to create links.
  • breaks - if true, newlines characters (\n) are converted to <br> tags. This only applies to markdown input. Usually you want to set this to true.
  • skipSanitization - if true, html is not sanitized. This is not recommended, as it can lead to XSS attacks. Set this to false always for production use.
  • allowInsecureScriptTags - if true, script tags are not removed from the input. This is not recommended, as it can lead to XSS attacks. Set this to false always for production use.
  • addNofollowToLinks - if true, rel="nofollow" is added to all links.
  • addTargetBlankToLinks - if true, target="_blank" is added to all links.
  • doNotShowImages - if true, images are not being rendered as <img> tags but as <pre> tags with the image url.
  • assetsWidth - width of the images and embeds in pixels.
  • assetsHeight - height of the images and embeds in pixels.
  • imageProxyFn - function that takes an image url and returns a proxied url. This can be useful to use a proxy to display images. It's also useful to resize images.
  • hashtagUrlFn - function that takes a hashtag and returns a url to the hashtag page.
  • usertagUrlFn - function that takes a usertag and returns a url to the user profile. This might be useful if you want to differentiate between internal and external links for some specific accounts, like bad actors.
  • isLinkSafeFn - function that takes a link and returns true if the link is safe to display. This can be useful to filter out links to phishing sites or other malicious content. If this function returns false, the link is not displayed and title is set to phishing warning.
  • addExternalCssClassToMatchingLinksFn - function that takes a link and returns true if the link should have cssClassForExternalLinks added to it. This can be useful to differentiate appearance between internal and external links.
  • addTargetBlankToLinks - if true, target="_blank" is added to all links.
  • cssClassForInternalLinks - if set, this class is added to all internal links.
  • cssClassForExternalLinks - if set, this class is added to all external links if addExternalCssClassToMatchingLinksFn returns true.
  • ipfsPrefix - if set, this prefix is added to all IPFS links. This can be useful if you want to use a public IPFS gateway to display ipfs images. It may or may not end with a slash.

Development

Library is written in typescript and expects NodeJS v20 or higher. If you use nvm, you can run nvm install and nvm use to switch to the right version automatically.

To start developing:

$ npm install
$ npm run build

Testing

Unit tests

The library is tested with mocha and chai. To run unit tests:

$ npm run test

Integration tests

Integration tests are run with testcafe. Please note you need to rebuild the library before running the tests in order to have the latest version of the library embedded in the test page. Run npm run build before running the tests.

To run integration tests with your default browser (chrome):

$ npm run verify:chrome
$ npm run verify:firefox

Linting

In order to provide consistent code style, the library is linted with eslint with prettier and typescript plugin. This is enforced in CI and git hooks.

To run linter:

$ npm run lint

Semantic versioning

Library follows semantic versioning and is released to NPM registry automatically with CI after a merge to master. CI and husky is configured in a way to enforce Conventional Commits. Git hooks are installed to enforce this in local development.

Versioning is done automatically with semantic-release. Please note that the version is bumped automatically based on the commit messages.