
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
tiny-marked
Advanced tools
A tiny markdown subset parser that is ≈ 1kb in size. Outputs a tree structure instead of completed string. This way you can handle that logic your self and render it in any way. Run it on frontend with react or other types of components, use Nodejs to prerender / analyze content.
Can handle:
- Blockquote
- Bold
- Breaklines
- Heading
- Images
- Italic
- Links
- Unordered lists
- footnote
- strikethrough
- block
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'
import {footnoteParser} from 'tiny-marked/lib/parsers/footnote-parser'
import {strikeParser} from 'tiny-marked/lib/parsers/strike-parser'
import {blockParser} from 'tiny-marked/lib/parsers/block-parser'
const result = parse('**[text](https://example.com)**', [
blockquoteParser,
listParser,
headingParser,
linkParser,
boldItalicParser,
breaklinesParser,
footnoteParser,
strikeParser,
blockParser,
])
/* result
[
{
type: 'strong',
value: [
{
type: 'a',
value: ['text'],
attributes: {
href: 'https://example.com',
}
},
],
},
]
*/
const result = parse('**bold** *italic* [text](https://example.com)', [
blockquoteParser,
listParser,
headingParser,
linkParser,
boldItalicParser,
breaklinesParser,
footnoteParser,
strikeParser,
blockParser,
])
/* result
[
{
type: 'strong',
value: ['bold'],
},
' ',
{
type: 'em',
value: ['italic'],
},
' ',
{
type: 'a',
value: ['text'],
attributes: {
href: 'https://example.com',
}
},
]
*/
Parses blocks quotes.
import:
import {blockquoteParser} from 'tiny-marked/lib/parsers/blockquote-parser'
Example:
> Hello
Result:
// > block
{
type: 'blockquote',
value: ['block'],
attributes: {},
}
Parses unordered lists
import:
import {listParser} from 'tiny-marked/lib/parsers/list-parser'
Example:
* Hello
* hello
Result:
// * item
{
type: 'li',
value: ['item'],
attributes: {},
}
Parses headings 1-6
import:
import {headingParser} from 'tiny-marked/lib/parsers/heading-parser'
Example:
# Hello
###### Hello
Result:
// # title
{
type: 'h1',
value: ['title'],
attributes: {},
}
Parses links, images, emails
import:
import {linkParser} from 'tiny-marked/lib/parsers/link-parser'
Example:
[link](https//example.com)

Result:
// '[text](https://example.com)'
{
type: 'a',
value: ['text'],
attributes: {href: 'https://example.com'},
}
Parses bold and italic
import:
import {boldItalicParser} from 'tiny-marked/lib/parsers/bold-italic-parser'
Example:
**This text is bold**
*Italic text*
Result:
// **title**
{
type: 'strong',
value: ['title'],
attributes: {},
}
Parses break lines
import:
import {breaklinesParser} from 'tiny-marked/lib/parsers/breaklines-parser'
Example:
\n
\r
<br />
Result:
// <br/>
{
type: 'br',
value: ['<br/>'],
attributes: {},
}
Parses footnotes / references
import:
import {footnoteParser} from 'tiny-marked/lib/parsers/footnote-parser'
Example:
this is a footnote [^1]
[^1]: it references this
Result:
// [^note]
{
type: "footnote",
value: ["note"],
attributes: {}
}
// [^note]: result`
{
type: "footnote",
value: ["note"],
attributes: {"end": true}
}
Parses strikethroughs
import:
import {strikeParser} from 'tiny-marked/lib/parsers/strike-parser'
Example:
~~text~~
Result:
// ~~Striked~~
{
type: 's',
value: ['Striked'],
attributes: {},
}
Parses blocks / codeblocks
import:
import {blockParser} from 'tiny-marked/lib/parsers/block-parser'
Example:
\```
content
\```
Result:
// `block`
{
type: 'code',
value: ['block'],
attributes: {},
}
If you want to go through the result and build components, strings, analyze etc, i have two examples provided here.
First
Using recursive map, simply run a map function on every child value. This would fit almost every usecase the best.
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.attributes.href}">${components}</a>`
}
return data.match
}
const data = [
{
type: 'strong',
value: [
{
type: 'a',
value: ['bold link'],
attributes: {
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.attributes.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'],
attributes: {
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 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 {
/**
* Required
* Add a regex
* This example matches on "woow" then everything until a space or enter.
**/
regex: /(woow[a-z\d-]+)/gim,
/**
* Optional
* Ignore nested parsing by adding name of parsers.
* example: adding 'boldItalicParser' for linkParser removes abillity of bolded link: **[text](example.se)**
**/
ingore: []
/**
* Required
* Add a replacer function, runs on regex match
* Parameter match. Results from your reges, could be multible match params depending on your regex.
**/
replacer: (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.
// You can also use the `ignore` property to prevent self reccursion if needed.
return createElement('woow', parseElements(content), {
/* place custom attributes here, etc href link */
custom: 'example',
})
},
}
}
/**
* match result from woowParser with input "woowHello"
* [{type: 'woow', value: ['Hello'], attributes: { custom: 'example' } }]
**/
FAQs
A ≈1kb markdown parser with tree output and Typescript typings
The npm package tiny-marked receives a total of 8 weekly downloads. As such, tiny-marked popularity was classified as not popular.
We found that tiny-marked demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.