Skip to content

Commit 977efba

Browse files
committed
use proper markdown ast structure
updated the code to use markdown ast instead of html templates. also, the main wrapper is now a blockquote. Signed-off-by: rishichawda <[email protected]>
1 parent 62db9b7 commit 977efba

File tree

7 files changed

+164
-133
lines changed

7 files changed

+164
-133
lines changed

index.ts

Lines changed: 7 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { visit } from 'unist-util-visit'
22
import type { Node, Parent } from 'unist'
33
import type { Blockquote, Paragraph, Text } from 'mdast'
4-
import type { NoteNode } from './lib/types/index.js'
54
import { NOTE_TYPES } from './lib/types/index.js'
65
import { styles } from './lib/styles.js'
6+
import { createNoteStructure } from './lib/node-structure.js'
77

88
export default function remarkNotes() {
99
let hasInjectedStyles = false
@@ -62,48 +62,14 @@ export default function remarkNotes() {
6262
}
6363

6464
// Get the icon for this note type
65-
const noteConfig = NOTE_TYPES[noteType]
66-
const icon = noteConfig.icon
65+
const noteConfig = NOTE_TYPES[noteType];
66+
const iconSvg = noteConfig.icon;
6767

68-
// Create header with icon and title
69-
const headerNode = {
70-
type: 'html',
71-
value: `<div class="remark-note-header"><span class="remark-note-icon">${icon}</span><span class="remark-note-title">${noteType}</span></div>`
72-
}
73-
74-
const contentWrapperStart = {
75-
type: 'html',
76-
value: '<div class="remark-note-content">'
77-
}
78-
79-
const contentWrapperEnd = {
80-
type: 'html',
81-
value: '</div>'
82-
}
83-
84-
// Wrap content with header and content wrapper
85-
const wrappedChildren = [
86-
headerNode,
87-
contentWrapperStart,
88-
...children,
89-
contentWrapperEnd
90-
]
91-
92-
// Create the custom NoteNode
93-
const noteNode = {
94-
type: 'note',
95-
noteType: noteType,
96-
data: {
97-
hName: 'div',
98-
hProperties: {
99-
className: ['remark-note', noteType]
100-
}
101-
},
102-
children: wrappedChildren
103-
} as NoteNode
68+
// Create the note structure using proper mdast nodes
69+
const noteContainer = createNoteStructure(noteType, iconSvg, children);
10470

105-
// Replace the blockquote with the note node in the parent
106-
(parent as Parent).children[index] = noteNode as any
71+
// Replace the blockquote with the container
72+
(parent as Parent).children[index] = noteContainer;
10773
})
10874
}
10975
}

lib/node-structure.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/**
2+
* Creates the mdast node structure for a note callout
3+
*
4+
* This module handles the creation of proper mdast nodes with transformation hints
5+
* that tell remark-rehype how to convert them to the appropriate HTML structure.
6+
*
7+
* @module lib/create-note-structure
8+
*/
9+
10+
import type { Node } from 'unist'
11+
12+
/**
13+
* Creates a properly structured mdast node for a note callout
14+
*
15+
* The structure uses standard mdast node types (paragraph, text) with data hints
16+
* (hName, hProperties) to tell remark-rehype how to transform them into the
17+
* desired HTML structure without requiring manual handlers.
18+
*
19+
* Only the SVG icon uses raw HTML - everything else is proper mdast nodes.
20+
*
21+
* @param noteType - The type of note (note, tip, important, etc.)
22+
* @param iconSvg - The SVG icon as an HTML string
23+
* @param children - The content nodes (markdown) to include in the note
24+
* @returns A mdast node that will be transformed to the note HTML structure
25+
*/
26+
export function createNoteStructure(
27+
noteType: string,
28+
iconSvg: string,
29+
children: Node[]
30+
): any {
31+
// Create icon span (SVG needs to be raw HTML)
32+
const iconNode: any = {
33+
type: 'paragraph',
34+
data: {
35+
hName: 'span',
36+
hProperties: {
37+
className: ['remark-note-icon']
38+
}
39+
},
40+
children: [
41+
{
42+
type: 'html',
43+
value: iconSvg
44+
}
45+
]
46+
}
47+
48+
// Create title span
49+
const titleNode: any = {
50+
type: 'paragraph',
51+
data: {
52+
hName: 'span',
53+
hProperties: {
54+
className: ['remark-note-title']
55+
}
56+
},
57+
children: [
58+
{
59+
type: 'text',
60+
value: noteType
61+
}
62+
]
63+
}
64+
65+
// Create header div
66+
const headerNode: any = {
67+
type: 'paragraph',
68+
data: {
69+
hName: 'div',
70+
hProperties: {
71+
className: ['remark-note-header']
72+
}
73+
},
74+
children: [iconNode, titleNode]
75+
}
76+
77+
// Create content wrapper div
78+
const contentNode: any = {
79+
type: 'paragraph',
80+
data: {
81+
hName: 'div',
82+
hProperties: {
83+
className: ['remark-note-content']
84+
}
85+
},
86+
children: children
87+
}
88+
89+
// Build the structure: wrap everything in a blockquote container with data hints
90+
// Using blockquote for semantic HTML since the source is a blockquote
91+
const noteContainer: any = {
92+
type: 'paragraph', // Use a standard mdast type
93+
data: {
94+
hName: 'blockquote', // Transform to blockquote for semantic HTML
95+
hProperties: {
96+
className: ['remark-note', noteType]
97+
}
98+
},
99+
children: [headerNode, contentNode]
100+
}
101+
102+
return noteContainer
103+
}

