0.0.11 • Published 11 months ago
tiny-marked v0.0.11
tiny-marked
A tiny markdown subset parser that is ≈ 1kb in size
Can handle:
- Blockquote
- Bold
- Breaklines
- Heading
- Images
- Italic
- Links
- Unordered lists
Install
$ npm i tiny-marked
Usage example
import {parse} from 'tiny-marked'
import {blockquoteParser} from 'tiny-marked/lib/parsers/blockquote-parser'
import {boldItalicParser} from 'tiny-marked/lib/parsers/bold-italic-parser'
import {breaklinesParser} from 'tiny-marked/lib/parsers/breaklines-parser'
import {headingParser} from 'tiny-marked/lib/parsers/heading-parser'
import {linkParser} from 'tiny-marked/lib/parsers/link-parser'
import {listParser} from 'tiny-marked/lib/parsers/list-parser'
const result = parse('**[text](https://example.com)**', [
blockquoteParser,
listParser,
headingParser,
linkParser,
boldItalicParser,
breaklinesParser,
])
/* result
[
{
type: 'strong',
value: [
{
type: 'a',
value: ['text'],
href: 'https://example.com',
},
],
},
]
*/
const result = parse('**bold** *italic* [text](https://example.com)', [
blockquoteParser,
listParser,
headingParser,
linkParser,
boldItalicParser,
breaklinesParser,
])
/* result
[
{
type: 'strong',
value: ['bold'],
},
' ',
{
type: 'em',
value: ['italic'],
},
' ',
{
type: 'a',
value: ['text'],
href: 'https://example.com',
},
]
*/
Built in parsers
blockquoteParser
Parses blocks quotes.
import:
import {blockquoteParser} from 'tiny-marked/lib/parsers/blockquote-parser'
Example:
> Hello
listParser
Parses unordered lists
import:
import {listParser} from 'tiny-marked/lib/parsers/list-parser'
Example:
* Hello
* hello
headingParser
Parses headings 1-6
import:
import {headingParser} from 'tiny-marked/lib/parsers/heading-parser'
Example:
# Hello
###### Hello
linkParser
Parses links, images, emails
import:
import {linkParser} from 'tiny-marked/lib/parsers/link-parser'
Example:
[link](https//example.com)

boldItalicParser
Parses bold and italic
import:
import {boldItalicParser} from 'tiny-marked/lib/parsers/bold-italic-parser'
Example:
**This text is bold**
*Italic text*
breaklinesParser
Parses break lines
import:
import {breaklinesParser} from 'tiny-marked/lib/parsers/breaklines-parser'
Example:
\n
\r
<br />
Build string or components
Some alternatives to building component or string from parse result.
First
Using recursive map
function build(data) {
if (typeof data === 'string') {
return data
}
if (data.type === 'strong') {
const components = data.value.map(build).join('')
return `<strong>${components}</strong>`
}
if (data.type === 'em') {
const components = data.value.map(build).join('')
return `<em>${components}</em>`
}
if (data.type === 'a') {
const components = data.value.map(build).join('')
return `<a href="${data.href}">${components}</a>`
}
return data.match
}
const data = [
{
type: 'strong',
value: [
{
type: 'a',
value: ['bold link'],
href: 'https://example.com',
},
],
},
' ',
{
type: 'em',
value: ['italic'],
},
]
const components = data.map(build)
console.log(components.join(''))
/* result
<strong><a href="https://example.com">bold link</a></strong> <em>italic</em>
*/
Second
Using an iterator to flatten the list and give action on when to open or close elements
function* traverse(list: Array<Match | string>) {
let index = 0
while (list[index] !== undefined) {
const item = list[index]
index += 1
if (typeof item === 'string') {
yield {type: 'string', value: item}
continue
}
yield {type: item.type, action: 'open'}
const iterator = traverse(item.value)
let message = iterator.next()
while (!message.done) {
yield message.value
message = iterator.next()
}
yield {type: item.type, action: 'close'}
}
return
}
function build(list) {
const iterator = traverse(list)
let str = ''
let message = iterator.next()
while (!message.done) {
const item = message.value
switch (item.type) {
case 'string':
str += item.value
break
case 'strong':
if (item.action === 'open') {
str += `<strong>`
} else {
str += '</strong>'
}
break
case 'a':
if (item.action === 'open') {
str += `<a href="${item.href}">`
} else {
str += '</a>'
}
break
case 'em':
if (item.action === 'open') {
str += `<em>`
} else {
str += '</em>'
}
break
}
message = iterator.next()
}
return str
}
const data = [
{
type: 'strong',
value: [
{
type: 'a',
value: ['bold link'],
href: 'https://example.com',
},
],
},
' ',
{
type: 'em',
value: ['italic'],
},
]
console.log(build(data))
/** result
<strong><a href="https://example.com">bold link</a></strong> <em>italic</em>
*/
Create your own parser
Create a function that implements the Parser
interface.
Example
woowHello
import {createElement} from 'tiny-marked'
// parser type Parser<'woow'> should match createElement('woow'
const woowParser: Parser<'woow'> = ({parseElements}) => {
return {
/**
* Add a regex
* This example matches on "woow" then everything until a space or enter
**/
regex: /(woow[a-z\d-]+)/gim,
/**
* Add a replacer function,
* The first param will be id (not an uniq id!)
* Then matching results from your reges, could be multible match params depending on your regex
**/
replacer: (id, match) => {
const content = match.slice(4) // get everything after "woow"
// create your element, this one is called woow
// pass your content with the matcher removed (remove "wooow")
// this content can be parsed again so its importat to remove the matcher or endless recursion will occur
return createElement('woow', parseElements(content), id)
},
}
}
/**
* match result from woowParser with input "woowHello"
* [{type: 'woow', value: ['Hello']}]
**/