@changerawr/markdown 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +474 -0
- package/dist/index.d.mts +585 -0
- package/dist/index.d.ts +585 -0
- package/dist/index.js +2275 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2184 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react/index.d.mts +264 -0
- package/dist/react/index.d.ts +264 -0
- package/dist/react/index.js +1791 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +1752 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/standalone.d.mts +141 -0
- package/dist/standalone.d.ts +141 -0
- package/dist/standalone.global.js +193 -0
- package/dist/standalone.global.js.map +1 -0
- package/dist/standalone.js +187 -0
- package/dist/standalone.js.map +1 -0
- package/dist/standalone.mjs +187 -0
- package/dist/standalone.mjs.map +1 -0
- package/package.json +110 -0
package/README.md
ADDED
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
# @changerawr/markdown
|
|
2
|
+
|
|
3
|
+
> Powerful TypeScript-first markdown renderer with custom extensions - supports HTML, Tailwind CSS, and JSON outputs
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@changerawr/markdown)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](#testing)
|
|
8
|
+
|
|
9
|
+
## โจ Features
|
|
10
|
+
|
|
11
|
+
- ๐ **Multiple Output Formats**: HTML, Tailwind CSS, or JSON AST
|
|
12
|
+
- ๐งฉ **Custom Extensions**: Built-in Alert, Button, and Embed extensions
|
|
13
|
+
- โ๏ธ **React Integration**: Drop-in `<MarkdownRenderer>` component + hooks
|
|
14
|
+
- ๐ฆ **Vanilla JS Support**: Use anywhere with `renderCum()` function
|
|
15
|
+
- ๐ **TypeScript First**: Fully typed with excellent IntelliSense
|
|
16
|
+
- ๐ฏ **Performance Focused**: Efficient parsing and rendering
|
|
17
|
+
- ๐ก๏ธ **Secure**: Built-in HTML sanitization with DOMPurify
|
|
18
|
+
- ๐ง **Extensible**: Easy-to-write custom extensions
|
|
19
|
+
- ๐จ **Themeable**: Customizable CSS classes and styling
|
|
20
|
+
|
|
21
|
+
## ๐ฆ Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @changerawr/markdown
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
For React usage:
|
|
28
|
+
```bash
|
|
29
|
+
npm install @changerawr/markdown react react-dom
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## ๐ Quick Start
|
|
33
|
+
|
|
34
|
+
### Basic Usage (Vanilla JS)
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { renderMarkdown } from '@changerawr/markdown';
|
|
38
|
+
|
|
39
|
+
const html = renderMarkdown('# Hello **World**!');
|
|
40
|
+
console.log(html);
|
|
41
|
+
// Output: <h1 class="text-3xl font-bold mt-8 mb-4">Hello <strong class="font-bold">World</strong>!</h1>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### React Component
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import { MarkdownRenderer } from '@changerawr/markdown/react';
|
|
48
|
+
|
|
49
|
+
function App() {
|
|
50
|
+
const markdown = `
|
|
51
|
+
# Welcome to Changerawr Markdown
|
|
52
|
+
|
|
53
|
+
This is **bold text** and this is *italic text*.
|
|
54
|
+
|
|
55
|
+
- List item 1
|
|
56
|
+
- List item 2
|
|
57
|
+
|
|
58
|
+
:::info
|
|
59
|
+
This is an info alert with our custom extension!
|
|
60
|
+
:::
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<MarkdownRenderer
|
|
65
|
+
content={markdown}
|
|
66
|
+
className="prose max-w-none"
|
|
67
|
+
/>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### React Hooks
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import { useMarkdown, useMarkdownEngine } from '@changerawr/markdown/react';
|
|
76
|
+
|
|
77
|
+
function MarkdownEditor() {
|
|
78
|
+
const [content, setContent] = useState('# Hello World');
|
|
79
|
+
const { html, tokens, isLoading, error } = useMarkdown(content);
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<div className="grid grid-cols-2 gap-4">
|
|
83
|
+
<textarea
|
|
84
|
+
value={content}
|
|
85
|
+
onChange={(e) => setContent(e.target.value)}
|
|
86
|
+
className="border p-4"
|
|
87
|
+
/>
|
|
88
|
+
<div
|
|
89
|
+
dangerouslySetInnerHTML={{ __html: html }}
|
|
90
|
+
className="border p-4 prose"
|
|
91
|
+
/>
|
|
92
|
+
</div>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## ๐จ Output Formats
|
|
98
|
+
|
|
99
|
+
### Tailwind CSS (Default)
|
|
100
|
+
Perfect for modern web applications using Tailwind CSS:
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { renderToTailwind } from '@changerawr/markdown';
|
|
104
|
+
|
|
105
|
+
const html = renderToTailwind('# Heading');
|
|
106
|
+
// <h1 class="text-3xl font-bold mt-8 mb-4">Heading</h1>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Plain HTML
|
|
110
|
+
Clean HTML without any CSS framework dependencies:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { renderToHTML } from '@changerawr/markdown';
|
|
114
|
+
|
|
115
|
+
const html = renderToHTML('# Heading');
|
|
116
|
+
// <h1>Heading</h1>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### JSON AST
|
|
120
|
+
For advanced processing and custom rendering:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { renderToJSON } from '@changerawr/markdown';
|
|
124
|
+
|
|
125
|
+
const ast = renderToJSON('# Heading');
|
|
126
|
+
// { type: 'heading', content: 'Heading', level: 1, ... }
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## ๐งฉ Built-in Extensions
|
|
130
|
+
|
|
131
|
+
### Alert Boxes
|
|
132
|
+
Create beautiful alert boxes with different styles:
|
|
133
|
+
|
|
134
|
+
```markdown
|
|
135
|
+
:::info Important Info
|
|
136
|
+
This is an informational alert with custom styling.
|
|
137
|
+
:::
|
|
138
|
+
|
|
139
|
+
:::warning Be Careful
|
|
140
|
+
This is a warning alert.
|
|
141
|
+
:::
|
|
142
|
+
|
|
143
|
+
:::error Something went wrong
|
|
144
|
+
This is an error alert.
|
|
145
|
+
:::
|
|
146
|
+
|
|
147
|
+
:::success Task Complete
|
|
148
|
+
This is a success alert.
|
|
149
|
+
:::
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Interactive Buttons
|
|
153
|
+
Add styled buttons with custom actions:
|
|
154
|
+
|
|
155
|
+
```markdown
|
|
156
|
+
[button:Get Started](https://example.com){primary,lg}
|
|
157
|
+
[button:Learn More](https://docs.example.com){secondary,sm}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Media Embeds
|
|
161
|
+
Embed videos, images, and other media:
|
|
162
|
+
|
|
163
|
+
```markdown
|
|
164
|
+
[embed:youtube](https://www.youtube.com/watch?v=dQw4w9WgXcQ){autoplay:1}
|
|
165
|
+
[embed:image](https://example.com/image.jpg){width:800,height:600}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## โ๏ธ React Components
|
|
169
|
+
|
|
170
|
+
### MarkdownRenderer
|
|
171
|
+
The main component for rendering markdown:
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
<MarkdownRenderer
|
|
175
|
+
content="# Hello World"
|
|
176
|
+
format="tailwind"
|
|
177
|
+
className="prose"
|
|
178
|
+
onRender={(html, tokens) => console.log('Rendered!', { html, tokens })}
|
|
179
|
+
onError={(error) => console.error('Error:', error)}
|
|
180
|
+
/>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Specialized Components
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
// Simple Tailwind renderer
|
|
187
|
+
<SimpleMarkdownRenderer content="# Simple" />
|
|
188
|
+
|
|
189
|
+
// HTML-only renderer (no CSS classes)
|
|
190
|
+
<HTMLMarkdownRenderer content="# Plain HTML" />
|
|
191
|
+
|
|
192
|
+
// With error boundary
|
|
193
|
+
<SafeMarkdownRenderer
|
|
194
|
+
content="# Safe"
|
|
195
|
+
errorFallback={(error) => <div>Oops: {error.message}</div>}
|
|
196
|
+
/>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## ๐ง Custom Extensions
|
|
200
|
+
|
|
201
|
+
Create powerful custom extensions to extend markdown syntax:
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import { ChangerawrMarkdown } from '@changerawr/markdown';
|
|
205
|
+
|
|
206
|
+
const engine = new ChangerawrMarkdown();
|
|
207
|
+
|
|
208
|
+
// Add a highlight extension
|
|
209
|
+
engine.registerExtension({
|
|
210
|
+
name: 'highlight',
|
|
211
|
+
parseRules: [{
|
|
212
|
+
name: 'highlight',
|
|
213
|
+
pattern: /==(.+?)==/g,
|
|
214
|
+
render: (match) => ({
|
|
215
|
+
type: 'highlight',
|
|
216
|
+
content: match[1],
|
|
217
|
+
raw: match[0]
|
|
218
|
+
})
|
|
219
|
+
}],
|
|
220
|
+
renderRules: [{
|
|
221
|
+
type: 'highlight',
|
|
222
|
+
render: (token) => `<mark class="bg-yellow-200 px-1">${token.content}</mark>`
|
|
223
|
+
}]
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
const html = engine.toHtml('This is ==highlighted text==');
|
|
227
|
+
// <mark class="bg-yellow-200 px-1">highlighted text</mark>
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## ๐ฏ Advanced Configuration
|
|
231
|
+
|
|
232
|
+
### Engine Configuration
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
import { ChangerawrMarkdown } from '@changerawr/markdown';
|
|
236
|
+
|
|
237
|
+
const engine = new ChangerawrMarkdown({
|
|
238
|
+
parser: {
|
|
239
|
+
debugMode: true,
|
|
240
|
+
validateMarkdown: true,
|
|
241
|
+
maxIterations: 10000
|
|
242
|
+
},
|
|
243
|
+
renderer: {
|
|
244
|
+
format: 'tailwind',
|
|
245
|
+
sanitize: true,
|
|
246
|
+
allowUnsafeHtml: false,
|
|
247
|
+
customClasses: {
|
|
248
|
+
'heading-1': 'text-4xl font-black mb-6',
|
|
249
|
+
'paragraph': 'text-lg leading-relaxed mb-4'
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### React Hook Options
|
|
256
|
+
|
|
257
|
+
```tsx
|
|
258
|
+
const { html, tokens, isLoading, error } = useMarkdown(content, {
|
|
259
|
+
format: 'tailwind',
|
|
260
|
+
debug: true,
|
|
261
|
+
extensions: [myCustomExtension],
|
|
262
|
+
config: {
|
|
263
|
+
renderer: {
|
|
264
|
+
sanitize: true,
|
|
265
|
+
customClasses: { /* ... */ }
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## ๐ญ Factory Functions
|
|
272
|
+
|
|
273
|
+
Convenient factory functions for common use cases:
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
import {
|
|
277
|
+
createEngine,
|
|
278
|
+
createHTMLEngine,
|
|
279
|
+
createTailwindEngine,
|
|
280
|
+
createDebugEngine,
|
|
281
|
+
createMinimalEngine
|
|
282
|
+
} from '@changerawr/markdown';
|
|
283
|
+
|
|
284
|
+
// General purpose engine
|
|
285
|
+
const engine = createEngine();
|
|
286
|
+
|
|
287
|
+
// HTML-only engine
|
|
288
|
+
const htmlEngine = createHTMLEngine();
|
|
289
|
+
|
|
290
|
+
// Debug-enabled engine
|
|
291
|
+
const debugEngine = createDebugEngine();
|
|
292
|
+
|
|
293
|
+
// Minimal engine (no built-in extensions)
|
|
294
|
+
const minimalEngine = createMinimalEngine();
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## ๐ฆ Standalone Usage (No React)
|
|
298
|
+
|
|
299
|
+
Perfect for Node.js, vanilla JavaScript, or any non-React environment:
|
|
300
|
+
|
|
301
|
+
```html
|
|
302
|
+
<script src="https://unpkg.com/@changerawr/markdown/dist/standalone.js"></script>
|
|
303
|
+
<script>
|
|
304
|
+
const html = ChangerawrMarkdown.renderCum('# Hello World!');
|
|
305
|
+
document.body.innerHTML = html;
|
|
306
|
+
</script>
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
```javascript
|
|
310
|
+
// Node.js
|
|
311
|
+
const { renderCum, parseCum } = require('@changerawr/markdown/standalone');
|
|
312
|
+
|
|
313
|
+
const html = renderCum('# Hello World');
|
|
314
|
+
const tokens = parseCum('# Hello World');
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## ๐จ Styling & Theming
|
|
318
|
+
|
|
319
|
+
### Custom CSS Classes
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
const engine = new ChangerawrMarkdown({
|
|
323
|
+
renderer: {
|
|
324
|
+
format: 'tailwind',
|
|
325
|
+
customClasses: {
|
|
326
|
+
'heading-1': 'text-5xl font-black text-purple-900 mb-8',
|
|
327
|
+
'heading-2': 'text-3xl font-bold text-purple-800 mb-6',
|
|
328
|
+
'paragraph': 'text-gray-700 leading-loose mb-6',
|
|
329
|
+
'blockquote': 'border-l-4 border-purple-500 pl-6 italic text-gray-600',
|
|
330
|
+
'code-inline': 'bg-purple-100 text-purple-800 px-2 py-1 rounded font-mono text-sm',
|
|
331
|
+
'code-block': 'bg-gray-900 text-gray-100 p-6 rounded-lg overflow-x-auto font-mono',
|
|
332
|
+
'link': 'text-purple-600 hover:text-purple-800 underline',
|
|
333
|
+
'list-item': 'mb-2 text-gray-700'
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Preset Configurations
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
import { createEngineWithPreset } from '@changerawr/markdown';
|
|
343
|
+
|
|
344
|
+
// Blog/article styling
|
|
345
|
+
const blogEngine = createEngineWithPreset('blog');
|
|
346
|
+
|
|
347
|
+
// Documentation styling
|
|
348
|
+
const docsEngine = createEngineWithPreset('docs');
|
|
349
|
+
|
|
350
|
+
// Minimal styling
|
|
351
|
+
const minimalEngine = createEngineWithPreset('minimal');
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## ๐ Debugging & Development
|
|
355
|
+
|
|
356
|
+
### Debug Mode
|
|
357
|
+
|
|
358
|
+
```tsx
|
|
359
|
+
<MarkdownRenderer
|
|
360
|
+
content="# Debug Me"
|
|
361
|
+
debug={true}
|
|
362
|
+
onRender={(html, tokens) => {
|
|
363
|
+
console.log('HTML:', html);
|
|
364
|
+
console.log('Tokens:', tokens);
|
|
365
|
+
}}
|
|
366
|
+
/>
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Debug Hook
|
|
370
|
+
|
|
371
|
+
```tsx
|
|
372
|
+
import { useMarkdownDebug } from '@changerawr/markdown/react';
|
|
373
|
+
|
|
374
|
+
function DebugComponent() {
|
|
375
|
+
const { html, tokens, debug, stats } = useMarkdownDebug('# Hello World');
|
|
376
|
+
|
|
377
|
+
return (
|
|
378
|
+
<div>
|
|
379
|
+
<div dangerouslySetInnerHTML={{ __html: html }} />
|
|
380
|
+
<pre>{JSON.stringify(debug, null, 2)}</pre>
|
|
381
|
+
</div>
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## ๐ Performance
|
|
387
|
+
|
|
388
|
+
### Metrics and Monitoring
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
const engine = createDebugEngine();
|
|
392
|
+
const html = engine.toHtml('# Large Document...');
|
|
393
|
+
|
|
394
|
+
const metrics = engine.getPerformanceMetrics();
|
|
395
|
+
console.log('Parse time:', metrics.parseTime);
|
|
396
|
+
console.log('Render time:', metrics.renderTime);
|
|
397
|
+
console.log('Total time:', metrics.totalTime);
|
|
398
|
+
console.log('Token count:', metrics.tokenCount);
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Optimization Tips
|
|
402
|
+
|
|
403
|
+
- Use `createMinimalEngine()` if you don't need built-in extensions
|
|
404
|
+
- Set `sanitize: false` if you trust your content (be careful!)
|
|
405
|
+
- Use `format: 'html'` for lighter output without CSS classes
|
|
406
|
+
- Implement custom extensions efficiently to avoid performance bottlenecks
|
|
407
|
+
|
|
408
|
+
## ๐งช Testing
|
|
409
|
+
|
|
410
|
+
All components and functions are thoroughly tested:
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
npm test # Run all tests
|
|
414
|
+
npm run test:watch # Run tests in watch mode
|
|
415
|
+
npm run test:coverage # Run with coverage report
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
## ๐ API Reference
|
|
419
|
+
|
|
420
|
+
### Core Functions
|
|
421
|
+
|
|
422
|
+
- `renderMarkdown(content: string): string` - Render with default Tailwind output
|
|
423
|
+
- `parseMarkdown(content: string): MarkdownToken[]` - Parse to token array
|
|
424
|
+
- `renderToHTML(markdown: string): string` - Render to plain HTML
|
|
425
|
+
- `renderToTailwind(markdown: string): string` - Render with Tailwind classes
|
|
426
|
+
- `renderToJSON(markdown: string): JsonAstNode` - Render to JSON AST
|
|
427
|
+
|
|
428
|
+
### React Components
|
|
429
|
+
|
|
430
|
+
- `<MarkdownRenderer />` - Main React component
|
|
431
|
+
- `<SimpleMarkdownRenderer />` - Tailwind-styled renderer
|
|
432
|
+
- `<HTMLMarkdownRenderer />` - Plain HTML renderer
|
|
433
|
+
- `<SafeMarkdownRenderer />` - With error boundary
|
|
434
|
+
|
|
435
|
+
### React Hooks
|
|
436
|
+
|
|
437
|
+
- `useMarkdown(content: string, options?)` - Main markdown processing hook
|
|
438
|
+
- `useMarkdownEngine(options?)` - Engine management hook
|
|
439
|
+
- `useMarkdownDebug(content: string)` - Debug information hook
|
|
440
|
+
|
|
441
|
+
### Classes
|
|
442
|
+
|
|
443
|
+
- `ChangerawrMarkdown` - Main engine class
|
|
444
|
+
- `MarkdownParser` - Content parsing
|
|
445
|
+
- `MarkdownRenderer` - Token rendering
|
|
446
|
+
|
|
447
|
+
## ๐ค Contributing
|
|
448
|
+
|
|
449
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
450
|
+
|
|
451
|
+
1. Fork the repository
|
|
452
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
453
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
454
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
455
|
+
5. Open a Pull Request
|
|
456
|
+
|
|
457
|
+
## ๐ License
|
|
458
|
+
|
|
459
|
+
MIT ยฉ [Changerawr Team](https://github.com/changerawr)
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## ๐ก What Makes It Special?
|
|
464
|
+
|
|
465
|
+
- **TypeScript-First**: Built with TypeScript from the ground up for excellent developer experience
|
|
466
|
+
- **Framework Agnostic**: Works with React, Vue, Svelte, vanilla JS, or any framework
|
|
467
|
+
- **Extensible Architecture**: Easy to add custom markdown syntax and rendering
|
|
468
|
+
- **Production Ready**: Thoroughly tested, performant, and secure
|
|
469
|
+
- **Modern Output**: Tailwind CSS support for modern web applications
|
|
470
|
+
- **Developer Friendly**: Great debugging tools and clear error messages
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
**[Get Started](https://github.com/changerawr/markdown#installation) โข [Documentation](https://github.com/changerawr/markdown) โข [Examples](https://github.com/changerawr/markdown/tree/main/examples) โข [Contributing](https://github.com/changerawr/markdown/blob/main/CONTRIBUTING.md)**
|