ds-markdown 0.1.2-beta.2 โ†’ 0.1.2

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.ko.md CHANGED
@@ -18,6 +18,57 @@
18
18
 
19
19
  ---
20
20
 
21
+ ## ๐Ÿ“‹ ๋ชฉ์ฐจ
22
+
23
+ - [โœจ ํ•ต์‹ฌ ๊ธฐ๋Šฅ](#-ํ•ต์‹ฌ-๊ธฐ๋Šฅ)
24
+ - [๐Ÿ“ฆ ๋น ๋ฅธ ์„ค์น˜](#-๋น ๋ฅธ-์„ค์น˜)
25
+ - [๐Ÿš€ 5๋ถ„ ๋น ๋ฅธ ์‹œ์ž‘](#-5๋ถ„-๋น ๋ฅธ-์‹œ์ž‘)
26
+ - [๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•](#๊ธฐ๋ณธ-์‚ฌ์šฉ๋ฒ•)
27
+ - [ํƒ€์ดํ•‘ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋น„ํ™œ์„ฑํ™”](#ํƒ€์ดํ•‘-์• ๋‹ˆ๋ฉ”์ด์…˜-๋น„ํ™œ์„ฑํ™”)
28
+ - [์ˆ˜ํ•™ ๊ณต์‹ ์ง€์›](#์ˆ˜ํ•™-๊ณต์‹-์ง€์›)
29
+ - [AI ๋Œ€ํ™” ์‹œ๋‚˜๋ฆฌ์˜ค](#ai-๋Œ€ํ™”-์‹œ๋‚˜๋ฆฌ์˜ค)
30
+ - [๐ŸŽฏ ๊ณ ๊ธ‰ ์ฝœ๋ฐฑ ์ œ์–ด](#-๊ณ ๊ธ‰-์ฝœ๋ฐฑ-์ œ์–ด)
31
+ - [๐Ÿ”„ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์‹œ์ž‘ ๋ฐ๋ชจ](#-์• ๋‹ˆ๋ฉ”์ด์…˜-์žฌ์‹œ์ž‘-๋ฐ๋ชจ)
32
+ - [โ–ถ๏ธ ์ˆ˜๋™ ์‹œ์ž‘ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ฐ๋ชจ](#๏ธ-์ˆ˜๋™-์‹œ์ž‘-์• ๋‹ˆ๋ฉ”์ด์…˜-๋ฐ๋ชจ)
33
+ - [๐Ÿ“š ์™„์ „ API ๋ฌธ์„œ](#-์™„์ „-api-๋ฌธ์„œ)
34
+ - [๐Ÿงฎ ์ˆ˜ํ•™ ๊ณต์‹ ์‚ฌ์šฉ ๊ฐ€์ด๋“œ](#-์ˆ˜ํ•™-๊ณต์‹-์‚ฌ์šฉ-๊ฐ€์ด๋“œ)
35
+ - [๐Ÿ”Œ ํ”Œ๋Ÿฌ๊ทธ์ธ ์‹œ์Šคํ…œ](#-ํ”Œ๋Ÿฌ๊ทธ์ธ-์‹œ์Šคํ…œ)
36
+ - [๐ŸŽ›๏ธ ํƒ€์ด๋จธ ๋ชจ๋“œ ์ƒ์„ธ](#๏ธ-ํƒ€์ด๋จธ-๋ชจ๋“œ-์ƒ์„ธ)
37
+ - [๐Ÿ’ก ์‹ค์ „ ์˜ˆ์ œ](#-์‹ค์ „-์˜ˆ์ œ)
38
+ - [๐Ÿ”ง ๋ชจ๋ฒ” ์‚ฌ๋ก€](#-๋ชจ๋ฒ”-์‚ฌ๋ก€)
39
+
40
+ ---
41
+
42
+ ## โ“ ์™œ ds-markdown์„ ์จ์•ผ ํ•˜๋‚˜์š”?
43
+
44
+ - **AI ์ฑ„ํŒ… ๊ฒฝํ—˜ ์™„๋ฒฝ ์žฌํ˜„**
45
+ DeepSeek ๋“ฑ ์ฃผ์š” AI ์ฑ„ํŒ… UI์˜ ํƒ€์ดํ•‘ ์• ๋‹ˆ๋ฉ”์ด์…˜๊ณผ ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต์„ 1:1๋กœ ์žฌํ˜„, "AI๊ฐ€ ์ƒ๊ฐ/๋‹ต๋ณ€ ์ค‘"์ธ ์ง„์งœ ๊ฐ™์€ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
46
+
47
+ - **๋ฐฑ์—”๋“œ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐ์ดํ„ฐ ์™„๋ฒฝ ๋Œ€์‘**
48
+ ๋งŽ์€ AI/LLM ๋ฐฑ์—”๋“œ(OpenAI, DeepSeek ๋“ฑ)๋Š” ํ•œ ๋ฒˆ์— ์—ฌ๋Ÿฌ ๊ธ€์ž๊ฐ€ ํฌํ•จ๋œ chunk๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
49
+ **ds-markdown์€ ๊ฐ chunk๋ฅผ ์ž๋™์œผ๋กœ ํ•œ ๊ธ€์ž์”ฉ ๋ถ„๋ฆฌํ•ด, ๋ฐฑ์—”๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๊ธ€์ž๋ฅผ ํ•œ ๋ฒˆ์— ๋ณด๋‚ด๋„ ํ•ญ์ƒ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ํ•œ ๊ธ€์ž์”ฉ ํƒ€์ดํ•‘ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.**
50
+
51
+ - **์™„๋ฒฝํ•œ Markdown & ์ˆ˜์‹ ์ง€์›**
52
+ KaTeX ๋‚ด์žฅ, ๋ชจ๋“  ์ฃผ์š” Markdown ๊ตฌ๋ฌธ๊ณผ ์ˆ˜์‹ ์ง€์›โ€”๊ธฐ์ˆ  Q&A, ๊ต์œก, ์ง€์‹๋ฒ ์ด์Šค์— ์ตœ์ .
53
+
54
+ - **์ตœ๊ณ ์˜ ๊ฐœ๋ฐœ ๊ฒฝํ—˜**
55
+ ํ’๋ถ€ํ•œ ๋ช…๋ นํ˜• API, ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐ์ดํ„ฐ, ๋น„๋™๊ธฐ ์ฝœ๋ฐฑ, ํ”Œ๋Ÿฌ๊ทธ์ธ ํ™•์žฅ ๋“ฑ์œผ๋กœ ์œ ์—ฐํ•œ ์ œ์–ด ๊ฐ€๋Šฅ.
56
+
57
+ - **๊ฐ€๋ณ๊ณ  ๊ณ ์„ฑ๋Šฅ**
58
+ ์ž‘์€ ์šฉ๋Ÿ‰, ๋น ๋ฅธ ์†๋„, ๋ชจ๋ฐ”์ผ/๋ฐ์Šคํฌํƒ‘ ๋ชจ๋‘ ์ง€์›. ํ•ต์‹ฌ ์˜์กด์„ฑ์€ [react-markdown](https://github.com/remarkjs/react-markdown) (์—…๊ณ„ ํ‘œ์ค€์˜ ์„ฑ์ˆ™ํ•œ Markdown ๋ Œ๋”๋Ÿฌ) ํ•˜๋‚˜๋ฟ์ด๋ฉฐ, ๊ทธ ์™ธ ๋ฌด๊ฑฐ์šด ์˜์กด์„ฑ์€ ์—†์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
59
+
60
+ - **๋‹ค์ค‘ ํ…Œ๋งˆ ๋ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ ์•„ํ‚คํ…์ฒ˜**
61
+ ๋ผ์ดํŠธ/๋‹คํฌ ํ…Œ๋งˆ ์ „ํ™˜, remark/rehype ํ”Œ๋Ÿฌ๊ทธ์ธ ํ˜ธํ™˜, ๊ณ ๊ธ‰ ํ™•์žฅ์„ฑ.
62
+
63
+ - **๋‹ค์–‘ํ•œ ํ™œ์šฉ ์‚ฌ๋ก€**
64
+ - AI ์ฑ—๋ด‡/์–ด์‹œ์Šคํ„ดํŠธ
65
+ - ์‹ค์‹œ๊ฐ„ Q&A/์ง€์‹๋ฒ ์ด์Šค
66
+ - ๊ต์œก/์ˆ˜ํ•™/ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ฝ˜ํ…์ธ 
67
+ - ์ œํ’ˆ ๋ฐ๋ชจ, ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ๋ฌธ์„œ
68
+ - "ํƒ€์ž๊ธฐ" ์• ๋‹ˆ๋ฉ”์ด์…˜๊ณผ ์ŠคํŠธ๋ฆฌ๋ฐ Markdown์ด ํ•„์š”ํ•œ ๋ชจ๋“  ์ƒํ™ฉ
69
+
70
+ ---
71
+
21
72
  ## โœจ ํ•ต์‹ฌ ๊ธฐ๋Šฅ
22
73
 
23
74
  ### ๐Ÿค– **AI ๋Œ€ํ™” ์‹œ๋‚˜๋ฆฌ์˜ค**
@@ -194,28 +245,43 @@ React 19๋Š” ๋งŽ์€ ํฅ๋ฏธ๋กœ์šด ์ƒˆ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:
194
245
  import DsMarkdown, { MarkdownCMD } from 'ds-markdown';
195
246
  ```
196
247
 
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` |
248
+ | ์†์„ฑ | ํƒ€์ž… | ์„ค๋ช… | ๊ธฐ๋ณธ๊ฐ’ |
249
+ | ------------------- | ------------------------------------------- | ---------------------------------------------------------- | ---------------------------------------------------------------------- |
250
+ | `interval` | `number` | ํƒ€์ดํ•‘ ๊ฐ„๊ฒฉ (๋ฐ€๋ฆฌ์ดˆ) | `30` |
251
+ | `timerType` | `'setTimeout'` \| `'requestAnimationFrame'` | ํƒ€์ด๋จธ ํƒ€์ž… | ํ˜„์žฌ ๊ธฐ๋ณธ๊ฐ’์€ `setTimeout`, ๋‚˜์ค‘์— `requestAnimationFrame`๋กœ ๋ณ€๊ฒฝ ์˜ˆ์ • |
252
+ | `answerType` | `'thinking'` \| `'answer'` | ์ฝ˜ํ…์ธ  ํƒ€์ž… (์Šคํƒ€์ผ ์˜ํ–ฅ) | `'answer'` |
253
+ | `theme` | `'light'` \| `'dark'` | ํ…Œ๋งˆ ํƒ€์ž… | `'light'` |
254
+ | `plugins` | `IMarkdownPlugin[]` | ํ”Œ๋Ÿฌ๊ทธ์ธ ์„ค์ • | `[]` |
255
+ | `math` | [IMarkdownMath](#IMarkdownMath) | ์ˆ˜ํ•™ ๊ณต์‹ ์„ค์ • | `{ splitSymbol: 'dollar' }` |
256
+ | `onEnd` | `(data: EndData) => void` | ํƒ€์ดํ•‘ ์™„๋ฃŒ ์ฝœ๋ฐฑ | - |
257
+ | `onStart` | `(data: StartData) => void` | ํƒ€์ดํ•‘ ์‹œ์ž‘ ์ฝœ๋ฐฑ | - |
258
+ | `onBeforeTypedChar` | `(data: IBeforeTypedChar) => Promise<void>` | ๋ฌธ์ž ํƒ€์ดํ•‘ ์ „ ์ฝœ๋ฐฑ, ๋น„๋™๊ธฐ ์ž‘์—… ์ง€์›, ํ›„์† ํƒ€์ดํ•‘ ์ฐจ๋‹จ | - |
259
+ | `onTypedChar` | `(data: ITypedChar) => void` | ๋ฌธ์ž ํƒ€์ดํ•‘ ํ›„ ์ฝœ๋ฐฑ | - |
260
+ | `disableTyping` | `boolean` | ํƒ€์ดํ•‘ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋น„ํ™œ์„ฑํ™” | `false` |
261
+ | `autoStartTyping` | `boolean` | ํƒ€์ดํ•‘ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ž๋™ ์‹œ์ž‘ ์—ฌ๋ถ€, false์ธ ๊ฒฝ์šฐ ์ˆ˜๋™ ํŠธ๋ฆฌ๊ฑฐ | `true` |
209
262
 
210
263
  > ์ฐธ๊ณ : ํƒ€์ดํ•‘ ์ค‘์— `disableTyping`์ด `true`์—์„œ `false`๋กœ ๋ณ€๊ฒฝ๋˜๋ฉด ๋‹ค์Œ ํƒ€์ดํ•‘ ํŠธ๋ฆฌ๊ฑฐ ์‹œ ๋‚จ์€ ๋ชจ๋“  ๋ฌธ์ž๊ฐ€ ํ•œ ๋ฒˆ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
211
264
 
265
+ ### IBeforeTypedChar
266
+
267
+ | ์†์„ฑ | ํƒ€์ž… | ์„ค๋ช… | ๊ธฐ๋ณธ๊ฐ’ |
268
+ | -------------- | ------------ | ------------------------------ | ------ |
269
+ | `currentIndex` | `number` | ์ „์ฒด ๋ฌธ์ž์—ด์—์„œ ํ˜„์žฌ ์ธ๋ฑ์Šค | `0` |
270
+ | `currentChar` | `string` | ํƒ€์ดํ•‘ ์˜ˆ์ • ๋ฌธ์ž | - |
271
+ | `answerType` | `AnswerType` | ์ฝ˜ํ…์ธ  ํƒ€์ž… (thinking/answer) | - |
272
+ | `prevStr` | `string` | ํ˜„์žฌ ํƒ€์ž… ์ฝ˜ํ…์ธ ์˜ ์ด์ „ ๋ฌธ์ž์—ด | - |
273
+ | `percent` | `number` | ํƒ€์ดํ•‘ ์ง„ํ–‰๋ฅ  ๋ฐฑ๋ถ„์œจ (0-100) | `0` |
274
+
212
275
  ### ITypedChar
213
276
 
214
- | ์†์„ฑ | ํƒ€์ž… | ์„ค๋ช… | ๊ธฐ๋ณธ๊ฐ’ |
215
- | -------------- | -------- | --------------------------- | ------ |
216
- | `percent` | `number` | ํƒ€์ดํ•‘ ์ง„ํ–‰๋ฅ  ๋ฐฑ๋ถ„์œจ | `0` |
217
- | `currentChar` | `string` | ํ˜„์žฌ ํƒ€์ดํ•‘ ์ค‘์ธ ๋ฌธ์ž | - |
218
- | `currentIndex` | `number` | ์ „์ฒด ๋ฌธ์ž์—ด์—์„œ ํ˜„์žฌ ์ธ๋ฑ์Šค | `0` |
277
+ | ์†์„ฑ | ํƒ€์ž… | ์„ค๋ช… | ๊ธฐ๋ณธ๊ฐ’ |
278
+ | -------------- | ------------ | -------------------------------- | ------ |
279
+ | `currentIndex` | `number` | ์ „์ฒด ๋ฌธ์ž์—ด์—์„œ ํ˜„์žฌ ์ธ๋ฑ์Šค | `0` |
280
+ | `currentChar` | `string` | ํƒ€์ดํ•‘๋œ ๋ฌธ์ž | - |
281
+ | `answerType` | `AnswerType` | ์ฝ˜ํ…์ธ  ํƒ€์ž… (thinking/answer) | - |
282
+ | `prevStr` | `string` | ํ˜„์žฌ ํƒ€์ž… ์ฝ˜ํ…์ธ ์˜ ์ด์ „ ๋ฌธ์ž์—ด | - |
283
+ | `currentStr` | `string` | ํ˜„์žฌ ํƒ€์ž… ์ฝ˜ํ…์ธ ์˜ ์™„์ „ํ•œ ๋ฌธ์ž์—ด | - |
284
+ | `percent` | `number` | ํƒ€์ดํ•‘ ์ง„ํ–‰๋ฅ  ๋ฐฑ๋ถ„์œจ (0-100) | `0` |
219
285
 
220
286
  #### IMarkdownMath
221
287
 
@@ -241,26 +307,32 @@ import DsMarkdown, { MarkdownCMD } from 'ds-markdown';
241
307
 
242
308
  #### ๊ธฐ๋ณธ ๋‚ด๋ณด๋‚ด๊ธฐ DsMarkdown
243
309
 
244
- | ๋ฉ”์„œ๋“œ | ๋งค๊ฐœ๋ณ€์ˆ˜ | ์„ค๋ช… |
245
- | -------- | -------- | --------------- |
246
- | `stop` | - | ํƒ€์ดํ•‘ ์ผ์‹œ์ •์ง€ |
247
- | `resume` | - | ํƒ€์ดํ•‘ ์žฌ๊ฐœ |
310
+ | ๋ฉ”์„œ๋“œ | ๋งค๊ฐœ๋ณ€์ˆ˜ | ์„ค๋ช… |
311
+ | --------- | -------- | ----------------------------------------------------- |
312
+ | `start` | - | ํƒ€์ดํ•‘ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ์ž‘ |
313
+ | `stop` | - | ํƒ€์ดํ•‘ ์ผ์‹œ์ •์ง€ |
314
+ | `resume` | - | ํƒ€์ดํ•‘ ์žฌ๊ฐœ |
315
+ | `restart` | - | ํƒ€์ดํ•‘ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์‹œ์ž‘, ํ˜„์žฌ ์ฝ˜ํ…์ธ ๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ์žฌ์ƒ |
248
316
 
249
317
  #### MarkdownCMD ๋…ธ์ถœ ๋ฉ”์„œ๋“œ
250
318
 
251
- | ๋ฉ”์„œ๋“œ | ๋งค๊ฐœ๋ณ€์ˆ˜ | ์„ค๋ช… |
252
- | ----------------- | ------------------------------------------- | -------------------------- |
253
- | `push` | `(content: string, answerType: AnswerType)` | ์ฝ˜ํ…์ธ  ์ถ”๊ฐ€ ๋ฐ ํƒ€์ดํ•‘ ์‹œ์ž‘ |
254
- | `clear` | - | ๋ชจ๋“  ์ฝ˜ํ…์ธ  ๋ฐ ์ƒํƒœ ์ง€์šฐ๊ธฐ |
255
- | `triggerWholeEnd` | - | ์ˆ˜๋™์œผ๋กœ ์™„๋ฃŒ ์ฝœ๋ฐฑ ํŠธ๋ฆฌ๊ฑฐ |
256
- | `stop` | - | ํƒ€์ดํ•‘ ์ผ์‹œ์ •์ง€ |
257
- | `resume` | - | ํƒ€์ดํ•‘ ์žฌ๊ฐœ |
319
+ | ๋ฉ”์„œ๋“œ | ๋งค๊ฐœ๋ณ€์ˆ˜ | ์„ค๋ช… |
320
+ | ----------------- | ------------------------------------------- | ----------------------------------------------------- |
321
+ | `push` | `(content: string, answerType: AnswerType)` | ์ฝ˜ํ…์ธ  ์ถ”๊ฐ€ ๋ฐ ํƒ€์ดํ•‘ ์‹œ์ž‘ |
322
+ | `clear` | - | ๋ชจ๋“  ์ฝ˜ํ…์ธ  ๋ฐ ์ƒํƒœ ์ง€์šฐ๊ธฐ |
323
+ | `triggerWholeEnd` | - | ์ˆ˜๋™์œผ๋กœ ์™„๋ฃŒ ์ฝœ๋ฐฑ ํŠธ๋ฆฌ๊ฑฐ |
324
+ | `start` | - | ํƒ€์ดํ•‘ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ์ž‘ |
325
+ | `stop` | - | ํƒ€์ดํ•‘ ์ผ์‹œ์ •์ง€ |
326
+ | `resume` | - | ํƒ€์ดํ•‘ ์žฌ๊ฐœ |
327
+ | `restart` | - | ํƒ€์ดํ•‘ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์‹œ์ž‘, ํ˜„์žฌ ์ฝ˜ํ…์ธ ๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ์žฌ์ƒ |
258
328
 
259
329
  **์‚ฌ์šฉ ์˜ˆ:**
260
330
 
261
331
  ```tsx
332
+ markdownRef.current?.start(); // ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ์ž‘
262
333
  markdownRef.current?.stop(); // ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ผ์‹œ์ •์ง€
263
334
  markdownRef.current?.resume(); // ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ๊ฐœ
335
+ markdownRef.current?.restart(); // ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์‹œ์ž‘
264
336
  ```
265
337
 
266
338
  ---
@@ -586,3 +658,148 @@ import { MarkdownCMDRef } from 'ds-markdown';
586
658
  const ref = useRef<MarkdownCMDRef>(null);
587
659
  // ์™„์ „ํ•œ TypeScript ํƒ€์ž… ํžŒํŠธ
588
660
  ```
661
+
662
+ ### ๐Ÿ”„ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์‹œ์ž‘ ๋ฐ๋ชจ
663
+
664
+ ```tsx
665
+ import { useRef, useState } from 'react';
666
+ import { MarkdownCMD, MarkdownCMDRef } from 'ds-markdown';
667
+
668
+ function RestartDemo() {
669
+ const markdownRef = useRef<MarkdownCMDRef>(null);
670
+ const [isPlaying, setIsPlaying] = useState(false);
671
+ const [hasStarted, setHasStarted] = useState(false);
672
+
673
+ const startContent = () => {
674
+ markdownRef.current?.clear();
675
+ markdownRef.current?.push(
676
+ '# ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์‹œ์ž‘ ๋ฐ๋ชจ\n\n' +
677
+ '์ด ์˜ˆ์ œ๋Š” `restart()` ๋ฉ”์„œ๋“œ์˜ ์‚ฌ์šฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค:\n\n' +
678
+ '- ๐Ÿ”„ **์žฌ์‹œ์ž‘**: ํ˜„์žฌ ์ฝ˜ํ…์ธ ๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ์žฌ์ƒ\n' +
679
+ '- โธ๏ธ **์ผ์‹œ์ •์ง€/์žฌ๊ฐœ**: ์–ธ์ œ๋“ ์ง€ ์ผ์‹œ์ •์ง€์™€ ์žฌ๊ฐœ ๊ฐ€๋Šฅ\n' +
680
+ '- ๐ŸŽฏ **์ •๋ฐ€ ์ œ์–ด**: ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์ƒ ์ƒํƒœ์˜ ์™„์ „ํ•œ ์ œ์–ด\n\n' +
681
+ 'ํ˜„์žฌ ์ƒํƒœ: ' +
682
+ (isPlaying ? '์žฌ์ƒ ์ค‘' : '์ผ์‹œ์ •์ง€') +
683
+ '\n\n' +
684
+ '์ด๋Š” ๋งค์šฐ ์‹ค์šฉ์ ์ธ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค!',
685
+ 'answer',
686
+ );
687
+ setIsPlaying(true);
688
+ };
689
+
690
+ const handleStart = () => {
691
+ if (hasStarted) {
692
+ // ์ด๋ฏธ ์‹œ์ž‘๋œ ๊ฒฝ์šฐ ์žฌ์‹œ์ž‘
693
+ markdownRef.current?.restart();
694
+ } else {
695
+ // ์ฒซ ๋ฒˆ์งธ ์‹œ์ž‘
696
+ markdownRef.current?.start();
697
+ setHasStarted(true);
698
+ }
699
+ setIsPlaying(true);
700
+ };
701
+
702
+ const handleStop = () => {
703
+ markdownRef.current?.stop();
704
+ setIsPlaying(false);
705
+ };
706
+
707
+ const handleResume = () => {
708
+ markdownRef.current?.resume();
709
+ setIsPlaying(true);
710
+ };
711
+
712
+ const handleRestart = () => {
713
+ markdownRef.current?.restart();
714
+ setIsPlaying(true);
715
+ };
716
+
717
+ const handleEnd = () => {
718
+ setIsPlaying(false);
719
+ };
720
+
721
+ return (
722
+ <div>
723
+ <div style={{ marginBottom: '10px', display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
724
+ <button onClick={startContent}>๐Ÿš€ ์ฝ˜ํ…์ธ  ์‹œ์ž‘</button>
725
+ <button onClick={handleStart} disabled={isPlaying}>
726
+ {hasStarted ? '๐Ÿ”„ ์žฌ์‹œ์ž‘' : 'โ–ถ๏ธ ์‹œ์ž‘'}
727
+ </button>
728
+ <button onClick={handleStop} disabled={!isPlaying}>
729
+ โธ๏ธ ์ผ์‹œ์ •์ง€
730
+ </button>
731
+ <button onClick={handleResume} disabled={isPlaying}>
732
+ โ–ถ๏ธ ์žฌ๊ฐœ
733
+ </button>
734
+ <button onClick={handleRestart}>๐Ÿ”„ ์žฌ์‹œ์ž‘</button>
735
+ </div>
736
+
737
+ <div style={{ margin: '10px 0', padding: '10px', background: '#f5f5f5', borderRadius: '4px' }}>
738
+ <strong>์• ๋‹ˆ๋ฉ”์ด์…˜ ์ƒํƒœ:</strong> {isPlaying ? '๐ŸŸข ์žฌ์ƒ ์ค‘' : '๐Ÿ”ด ์ผ์‹œ์ •์ง€'}
739
+ </div>
740
+
741
+ <MarkdownCMD ref={markdownRef} interval={25} onEnd={handleEnd} />
742
+ </div>
743
+ );
744
+ }
745
+ ```
746
+
747
+ ### โ–ถ๏ธ ์ˆ˜๋™ ์‹œ์ž‘ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ฐ๋ชจ
748
+
749
+ ```tsx
750
+ import { useRef, useState } from 'react';
751
+ import { MarkdownCMD, MarkdownCMDRef } from 'ds-markdown';
752
+
753
+ function StartDemo() {
754
+ const markdownRef = useRef<MarkdownCMDRef>(null);
755
+ const [isPlaying, setIsPlaying] = useState(false);
756
+ const [hasStarted, setHasStarted] = useState(false);
757
+
758
+ const loadContent = () => {
759
+ markdownRef.current?.clear();
760
+ markdownRef.current?.push(
761
+ '# ์ˆ˜๋™ ์‹œ์ž‘ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ฐ๋ชจ\n\n' +
762
+ '์ด ์˜ˆ์ œ๋Š” `start()` ๋ฉ”์„œ๋“œ์˜ ์‚ฌ์šฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค:\n\n' +
763
+ '- ๐ŸŽฏ **์ˆ˜๋™ ์ œ์–ด**: `autoStartTyping=false`์ผ ๋•Œ ์ˆ˜๋™์œผ๋กœ `start()`๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค\n' +
764
+ '- โฑ๏ธ **์ง€์—ฐ ์‹œ์ž‘**: ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ ํ›„ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค\n' +
765
+ '- ๐ŸŽฎ **๊ฒŒ์ž„ํ™”**: ์‚ฌ์šฉ์ž์˜ ์ ๊ทน์„ฑ์ด ํ•„์š”ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค\n\n' +
766
+ '"์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ์ž‘" ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์—ฌ ํƒ€์ดํ•‘ ํšจ๊ณผ๋ฅผ ์ˆ˜๋™์œผ๋กœ ํŠธ๋ฆฌ๊ฑฐํ•˜์„ธ์š”!',
767
+ 'answer',
768
+ );
769
+ setIsPlaying(false);
770
+ };
771
+
772
+ const handleStart = () => {
773
+ if (hasStarted) {
774
+ // ์ด๋ฏธ ์‹œ์ž‘๋œ ๊ฒฝ์šฐ ์žฌ์‹œ์ž‘
775
+ markdownRef.current?.restart();
776
+ } else {
777
+ // ์ฒซ ๋ฒˆ์งธ ์‹œ์ž‘
778
+ markdownRef.current?.start();
779
+ setHasStarted(true);
780
+ }
781
+ setIsPlaying(true);
782
+ };
783
+
784
+ const handleEnd = () => {
785
+ setIsPlaying(false);
786
+ };
787
+
788
+ return (
789
+ <div>
790
+ <div style={{ marginBottom: '10px', display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
791
+ <button onClick={loadContent}>๐Ÿ“ ์ฝ˜ํ…์ธ  ๋กœ๋“œ</button>
792
+ <button onClick={handleStart} disabled={isPlaying}>
793
+ {hasStarted ? '๐Ÿ”„ ์žฌ์‹œ์ž‘' : 'โ–ถ๏ธ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ์ž‘'}
794
+ </button>
795
+ </div>
796
+
797
+ <div style={{ margin: '10px 0', padding: '10px', background: '#f5f5f5', borderRadius: '4px' }}>
798
+ <strong>์ƒํƒœ:</strong> {isPlaying ? '๐ŸŸข ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์ƒ ์ค‘' : '๐Ÿ”ด ์‹œ์ž‘ ๋Œ€๊ธฐ ์ค‘'}
799
+ </div>
800
+
801
+ <MarkdownCMD ref={markdownRef} interval={30} autoStartTyping={false} onEnd={handleEnd} />
802
+ </div>
803
+ );
804
+ }
805
+ ```