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

@connectv/marked

v0.2.4

Published

component-based markdown renderer

Downloads

62

Readme

@connectv/marked

Build Status Code Coverage NPM Version License

Component-based markdown renderer for CONNECTIVE HTML. The component-based approach allows you to provide your own custom (possibly interactive) components for the markdown conversion:

// my-header.tsx

function MyHeader({ depth, slug }, renderer, content) {
  return <div class={'title title-' + depth} id={'header-' + slug}>{content}</div>;
}
// index.tsx

import { marked } from '@connectv/marked';
import { Renderer } from '@connectv/html';

import { MyHeader } from './my-header';

const renderer = new Renderer();

renderer.render(marked('## Hellow World!', {
  Heading: MyHeader
})).on(document.body);

//
// Result:
// <div class="title title-2" id="header-hellow-world">Hellow World!</div>
//

Installation

npm i @connectv/marked

For providing your own custom components in JSX/TSX, you need to configure your transpiler accordingly. Here is how to do it for Typescript and here you can see how to do it for Babel.

Usage

Basic

import { Renderer } from '@connectv/html';
import { marked } from '@connectv/marked';

const renderer = new Renderer();
const md = `
# Hellow!

So this is some markdown text with **some features** and stuff.
`;

renderer.render(marked(md)).on(document.body);

Server-side rendering (using CONNECTIVE SDH):

import { compile } from '@connectv/sdh';
import { marked } from '@connectv/marked';

compile(marked(`
# Hellow Again!

Some other [markdown](https://en.wikipedia.org/wiki/Markdown) for you.
`))
.save('dist/index.html');

Overriding Components

As mentioned above, the main point of this library is to provide your own custom components for generating DOM from the markdown:

// my-code.tsx

export function MyCode({ lang }, renderer, content) {
  return <pre onclick={() => copyToClipboard(content)}>
    <code class={'code ' + lang}>{content}</code>
  </pre>;
}
// index.tsx

import { marked } from '@connectv/marked';
import { Renderer } from '@connect/html';

import { MyCode } from './my-code';

const renderer = new Renderer();
const md = `
# Example Code:
\`\`\`typescript
export function something() {
  console.log('Halo!');
}
\`\`\`
`;

renderer.render(marked(md, {
  Code: MyCode
})).on(document.body);

The following components can be overriden, alongside the properties that the markdown parser would pass to each component:

  • Space: used for empty spaces. No props passed to this component.
  • Hr: used for horizontal lines (---). No props passed to this component.
  • Heading: used for headings (# Heading). Props:
    • depth: depth of the heading, i.e. # Heading 1, ## Heading 2, ### Heading 3, etc.
    • slug: a slug associated with this heading. Can be used to set the content's id so that it is linkable.
  • Code: used for code blocks (not inline codes). Props:
    • lang: the language set for this code block, e.g. ```typescript.
  • BlockQuote: used for block quotes > something. No props passed to this component.
  • List: used for lists. Props:
    • ordered: whether the list is ordered or unordered.
  • ListItem: used for items of a list. No props passed to this component.
  • Html: used for inline HTML code. Props:
    • content: the string representation of the HTML code.
  • Paragraph: used for plain text. No props passed to this component.
  • Table: used for tables. Props:
    • header: HTML element representing the header of the table.
    • body: HTML element representing body of the table.
  • TableRow: used for each row of a table. No props passed to this component.
  • TableCell: used for body cells of a table (not header cells). Props:
    • align: the alignment of the cell.
  • TableHeaderCell: used for header cells of a table (not body cells). Props:
    • align: the alignment of the cell.
  • Link: used for links, e.g. [content](href "title"). Props:
    • href: the URL of the link
    • title: the "title" attribute of the link
  • Em: used for emphasized text, e.g. _hellow_. No props passed to this component.
  • Strong: used for strong text, e.g. **hellow**. No props passed to this component.
  • Del: used for deleted text, e.g. ~~hellow~~. No props passed to this component.
  • Image: used for images, e.g. ![alt](src). Props:
    • alt: the alt text passed for the image,
    • src: the source URL of the image.
  • CodeSpan: used for inline code-spans, e.g. `content`. No props passed to this component.
  • Text: used for normal text. No props passed to this component.

Custom Quoted Components

You can also use custom components (i.e. components that represent custom structural elements):

// tabs.tsx

export function Tabs(_, renderer, content) {
  return <div class="tabs">{content}</div>;
}

export function Tab({ name, default }, renderer, content) {
  return <div class="tab" data-tab-name={name} data-default-tab={default==='true'}>{content}</div>;
}
// index.tsx

import { compile } from '@connectv/sdh';
import { marked, quotedComponents } from '@connectv/marked';

import { Tabs, Tab } from './tabs';

const markdown = `
# Some markdown content

> :Tabs
> > :Tab name=first tab, default=true
> >
> > content of the first tab
>
> > :Tab name=second tab
> >
> > content of the second tab
`

compile(marked(markdown, {
  BlockQuote: quotedComponents({ Tabs, Tab })
}))
.save('dist/index.html');

Result (dist/index.html):

<html>
  <head></head>
  <body>
    <h1 id="some-markdown-content">Some markdown content</h1>
    <div class="tabs">
      <div class="tab" data-tab-name="first tab" data-default-tab>
        <p>content of the first tab</p>
      </div>
      <div class="tab" data-tab-name="second tab">
        <p>content of the second tab</p>
      </div>
    </div>
  </body>
</html>

The quotedComponents() method basically provides an override for BlockQuote. It will look at each block-quote and check if the first line starts with :, in that case it will find corresponding component from given map, parse its props, and pass the rest of the content of the block-quote as the component's content.

Custom Linked Components

Similar to custom quoted components, you can utilize custom linked components for custom structural elements that are inline (i.e. appear within other text):

// tag.tsx

export function Tag(_, renderer, content) {
  return <span class="tag">#{content}</div>;
}
// index.tsx

import { compile } from '@connectv/sdh';
import { marked, linkedComponents } from '@connectv/marked';

import { Tag } from './tag';

const markdown = `
# Some markdown content

Hellow [world](:Tag)
`

compile(marked(markdown, {
  Link: linkedComponents({ Tag })
}))
.save('dist/index.html');

Result (dist/index.html):

<html>
  <head></head>
  <body>
    <h1 id="some-markdown-content">Some markdown content</h1>
    <p>
      Hellow <span class="tag">#world</span>
    </p>
  </body>
</html>

Markdown Features

marked is used under the hood, so all features supported by marked are supported here.