Skip to content

Commit

Permalink
feat: add alert blockquote handling
Browse files Browse the repository at this point in the history
  • Loading branch information
quantizor committed Nov 20, 2024
1 parent 8109434 commit 20777bf
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 19 deletions.
12 changes: 12 additions & 0 deletions .changeset/shaggy-ants-collect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'markdown-to-jsx': minor
---

Add support for GFM alert-style blockquotes.

```md
> [!Note]
> This is a note-flavored alert blockquote. The "Note" text is injected as a `<header>` by
> default and the blockquote can be styled via the injected class `markdown-alert-note`
> for example.
```
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ node_modules/
.git/
.DS_Store
coverage/
dist/
*.log
package-lock.json
npm-shrinkwrap.json
Expand All @@ -15,3 +14,8 @@ npm-shrinkwrap.json
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# ephemeral files
dist/
docs/markdown-to-jsx.js
docs/markdown-to-jsx.js.map
7 changes: 5 additions & 2 deletions docs/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!doctype html>
<!DOCTYPE html>
<html>
<head>
<title>markdown-to-jsx: try it live!</title>
Expand Down Expand Up @@ -45,7 +45,7 @@
<script type="text/plain" id="sample-content">
# This is Markdown

#### You can edit me!
You can edit me!

[Markdown](http://daringfireball.net/projects/markdown/) lets you write content in a really natural way.

Expand All @@ -57,6 +57,9 @@

<small>Sample content borrowed with thanks from [elm-markdown](http://elm-lang.org/examples/markdown) ❤️</small>

> [!Tip]
> Normal and "alert" blockquotes are possible. Use `renderRule` for more control if needed.

Custom handling of code blocks (or any rule!) is possible with the [`renderRule` option](https://github.com/quantizor/markdown-to-jsx#optionsrenderrule). For example, LaTeX support via [`@matejmazur/react-katex`](https://www.npmjs.com/package/@matejmazur/react-katex):

```latex
Expand Down
2 changes: 0 additions & 2 deletions docs/markdown-to-jsx.js

This file was deleted.

1 change: 0 additions & 1 deletion docs/markdown-to-jsx.js.map

This file was deleted.

15 changes: 15 additions & 0 deletions index.compiler.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,21 @@ describe('misc block level elements', () => {
</div>
`)
})

it('should handle alert blockquotes', () => {
render(compiler('> [!NOTE]\n> Something important, perhaps?'))

expect(root.innerHTML).toMatchInlineSnapshot(`
<blockquote class="markdown-alert-note">
<header>
NOTE
</header>
<p>
Something important, perhaps?
</p>
</blockquote>
`)
})
})

describe('headings', () => {
Expand Down
38 changes: 28 additions & 10 deletions index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,9 @@ const ATTR_EXTRACTOR_R =

const AUTOLINK_MAILTO_CHECK_R = /mailto:/i
const BLOCK_END_R = /\n{2,}$/
const BLOCKQUOTE_R = /^(\s*>[\s\S]*?)(?=\n{2,})/
const BLOCKQUOTE_R = /^(\s*>[\s\S]*?)(?=\n\n|$)/
const BLOCKQUOTE_TRIM_LEFT_MULTILINE_R = /^ *> ?/gm
const BLOCKQUOTE_ALERT_R = /^(?:\[!([^\]]*)\]\n)?([\s\S]*)/
const BREAK_LINE_R = /^ {2,}\n/
const BREAK_THEMATIC_R = /^(?:( *[-*_])){3,} *(?:\n *)+\n/
const CODE_BLOCK_FENCED_R =
Expand Down Expand Up @@ -1302,19 +1303,35 @@ export function compiler(
match: blockRegex(BLOCKQUOTE_R),
order: Priority.HIGH,
parse(capture, parse, state) {
const [, alert, content] = capture[0]
.replace(BLOCKQUOTE_TRIM_LEFT_MULTILINE_R, '')
.match(BLOCKQUOTE_ALERT_R)

return {
children: parse(
capture[0].replace(BLOCKQUOTE_TRIM_LEFT_MULTILINE_R, ''),
state
),
alert,
children: parse(content, state),
}
},
render(node, output, state) {
return (
<blockquote key={state.key}>
{output(node.children, state)}
</blockquote>
)
const props = {
key: state.key,
} as Record<string, unknown>

if (node.alert) {
props.className =
'markdown-alert-' +
options.slugify(node.alert.toLowerCase(), slugify)

node.children.unshift({
attrs: {},
children: [{ type: RuleType.text, text: node.alert }],
noInnerParse: true,
type: RuleType.htmlBlock,
tag: 'header',
})
}

return h('blockquote', props, output(node.children, state))
},
},

Expand Down Expand Up @@ -2019,6 +2036,7 @@ export namespace MarkdownToJSX {
}

export interface BlockQuoteNode {
alert?: string
children: MarkdownToJSX.ParserResult[]
type: typeof RuleType.blockQuote
}
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@
"size-limit": [
{
"path": "./dist/index.module.js",
"limit": "6.25 kB"
"limit": "6.3 kB"
},
{
"path": "./dist/index.modern.js",
"limit": "6.2 kB"
"limit": "6.3 kB"
}
],
"jest": {
Expand Down
21 changes: 20 additions & 1 deletion site.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as React from 'react'
import * as ReactDOM from 'react-dom'
import styled, { createGlobalStyle, css, CSSProp } from 'styled-components'
import TeX from '@matejmazur/react-katex'
import Markdown, { MarkdownToJSX, RuleType } from './'
import Markdown, { MarkdownToJSX, RuleType } from './index'

declare global {
interface Window {
Expand Down Expand Up @@ -181,6 +181,25 @@ const GlobalStyles = createGlobalStyle`
p {
text-wrap: balance;
}
blockquote {
border-left: 1px solid #333;
margin: 1.5em 0;
padding-left: 1em;
&.markdown-alert-tip header {
color: limegreen;
&::before {
content: '★';
margin-right: 4px;
}
}
header + * {
margin-top: 0.25em;
}
}
`

const Header = styled.header`
Expand Down

0 comments on commit 20777bf

Please sign in to comment.