lib/types/index.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,11 @@
22
* Type definitions for remark-notes-plugin
33
*
44
* This module exports all TypeScript types and interfaces used by the plugin.
5-
* It provides type definitions for custom AST nodes, note configurations,
6-
* and type guard utilities.
5+
* It provides type definitions for note configurations.
76
*
87
* @module lib/types
98
*/
109

11-
// Note node type definitions
12-
export type { NoteNode } from './node.js'
13-
export { isNoteNode } from './node.js'
14-
1510
// Note configuration type definitions
1611
export type { NoteType, NoteTypes } from './noteTypes.js'
1712
export { NOTE_TYPES } from './noteTypes.js'

lib/types/node.ts

Lines changed: 0 additions & 86 deletions
This file was deleted.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"postcss": "^8.5.3",
6161
"postcss-cli": "^11.0.1",
6262
"rehype-parse": "^9.0.1",
63+
"rehype-raw": "^7.0.0",
6364
"rehype-stringify": "^10.0.1",
6465
"remark-parse": "^11.0.0",
6566
"remark-rehype": "^11.1.2",

styles.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
/* Base note container */
22
.remark-note {
3+
/* Reset blockquote defaults */
34
margin: 1.5rem 0;
45
padding: 1.25rem;
6+
quotes: none;
7+
font-weight: normal;
8+
font-style: normal;
9+
10+
/* Custom note styles */
511
border-radius: 0.5rem;
612
border: 1px solid;
713
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

yarn.lock

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,25 @@ hast-util-parse-selector@^4.0.0:
542542
dependencies:
543543
"@types/hast" "^3.0.0"
544544

545+
hast-util-raw@^9.0.0:
546+
version "9.1.0"
547+
resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-9.1.0.tgz#79b66b26f6f68fb50dfb4716b2cdca90d92adf2e"
548+
integrity sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==
549+
dependencies:
550+
"@types/hast" "^3.0.0"
551+
"@types/unist" "^3.0.0"
552+
"@ungap/structured-clone" "^1.0.0"
553+
hast-util-from-parse5 "^8.0.0"
554+
hast-util-to-parse5 "^8.0.0"
555+
html-void-elements "^3.0.0"
556+
mdast-util-to-hast "^13.0.0"
557+
parse5 "^7.0.0"
558+
unist-util-position "^5.0.0"
559+
unist-util-visit "^5.0.0"
560+
vfile "^6.0.0"
561+
web-namespaces "^2.0.0"
562+
zwitch "^2.0.0"
563+
545564
hast-util-to-html@^9.0.0, hast-util-to-html@^9.0.5:
546565
version "9.0.5"
547566
resolved "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz"
@@ -559,6 +578,19 @@ hast-util-to-html@^9.0.0, hast-util-to-html@^9.0.5:
559578
stringify-entities "^4.0.0"
560579
zwitch "^2.0.4"
561580

581+
hast-util-to-parse5@^8.0.0:
582+
version "8.0.0"
583+
resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz#477cd42d278d4f036bc2ea58586130f6f39ee6ed"
584+
integrity sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==
585+
dependencies:
586+
"@types/hast" "^3.0.0"
587+
comma-separated-tokens "^2.0.0"
588+
devlop "^1.0.0"
589+
property-information "^6.0.0"
590+
space-separated-tokens "^2.0.0"
591+
web-namespaces "^2.0.0"
592+
zwitch "^2.0.0"
593+
562594
hast-util-whitespace@^3.0.0:
563595
version "3.0.0"
564596
resolved "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz"
@@ -1248,6 +1280,11 @@ pretty-hrtime@^1.0.3:
12481280
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
12491281
integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==
12501282

1283+
property-information@^6.0.0:
1284+
version "6.5.0"
1285+
resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec"
1286+
integrity sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==
1287+
12511288
property-information@^7.0.0:
12521289
version "7.0.0"
12531290
resolved "https://registry.npmjs.org/property-information/-/property-information-7.0.0.tgz"
@@ -1276,6 +1313,15 @@ rehype-parse@^9.0.1:
12761313
hast-util-from-html "^2.0.0"
12771314
unified "^11.0.0"
12781315

1316+
rehype-raw@^7.0.0:
1317+
version "7.0.0"
1318+
resolved "https://registry.yarnpkg.com/rehype-raw/-/rehype-raw-7.0.0.tgz#59d7348fd5dbef3807bbaa1d443efd2dd85ecee4"
1319+
integrity sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==
1320+
dependencies:
1321+
"@types/hast" "^3.0.0"
1322+
hast-util-raw "^9.0.0"
1323+
vfile "^6.0.0"
1324+
12791325
rehype-stringify@^10.0.1:
12801326
version "10.0.1"
12811327
resolved "https://registry.yarnpkg.com/rehype-stringify/-/rehype-stringify-10.0.1.tgz#2ec1ebc56c6aba07905d3b4470bdf0f684f30b75"

0 commit comments

Comments
 (0)