ds-markdown 0.1.0 → 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 +129 -240
- package/README.ja.md +209 -161
- package/README.ko.md +323 -236
- package/README.md +67 -37
- package/dist/cjs/MarkdownCMD/index.js +23 -17
- package/dist/cjs/MarkdownCMD/index.js.map +1 -1
- package/dist/cjs/defined.d.ts +3 -2
- package/dist/cjs/hooks/useTypingTask.d.ts +2 -0
- package/dist/cjs/hooks/useTypingTask.js +53 -2
- package/dist/cjs/hooks/useTypingTask.js.map +1 -1
- package/dist/cjs/utils/remarkMathBracket.js +19 -6
- package/dist/cjs/utils/remarkMathBracket.js.map +1 -1
- package/dist/esm/MarkdownCMD/index.js +23 -17
- package/dist/esm/MarkdownCMD/index.js.map +1 -1
- package/dist/esm/defined.d.ts +3 -2
- package/dist/esm/hooks/useTypingTask.d.ts +2 -0
- package/dist/esm/hooks/useTypingTask.js +53 -2
- package/dist/esm/hooks/useTypingTask.js.map +1 -1
- package/dist/esm/utils/remarkMathBracket.js +19 -6
- package/dist/esm/utils/remarkMathBracket.js.map +1 -1
- package/package.json +2 -2
package/README.ja.md
CHANGED
|
@@ -20,39 +20,30 @@
|
|
|
20
20
|
|
|
21
21
|
## ✨ コア機能
|
|
22
22
|
|
|
23
|
-
###
|
|
23
|
+
### 🤖 **AI 会話シナリオ**
|
|
24
24
|
|
|
25
25
|
- [DeepSeek ウェブサイト](https://chat.deepseek.com/) のチャット応答効果を1:1で再現
|
|
26
26
|
- 思考プロセス(`thinking`)と回答内容(`answer`)の両方のモードをサポート
|
|
27
|
-
-
|
|
28
|
-
- ライト/ダークテーマのサポート、様々なシナリオに完璧に対応
|
|
27
|
+
- ストリーミングデータに完璧に対応、ユーザー入力への遅延ゼロ応答
|
|
29
28
|
|
|
30
|
-
###
|
|
29
|
+
### 📊 **コンテンツ表示シナリオ**
|
|
31
30
|
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
31
|
+
- コードハイライト、テーブル、リストなどを含む完全な Markdown 構文サポート
|
|
32
|
+
- 数式レンダリング (KaTeX)、`$...$` と `\[...\]` 構文をサポート
|
|
33
|
+
- ライト/ダークテーマサポート、様々なプロダクトスタイルに対応
|
|
34
|
+
- remark/rehype プラグイン拡張をサポートするプラグインアーキテクチャ
|
|
35
35
|
|
|
36
|
-
###
|
|
36
|
+
### �� **開発者エクスペリエンス**
|
|
37
37
|
|
|
38
|
-
- 高頻度タイピングサポート(`requestAnimationFrame` モードでは `0ms` に近いタイピング間隔をサポート)
|
|
39
|
-
- フレーム同期レンダリング、ブラウザの 60fps と完璧にマッチ
|
|
40
|
-
- スマート文字バッチ処理により、より自然な視覚効果
|
|
41
38
|
- タイピングの中断 `stop` と再開 `resume` をサポート
|
|
39
|
+
- タイピングの無効化と有効化をサポート
|
|
42
40
|
|
|
43
|
-
###
|
|
44
|
-
|
|
45
|
-
- **宣言的 API**:シンプルなシナリオに適し、React スタイル
|
|
46
|
-
- **命令的 API**:ストリーミングデータに適し、より良いパフォーマンス
|
|
47
|
-
- **ネイティブ TypeScript サポート**:完全な型ヒント
|
|
48
|
-
|
|
49
|
-
### 🧮 **数式サポート**
|
|
41
|
+
### 🎬 **滑らかなアニメーション**
|
|
50
42
|
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
- **テーマ適応**:ライト/ダークテーマへの自動適応
|
|
43
|
+
- デュアルタイマーモード最適化、`requestAnimationFrame` と `setTimeout` モードをサポート
|
|
44
|
+
- 高頻度タイピングサポート(`requestAnimationFrame` モードでは `0ms` に近いタイピング間隔をサポート)
|
|
45
|
+
- フレーム同期レンダリング、ブラウザのリフレッシュレートと完璧にマッチ
|
|
46
|
+
- スマート文字バッチ処理により、より自然な視覚効果
|
|
56
47
|
|
|
57
48
|
---
|
|
58
49
|
|
|
@@ -76,8 +67,10 @@ pnpm add ds-markdown
|
|
|
76
67
|
[DEMO](https://stackblitz.com/edit/stackblitz-starters-7vcclcw7?file=index.html)
|
|
77
68
|
|
|
78
69
|
```html
|
|
79
|
-
<!--
|
|
70
|
+
<!-- スタイルのインポート、必須 -->
|
|
80
71
|
<link rel="stylesheet" href="https://esm.sh/ds-markdown/dist/style.css" />
|
|
72
|
+
|
|
73
|
+
<!-- katex数学公式スタイルのインポート、必要な場合のみ -->
|
|
81
74
|
<link rel="stylesheet" href="https://esm.sh/ds-markdown/dist/katex.css" />
|
|
82
75
|
|
|
83
76
|
<!-- コンポーネントのインポート -->
|
|
@@ -105,18 +98,42 @@ function App() {
|
|
|
105
98
|
}
|
|
106
99
|
```
|
|
107
100
|
|
|
101
|
+
### タイピングアニメーションの無効化
|
|
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 ? '有効' : '無効'}にするタイピング効果</button>
|
|
113
|
+
|
|
114
|
+
<DsMarkdown interval={20} answerType="answer" disableTyping={disableTyping}>
|
|
115
|
+
# 静的表示モード `disableTyping` が `true` の場合、コンテンツはタイピングアニメーション効果なしで即座に全て表示されます。これは特定のシナリオで非常に有用です: - 📄 静的ドキュメント表示 - 🔄
|
|
116
|
+
表示モードの切り替え - ⚡ コンテンツの素早いプレビュー
|
|
117
|
+
</DsMarkdown>
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
108
123
|
### 数式サポート
|
|
109
124
|
|
|
110
125
|
```tsx
|
|
111
126
|
import DsMarkdown from 'ds-markdown';
|
|
127
|
+
// 数式を表示する必要がある場合は、数式変換プラグインを取り込む
|
|
112
128
|
import { katexPlugin } from 'ds-markdown/plugins';
|
|
113
129
|
import 'ds-markdown/style.css';
|
|
114
|
-
|
|
130
|
+
// 数式を表示する必要がある場合は、数学公式スタイルを取り込む
|
|
131
|
+
import 'ds-markdown/katex.css';
|
|
115
132
|
|
|
116
133
|
function MathDemo() {
|
|
117
134
|
return (
|
|
118
135
|
<DsMarkdown interval={20} answerType="answer" plugins={[katexPlugin]} math={{ splitSymbol: 'dollar' }}>
|
|
119
|
-
# ピタゴラスの定理 直角三角形では、斜辺の二乗は二つの直角辺の二乗の和に等しい: $a^2 + b^2 = c^2$ ここで: - $a$ と $b$ は直角辺 - $c$ は斜辺
|
|
136
|
+
# ピタゴラスの定理 直角三角形では、斜辺の二乗は二つの直角辺の二乗の和に等しい: $a^2 + b^2 = c^2$ ここで: - $a$ と $b$ は直角辺 - $c$ は斜辺 古典的な「勾三股四弦五」の場合: $c = \sqrt
|
|
120
137
|
{3 ^ (2 + 4) ^ 2} = \sqrt{25} = 5$
|
|
121
138
|
</DsMarkdown>
|
|
122
139
|
);
|
|
@@ -171,40 +188,73 @@ React 19 は多くのエキサイティングな新機能をもたらします
|
|
|
171
188
|
|
|
172
189
|
## 📚 完全 API ドキュメント
|
|
173
190
|
|
|
174
|
-
###
|
|
191
|
+
### デフォルトエクスポート DsMarkdown と MarkdownCMD の props
|
|
192
|
+
|
|
193
|
+
```js
|
|
194
|
+
import DsMarkdown, { MarkdownCMD } from 'ds-markdown';
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
| プロパティ | 型 | 説明 | デフォルト |
|
|
198
|
+
| --------------- | --------------------------------------------- | ---------------------------------- | --------------------------------------------------------------------- |
|
|
199
|
+
| `interval` | `number` | タイピング間隔(ミリ秒) | `30` |
|
|
200
|
+
| `timerType` | `'setTimeout'` \| `'requestAnimationFrame'` | タイマータイプ | 現在のデフォルトは`setTimeout`、後で`requestAnimationFrame`に変更予定 |
|
|
201
|
+
| `answerType` | `'thinking'` \| `'answer'` | コンテンツタイプ(スタイルに影響) | `'answer'` |
|
|
202
|
+
| `theme` | `'light'` \| `'dark'` | テーマタイプ | `'light'` |
|
|
203
|
+
| `plugins` | `IMarkdownPlugin[]` | プラグイン設定 | `[]` |
|
|
204
|
+
| `math` | [IMarkdownMath](#IMarkdownMath) | 数式設定 | `{ splitSymbol: 'dollar' }` |
|
|
205
|
+
| `onEnd` | `(data: EndData) => void` | タイピング完了コールバック | - |
|
|
206
|
+
| `onStart` | `(data: StartData) => void` | タイピング開始コールバック | - |
|
|
207
|
+
| `onTypedChar` | `(data: `[ITypedChar](#ITypedChar)`) => void` | 文字ごとのタイピングコールバック | - |
|
|
208
|
+
| `disableTyping` | `boolean` | タイピングアニメーション効果を無効 | `false` |
|
|
209
|
+
|
|
210
|
+
> 注意: タイピング中に `disableTyping` が `true` から `false` に変わると、次のタイピングトリガー時に残りの全文字が一度に表示されます。
|
|
175
211
|
|
|
176
|
-
|
|
177
|
-
| ------------- | ------------------------------------------- | -------------------------------- | --------------------------------------------------------------------- |
|
|
178
|
-
| `interval` | `number` | タイピング間隔(ミリ秒) | `30` |
|
|
179
|
-
| `timerType` | `'setTimeout'` \| `'requestAnimationFrame'` | タイマータイプ | 現在のデフォルトは`setTimeout`、後で`requestAnimationFrame`に変更予定 |
|
|
180
|
-
| `answerType` | `'thinking'` \| `'answer'` | コンテンツタイプ | `'answer'` |
|
|
181
|
-
| `theme` | `'light'` \| `'dark'` | テーマタイプ | `'light'` |
|
|
182
|
-
| `math` | `IMarkdownMath` | 数式設定 | `{ isOpen: false, splitSymbol: 'dollar' }` |
|
|
183
|
-
| `onEnd` | `(data: EndData) => void` | タイピング完了コールバック | - |
|
|
184
|
-
| `onStart` | `(data: StartData) => void` | タイピング開始コールバック | - |
|
|
185
|
-
| `onTypedChar` | `(data: CharData) => void` | 文字ごとのタイピングコールバック | - |
|
|
212
|
+
### ITypedChar
|
|
186
213
|
|
|
187
|
-
|
|
214
|
+
| プロパティ | 型 | 説明 | デフォルト |
|
|
215
|
+
| -------------- | -------- | -------------------------------- | ---------- |
|
|
216
|
+
| `percent` | `number` | タイピング進行パーセンテージ | `0` |
|
|
217
|
+
| `currentChar` | `string` | 現在タイピング中の文字 | - |
|
|
218
|
+
| `currentIndex` | `number` | 文字列全体での現在のインデックス | `0` |
|
|
188
219
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
|
192
|
-
|
|
|
220
|
+
#### IMarkdownMath
|
|
221
|
+
|
|
222
|
+
| プロパティ | 型 | 説明 | デフォルト |
|
|
223
|
+
| ------------- | ------------------------- | -------------------- | ---------- |
|
|
224
|
+
| `splitSymbol` | `'dollar'` \| `'bracket'` | 数式区切り文字タイプ | `'dollar'` |
|
|
193
225
|
|
|
194
226
|
**区切り文字の説明:**
|
|
195
227
|
|
|
196
228
|
- `'dollar'`:`$...$` と `$$...$$` 構文を使用
|
|
197
229
|
- `'bracket'`:`\(...\)` と `\[...\]` 構文を使用
|
|
198
230
|
|
|
199
|
-
|
|
231
|
+
#### IMarkdownPlugin
|
|
232
|
+
|
|
233
|
+
| プロパティ | 型 | 説明 | デフォルト |
|
|
234
|
+
| -------------- | ------------------------- | ----------------- | ---------- |
|
|
235
|
+
| `remarkPlugin` | `unknown` | remark プラグイン | - |
|
|
236
|
+
| `rehypePlugin` | `unknown` | rehype プラグイン | - |
|
|
237
|
+
| `type` | `'buildIn'` \| `'custom'` | プラグインタイプ | - |
|
|
238
|
+
| `id` | `any` | プラグイン固有ID | - |
|
|
239
|
+
|
|
240
|
+
### コンポーネント公開メソッド
|
|
241
|
+
|
|
242
|
+
#### デフォルトエクスポート DsMarkdown
|
|
243
|
+
|
|
244
|
+
| メソッド | パラメータ | 説明 |
|
|
245
|
+
| -------- | ---------- | -------------------- |
|
|
246
|
+
| `stop` | - | タイピングを一時停止 |
|
|
247
|
+
| `resume` | - | タイピングを再開 |
|
|
200
248
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
|
204
|
-
|
|
|
205
|
-
| `
|
|
206
|
-
| `
|
|
207
|
-
| `
|
|
249
|
+
#### MarkdownCMD 公開メソッド
|
|
250
|
+
|
|
251
|
+
| メソッド | パラメータ | 説明 |
|
|
252
|
+
| ----------------- | ------------------------------------------- | ---------------------------------- |
|
|
253
|
+
| `push` | `(content: string, answerType: AnswerType)` | コンテンツを追加してタイピング開始 |
|
|
254
|
+
| `clear` | - | 全コンテンツと状態をクリア |
|
|
255
|
+
| `triggerWholeEnd` | - | 手動で完了コールバックを発火 |
|
|
256
|
+
| `stop` | - | タイピングを一時停止 |
|
|
257
|
+
| `resume` | - | タイピングを再開 |
|
|
208
258
|
|
|
209
259
|
**使用例:**
|
|
210
260
|
|
|
@@ -217,11 +267,17 @@ markdownRef.current?.resume(); // アニメーションを再開
|
|
|
217
267
|
|
|
218
268
|
## 🧮 数式使用ガイド
|
|
219
269
|
|
|
270
|
+
[DEMO1:ピタゴラスの定理](https://stackblitz.com/edit/vitejs-vite-z94syu8j?file=src%2FApp.tsx)
|
|
271
|
+
|
|
272
|
+
[DEMO2:問題解答](https://stackblitz.com/edit/vitejs-vite-xk9lxagc?file=README.md)
|
|
273
|
+
|
|
220
274
|
### 基本構文
|
|
221
275
|
|
|
222
276
|
```tsx
|
|
223
|
-
|
|
224
|
-
|
|
277
|
+
import { katexPlugin } from 'ds-markdown/plugins';
|
|
278
|
+
|
|
279
|
+
// 1. 数式サポートを有効化
|
|
280
|
+
<DsMarkdown plugins={[katexPlugin]}>
|
|
225
281
|
# 数式の例
|
|
226
282
|
|
|
227
283
|
// インライン数式
|
|
@@ -236,13 +292,19 @@ markdownRef.current?.resume(); // アニメーションを再開
|
|
|
236
292
|
|
|
237
293
|
```tsx
|
|
238
294
|
// ドル記号区切り文字を使用(デフォルト)
|
|
239
|
-
<DsMarkdown
|
|
295
|
+
<DsMarkdown
|
|
296
|
+
plugins={[katexPlugin]}
|
|
297
|
+
math={{ splitSymbol: 'dollar' }}
|
|
298
|
+
>
|
|
240
299
|
インライン:$a + b = c$
|
|
241
300
|
ブロック:$$\sum_{i=1}^{n} x_i = x_1 + x_2 + \cdots + x_n$$
|
|
242
301
|
</DsMarkdown>
|
|
243
302
|
|
|
244
303
|
// 括弧区切り文字を使用
|
|
245
|
-
<DsMarkdown
|
|
304
|
+
<DsMarkdown
|
|
305
|
+
plugins={[katexPlugin]}
|
|
306
|
+
math={{ splitSymbol: 'bracket' }}
|
|
307
|
+
>
|
|
246
308
|
インライン:\(a + b = c\)
|
|
247
309
|
ブロック:\[\sum_{i=1}^{n} x_i = x_1 + x_2 + \cdots + x_n\]
|
|
248
310
|
</DsMarkdown>
|
|
@@ -251,8 +313,18 @@ markdownRef.current?.resume(); // アニメーションを再開
|
|
|
251
313
|
### ストリーミング数式
|
|
252
314
|
|
|
253
315
|
```tsx
|
|
254
|
-
//
|
|
255
|
-
const mathContent = [
|
|
316
|
+
// ストリーミング出力での数式を完璧にサポート
|
|
317
|
+
const mathContent = [
|
|
318
|
+
'ピタゴラスの定理:',
|
|
319
|
+
'$a^2 + b^2 = c^2$',
|
|
320
|
+
'\n\n',
|
|
321
|
+
'ここで:',
|
|
322
|
+
'- $a$ と $b$ は直角辺\n',
|
|
323
|
+
'- $c$ は斜辺\n\n',
|
|
324
|
+
'古典的な「勾三股四弦五」の場合:\n',
|
|
325
|
+
'$c = \\sqrt{3^2 + 4^2} = \\sqrt{25} = 5$\n\n',
|
|
326
|
+
'この定理は幾何学で広く応用されています!',
|
|
327
|
+
];
|
|
256
328
|
|
|
257
329
|
mathContent.forEach((chunk) => {
|
|
258
330
|
markdownRef.current?.push(chunk, 'answer');
|
|
@@ -262,7 +334,7 @@ mathContent.forEach((chunk) => {
|
|
|
262
334
|
### スタイルカスタマイズ
|
|
263
335
|
|
|
264
336
|
```css
|
|
265
|
-
/*
|
|
337
|
+
/* 数式スタイルカスタマイズ */
|
|
266
338
|
.katex {
|
|
267
339
|
font-size: 1.1em;
|
|
268
340
|
}
|
|
@@ -272,7 +344,7 @@ mathContent.forEach((chunk) => {
|
|
|
272
344
|
text-align: center;
|
|
273
345
|
}
|
|
274
346
|
|
|
275
|
-
/*
|
|
347
|
+
/* ダークテーマ対応 */
|
|
276
348
|
[data-theme='dark'] .katex {
|
|
277
349
|
color: #e1e1e1;
|
|
278
350
|
}
|
|
@@ -280,54 +352,85 @@ mathContent.forEach((chunk) => {
|
|
|
280
352
|
|
|
281
353
|
---
|
|
282
354
|
|
|
355
|
+
## 🔌 プラグインシステム
|
|
356
|
+
|
|
357
|
+
### 内蔵プラグイン
|
|
358
|
+
|
|
359
|
+
#### KaTeX 数式プラグイン
|
|
360
|
+
|
|
361
|
+
```tsx
|
|
362
|
+
import { katexPlugin } from 'ds-markdown/plugins';
|
|
363
|
+
|
|
364
|
+
// 数式サポートを有効化
|
|
365
|
+
<DsMarkdown plugins={[katexPlugin]}>数式:$E = mc^2$</DsMarkdown>;
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### カスタムプラグイン
|
|
369
|
+
|
|
370
|
+
```tsx
|
|
371
|
+
import { createBuildInPlugin } from 'ds-markdown/plugins';
|
|
372
|
+
|
|
373
|
+
// カスタムプラグインを作成
|
|
374
|
+
const customPlugin = createBuildInPlugin({
|
|
375
|
+
remarkPlugin: yourRemarkPlugin,
|
|
376
|
+
rehypePlugin: yourRehypePlugin,
|
|
377
|
+
id: Symbol('custom-plugin'),
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
// カスタムプラグインを使用
|
|
381
|
+
<DsMarkdown plugins={[katexPlugin, customPlugin]}>コンテンツ</DsMarkdown>;
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
283
386
|
## 🎛️ タイマーモード詳細
|
|
284
387
|
|
|
285
|
-
### `requestAnimationFrame` モード
|
|
388
|
+
### `requestAnimationFrame` モード 🌟 (推奨)
|
|
286
389
|
|
|
287
390
|
```typescript
|
|
288
391
|
// 🎯 特徴
|
|
289
392
|
- 時間駆動:実際の経過時間に基づいて文字数を計算
|
|
290
|
-
-
|
|
393
|
+
- バッチ処理:単一フレーム内で複数文字を処理可能
|
|
291
394
|
- フレーム同期:ブラウザの60fpsリフレッシュレートと同期
|
|
292
395
|
- 高頻度最適化:interval < 16msの高速タイピングを完璧にサポート
|
|
293
396
|
|
|
294
397
|
// 🎯 適用シナリオ
|
|
295
398
|
- モダンWebアプリケーションのデフォルト選択
|
|
296
|
-
-
|
|
297
|
-
-
|
|
298
|
-
- AIリアルタイム会話シナリオ
|
|
399
|
+
- 滑らかなアニメーション効果の追求
|
|
400
|
+
- 高頻度タイピング (interval > 0 で十分)
|
|
401
|
+
- AI リアルタイム会話シナリオ
|
|
299
402
|
```
|
|
300
403
|
|
|
301
|
-
### `setTimeout` モード
|
|
404
|
+
### `setTimeout` モード 📟 (互換)
|
|
302
405
|
|
|
303
406
|
```typescript
|
|
304
407
|
// 🎯 特徴
|
|
305
|
-
-
|
|
306
|
-
-
|
|
307
|
-
-
|
|
408
|
+
- 単一文字:毎回正確に一文字を処理
|
|
409
|
+
- 固定間隔:設定時間通りに厳密実行
|
|
410
|
+
- リズム感:クラシックタイプライターのリズム感
|
|
308
411
|
- 精密制御:特定のタイミング要件に適している
|
|
309
412
|
|
|
310
413
|
// 🎯 適用シナリオ
|
|
311
414
|
- 精密な時間制御が必要
|
|
312
|
-
-
|
|
313
|
-
-
|
|
415
|
+
- レトロタイプライター効果の創出
|
|
416
|
+
- 互換性要件が高いシナリオ
|
|
314
417
|
```
|
|
315
418
|
|
|
316
419
|
### 📊 パフォーマンス比較
|
|
317
420
|
|
|
318
|
-
| 特徴 | requestAnimationFrame | setTimeout
|
|
319
|
-
| -------------------------------- | ----------------------------------- |
|
|
320
|
-
| **文字処理** |
|
|
321
|
-
| **高頻度間隔** | ✅
|
|
322
|
-
| **低頻度間隔** | ✅
|
|
323
|
-
| **視覚効果** | 🎬 滑らかなアニメーション感 | ⚡
|
|
324
|
-
| **パフォーマンスオーバーヘッド** | 🟢
|
|
421
|
+
| 特徴 | requestAnimationFrame | setTimeout |
|
|
422
|
+
| -------------------------------- | ----------------------------------- | -------------------- |
|
|
423
|
+
| **文字処理** | フレームあたり複数文字 | 一度に一文字 |
|
|
424
|
+
| **高頻度間隔** | ✅ 優秀 (5ms → フレームあたり3文字) | ❌ ラグ可能性あり |
|
|
425
|
+
| **低頻度間隔** | ✅ 正常 (100ms → 6フレーム後1文字) | ✅ 精密 |
|
|
426
|
+
| **視覚効果** | 🎬 滑らかなアニメーション感 | ⚡ 精密なリズム感 |
|
|
427
|
+
| **パフォーマンスオーバーヘッド** | 🟢 低 (フレーム同期) | 🟡 中程度 (タイマー) |
|
|
325
428
|
|
|
326
|
-
|
|
429
|
+
高頻度は `requestAnimationFrame` 推奨、低頻度は `setTimeout` 推奨
|
|
327
430
|
|
|
328
431
|
---
|
|
329
432
|
|
|
330
|
-
## 💡
|
|
433
|
+
## 💡 実戦例
|
|
331
434
|
|
|
332
435
|
### 📝 AI ストリーミング会話
|
|
333
436
|
|
|
@@ -340,25 +443,25 @@ import { MarkdownCMD, MarkdownCMDRef } from 'ds-markdown';
|
|
|
340
443
|
function StreamingChat() {
|
|
341
444
|
const markdownRef = useRef<MarkdownCMDRef>(null);
|
|
342
445
|
|
|
343
|
-
// AI
|
|
446
|
+
// AI ストリーミング応答のシミュレート
|
|
344
447
|
const simulateAIResponse = async () => {
|
|
345
448
|
markdownRef.current?.clear();
|
|
346
449
|
|
|
347
450
|
// 思考段階
|
|
348
|
-
markdownRef.current?.push('🤔
|
|
451
|
+
markdownRef.current?.push('🤔 あなたの質問を分析中...', 'thinking');
|
|
349
452
|
await delay(1000);
|
|
350
|
-
markdownRef.current?.push('\n\n✅
|
|
453
|
+
markdownRef.current?.push('\n\n✅ 分析完了、回答開始', 'thinking');
|
|
351
454
|
|
|
352
455
|
// ストリーミング回答
|
|
353
456
|
const chunks = [
|
|
354
457
|
'# React 19 新機能解析\n\n',
|
|
355
458
|
'## 🚀 React Compiler\n',
|
|
356
|
-
'React 19
|
|
357
|
-
'- 🎯
|
|
358
|
-
'- ⚡
|
|
459
|
+
'React 19 の最大のハイライトは **React Compiler** の導入です:\n\n',
|
|
460
|
+
'- 🎯 **自動最適化**:手動でのmemoやuseMemoが不要\n',
|
|
461
|
+
'- ⚡ **パフォーマンス向上**:コンパイル時最適化、ランタイムゼロオーバーヘッド\n',
|
|
359
462
|
'- 🔧 **後方互換性**:既存コードの修正不要\n\n',
|
|
360
|
-
'## 📝 Actions
|
|
361
|
-
'新しいActions API
|
|
463
|
+
'## 📝 Actions でフォーム簡素化\n',
|
|
464
|
+
'新しい Actions API でフォーム処理がより簡単に:\n\n',
|
|
362
465
|
'```tsx\n',
|
|
363
466
|
'function ContactForm({ action }) {\n',
|
|
364
467
|
' const [state, formAction] = useActionState(action, null);\n',
|
|
@@ -370,7 +473,7 @@ function StreamingChat() {
|
|
|
370
473
|
' );\n',
|
|
371
474
|
'}\n',
|
|
372
475
|
'```\n\n',
|
|
373
|
-
'
|
|
476
|
+
'この回答がお役に立てれば幸いです!🎉',
|
|
374
477
|
];
|
|
375
478
|
|
|
376
479
|
for (const chunk of chunks) {
|
|
@@ -383,7 +486,7 @@ function StreamingChat() {
|
|
|
383
486
|
<div className="chat-container">
|
|
384
487
|
<button onClick={simulateAIResponse}>🤖 React 19 新機能について質問</button>
|
|
385
488
|
|
|
386
|
-
<MarkdownCMD ref={markdownRef} interval={10} timerType="requestAnimationFrame" onEnd={(data) => console.log('
|
|
489
|
+
<MarkdownCMD ref={markdownRef} interval={10} timerType="requestAnimationFrame" onEnd={(data) => console.log('セクション完了:', data)} />
|
|
387
490
|
</div>
|
|
388
491
|
);
|
|
389
492
|
}
|
|
@@ -394,6 +497,8 @@ const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
394
497
|
### 🧮 数式ストリーミングレンダリング
|
|
395
498
|
|
|
396
499
|
```tsx
|
|
500
|
+
import { katexPlugin } from 'ds-markdown/plugins';
|
|
501
|
+
|
|
397
502
|
function MathStreamingDemo() {
|
|
398
503
|
const markdownRef = useRef<MarkdownCMDRef>(null);
|
|
399
504
|
|
|
@@ -401,13 +506,13 @@ function MathStreamingDemo() {
|
|
|
401
506
|
markdownRef.current?.clear();
|
|
402
507
|
|
|
403
508
|
const mathChunks = [
|
|
404
|
-
'#
|
|
509
|
+
'# ピタゴラスの定理詳解\n\n',
|
|
405
510
|
'直角三角形では、斜辺の二乗は二つの直角辺の二乗の和に等しい:\n\n',
|
|
406
511
|
'$a^2 + b^2 = c^2$\n\n',
|
|
407
512
|
'ここで:\n',
|
|
408
513
|
'- $a$ と $b$ は直角辺\n',
|
|
409
514
|
'- $c$ は斜辺\n\n',
|
|
410
|
-
'
|
|
515
|
+
'古典的な「勾三股四弦五」の場合:\n',
|
|
411
516
|
'$c = \\sqrt{3^2 + 4^2} = \\sqrt{25} = 5$\n\n',
|
|
412
517
|
'この定理は幾何学で広く応用されています!',
|
|
413
518
|
];
|
|
@@ -422,70 +527,12 @@ function MathStreamingDemo() {
|
|
|
422
527
|
<div>
|
|
423
528
|
<button onClick={simulateMathResponse}>📐 ピタゴラスの定理を説明</button>
|
|
424
529
|
|
|
425
|
-
<MarkdownCMD ref={markdownRef} interval={20} timerType="requestAnimationFrame" math={{
|
|
530
|
+
<MarkdownCMD ref={markdownRef} interval={20} timerType="requestAnimationFrame" plugins={[katexPlugin]} math={{ splitSymbol: 'dollar' }} />
|
|
426
531
|
</div>
|
|
427
532
|
);
|
|
428
533
|
}
|
|
429
534
|
```
|
|
430
535
|
|
|
431
|
-
### 🔄 ストリーミングMarkdown構文処理
|
|
432
|
-
|
|
433
|
-
**核心問題**:ストリーミング出力時に不完全なMarkdown構文がレンダリングエラーを引き起こす
|
|
434
|
-
|
|
435
|
-
```tsx
|
|
436
|
-
// 🚨 問題シナリオ
|
|
437
|
-
push('#'); // "# "
|
|
438
|
-
push(' '); // "# "
|
|
439
|
-
push('タイトル'); // "# タイトル"
|
|
440
|
-
push('\n'); // "# タイトル\n"
|
|
441
|
-
push('1'); // "# タイトル\n1" ← ここで段落として誤解析される
|
|
442
|
-
push('.'); // "# タイトル\n1." ← 正しいリストを形成
|
|
443
|
-
push(' 項目'); // "# タイトル\n1. 項目"
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
**✅ スマート解決策**:内蔵同期バッファリングメカニズム
|
|
447
|
-
|
|
448
|
-
```tsx
|
|
449
|
-
// コンポーネントが構文境界をインテリジェントに処理
|
|
450
|
-
const handleStreamingMarkdown = () => {
|
|
451
|
-
const chunks = ['#', ' ', '使用', 'スキル', '\n', '1', '.', ' ', 'スキル1', '\n', '2', '.', ' スキル2'];
|
|
452
|
-
|
|
453
|
-
chunks.forEach((chunk) => {
|
|
454
|
-
markdownRef.current?.push(chunk, 'answer');
|
|
455
|
-
// 遅延不要、コンポーネントが内部でインテリジェントにバッファリング
|
|
456
|
-
});
|
|
457
|
-
};
|
|
458
|
-
|
|
459
|
-
// 🧠 インテリジェント処理フロー:
|
|
460
|
-
// 1. "# 使用スキル\n1" のような不完全な構文をリアルタイム検出
|
|
461
|
-
// 2. インテリジェントバッファリング、より多くの文字を待機
|
|
462
|
-
// 3. "." を受信して "1." を形成した後すぐに処理
|
|
463
|
-
// 4. ゼロ遅延、純粋な同期処理
|
|
464
|
-
```
|
|
465
|
-
|
|
466
|
-
**サポートされる構文検出**:
|
|
467
|
-
|
|
468
|
-
````typescript
|
|
469
|
-
// ✅ 完全な構文(即座に処理)
|
|
470
|
-
'## タイトル'; // 完全なタイトル
|
|
471
|
-
'1. リスト項目'; // 完全なリスト項目
|
|
472
|
-
'- 項目'; // 完全な順序なしリスト
|
|
473
|
-
'> 引用コンテンツ'; // 完全な引用
|
|
474
|
-
'```javascript'; // コードブロック開始
|
|
475
|
-
'```'; // コードブロック終了
|
|
476
|
-
'改行で終わるコンテンツ\n'; // 改行境界
|
|
477
|
-
'$a + b$'; // 完全な数式
|
|
478
|
-
'$$\\sum x$$'; // 完全なブロック数式
|
|
479
|
-
|
|
480
|
-
// 🔄 不完全な構文(インテリジェントバッファリング)
|
|
481
|
-
'##'; // タイトル記号のみ
|
|
482
|
-
'1'; // 数字のみ
|
|
483
|
-
'```java'; // 可能性のあるコードブロック開始
|
|
484
|
-
'$a +'; // 不完全な数式
|
|
485
|
-
````
|
|
486
|
-
|
|
487
|
-
---
|
|
488
|
-
|
|
489
536
|
## 🔧 ベストプラクティス
|
|
490
537
|
|
|
491
538
|
### 1. パフォーマンス最適化
|
|
@@ -494,40 +541,41 @@ const handleStreamingMarkdown = () => {
|
|
|
494
541
|
// ✅ 推奨設定
|
|
495
542
|
<DsMarkdown
|
|
496
543
|
timerType="requestAnimationFrame"
|
|
497
|
-
interval={15} // 15-30msが最適な体験
|
|
544
|
+
interval={15} // 15-30ms が最適な体験
|
|
498
545
|
/>
|
|
499
546
|
|
|
500
|
-
// ❌
|
|
547
|
+
// ❌ 過小な間隔は避ける
|
|
501
548
|
<DsMarkdown interval={1} /> // パフォーマンス問題を引き起こす可能性
|
|
502
549
|
```
|
|
503
550
|
|
|
504
551
|
### 2. ストリーミングデータ処理
|
|
505
552
|
|
|
506
553
|
```tsx
|
|
507
|
-
// ✅ 推奨:命令的API
|
|
554
|
+
// ✅ 推奨:命令的 API
|
|
508
555
|
const ref = useRef<MarkdownCMDRef>(null);
|
|
509
556
|
useEffect(() => {
|
|
510
557
|
ref.current?.push(newChunk, 'answer');
|
|
511
558
|
}, [newChunk]);
|
|
512
559
|
|
|
513
|
-
// ❌ 避ける:頻繁なchildren更新
|
|
560
|
+
// ❌ 避ける:頻繁な children 更新
|
|
514
561
|
const [content, setContent] = useState('');
|
|
515
|
-
//
|
|
562
|
+
// 各更新で全コンテンツを再解析
|
|
516
563
|
```
|
|
517
564
|
|
|
518
565
|
### 3. 数式最適化
|
|
519
566
|
|
|
520
567
|
```tsx
|
|
521
|
-
// ✅
|
|
568
|
+
// ✅ 推奨:オンデマンドで数式スタイルを読み込み
|
|
522
569
|
import 'ds-markdown/style.css';
|
|
523
570
|
import 'ds-markdown/katex.css'; // 必要な時のみインポート
|
|
524
571
|
|
|
525
|
-
// ✅
|
|
526
|
-
// シンプルな数式には $...$
|
|
527
|
-
// 複雑な数式には $$...$$
|
|
572
|
+
// ✅ 推奨:適切な区切り文字の使用
|
|
573
|
+
// シンプルな数式には $...$ がより簡潔
|
|
574
|
+
// 複雑な数式には $$...$$ がより明確
|
|
528
575
|
|
|
529
|
-
//
|
|
530
|
-
|
|
576
|
+
// ✅ 推奨:プラグイン設定
|
|
577
|
+
import { katexPlugin } from 'ds-markdown/plugins';
|
|
578
|
+
<DsMarkdown plugins={[katexPlugin]}>数式コンテンツ</DsMarkdown>;
|
|
531
579
|
```
|
|
532
580
|
|
|
533
581
|
### 4. 型安全性
|
|
@@ -536,7 +584,7 @@ import 'ds-markdown/katex.css'; // 必要な時のみインポート
|
|
|
536
584
|
import { MarkdownCMDRef } from 'ds-markdown';
|
|
537
585
|
|
|
538
586
|
const ref = useRef<MarkdownCMDRef>(null);
|
|
539
|
-
// 完全なTypeScript型ヒント
|
|
587
|
+
// 完全な TypeScript 型ヒント
|
|
540
588
|
```
|
|
541
589
|
|
|
542
590
|
### 5. スタイルカスタマイズ
|