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

@xan105/markdown

v0.4.0

Published

Web-component to render markdown into html with syntax highlighting

Downloads

13

Readme

About

Web-component to load an external markdown file (.md) and render it into sanitized HTML.

  • Syntax highlighting
  • Table of contents
  • Copy code to clipboard
  • Light DOM CSS styling
  • Optional JavaScript API

📦 Scoped @xan105 packages are for my own personal use but feel free to use them.

Published on webcomponents.org

Example

Import and define the Web-component:

import { Markdown } from "/path/to/md.js"
customElements.define("mark-down", Markdown);

HTML:

  <mark-down src="/path/to/md"></mark-down>

Optional JavaScript API:

  const el = document.querySelector("mark-down");
  el.addEventListener("load", ()=>{
    console.log("loading...");
  });
  el.addEventListener("success", ()=>{
    console.log("ok");
  });
  el.addEventListener("failure", ({detail})=>{
    console.error(detail.error);
  });

  //auto rendering (default)
  el.integrity = "sha384-0xABCD...";
  el.src = "/path/to/md";

  //manual rendering
  el.manual = true;
  el.src = "/path/to/md";
  el.render().catch((err)=>{
    console.error(err);
  });
  
  //Table of contents
  querySelector("#toc").innerHTML = el.headings.toHTML({ depth: 4 });
  
  el.addEventListener("intersect", ({detail})=>{
    //Do something when a heading (h1, h2, ...) has entered the top of the viewport
    querySelector(`#toc a[href="#${detail.id}"]`).classList.add("active");
  });

Install

npm i @xan105/markdown

💡 The bundled library and its minified version can be found in the ./dist folder.

Via importmap

Create an importmap and add it to your html:

  <script type="importmap">
  {
    "imports": {
      "@xan105/markdown": "./path/to/node_modules/@xan105/markdown/dist/md.min.js"
    }
  }
  </script>
  <script src="./index.js" type="module"></script>
  </body>
</html>

index.js:

import { Markdown } from "@xan105/markdown"
customElements.define("mark-down", Markdown);

Styling

Markdown is rendered into the light DOM without any predefined CSS styling, this is by design. Use regular selectors to style just like you would for the rest of the page.

For syntax highlighting you can use one of the many hljs themes available.

💡That being said, there is a basic CSS style with Github-like syntax highlighting available in the ./dist folder to get you started.

Copy to clipboard

To target the "copy to clipboard" unstyled button added to "code blocks" use CSS ::part() selector:

clipboard-copy-code { display: block } //by default it is not rendered (display: none)
clipboard-copy-code::part(button) { ... }
clipboard-copy-code::part(button)::before { /*go nuts this also works*/ }

clipboard-copy-code will have the attribute copied set when the content has been copied to the clipboard; You can target it via CSS and add a timeout (ms) attribute/property value if you wish to do some kind of animation on copy.

clipboard-copy-code also fires a copied event just in case.

API

⚠️ This module is only available as an ECMAScript module (ESM) and is intended for the browser.

Named export

Markdown(): Class

This is a Web-component as such you need to define it:

import { Markdown } from "/path/to/md.js"
customElements.define("mark-down", Markdown);

Events

  • change()

    The source (src) attribute has changed.

  • load()

    Markdown is being loaded.

  • render()

    Markdown is being rendered.

  • success()

    Markdown was rendered without any issue.

  • failure(detail: object)

    Something went wrong, see detail:

    { error: Error }
  • intersect(detail: object)

    A heading (h1, h2, ...) has entered the top of the viewport, see detail:

    { id: string }

Attribute / Property

  • src: string

    Path/URL to the .md file to load.

  • integrity: string

    Integrity hash passed to fetch(). See Subresource Integrity for more details.

  • manual: boolean

    If set markdown will not be rendered automatically and you will have to call the render() method yourself (see below).

  • rendered: boolean (Read-only)

    Whether the markdown was succesfuly rendered or not. You can use :not([rendered]) in your CSS to style the element differently before rendering.

Property

  • headings: Set<object> (Read-only)

    List of all headings (h1, h2, ...) with an id and text content represented as follows:

    {
      id: string,
      level: number,
      title: string
    }

    Example:

      //<h2 id="user-content-links">Links</h2>
      { id: "user-content-links", title: "Links", level: 2 }

    The returned Set is extended with an additional toHTML() function:

    • toHTML(options?: object): string

      Which returns sanitized HTML string representing the table of contents from the headings (nested list).

        <ul>
          <li><a href="#id">title</a></li>
          <li>
            <ul>
              <li><a href="#id">title</a></li>
              <li><a href="#id">title</a></li>
            </ul>
          </li>
        <ul/>

      Options:

      • depth?: number (6)

        How deep to list ? Headings start from 1 to 6.

      • ordered?: boolean (false)

        When set to false the root of the list is ul otherwise ol.

Methods

  • render(): Promise<void>

    Load and render markdown into sanitized HTML.

    ✔️ Resolves when markdown has been sucesfully rendered. ❌ Rejects on error

    💡 Invoking this method still triggers related events.