@iandx/markit
TypeScript icon, indicating that this package has built-in type declarations

0.1.6Β β€’Β PublicΒ β€’Β Published

Markit

A powerful markdown parser and renderer for react

  • πŸ‘ build for high extensibility
  • ⚑️ yet still very fast
  • πŸ’« best practice for react
  • ✨ incremental parsing to avoid unnecessary dom re-render
  • 🎨 easy to customize

Install

npm install @iandx/markit

Quick start

import { ReactMarkit } from '@iandx/markit';
function App () {
    const content = '# Welcome to **use** *Markit*';
    return(
        <ReactMarkit content={content}/>
    )
}

Usage

ReactMarkit

  • Basic React component. Give it a content or children prop as its rendering content

    Use whichever you like

let content = "* this is a list"
const Markit1 = () => 
    <ReactMarkit content={content} />
const Markit2 = () =>
    <ReactMarkit>{content}<ReactMarkit/>

Markit

Global init markit

import {Markit} from "@iandx/markit"
Markit.init({
    tabSpaceNum: 2,
    softBreak: true,
    geneId: false
})
properties type default description
tabSpaceNum number 2 a tab "\t" equals to how many spaces
softBreak number true if set "true", "\n" will be recognized as a soft break instead of a new line
geneId number false give each AST a unique id, useful for increnmental parsing

Default rules and drop rules

  • Inline

    type description
    Bold **bold**
    Italic *italic*
    Strike ~~strike through~~
    Underline <u>underline<u>, _!also underline!_
    Code `code`
    Link [link title](link_url)
    Escape character like \*, \_, \~
    Superscript ^superscript^
    Subscript ~subscript~
    Highlight ==hightlight==
    HtmlTag <anyTag>content</anyTag>
    Math $latex math formula like \frac{1}{2}$
    FootnoteSup [^footnotesup] will link to the end of the page
    LinkTag [link tag] will be a link if supply a link block

    if you don't want some provided inline features, you can easily drop it by using

    import {Markit} from "@iandx/markit"
    Markit.dropRule.inline(["Math", "LinkTag"])
  • block

    type blockType description
    Heading leaf # this is heading1
    this is also heading1
    =====
    Blockquote leaf > blockquote
    >> level2
    CodeBlock leaf ``` javascript
    function test() {
    console.log("hi")
    }
    ```
    Divider leaf ----[dashed]
    Image leaf ![alt_content](url hover_title 50% center)
    MathBlock leaf $$
    Math block \sqrt{a}
    $$
    Latex leaf $$$
    Latex block \sqrt{a}
    $$$
    Footnote leaf [^footnotesup]: content
    LinkTagBlock leaf [^linkTag]: replaced url
    Comment leaf // any comment
    UnorderedList container * unordered list
    + also unordered list
    - still unordered list
    OrderedList container 1. OrderedList
    1. will display 2 in this line
    CheckList container - [x] GFM to-do list

    if you don't want some provided inline features, you can easily drop it by using

    import {Markit} from "@iandx/markit"
    Markit.dropRule.block(["Comment", "Image", "Divider"])

Add new rules

inline First we will introduce the structure of the syntax rule. Following are the properties.

tags An object to define syntax token. You may use the following properties to config.

  • leading A String which will be recognized as syntax token used before text, e.g. '##'
  • round A String which will be recognized as syntax token used around text, e.g. '**'
  • wrap A array which will be recognized as syntax token used in the left and right of the text. e.g. ['','']
  • exact A String or a regular expression

trimText A callback function which recieves a raw text and usually returns the text after triming the tags. Note: using leading, round, wrap, the parser will help you trim the tags token by default

parseContent A callback function which recieve the trimmed text

getProps A callback function which recieve the raw text, get the additional props, then return.

recheckMatch A callback function which recieve the raw text to recheck if the raw text match the syntax token.

order

Now, you may use addRule to custom your own syntax.

addRule({name,rule,view})

  • name A string used to identify the rule.
  • rule A object introducing before to describe the custom syntax.
  • view A function which returns a React component matching your custom token.

Following is an example.

// add a block syntax
Markit.addRule.block({
    name: "CustomHeading",
    rule: {
        tags: {
            leading: /#{1,5} /, 
            exact: [/(?:\n|^).+?\n===+ */, /(?:\n|^).+? ?\n---+ */]
        },
    getProps: (raw) => {
        let headingLevel: number
        let hashHeadingMatch = raw.match(/^#+ /)
        if (hashHeadingMatch) {
        headingLevel = hashHeadingMatch![0].trim().length
        } else {
        let heading1Match = raw.match(/\n===+/)
        headingLevel = !!heading1Match ? 1 : 2
        }
        return {headingLevel}
    },
    trimText: raw => raw.replaceAll(/\n((===+)|(---+))/g, "").replaceAll(/^#{1,5} /g, ""),
    parseContent: text => text,
    recheckMatch: raw => {
        return true
    },
    blockType: "leaf"
    },
    view: (content: any, {headingLevel, blockProp}) =>
    Span(content+(!!blockProp ? blockProp.a:"")).fontSize(`${(5 - (headingLevel ?? 1)) * 6 + 15}px`)
    })

// add a inline syntax
Markit.addRule.inline({
    name: "Italic",
    rule: {
        tags: {
            round: "[em]",
            exact: [
                /\*(?!\s)(?:(?:[^*]*?(?:\*\*[^*]+?\*\*[^*]*?)+?)+?|[^*]+)\*/,
            ]
        },
        trimText: (text: string) => text.replace(/^\*|\*$/g, ""),
    },
    // view:  (content) => ()
})

you may use dropRuleto remove one of the syntax rule.

// remove a block syntax rule
Markit.dropRule.block(["Heading"])

// remove a inline syntax rule
Markit.dropRule.inline(["Italic"])

Advanced

MarkitView

API

Markit

API

function description parameter
init to certain props init a Markit object
parse return a markdonwerTree array string
Usage
import { Markit } from '@iandx/markit'

Markit.init({softBreak: false})
const markitASTs = Markit.parse('## Markit **fast** ')

MarkdonwerTree

Markit.parse will parse the text iteratively where there is a markdown syntax. We design a tree to contain the parsed result called MarkdonwerTrees.

Note: The type of leaf node must be "Text" or "Heading"

The node of MarkdonwerTree has the following properties.

properties description type value
content its children which are also the markdownTrees or string
id block id
level block level or inline level string "block"/"inline"
props additional properties object
raw the text inclues markdown syntax string
type the markdown type. e.g."OrderedList", "Heading" string

Custom Syntax

Readme

Keywords

none

Package Sidebar

Install

npm i @iandx/markit

Weekly Downloads

0

Version

0.1.6

License

none

Unpacked Size

175 kB

Total Files

39

Last publish

Collaborators

  • iandx