ds-markdown 0.1.1 → 0.1.2-beta.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.en.md CHANGED
@@ -20,39 +20,30 @@ A React component designed specifically for modern AI applications, providing sm
20
20
 
21
21
  ## ✨ Core Features
22
22
 
23
- ### 🎯 **Perfect Replication**
23
+ ### 🤖 **AI Conversation Scenarios**
24
24
 
25
25
  - 1:1 recreation of [DeepSeek website](https://chat.deepseek.com/) chat response effects
26
26
  - Support for both thinking process (`thinking`) and answer content (`answer`) modes
27
- - Native Markdown syntax support, including code highlighting, tables, lists, etc.
28
- - Light/dark theme support, perfectly adapting to different scenarios
27
+ - Perfect adaptation to streaming data with zero-delay response to user input
29
28
 
30
- ### **Ultimate Performance**
29
+ ### 📊 **Content Display Scenarios**
31
30
 
32
- - Smart batch processing, zero lag rendering for large documents
33
- - Dual timer modes: `requestAnimationFrame` + `setTimeout`
34
- - Built-in streaming syntax buffering, avoiding incomplete Markdown rendering errors
31
+ - Complete Markdown syntax support, including code highlighting, tables, lists, etc.
32
+ - Mathematical formula rendering (KaTeX), supporting `$...$` and `\[...\]` syntax
33
+ - Light/dark theme support, adapting to different product styles
34
+ - Plugin architecture supporting remark/rehype plugin extensions
35
35
 
36
- ### 🎬 **Smooth Animation**
36
+ ### 🔧 **Developer Experience**
37
37
 
38
- - High-frequency typing support (`requestAnimationFrame` mode supports typing intervals as low as `0ms`)
39
- - Frame-synchronized rendering, perfectly matching browser 60fps
40
- - Smart character batch processing for more natural visual effects
41
38
  - Support for typing interruption `stop` and resume `resume`
39
+ - Support for disabling and enabling typing
42
40
 
43
- ### 🔧 **Flexible and Easy to Use**
44
-
45
- - **Declarative API**: Suitable for simple scenarios, React-style
46
- - **Imperative API**: Suitable for streaming data, better performance
47
- - **Native TypeScript support**: Complete type hints
48
-
49
- ### 🧮 **Mathematical Formula Support**
41
+ ### 🎬 **Smooth Animation**
50
42
 
51
- - **KaTeX Integration**: High-performance mathematical formula rendering
52
- - **Plugin Architecture**: Flexible configuration through plugin system
53
- - **Dual Syntax Support**: `$...$` and `\[...\]` delimiters
54
- - **Streaming Compatible**: Perfect support for mathematical formulas in typing animations
55
- - **Theme Adaptation**: Automatic adaptation to light/dark themes
43
+ - Dual timer mode optimization, supporting `requestAnimationFrame` and `setTimeout` modes
44
+ - High-frequency typing support (`requestAnimationFrame` mode supports typing intervals as low as `0ms`)
45
+ - Frame-synchronized rendering, perfectly matching browser refresh rate
46
+ - Smart character batch processing for more natural visual effects
56
47
 
57
48
  ---
58
49
 
@@ -76,8 +67,10 @@ No installation required, use directly in browser:
76
67
  [DEMO](https://stackblitz.com/edit/stackblitz-starters-7vcclcw7?file=index.html)
77
68
 
78
69
  ```html
79
- <!-- Import styles -->
70
+ <!-- Import styles, required -->
80
71
  <link rel="stylesheet" href="https://esm.sh/ds-markdown/dist/style.css" />
72
+
73
+ <!-- Import katex math formula styles, only if needed -->
81
74
  <link rel="stylesheet" href="https://esm.sh/ds-markdown/dist/katex.css" />
82
75
 
83
76
  <!-- Import component -->
@@ -105,13 +98,37 @@ function App() {
105
98
  }
106
99
  ```
107
100
 
101
+ ### Disable Typing Animation
102
+
103
+ ```tsx
104
+ import DsMarkdown from 'ds-markdown';
105
+ import 'ds-markdown/style.css';
106
+
107
+ function StaticDemo() {
108
+ const [disableTyping, setDisableTyping] = useState(false);
109
+
110
+ return (
111
+ <div>
112
+ <button onClick={() => setDisableTyping(!disableTyping)}>{disableTyping ? 'Enable' : 'Disable'} Typing Effect</button>
113
+
114
+ <DsMarkdown interval={20} answerType="answer" disableTyping={disableTyping}>
115
+ # Static Display Mode When `disableTyping` is `true`, content will be displayed immediately without typing animation. This is very useful in certain scenarios: - 📄 Static document display -
116
+ 🔄 Toggle display modes - ⚡ Quick content preview
117
+ </DsMarkdown>
118
+ </div>
119
+ );
120
+ }
121
+ ```
122
+
108
123
  ### Mathematical Formula Support
109
124
 
110
125
  ```tsx
111
126
  import DsMarkdown from 'ds-markdown';
127
+ // If you need to display formulas, import the formula conversion plugin
112
128
  import { katexPlugin } from 'ds-markdown/plugins';
113
129
  import 'ds-markdown/style.css';
114
- import 'ds-markdown/katex.css'; // Import mathematical formula styles
130
+ // If you need to display formulas, import mathematical formula styles
131
+ import 'ds-markdown/katex.css';
115
132
 
116
133
  function MathDemo() {
117
134
  return (
@@ -171,32 +188,47 @@ Let's explore these new features together!`);
171
188
 
172
189
  ## 📚 Complete API Documentation
173
190
 
174
- ### Declarative API (Recommended for Beginners)
191
+ ### Default export DsMarkdown and MarkdownCMD props
192
+
193
+ ```js
194
+ import DsMarkdown, { MarkdownCMD } from 'ds-markdown';
195
+ ```
196
+
197
+ | Property | Type | Description | Default |
198
+ | --------------- | --------------------------------------------- | ------------------------------- | ----------------------------------------------------------------------------- |
199
+ | `interval` | `number` | Typing interval (milliseconds) | `30` |
200
+ | `timerType` | `'setTimeout'` \| `'requestAnimationFrame'` | Timer type | Current default is `setTimeout`, will change to `requestAnimationFrame` later |
201
+ | `answerType` | `'thinking'` \| `'answer'` | Content type (affects styling) | `'answer'` |
202
+ | `theme` | `'light'` \| `'dark'` | Theme type | `'light'` |
203
+ | `plugins` | `IMarkdownPlugin[]` | Plugin configuration | `[]` |
204
+ | `math` | [IMarkdownMath](#IMarkdownMath) | Mathematical formula config | `{ splitSymbol: 'dollar' }` |
205
+ | `onEnd` | `(data: EndData) => void` | Typing completion callback | - |
206
+ | `onStart` | `(data: StartData) => void` | Typing start callback | - |
207
+ | `onTypedChar` | `(data: `[ITypedChar](#ITypedChar)`) => void` | Character-by-character callback | - |
208
+ | `disableTyping` | `boolean` | Disable typing animation | `false` |
209
+
210
+ > Note: If `disableTyping` changes from `true` to `false` during typing, all remaining characters will be displayed at once on the next typing trigger.
211
+
212
+ ### ITypedChar
175
213
 
176
- | Property | Type | Description | Default |
177
- | ------------- | ------------------------------------------- | ---------------------------------- | ----------------------------------------------------------------------------- |
178
- | `interval` | `number` | Typing interval (milliseconds) | `30` |
179
- | `timerType` | `'setTimeout'` \| `'requestAnimationFrame'` | Timer type | Current default is `setTimeout`, will change to `requestAnimationFrame` later |
180
- | `answerType` | `'thinking'` \| `'answer'` | Content type (affects style theme) | `'answer'` |
181
- | `theme` | `'light'` \| `'dark'` | Theme type | `'light'` |
182
- | `plugins` | `IMarkdownPlugin[]` | Plugin configuration | `[]` |
183
- | `math` | `IMarkdownMath` | Mathematical formula configuration | `{ splitSymbol: 'dollar' }` |
184
- | `onEnd` | `(data: EndData) => void` | Typing completion callback | - |
185
- | `onStart` | `(data: StartData) => void` | Typing start callback | - |
186
- | `onTypedChar` | `(data: CharData) => void` | Per-character typing callback | - |
214
+ | Property | Type | Description | Default |
215
+ | -------------- | -------- | ---------------------------------- | ------- |
216
+ | `percent` | `number` | Typing progress percentage | `0` |
217
+ | `currentChar` | `string` | Current character being typed | - |
218
+ | `currentIndex` | `number` | Current index in the entire string | `0` |
187
219
 
188
- ### Mathematical Formula Configuration
220
+ #### IMarkdownMath
189
221
 
190
- | Property | Type | Description | Default |
191
- | ------------- | ------------------------- | ----------------------------------- | --------- |
192
- | `splitSymbol` | `'dollar'` \| `'bracket'` | Mathematical formula delimiter type | `'dollar' |
222
+ | Property | Type | Description | Default |
223
+ | ------------- | ------------------------- | ------------------------------ | ---------- |
224
+ | `splitSymbol` | `'dollar'` \| `'bracket'` | Mathematical formula delimiter | `'dollar'` |
193
225
 
194
- **Delimiter Description:**
226
+ **Delimiter explanation:**
195
227
 
196
- - `'dollar'`: Use `$...$` and `$$...$$` syntax
197
- - `'bracket'`: Use `\(...\)` and `\[...\]` syntax
228
+ - `'dollar'`: Uses `$...$` and `$$...$$` syntax
229
+ - `'bracket'`: Uses `\(...\)` and `\[...\]` syntax
198
230
 
199
- ### Plugin Configuration
231
+ #### IMarkdownPlugin
200
232
 
201
233
  | Property | Type | Description | Default |
202
234
  | -------------- | ------------------------- | ---------------- | ------- |
@@ -205,17 +237,26 @@ Let's explore these new features together!`);
205
237
  | `type` | `'buildIn'` \| `'custom'` | Plugin type | - |
206
238
  | `id` | `any` | Plugin unique ID | - |
207
239
 
208
- ### Imperative API (Recommended for Streaming Scenarios)
240
+ ### Component Exposed Methods
241
+
242
+ #### Default export DsMarkdown
243
+
244
+ | Method | Parameters | Description |
245
+ | -------- | ---------- | ------------- |
246
+ | `stop` | - | Pause typing |
247
+ | `resume` | - | Resume typing |
248
+
249
+ #### MarkdownCMD Exposed Methods
209
250
 
210
251
  | Method | Parameters | Description |
211
252
  | ----------------- | ------------------------------------------- | ----------------------------- |
212
253
  | `push` | `(content: string, answerType: AnswerType)` | Add content and start typing |
213
254
  | `clear` | - | Clear all content and state |
214
255
  | `triggerWholeEnd` | - | Manually trigger end callback |
215
- | `stop` | - | Pause typing animation |
216
- | `resume` | - | Resume typing animation |
256
+ | `stop` | - | Pause typing |
257
+ | `resume` | - | Resume typing |
217
258
 
218
- **Usage Example:**
259
+ **Usage example:**
219
260
 
220
261
  ```tsx
221
262
  markdownRef.current?.stop(); // Pause animation
@@ -226,6 +267,10 @@ markdownRef.current?.resume(); // Resume animation
226
267
 
227
268
  ## 🧮 Mathematical Formula Usage Guide
228
269
 
270
+ [DEMO1: Pythagorean Theorem](https://stackblitz.com/edit/vitejs-vite-z94syu8j?file=src%2FApp.tsx)
271
+
272
+ [DEMO2: Problem Solving](https://stackblitz.com/edit/vitejs-vite-xk9lxagc?file=README.md)
273
+
229
274
  ### Basic Syntax
230
275
 
231
276
  ```tsx
@@ -246,7 +291,7 @@ import { katexPlugin } from 'ds-markdown/plugins';
246
291
  ### Delimiter Selection
247
292
 
248
293
  ```tsx
249
- // Use dollar symbol delimiters (default)
294
+ // Using dollar sign delimiters (default)
250
295
  <DsMarkdown
251
296
  plugins={[katexPlugin]}
252
297
  math={{ splitSymbol: 'dollar' }}
@@ -255,7 +300,7 @@ import { katexPlugin } from 'ds-markdown/plugins';
255
300
  Block: $$\sum_{i=1}^{n} x_i = x_1 + x_2 + \cdots + x_n$$
256
301
  </DsMarkdown>
257
302
 
258
- // Use bracket delimiters
303
+ // Using bracket delimiters
259
304
  <DsMarkdown
260
305
  plugins={[katexPlugin]}
261
306
  math={{ splitSymbol: 'bracket' }}
@@ -270,10 +315,10 @@ import { katexPlugin } from 'ds-markdown/plugins';
270
315
  ```tsx
271
316
  // Perfect support for mathematical formulas in streaming output
272
317
  const mathContent = [
273
- 'Pythagorean Theorem: ',
318
+ 'Pythagorean Theorem:',
274
319
  '$a^2 + b^2 = c^2$',
275
320
  '\n\n',
276
- 'Where:\n',
321
+ 'Where:',
277
322
  '- $a$ and $b$ are the legs\n',
278
323
  '- $c$ is the hypotenuse\n\n',
279
324
  'For the classic "3-4-5" triangle:\n',
@@ -344,15 +389,15 @@ const customPlugin = createBuildInPlugin({
344
389
 
345
390
  ```typescript
346
391
  // 🎯 Features
347
- - Time-driven: Calculate character count based on actual elapsed time
348
- - Batch processing: Can process multiple characters per frame
349
- - Frame synchronization: Synchronized with browser 60fps refresh rate
350
- - High-frequency optimization: Perfect support for high-speed typing with interval < 16ms
392
+ - Time-driven: Calculates character count based on actual elapsed time
393
+ - Batch processing: Can process multiple characters in a single frame
394
+ - Frame-synchronized: Syncs with browser 60fps refresh rate
395
+ - High-frequency optimized: Perfect support for interval < 16ms high-speed typing
351
396
 
352
397
  // 🎯 Use Cases
353
398
  - Default choice for modern web applications
354
- - Pursuing smooth animation effects
355
- - High-frequency typing (interval > 0 is sufficient)
399
+ - Pursuit of smooth animation effects
400
+ - High-frequency typing (interval > 0 works)
356
401
  - AI real-time conversation scenarios
357
402
  ```
358
403
 
@@ -360,28 +405,28 @@ const customPlugin = createBuildInPlugin({
360
405
 
361
406
  ```typescript
362
407
  // 🎯 Features
363
- - Single character: Process exactly one character each time
364
- - Fixed interval: Execute strictly according to set time
365
- - Beat feeling: Classic typewriter rhythm
408
+ - Single character: Precisely processes one character at a time
409
+ - Fixed interval: Strictly executes at set time intervals
410
+ - Rhythmic: Classic typewriter rhythm feel
366
411
  - Precise control: Suitable for specific timing requirements
367
412
 
368
413
  // 🎯 Use Cases
369
- - Need precise time control
414
+ - Need precise timing control
370
415
  - Creating retro typewriter effects
371
416
  - Scenarios with high compatibility requirements
372
417
  ```
373
418
 
374
419
  ### 📊 Performance Comparison
375
420
 
376
- | Feature | requestAnimationFrame | setTimeout |
377
- | --------------------------- | ---------------------------------------------- | ------------------------------- |
378
- | **Character Processing** | Can process multiple characters per frame | Process one character each time |
379
- | **High-frequency Interval** | ✅ Excellent (5ms → 3 characters per frame) | ❌ May lag |
380
- | **Low-frequency Interval** | ✅ Normal (100ms → 1 character after 6 frames) | ✅ Precise |
381
- | **Visual Effect** | 🎬 Smooth animation feeling | ⚡ Precise beat feeling |
382
- | **Performance Overhead** | 🟢 Low (frame synchronization) | 🟡 Medium (timer) |
421
+ | Feature | requestAnimationFrame | setTimeout |
422
+ | ------------------------ | ----------------------------------- | ----------------------- |
423
+ | **Character Processing** | Multiple characters per frame | One character at a time |
424
+ | **High Frequency** | ✅ Excellent (5ms → 3 chars/frame) | ❌ May lag |
425
+ | **Low Frequency** | ✅ Normal (100ms → 1 char/6 frames) | ✅ Precise |
426
+ | **Visual Effect** | 🎬 Smooth animation feel | ⚡ Precise rhythm feel |
427
+ | **Performance Overhead** | 🟢 Low (frame-synced) | 🟡 Medium (timer) |
383
428
 
384
- High-frequency recommended `requestAnimationFrame`, low-frequency recommended `setTimeout`
429
+ High frequency recommended `requestAnimationFrame`, low frequency recommended `setTimeout`
385
430
 
386
431
  ---
387
432
 
@@ -405,16 +450,16 @@ function StreamingChat() {
405
450
  // Thinking phase
406
451
  markdownRef.current?.push('🤔 Analyzing your question...', 'thinking');
407
452
  await delay(1000);
408
- markdownRef.current?.push('\n\n✅ Analysis complete, starting to answer', 'thinking');
453
+ markdownRef.current?.push('\n\n✅ Analysis complete, starting answer', 'thinking');
409
454
 
410
455
  // Streaming answer
411
456
  const chunks = [
412
- '# React 19 New Features Analysis\n\n',
457
+ '# React 19 Feature Analysis\n\n',
413
458
  '## 🚀 React Compiler\n',
414
459
  'The biggest highlight of React 19 is the introduction of **React Compiler**:\n\n',
415
- '- 🎯 **Automatic Optimization**: No need for manual memo and useMemo\n',
416
- '- ⚡ **Performance Boost**: Compile-time optimization, zero runtime overhead\n',
417
- '- 🔧 **Backward Compatible**: No need to modify existing code\n\n',
460
+ '- 🎯 **Automatic optimization**: No need for manual memo and useMemo\n',
461
+ '- ⚡ **Performance boost**: Compile-time optimization, zero runtime overhead\n',
462
+ '- 🔧 **Backward compatible**: Existing code needs no modification\n\n',
418
463
  '## 📝 Actions Simplify Forms\n',
419
464
  'The new Actions API makes form handling simpler:\n\n',
420
465
  '```tsx\n',
@@ -439,9 +484,9 @@ function StreamingChat() {
439
484
 
440
485
  return (
441
486
  <div className="chat-container">
442
- <button onClick={simulateAIResponse}>🤖 Ask about React 19 New Features</button>
487
+ <button onClick={simulateAIResponse}>🤖 Ask about React 19 features</button>
443
488
 
444
- <MarkdownCMD ref={markdownRef} interval={10} timerType="requestAnimationFrame" onEnd={(data) => console.log('Paragraph complete:', data)} />
489
+ <MarkdownCMD ref={markdownRef} interval={10} timerType="requestAnimationFrame" onEnd={(data) => console.log('Section complete:', data)} />
445
490
  </div>
446
491
  );
447
492
  }
@@ -461,7 +506,7 @@ function MathStreamingDemo() {
461
506
  markdownRef.current?.clear();
462
507
 
463
508
  const mathChunks = [
464
- '# Pythagorean Theorem Explanation\n\n',
509
+ '# Pythagorean Theorem Explained\n\n',
465
510
  'In a right triangle, the square of the hypotenuse equals the sum of squares of the two legs:\n\n',
466
511
  '$a^2 + b^2 = c^2$\n\n',
467
512
  'Where:\n',
@@ -488,64 +533,6 @@ function MathStreamingDemo() {
488
533
  }
489
534
  ```
490
535
 
491
- ### 🔄 Streaming Markdown Syntax Processing
492
-
493
- **Core Problem**: Incomplete Markdown syntax during streaming output can cause rendering errors
494
-
495
- ```tsx
496
- // 🚨 Problem scenario
497
- push('#'); // "# "
498
- push(' '); // "# "
499
- push('Title'); // "# Title"
500
- push('\n'); // "# Title\n"
501
- push('1'); // "# Title\n1" ← This will be incorrectly parsed as paragraph
502
- push('.'); // "# Title\n1." ← Forms correct list
503
- push(' Item'); // "# Title\n1. Item"
504
- ```
505
-
506
- **✅ Smart Solution**: Built-in synchronous buffering mechanism
507
-
508
- ```tsx
509
- // Component intelligently handles syntax boundaries
510
- const handleStreamingMarkdown = () => {
511
- const chunks = ['#', ' ', 'Use', 'Skills', '\n', '1', '.', ' ', 'Skill1', '\n', '2', '.', ' Skill2'];
512
-
513
- chunks.forEach((chunk) => {
514
- markdownRef.current?.push(chunk, 'answer');
515
- // No delay needed, component internally buffers intelligently
516
- });
517
- };
518
-
519
- // 🧠 Intelligent processing flow:
520
- // 1. Real-time detection of incomplete syntax like "# Use Skills\n1"
521
- // 2. Intelligent buffering, waiting for more characters
522
- // 3. Process immediately after receiving "." to form "1."
523
- // 4. Zero delay, pure synchronous processing
524
- ```
525
-
526
- **Supported Syntax Detection**:
527
-
528
- ````typescript
529
- // ✅ Complete syntax (immediate processing)
530
- '## Title'; // Complete title
531
- '1. List item'; // Complete list item
532
- '- Item'; // Complete unordered list
533
- '> Quote content'; // Complete quote
534
- '```javascript'; // Code block start
535
- '```'; // Code block end
536
- 'Content ending with newline\n'; // Newline boundary
537
- '$a + b$'; // Complete mathematical formula
538
- '$$\\sum x$$'; // Complete block mathematical formula
539
-
540
- // 🔄 Incomplete syntax (intelligent buffering)
541
- '##'; // Only title symbol
542
- '1'; // Only number
543
- '```java'; // Possible code block start
544
- '$a +'; // Incomplete mathematical formula
545
- ````
546
-
547
- ---
548
-
549
536
  ## 🔧 Best Practices
550
537
 
551
538
  ### 1. Performance Optimization
@@ -572,21 +559,21 @@ useEffect(() => {
572
559
 
573
560
  // ❌ Avoid: Frequent children updates
574
561
  const [content, setContent] = useState('');
575
- // Each update will re-parse the entire content
562
+ // Each update re-parses the entire content
576
563
  ```
577
564
 
578
565
  ### 3. Mathematical Formula Optimization
579
566
 
580
567
  ```tsx
581
- // ✅ Recommended: Load mathematical formula styles on demand
568
+ // ✅ Recommended: Load math formula styles on demand
582
569
  import 'ds-markdown/style.css';
583
570
  import 'ds-markdown/katex.css'; // Only import when needed
584
571
 
585
- // ✅ Recommended: Reasonable use of delimiters
586
- // For simple formulas, use $...$ for conciseness
572
+ // ✅ Recommended: Use delimiters appropriately
573
+ // For simple formulas, use $...$ for simplicity
587
574
  // For complex formulas, use $$...$$ for clarity
588
575
 
589
- // ✅ Recommended: Plugin-based configuration
576
+ // ✅ Recommended: Plugin configuration
590
577
  import { katexPlugin } from 'ds-markdown/plugins';
591
578
  <DsMarkdown plugins={[katexPlugin]}>Mathematical formula content</DsMarkdown>;
592
579
  ```
@@ -599,101 +586,3 @@ import { MarkdownCMDRef } from 'ds-markdown';
599
586
  const ref = useRef<MarkdownCMDRef>(null);
600
587
  // Complete TypeScript type hints
601
588
  ```
602
-
603
- ### 5. Style Customization
604
-
605
- ```css
606
- /* Thinking area styles */
607
- .ds-markdown-thinking {
608
- background: rgba(255, 193, 7, 0.1);
609
- border-left: 3px solid #ffc107;
610
- padding: 12px;
611
- border-radius: 6px;
612
- margin: 8px 0;
613
- }
614
-
615
- /* Answer area styles */
616
- .ds-markdown-answer {
617
- color: #333;
618
- line-height: 1.6;
619
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
620
- }
621
-
622
- /* Code block styles */
623
- .ds-markdown pre {
624
- background: #f8f9fa;
625
- border-radius: 8px;
626
- padding: 16px;
627
- overflow-x: auto;
628
- }
629
-
630
- /* Table styles */
631
- .ds-markdown-table {
632
- border-collapse: collapse;
633
- width: 100%;
634
- margin: 16px 0;
635
- }
636
-
637
- .ds-markdown-table th,
638
- .ds-markdown-table td {
639
- border: 1px solid #ddd;
640
- padding: 8px 12px;
641
- text-align: left;
642
- }
643
-
644
- /* Mathematical formula styles */
645
- .katex {
646
- font-size: 1.1em;
647
- }
648
-
649
- .katex-display {
650
- margin: 1em 0;
651
- text-align: center;
652
- }
653
-
654
- /* Dark theme mathematical formulas */
655
- [data-theme='dark'] .katex {
656
- color: #e1e1e1;
657
- }
658
- ```
659
-
660
- ---
661
-
662
- ## 🌐 Compatibility
663
-
664
- | Environment | Version Requirement | Description |
665
- | -------------- | ----------------------------------- | ------------------------ |
666
- | **React** | 16.8.0+ | Requires Hooks support |
667
- | **TypeScript** | 4.0+ | Optional but recommended |
668
- | **Browser** | Chrome 60+, Firefox 55+, Safari 12+ | Modern browsers |
669
- | **Node.js** | 14.0+ | Build environment |
670
-
671
- ---
672
-
673
- ## 🤝 Contributing
674
-
675
- Welcome to submit Issues and Pull Requests!
676
-
677
- 1. Fork this repository
678
- 2. Create feature branch: `git checkout -b feature/amazing-feature`
679
- 3. Commit changes: `git commit -m 'Add amazing feature'`
680
- 4. Push branch: `git push origin feature/amazing-feature`
681
- 5. Submit Pull Request
682
-
683
- ---
684
-
685
- ## 📄 License
686
-
687
- MIT © [onshinpei](https://github.com/onshinpei)
688
-
689
- ---
690
-
691
- <div align="center">
692
- <strong>If this project helps you, please give it a ⭐️ Star!</strong>
693
-
694
- <br><br>
695
-
696
- [🐛 Report Issues](https://github.com/onshinpei/ds-markdown/issues) |
697
- [💡 Feature Suggestions](https://github.com/onshinpei/ds-markdown/issues) |
698
- [📖 View Documentation](https://onshinpei.github.io/ds-markdown/)
699
- </div>