Skip to content

Commit 1a0206a

Browse files
kaspernowakEndBug
andauthored
feat: Add support for Notion callout blocks (#66)
* feat: add support for notion callout blocks * feat: add GFM alert support and make emoji callouts optional * refactor: make GFM alert map use Notion type emojis * fix: remove callout children, improve typings * refactor: Use notion client ApiColor type for allowed callout colors * fix: cumulative update of dependencies * chore: update ts-expect-error comment * chore: update ci workflows * chore: change recommended engine version --------- Co-authored-by: Federico Grandi <fgrandi30@gmail.com>
1 parent 5b9f02d commit 1a0206a

15 files changed

Lines changed: 4064 additions & 3311 deletions

File tree

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
build/
2+
jest.config.ts

.github/workflows/ci.yml

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,24 @@ name: Node.js CI
55

66
on:
77
push:
8-
branches: [ master ]
8+
branches: [master]
99
pull_request:
10-
branches: [ master ]
10+
branches: [master]
1111

1212
jobs:
1313
build:
14-
1514
runs-on: ubuntu-latest
1615

1716
strategy:
1817
matrix:
19-
node-version: [12.x, 14.x, 16.x]
18+
node-version: [20.x, 22.x, 24.x]
2019
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
2120

2221
steps:
23-
- uses: actions/checkout@v2
24-
- name: Use Node.js ${{ matrix.node-version }}
25-
uses: actions/setup-node@v2
26-
with:
27-
node-version: ${{ matrix.node-version }}
28-
- run: npm ci
29-
- run: npm test
22+
- uses: actions/checkout@v4
23+
- name: Use Node.js ${{ matrix.node-version }}
24+
uses: actions/setup-node@v4
25+
with:
26+
node-version: ${{ matrix.node-version }}
27+
- run: npm ci
28+
- run: npm test

.github/workflows/release.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,17 @@ on:
33
release:
44
types: [published]
55
workflow_dispatch:
6-
76

87
jobs:
98
publish-npm:
109
name: Publish on NPM
1110
runs-on: ubuntu-latest
1211

1312
steps:
14-
- uses: actions/checkout@v2
13+
- uses: actions/checkout@v4
1514

1615
- name: Set up Node.js for NPM
17-
uses: actions/setup-node@v3
16+
uses: actions/setup-node@v4
1817
with:
1918
registry-url: 'https://registry.npmjs.org'
2019

@@ -28,10 +27,10 @@ jobs:
2827
runs-on: ubuntu-latest
2928

3029
steps:
31-
- uses: actions/checkout@v2
30+
- uses: actions/checkout@v4
3231

3332
- name: Set up Node.js for GPR
34-
uses: actions/setup-node@v3
33+
uses: actions/setup-node@v4
3534
with:
3635
registry-url: 'https://npm.pkg.github.com/'
3736

README.md

Lines changed: 255 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ Designed to make using the Notion SDK and API easier. Notion API version 1.0.
1818
- All headers (header levels >= 3 are treated as header level 3)
1919
- Code blocks, with language highlighting support
2020
- Block quotes
21+
- Supports GFM alerts (e.g. [!NOTE], [!TIP], [!IMPORTANT], [!WARNING], [!CAUTION])
22+
- Supports Notion callouts when blockquote starts with an emoji (optional, enabled with `enableEmojiCallouts`)
23+
- Automatically maps common emojis and alert types to appropriate background colors
24+
- Preserves formatting and nested blocks within callouts
2125
- Tables
2226
- Equations
2327
- Images
@@ -85,6 +89,10 @@ hello _world_
8589
***
8690
## heading2
8791
* [x] todo
92+
93+
> 📘 **Note:** Important _information_
94+
95+
> Some other blockquote
8896
`);
8997
```
9098

@@ -128,6 +136,11 @@ hello _world_
128136
]
129137
}
130138
},
139+
{
140+
"object": "block",
141+
"type": "divider",
142+
"divider": {}
143+
},
131144
{
132145
"object": "block",
133146
"type": "heading_2",
@@ -172,6 +185,248 @@ hello _world_
172185
],
173186
"checked": true
174187
}
188+
},
189+
{
190+
"type": "callout",
191+
"callout": {
192+
"rich_text": [
193+
{
194+
"type": "text",
195+
"text": {
196+
"content": "Note:"
197+
},
198+
"annotations": {
199+
"bold": true,
200+
"strikethrough": false,
201+
"underline": false,
202+
"italic": false,
203+
"code": false,
204+
"color": "default"
205+
}
206+
},
207+
{
208+
"type": "text",
209+
"text": {
210+
"content": " Important "
211+
}
212+
},
213+
{
214+
"type": "text",
215+
"text": {
216+
"content": "information"
217+
},
218+
"annotations": {
219+
"bold": false,
220+
"strikethrough": false,
221+
"underline": false,
222+
"italic": true,
223+
"code": false,
224+
"color": "default"
225+
}
226+
}
227+
],
228+
"icon": {
229+
"type": "emoji",
230+
"emoji": "📘"
231+
},
232+
"color": "blue_background"
233+
}
234+
},
235+
{
236+
"type": "quote",
237+
"quote": {
238+
"rich_text": [
239+
{
240+
"type": "text",
241+
"text": {
242+
"content": "Some other blockquote"
243+
},
244+
"annotations": {
245+
"bold": false,
246+
"strikethrough": false,
247+
"underline": false,
248+
"italic": false,
249+
"code": false,
250+
"color": "default"
251+
}
252+
}
253+
]
254+
}
255+
}
256+
]
257+
</pre>
258+
</details>
259+
260+
### Working with blockquotes
261+
262+
Martian supports three types of blockquotes:
263+
264+
1. Standard blockquotes:
265+
266+
```md
267+
> This is a regular blockquote
268+
> It can span multiple lines
269+
```
270+
271+
2. GFM alerts (based on [GFM Alerts](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts)):
272+
273+
```md
274+
> [!NOTE]
275+
> Important information that users should know
276+
277+
> [!WARNING]
278+
> Critical information that needs attention
279+
```
280+
281+
3. Emoji-style callouts (optional) (based on [ReadMe's markdown callouts](https://docs.readme.com/rdmd/docs/callouts)):
282+
283+
```md
284+
> 📘 **Note:** This is a callout with a blue background
285+
> It supports all markdown formatting and can span multiple lines
286+
287+
> **Warning:** This is a callout with a red background
288+
> Perfect for important warnings
289+
```
290+
291+
#### GFM Alerts
292+
293+
GFM alerts are automatically converted to Notion callouts with appropriate icons and colors:
294+
295+
- NOTE (📘, blue): Useful information that users should know
296+
- TIP (💡, green): Helpful advice for doing things better
297+
- IMPORTANT (☝️, purple): Key information users need to know
298+
- WARNING (⚠️, yellow): Urgent info that needs immediate attention
299+
- CAUTION (❗, red): Advises about risks or negative outcomes
300+
301+
#### Emoji-style Callouts
302+
303+
By default, emoji-style callouts are disabled. You can enable them using the `enableEmojiCallouts` option:
304+
305+
```ts
306+
const options = {
307+
enableEmojiCallouts: true,
308+
};
309+
```
310+
311+
When enabled, callouts are detected when a blockquote starts with an emoji. The emoji determines the callout's background color. The current supported color mappings are:
312+
313+
- 📘 (blue): Perfect for notes and information
314+
- 👍 (green): Success messages and tips
315+
- ❗ (red): Warnings and important notices
316+
- 🚧 (yellow): Work in progress or caution notices
317+
318+
All other emojis will have a default background color. The supported emoji color mappings can be expanded easily if needed.
319+
320+
If a blockquote doesn't match either GFM alert syntax or emoji-style callout syntax (when enabled), it will be rendered as a Notion quote block.
321+
322+
##### Examples
323+
324+
Standard blockquote:
325+
326+
```ts
327+
markdownToBlocks('> A regular blockquote');
328+
```
329+
330+
<details>
331+
<summary>Result</summary>
332+
<pre>
333+
[
334+
{
335+
"object": "block",
336+
"type": "quote",
337+
"quote": {
338+
"rich_text": [
339+
{
340+
"type": "text",
341+
"text": {
342+
"content": "A regular blockquote"
343+
}
344+
}
345+
]
346+
}
347+
}
348+
]
349+
</pre>
350+
</details>
351+
352+
GFM alert:
353+
354+
```ts
355+
markdownToBlocks('> [!NOTE]\n> Important information');
356+
```
357+
358+
<details>
359+
<summary>Result</summary>
360+
<pre>
361+
[
362+
{
363+
"object": "block",
364+
"type": "callout",
365+
"callout": {
366+
"rich_text": [
367+
{
368+
"type": "text",
369+
"text": {
370+
"content": "Note"
371+
}
372+
}
373+
],
374+
"icon": {
375+
"type": "emoji",
376+
"emoji": "ℹ️"
377+
},
378+
"color": "blue_background",
379+
"children": [
380+
{
381+
"type": "paragraph",
382+
"paragraph": {
383+
"rich_text": [
384+
{
385+
"type": "text",
386+
"text": {
387+
"content": "Important information"
388+
}
389+
}
390+
]
391+
}
392+
}
393+
]
394+
}
395+
}
396+
]
397+
</pre>
398+
</details>
399+
400+
Emoji-style callout (with `enableEmojiCallouts: true`):
401+
402+
```ts
403+
markdownToBlocks('> 📘 Note: Important information', {
404+
enableEmojiCallouts: true,
405+
});
406+
```
407+
408+
<details>
409+
<summary>Result</summary>
410+
<pre>
411+
[
412+
{
413+
"object": "block",
414+
"type": "callout",
415+
"callout": {
416+
"rich_text": [
417+
{
418+
"type": "text",
419+
"text": {
420+
"content": "Note: Important information"
421+
}
422+
}
423+
],
424+
"icon": {
425+
"type": "emoji",
426+
"emoji": "📘"
427+
},
428+
"color": "blue_background"
429+
}
175430
}
176431
]
177432
</pre>
@@ -338,11 +593,8 @@ Error: Unsupported markdown element: {"type":"heading","depth":1,"children":[{"t
338593
</pre>
339594
</details>
340595

341-
342-
343596
---
344597

345598
Built with 💙 by the team behind [Fabric](https://tryfabric.com).
346599

347600
<img src="https://static.scarf.sh/a.png?x-pxid=79ae4e0a-7e48-4965-8a83-808c009aa47a" />
348-

0 commit comments

Comments
 (0)