@iyulab/chat-components 0.11.8 → 0.12.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/CHANGELOG.md +79 -0
- package/dist/_virtual/{_@oxc-project_runtime@0.148.0 → _@oxc-project_runtime@0.149.0}/helpers/esm/decorate.js +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.148.0 → _@oxc-project_runtime@0.149.0}/helpers/esm/decorateMetadata.js +1 -1
- package/dist/components/blocks/UCodeBlock.js +2 -2
- package/dist/components/blocks/UElementBlock.js +2 -2
- package/dist/components/blocks/UFileBlock.js +2 -2
- package/dist/components/blocks/UMarkedBlock.d.ts +7 -2
- package/dist/components/blocks/UMarkedBlock.js +12 -7
- package/dist/components/blocks/URefBlock.js +2 -2
- package/dist/components/blocks/UTableBlock.js +2 -2
- package/dist/components/blocks/UTableBlock.styles.js +10 -1
- package/dist/components/blocks/UTextBlock.js +2 -2
- package/dist/components/message/UMessage.js +2 -2
- package/dist/components/prompt/UPrompt.js +2 -2
- package/dist/components/references/URefCard.js +2 -2
- package/dist/components/references/URefCardGroup.js +2 -2
- package/dist/components/references/URefCardGroup.styles.js +5 -0
- package/dist/components/references/URefTag.js +2 -2
- package/dist/components-extra/UChartBlock.js +2 -2
- package/dist/components-extra/UChartBlock.styles.js +15 -1
- package/dist/components-extra/UImagesBlock.js +2 -2
- package/dist/components-extra/UMapBlock.js +2 -2
- package/dist/components-extra/UMapBlock.styles.js +11 -1
- package/dist/components-extra/UVideoBlock.js +2 -2
- package/dist/node_modules/katex/dist/katex.js +26367 -0
- package/dist/react/UCodeBlock.d.ts +1 -1
- package/dist/react/UCodeBlock.js +1 -1
- package/dist/react/UElementBlock.d.ts +1 -1
- package/dist/react/UElementBlock.js +1 -1
- package/dist/react/UFileBlock.d.ts +1 -1
- package/dist/react/UFileBlock.js +1 -1
- package/dist/react/UImagesBlock.d.ts +1 -1
- package/dist/react/UImagesBlock.js +1 -1
- package/dist/react/UMapBlock.d.ts +1 -1
- package/dist/react/UMapBlock.js +1 -1
- package/dist/react/UMarkedBlock.d.ts +1 -1
- package/dist/react/UMarkedBlock.js +1 -1
- package/dist/react/UMessage.d.ts +1 -1
- package/dist/react/UMessage.js +1 -1
- package/dist/react/UPrompt.d.ts +3 -3
- package/dist/react/UPrompt.js +1 -1
- package/dist/react/URefBlock.d.ts +1 -1
- package/dist/react/URefBlock.js +1 -1
- package/dist/react/URefCard.d.ts +1 -1
- package/dist/react/URefCard.js +1 -1
- package/dist/react/URefCardGroup.d.ts +1 -1
- package/dist/react/URefCardGroup.js +1 -1
- package/dist/react/URefTag.d.ts +1 -1
- package/dist/react/URefTag.js +1 -1
- package/dist/react/UTableBlock.d.ts +1 -1
- package/dist/react/UTableBlock.js +1 -1
- package/dist/react/UTextBlock.d.ts +1 -1
- package/dist/react/UTextBlock.js +1 -1
- package/dist/react/UVideoBlock.d.ts +1 -1
- package/dist/react/UVideoBlock.js +1 -1
- package/dist/utilities/HtmlPlaceholder.d.ts +18 -1
- package/dist/utilities/HtmlPlaceholder.js +59 -4
- package/dist/utilities/markedKatex.d.ts +10 -0
- package/dist/utilities/markedKatex.js +106 -0
- package/package.json +7 -8
- package/skills/iyulab-chat-components/references/components/chart-block.md +17 -0
- package/skills/iyulab-chat-components/references/components/code-block.md +12 -0
- package/skills/iyulab-chat-components/references/components/images-block.md +10 -0
- package/skills/iyulab-chat-components/references/components/map-block.md +15 -0
- package/skills/iyulab-chat-components/references/components/marked-block.md +8 -0
- package/skills/iyulab-chat-components/references/components/message.md +8 -0
- package/skills/iyulab-chat-components/references/components/prompt.md +11 -0
- package/skills/iyulab-chat-components/references/components/table-block.md +15 -0
- package/skills/iyulab-chat-components/references/components/video-block.md +10 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { UCodeBlock as UCodeBlockElement } from '
|
|
2
|
+
import { UCodeBlock as UCodeBlockElement } from '@iyulab/chat-components/dist/components/blocks/UCodeBlock.js';
|
|
3
3
|
|
|
4
4
|
export declare const UCodeBlock: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<UCodeBlockElement>, keyof React.HTMLAttributes<UCodeBlockElement>>
|
package/dist/react/UCodeBlock.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { UCodeBlock as UCodeBlockElement } from '
|
|
3
|
+
import { UCodeBlock as UCodeBlockElement } from '@iyulab/chat-components/dist/components/blocks/UCodeBlock.js';
|
|
4
4
|
|
|
5
5
|
export const UCodeBlock = createComponent({
|
|
6
6
|
react: React,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { UElementBlock as UElementBlockElement } from '
|
|
2
|
+
import { UElementBlock as UElementBlockElement } from '@iyulab/chat-components/dist/components/blocks/UElementBlock.js';
|
|
3
3
|
|
|
4
4
|
export declare const UElementBlock: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<UElementBlockElement>, keyof React.HTMLAttributes<UElementBlockElement>>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { UElementBlock as UElementBlockElement } from '
|
|
3
|
+
import { UElementBlock as UElementBlockElement } from '@iyulab/chat-components/dist/components/blocks/UElementBlock.js';
|
|
4
4
|
|
|
5
5
|
export const UElementBlock = createComponent({
|
|
6
6
|
react: React,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { UFileBlock as UFileBlockElement } from '
|
|
2
|
+
import { UFileBlock as UFileBlockElement } from '@iyulab/chat-components/dist/components/blocks/UFileBlock.js';
|
|
3
3
|
|
|
4
4
|
export declare const UFileBlock: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<UFileBlockElement>, keyof React.HTMLAttributes<UFileBlockElement>>
|
package/dist/react/UFileBlock.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { UFileBlock as UFileBlockElement } from '
|
|
3
|
+
import { UFileBlock as UFileBlockElement } from '@iyulab/chat-components/dist/components/blocks/UFileBlock.js';
|
|
4
4
|
|
|
5
5
|
export const UFileBlock = createComponent({
|
|
6
6
|
react: React,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { UImagesBlock as UImagesBlockElement } from '
|
|
2
|
+
import { UImagesBlock as UImagesBlockElement } from '@iyulab/chat-components/dist/components-extra/UImagesBlock.js';
|
|
3
3
|
|
|
4
4
|
export declare const UImagesBlock: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<UImagesBlockElement>, keyof React.HTMLAttributes<UImagesBlockElement>>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { UImagesBlock as UImagesBlockElement } from '
|
|
3
|
+
import { UImagesBlock as UImagesBlockElement } from '@iyulab/chat-components/dist/components-extra/UImagesBlock.js';
|
|
4
4
|
|
|
5
5
|
export const UImagesBlock = createComponent({
|
|
6
6
|
react: React,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { UMapBlock as UMapBlockElement } from '
|
|
2
|
+
import { UMapBlock as UMapBlockElement } from '@iyulab/chat-components/dist/components-extra/UMapBlock.js';
|
|
3
3
|
|
|
4
4
|
export declare const UMapBlock: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<UMapBlockElement>, keyof React.HTMLAttributes<UMapBlockElement>>
|
package/dist/react/UMapBlock.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { UMapBlock as UMapBlockElement } from '
|
|
3
|
+
import { UMapBlock as UMapBlockElement } from '@iyulab/chat-components/dist/components-extra/UMapBlock.js';
|
|
4
4
|
|
|
5
5
|
export const UMapBlock = createComponent({
|
|
6
6
|
react: React,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { UMarkedBlock as UMarkedBlockElement } from '
|
|
2
|
+
import { UMarkedBlock as UMarkedBlockElement } from '@iyulab/chat-components/dist/components/blocks/UMarkedBlock.js';
|
|
3
3
|
|
|
4
4
|
export declare const UMarkedBlock: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<UMarkedBlockElement>, keyof React.HTMLAttributes<UMarkedBlockElement>>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { UMarkedBlock as UMarkedBlockElement } from '
|
|
3
|
+
import { UMarkedBlock as UMarkedBlockElement } from '@iyulab/chat-components/dist/components/blocks/UMarkedBlock.js';
|
|
4
4
|
|
|
5
5
|
export const UMarkedBlock = createComponent({
|
|
6
6
|
react: React,
|
package/dist/react/UMessage.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { UMessage as UMessageElement } from '
|
|
2
|
+
import { UMessage as UMessageElement } from '@iyulab/chat-components/dist/components/message/UMessage.js';
|
|
3
3
|
|
|
4
4
|
export declare const UMessage: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<UMessageElement>, keyof React.HTMLAttributes<UMessageElement>>
|
package/dist/react/UMessage.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { UMessage as UMessageElement } from '
|
|
3
|
+
import { UMessage as UMessageElement } from '@iyulab/chat-components/dist/components/message/UMessage.js';
|
|
4
4
|
|
|
5
5
|
export const UMessage = createComponent({
|
|
6
6
|
react: React,
|
package/dist/react/UPrompt.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { UPrompt as UPromptElement } from '
|
|
3
|
-
import { type StopEventDetail } from '
|
|
4
|
-
import { type SendEventDetail } from '
|
|
2
|
+
import { UPrompt as UPromptElement } from '@iyulab/chat-components/dist/components/prompt/UPrompt.js';
|
|
3
|
+
import { type StopEventDetail } from '@iyulab/chat-components/dist/events/StopEvent.js';
|
|
4
|
+
import { type SendEventDetail } from '@iyulab/chat-components/dist/events/SendEvent.js';
|
|
5
5
|
|
|
6
6
|
export declare const UPrompt: React.ForwardRefExoticComponent<
|
|
7
7
|
Omit<Partial<UPromptElement>, keyof React.HTMLAttributes<UPromptElement>>
|
package/dist/react/UPrompt.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { UPrompt as UPromptElement } from '
|
|
3
|
+
import { UPrompt as UPromptElement } from '@iyulab/chat-components/dist/components/prompt/UPrompt.js';
|
|
4
4
|
|
|
5
5
|
export const UPrompt = createComponent({
|
|
6
6
|
react: React,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { URefBlock as URefBlockElement } from '
|
|
2
|
+
import { URefBlock as URefBlockElement } from '@iyulab/chat-components/dist/components/blocks/URefBlock.js';
|
|
3
3
|
|
|
4
4
|
export declare const URefBlock: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<URefBlockElement>, keyof React.HTMLAttributes<URefBlockElement>>
|
package/dist/react/URefBlock.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { URefBlock as URefBlockElement } from '
|
|
3
|
+
import { URefBlock as URefBlockElement } from '@iyulab/chat-components/dist/components/blocks/URefBlock.js';
|
|
4
4
|
|
|
5
5
|
export const URefBlock = createComponent({
|
|
6
6
|
react: React,
|
package/dist/react/URefCard.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { URefCard as URefCardElement } from '
|
|
2
|
+
import { URefCard as URefCardElement } from '@iyulab/chat-components/dist/components/references/URefCard.js';
|
|
3
3
|
|
|
4
4
|
export declare const URefCard: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<URefCardElement>, keyof React.HTMLAttributes<URefCardElement>>
|
package/dist/react/URefCard.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { URefCard as URefCardElement } from '
|
|
3
|
+
import { URefCard as URefCardElement } from '@iyulab/chat-components/dist/components/references/URefCard.js';
|
|
4
4
|
|
|
5
5
|
export const URefCard = createComponent({
|
|
6
6
|
react: React,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { URefCardGroup as URefCardGroupElement } from '
|
|
2
|
+
import { URefCardGroup as URefCardGroupElement } from '@iyulab/chat-components/dist/components/references/URefCardGroup.js';
|
|
3
3
|
|
|
4
4
|
export declare const URefCardGroup: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<URefCardGroupElement>, keyof React.HTMLAttributes<URefCardGroupElement>>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { URefCardGroup as URefCardGroupElement } from '
|
|
3
|
+
import { URefCardGroup as URefCardGroupElement } from '@iyulab/chat-components/dist/components/references/URefCardGroup.js';
|
|
4
4
|
|
|
5
5
|
export const URefCardGroup = createComponent({
|
|
6
6
|
react: React,
|
package/dist/react/URefTag.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { URefTag as URefTagElement } from '
|
|
2
|
+
import { URefTag as URefTagElement } from '@iyulab/chat-components/dist/components/references/URefTag.js';
|
|
3
3
|
|
|
4
4
|
export declare const URefTag: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<URefTagElement>, keyof React.HTMLAttributes<URefTagElement>>
|
package/dist/react/URefTag.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { URefTag as URefTagElement } from '
|
|
3
|
+
import { URefTag as URefTagElement } from '@iyulab/chat-components/dist/components/references/URefTag.js';
|
|
4
4
|
|
|
5
5
|
export const URefTag = createComponent({
|
|
6
6
|
react: React,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { UTableBlock as UTableBlockElement } from '
|
|
2
|
+
import { UTableBlock as UTableBlockElement } from '@iyulab/chat-components/dist/components/blocks/UTableBlock.js';
|
|
3
3
|
|
|
4
4
|
export declare const UTableBlock: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<UTableBlockElement>, keyof React.HTMLAttributes<UTableBlockElement>>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { UTableBlock as UTableBlockElement } from '
|
|
3
|
+
import { UTableBlock as UTableBlockElement } from '@iyulab/chat-components/dist/components/blocks/UTableBlock.js';
|
|
4
4
|
|
|
5
5
|
export const UTableBlock = createComponent({
|
|
6
6
|
react: React,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { UTextBlock as UTextBlockElement } from '
|
|
2
|
+
import { UTextBlock as UTextBlockElement } from '@iyulab/chat-components/dist/components/blocks/UTextBlock.js';
|
|
3
3
|
|
|
4
4
|
export declare const UTextBlock: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<UTextBlockElement>, keyof React.HTMLAttributes<UTextBlockElement>>
|
package/dist/react/UTextBlock.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { UTextBlock as UTextBlockElement } from '
|
|
3
|
+
import { UTextBlock as UTextBlockElement } from '@iyulab/chat-components/dist/components/blocks/UTextBlock.js';
|
|
4
4
|
|
|
5
5
|
export const UTextBlock = createComponent({
|
|
6
6
|
react: React,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { UVideoBlock as UVideoBlockElement } from '
|
|
2
|
+
import { UVideoBlock as UVideoBlockElement } from '@iyulab/chat-components/dist/components-extra/UVideoBlock.js';
|
|
3
3
|
|
|
4
4
|
export declare const UVideoBlock: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<UVideoBlockElement>, keyof React.HTMLAttributes<UVideoBlockElement>>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createComponent } from '@lit/react';
|
|
3
|
-
import { UVideoBlock as UVideoBlockElement } from '
|
|
3
|
+
import { UVideoBlock as UVideoBlockElement } from '@iyulab/chat-components/dist/components-extra/UVideoBlock.js';
|
|
4
4
|
|
|
5
5
|
export const UVideoBlock = createComponent({
|
|
6
6
|
react: React,
|
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Marked 파싱 중 HTML이 GFM에 의해 오염되는 것을 방지하기 위해
|
|
3
|
-
* HTML을
|
|
3
|
+
* HTML을 센티널로 치환하고, 나중에 원래 HTML로 복원하는 유틸입니다.
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* 문자열에서 ref 플레이스홀더 센티널을 제거합니다.
|
|
7
|
+
*
|
|
8
|
+
* 코드블록처럼 **복원 대상이 아닌** 경로에서 쓴다 — 거기서는 ref 태그를 렌더하지 않고
|
|
9
|
+
* 원문을 그대로 보여야 하므로, 남은 센티널은 지운다(안 지우면 PUA 문자가 두부로 보인다).
|
|
10
|
+
* 형태를 아는 곳이 이 파일 하나뿐이도록 함수로 내보낸다 — 패턴을 호출부에 복제하면
|
|
11
|
+
* 종전처럼 한쪽만 바뀌어 어긋난다.
|
|
12
|
+
*/
|
|
13
|
+
export declare function stripRefPlaceholders(value: string): string;
|
|
5
14
|
export declare class HtmlPlaceholder {
|
|
6
15
|
private map;
|
|
7
16
|
private idx;
|
|
8
17
|
reset(): void;
|
|
9
18
|
store(html: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* 파싱 결과에서 센티널을 원래 HTML로 되돌립니다.
|
|
21
|
+
*
|
|
22
|
+
* ⚠**아무것도 보관하지 않았으면 손대지 않는다**(`idx === 0`). 그 경우 문자열에 센티널이
|
|
23
|
+
* 있다면 그것은 **작성자가 직접 쓴 글자**이지 우리가 넣은 것이 아니므로, 지우는 것이
|
|
24
|
+
* 오히려 콘텐츠 손실이다. 보관분이 있을 때 매칭되지 않는 키는 빈 문자열로 지운다 —
|
|
25
|
+
* 우리 것이 아닌 센티널이 화면에 두부로 남는 것을 막는다.
|
|
26
|
+
*/
|
|
10
27
|
restore(html: string): string;
|
|
11
28
|
}
|
|
@@ -1,8 +1,55 @@
|
|
|
1
1
|
//#region src/utilities/HtmlPlaceholder.ts
|
|
2
2
|
/**
|
|
3
3
|
* Marked 파싱 중 HTML이 GFM에 의해 오염되는 것을 방지하기 위해
|
|
4
|
-
* HTML을
|
|
4
|
+
* HTML을 센티널로 치환하고, 나중에 원래 HTML로 복원하는 유틸입니다.
|
|
5
5
|
*/
|
|
6
|
+
/**
|
|
7
|
+
* 센티널 경계 문자 — Unicode **Private Use Area**(U+E000..U+F8FF).
|
|
8
|
+
*
|
|
9
|
+
* ⚠**이 선택이 이 유틸의 계약 전부다.** 센티널은 marked 의 토크나이저를 **통과**해야 하고
|
|
10
|
+
* (그래야 `restore()` 가 출력에서 되찾는다), 동시에 marked 가 **HTML로 분류하지 않아야**
|
|
11
|
+
* 한다 — 분류되는 순간 `html` 토큰이 되어 소비자의 sanitizing 렌더러 손에 들어가고,
|
|
12
|
+
* 거기서 형태가 바뀌면 `restore()` 는 자기가 넣은 것을 더 이상 알아보지 못한다.
|
|
13
|
+
*
|
|
14
|
+
* 🔴**종전 판은 HTML 주석(`<!--ref:N-->`)이었고 바로 그 이유로 깨졌다.** marked 는 주석을
|
|
15
|
+
* `html` 토큰으로 잡고(실측: `text, html, text`), `UMarkedBlock` 의 XSS 하드닝 렌더러가
|
|
16
|
+
* 그것을 escape 하면 `<!--ref:N-->` 가 되어 복원 패턴에 걸리지 않는다 — 플레이스홀더가
|
|
17
|
+
* 화면에 **글자 그대로** 남는다. 「주석은 건드려지지 않는다」는 전제가 하드닝과 함께 깨진
|
|
18
|
+
* 것이고, ***전제를 고치는 대신 하드닝에 예외를 두면 다음 하드닝에서 같은 자리가 다시 깨진다.***
|
|
19
|
+
*
|
|
20
|
+
* PUA 문자는 마크다운 문법에서 아무 의미가 없어 **평문 텍스트로만** 토큰화되고(실측),
|
|
21
|
+
* `escapeHtmlText` 의 대상 문자(`& < > " '`)도 아니라 **escape 가 no-op** 이다. 코드블록·
|
|
22
|
+
* 테이블 셀·강조 안에서도 원형이 보존되는 것을 확인했다. ⇒ ***어떤 sanitizing 렌더러가***
|
|
23
|
+
* ***나중에 추가돼도 이 왕복은 깨지지 않는다.***
|
|
24
|
+
*
|
|
25
|
+
* ⚠**소스에는 escape 표기로 적는다** — 원시 PUA 문자를 파일에 두면 에디터·터미널·diff 에서
|
|
26
|
+
* 두부(tofu)나 빈칸으로 보여 「거기 무엇이 있는지」를 읽을 수 없다.
|
|
27
|
+
*/
|
|
28
|
+
var SENTINEL_OPEN = "";
|
|
29
|
+
var SENTINEL_CLOSE = "";
|
|
30
|
+
/**
|
|
31
|
+
* 센티널 매칭 패턴.
|
|
32
|
+
*
|
|
33
|
+
* `lastIndex` 상태를 공유하지 않도록 **매번 새로 만든다** — `g` 플래그가 붙은 정규식을
|
|
34
|
+
* 모듈 상수로 두고 `test()`/`replace()` 에 섞어 쓰면 호출 순서에 따라 조용히 빗나간다.
|
|
35
|
+
*
|
|
36
|
+
* ⚠**정규식 «리터럴»로 적고 문자열로 조립하지 않는다.** 템플릿 리터럴로 `new RegExp(...)`
|
|
37
|
+
* 을 만들면 백슬래시가 리터럴 단계에서 한 번 소비돼 숫자가 아니라 **글자 d 를 찾는** 정규식이
|
|
38
|
+
* 조용히 만들어진다(이 파일을 쓰다 실제로 한 번 만들었다). 경계 문자를 위 상수와
|
|
39
|
+
* 같은 값으로 두 번 적는 대가를 치르되, 두 자리가 **같은 파일 안**에 있고 회귀 테스트가 둘의 일치를 고정한다.
|
|
40
|
+
*/
|
|
41
|
+
var sentinelPattern = () => /\u{E000}\d+\u{E001}/gu;
|
|
42
|
+
/**
|
|
43
|
+
* 문자열에서 ref 플레이스홀더 센티널을 제거합니다.
|
|
44
|
+
*
|
|
45
|
+
* 코드블록처럼 **복원 대상이 아닌** 경로에서 쓴다 — 거기서는 ref 태그를 렌더하지 않고
|
|
46
|
+
* 원문을 그대로 보여야 하므로, 남은 센티널은 지운다(안 지우면 PUA 문자가 두부로 보인다).
|
|
47
|
+
* 형태를 아는 곳이 이 파일 하나뿐이도록 함수로 내보낸다 — 패턴을 호출부에 복제하면
|
|
48
|
+
* 종전처럼 한쪽만 바뀌어 어긋난다.
|
|
49
|
+
*/
|
|
50
|
+
function stripRefPlaceholders(value) {
|
|
51
|
+
return value.replace(sentinelPattern(), "");
|
|
52
|
+
}
|
|
6
53
|
var HtmlPlaceholder = class {
|
|
7
54
|
constructor() {
|
|
8
55
|
this.map = {};
|
|
@@ -13,14 +60,22 @@ var HtmlPlaceholder = class {
|
|
|
13
60
|
this.idx = 0;
|
|
14
61
|
}
|
|
15
62
|
store(html) {
|
|
16
|
-
const key =
|
|
63
|
+
const key = `${SENTINEL_OPEN}${this.idx++}${SENTINEL_CLOSE}`;
|
|
17
64
|
this.map[key] = html;
|
|
18
65
|
return key;
|
|
19
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* 파싱 결과에서 센티널을 원래 HTML로 되돌립니다.
|
|
69
|
+
*
|
|
70
|
+
* ⚠**아무것도 보관하지 않았으면 손대지 않는다**(`idx === 0`). 그 경우 문자열에 센티널이
|
|
71
|
+
* 있다면 그것은 **작성자가 직접 쓴 글자**이지 우리가 넣은 것이 아니므로, 지우는 것이
|
|
72
|
+
* 오히려 콘텐츠 손실이다. 보관분이 있을 때 매칭되지 않는 키는 빈 문자열로 지운다 —
|
|
73
|
+
* 우리 것이 아닌 센티널이 화면에 두부로 남는 것을 막는다.
|
|
74
|
+
*/
|
|
20
75
|
restore(html) {
|
|
21
76
|
if (this.idx === 0) return html;
|
|
22
|
-
return html.replace(
|
|
77
|
+
return html.replace(sentinelPattern(), (key) => this.map[key] ?? "");
|
|
23
78
|
}
|
|
24
79
|
};
|
|
25
80
|
//#endregion
|
|
26
|
-
export { HtmlPlaceholder };
|
|
81
|
+
export { HtmlPlaceholder, stripRefPlaceholders };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { KatexOptions } from 'katex';
|
|
2
|
+
import { MarkedExtension } from 'marked';
|
|
3
|
+
/** `marked` 확장이 받는 옵션 — `displayMode` 는 구분자가 정하므로 소비자가 줄 수 없다. */
|
|
4
|
+
export type MarkedKatexOptions = Omit<KatexOptions, "displayMode">;
|
|
5
|
+
/**
|
|
6
|
+
* `marked.use()` 에 넘길 수식 확장을 만든다.
|
|
7
|
+
*
|
|
8
|
+
* @param options KaTeX 렌더 옵션(`displayMode` 제외 — 구분자가 정한다).
|
|
9
|
+
*/
|
|
10
|
+
export declare function markedKatex(options?: MarkedKatexOptions): MarkedExtension;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import katex from "../node_modules/katex/dist/katex.js";
|
|
2
|
+
//#region src/utilities/markedKatex.ts
|
|
3
|
+
/**
|
|
4
|
+
* `marked` 에 TeX 수식 렌더를 붙이는 확장.
|
|
5
|
+
*
|
|
6
|
+
* 알고리즘(구분자 규칙과 토크나이저 구성)은 `marked-katex-extension`(MIT, © 2021 @markedjs)에서
|
|
7
|
+
* 왔고, 타입·옵션 표면은 이 패키지의 필요에 맞춰 다시 썼다.
|
|
8
|
+
*
|
|
9
|
+
* ## 두 가지 «모드»가 있고, 서로 다른 축이다
|
|
10
|
+
*
|
|
11
|
+
* - **`displayMode`** — KaTeX 에게 *"큰 조판으로 그려라"* 라고 말하는 것(`$$…$$`).
|
|
12
|
+
* - **블록 배치** — 수식이 문단 «밖»에 서는 것. `$$` 가 **자기 줄에 혼자** 있을 때만 일어난다.
|
|
13
|
+
*
|
|
14
|
+
* ⚠**둘은 함께 가지 않는다**: 한 줄 안의 `$$x$$` 는 `displayMode` 이면서 문단 «안»에 남는다.
|
|
15
|
+
* 두 축을 하나로 합치면 기존 문서의 조판이 바뀐다.
|
|
16
|
+
*
|
|
17
|
+
* ## 구분자 규칙
|
|
18
|
+
*
|
|
19
|
+
* - 인라인 `$…$` / `$$…$$` — 여는 구분자 뒤에 `$` 가 바로 오지 않아야 하고(빈 수식 방지),
|
|
20
|
+
* 내용은 **줄을 넘지 못하며**, 닫는 구분자 뒤에는 공백·구두점·문장 끝이 와야 한다.
|
|
21
|
+
* - 블록 `$$\n…\n$$` — 여는·닫는 `$$` 가 각각 자기 줄에 있을 때.
|
|
22
|
+
*
|
|
23
|
+
* 🔴**«수식이 아닌 것을 수식으로 만들지 않는 것»이 이 규칙의 목적이다.** 가장 흔한 오탐
|
|
24
|
+
* 경로는 통화 표기 둘(`from $5 to $10`)이고, 그것을 막는 것이 ⑴내용에서 개행을 배제하고
|
|
25
|
+
* ⑵닫는 구분자 뒤 문맥을 요구하는 두 조건이다. 규칙을 느슨하게 하면 본문이 통째로 한
|
|
26
|
+
* 수식으로 삼켜진다.
|
|
27
|
+
*/
|
|
28
|
+
/** 여는 구분자 뒤에 `$` 가 오지 않고, 내용이 줄을 넘지 않으며, 닫는 뒤가 공백·구두점·끝. */
|
|
29
|
+
var INLINE_RULE = /^(\${1,2})(?!\$)((?:\\.|[^\\\n])*?(?:\\.|[^\\\n$]))\1(?=[\s?!.,:?!。,:]|$)/;
|
|
30
|
+
/** `$$` 가 각각 자기 줄에 있는 형태. */
|
|
31
|
+
var BLOCK_RULE = /^(\${1,2})\n((?:\\[^]|[^\\])+?)\n\1(?:\n|$)/;
|
|
32
|
+
function render(options, token, newlineAfter) {
|
|
33
|
+
const html = katex.renderToString(token.text, {
|
|
34
|
+
...options,
|
|
35
|
+
displayMode: token.displayMode
|
|
36
|
+
});
|
|
37
|
+
return newlineAfter ? `${html}\n` : html;
|
|
38
|
+
}
|
|
39
|
+
function inlineKatex(options) {
|
|
40
|
+
return {
|
|
41
|
+
name: "inlineKatex",
|
|
42
|
+
level: "inline",
|
|
43
|
+
/**
|
|
44
|
+
* `marked` 가 «인라인 텍스트를 어디서 끊을지» 고르는 힌트.
|
|
45
|
+
*
|
|
46
|
+
* ⚠**이것은 규칙이 아니라 힌트다** — 여기서 걸러도 토크나이저는 그 뒤 위치에서 다시
|
|
47
|
+
* 호출되므로, 여는 `$` 앞에 공백이 없는 `a$x$` 도 결국 파싱된다. 문서의 조판을 바꾸지
|
|
48
|
+
* 않으려면 이 성질을 그대로 두어야 한다.
|
|
49
|
+
*/
|
|
50
|
+
start(src) {
|
|
51
|
+
let indexSrc = src;
|
|
52
|
+
let consumed = 0;
|
|
53
|
+
while (indexSrc) {
|
|
54
|
+
const index = indexSrc.indexOf("$");
|
|
55
|
+
if (index === -1) return;
|
|
56
|
+
if ((index === 0 || indexSrc.charAt(index - 1) === " ") && INLINE_RULE.test(indexSrc.substring(index))) return consumed + index;
|
|
57
|
+
const skipped = indexSrc.substring(index + 1);
|
|
58
|
+
const trimmed = skipped.replace(/^\$+/, "");
|
|
59
|
+
consumed += index + 1 + (skipped.length - trimmed.length);
|
|
60
|
+
indexSrc = trimmed;
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
tokenizer(src) {
|
|
64
|
+
const match = src.match(INLINE_RULE);
|
|
65
|
+
if (!match) return void 0;
|
|
66
|
+
return {
|
|
67
|
+
type: "inlineKatex",
|
|
68
|
+
raw: match[0],
|
|
69
|
+
text: match[2].trim(),
|
|
70
|
+
displayMode: match[1].length === 2
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
renderer(token) {
|
|
74
|
+
return render(options, token, false);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function blockKatex(options) {
|
|
79
|
+
return {
|
|
80
|
+
name: "blockKatex",
|
|
81
|
+
level: "block",
|
|
82
|
+
tokenizer(src) {
|
|
83
|
+
const match = src.match(BLOCK_RULE);
|
|
84
|
+
if (!match) return void 0;
|
|
85
|
+
return {
|
|
86
|
+
type: "blockKatex",
|
|
87
|
+
raw: match[0],
|
|
88
|
+
text: match[2].trim(),
|
|
89
|
+
displayMode: match[1].length === 2
|
|
90
|
+
};
|
|
91
|
+
},
|
|
92
|
+
renderer(token) {
|
|
93
|
+
return render(options, token, true);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* `marked.use()` 에 넘길 수식 확장을 만든다.
|
|
99
|
+
*
|
|
100
|
+
* @param options KaTeX 렌더 옵션(`displayMode` 제외 — 구분자가 정한다).
|
|
101
|
+
*/
|
|
102
|
+
function markedKatex(options = {}) {
|
|
103
|
+
return { extensions: [inlineKatex(options), blockKatex(options)] };
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
export { markedKatex };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/chat-components",
|
|
3
3
|
"description": "llm chat components for building chat interfaces",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.12.0",
|
|
5
5
|
"author": "iyulab",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
@@ -61,14 +61,13 @@
|
|
|
61
61
|
"typecheck": "tsc --noEmit"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@iyulab/components": "^1.23.0",
|
|
65
64
|
"highlight.js": "^11.11.1",
|
|
66
|
-
"katex": "^0.
|
|
65
|
+
"katex": "^0.18.7",
|
|
67
66
|
"lit": "^3.3.3",
|
|
68
|
-
"marked": "^18.0.6"
|
|
69
|
-
"marked-katex-extension": "5.1.10"
|
|
67
|
+
"marked": "^18.0.6"
|
|
70
68
|
},
|
|
71
69
|
"peerDependencies": {
|
|
70
|
+
"@iyulab/components": ">=1.23.0",
|
|
72
71
|
"@lit/react": ">=1.0.8",
|
|
73
72
|
"chart.js": ">=4.5.1",
|
|
74
73
|
"react": ">=18.0.0"
|
|
@@ -85,16 +84,16 @@
|
|
|
85
84
|
}
|
|
86
85
|
},
|
|
87
86
|
"devDependencies": {
|
|
88
|
-
"@eslint/js": "^
|
|
87
|
+
"@eslint/js": "^10.0.1",
|
|
89
88
|
"@types/node": "^26.1.1",
|
|
90
89
|
"@vitest/browser-playwright": "^4.1.10",
|
|
91
90
|
"chart.js": "^4.5.1",
|
|
92
|
-
"eslint": "^
|
|
91
|
+
"eslint": "^10.1.0",
|
|
93
92
|
"eslint-plugin-lit": "^2.3.1",
|
|
94
93
|
"glob": "^13.0.6",
|
|
95
94
|
"globals": "^17.7.0",
|
|
96
95
|
"openai": "^6.47.0",
|
|
97
|
-
"typescript": "^
|
|
96
|
+
"typescript": "^6.0.2",
|
|
98
97
|
"typescript-eslint": "^8.64.0",
|
|
99
98
|
"vite": "^8.1.4",
|
|
100
99
|
"vite-plugin-dts": "^5.0.3",
|
|
@@ -48,6 +48,23 @@ LLM output example (`block-json` code fence, rendered via `u-element-block`):
|
|
|
48
48
|
|
|
49
49
|
---
|
|
50
50
|
|
|
51
|
+
## Sizing
|
|
52
|
+
|
|
53
|
+
Content-sized by default: the toolbar plus the chart area. Measured at 600px wide with a small
|
|
54
|
+
bar chart, that is ~368px.
|
|
55
|
+
|
|
56
|
+
**A `max-height` (or `height`) on the host wins.** The toolbar keeps its height and the chart area
|
|
57
|
+
takes the rest, so nothing is clipped away:
|
|
58
|
+
|
|
59
|
+
```css
|
|
60
|
+
u-chart-block { max-height: 200px; }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Before this was fixed, the chart area kept its own height regardless — against a 120px host, 248px
|
|
64
|
+
of it was clipped by the block's `overflow: hidden` with no scrollbar left to reach it.
|
|
65
|
+
|
|
66
|
+
There is no size property or custom property for this — the host is the lever.
|
|
67
|
+
|
|
51
68
|
## Properties
|
|
52
69
|
|
|
53
70
|
| Property | Type | Default | Description |
|
|
@@ -23,6 +23,18 @@ Syntax-highlighted code block powered by Highlight.js. Shows a language label an
|
|
|
23
23
|
|
|
24
24
|
---
|
|
25
25
|
|
|
26
|
+
## Sizing
|
|
27
|
+
|
|
28
|
+
**There is no vertical cap.** Long code grows to its content rather than folding — measured: 200
|
|
29
|
+
lines render about 4,100px tall, with no vertical scrollbar of its own. Only long *lines* scroll,
|
|
30
|
+
horizontally, inside the code area.
|
|
31
|
+
|
|
32
|
+
That is deliberate, and it differs from [`u-table-block`](table-block.md), which caps at 480px:
|
|
33
|
+
folded code cannot be read, and the conversation the block sits in already scrolls.
|
|
34
|
+
|
|
35
|
+
Fenced code inside [`u-marked-block`](marked-block.md) renders as a nested `u-code-block`, so it
|
|
36
|
+
follows this same contract.
|
|
37
|
+
|
|
26
38
|
## Properties
|
|
27
39
|
|
|
28
40
|
| Property | Type | Default | Reflect | Description |
|
|
@@ -38,6 +38,16 @@ LLM output example (`block-json` code fence):
|
|
|
38
38
|
|
|
39
39
|
---
|
|
40
40
|
|
|
41
|
+
## Sizing
|
|
42
|
+
|
|
43
|
+
Height comes from width: each slide is `4 / 3`, so the block is as tall as its column is wide.
|
|
44
|
+
Measured at 600px wide, that is ~222px.
|
|
45
|
+
|
|
46
|
+
⚠**A `max-height` on the host does *not* shrink the images, and that is deliberate.** Squeezing them
|
|
47
|
+
vertically would break the aspect ratio and distort the picture, so the block overflows **visibly**
|
|
48
|
+
instead — it never clips, and nothing becomes unreachable. To make it shorter, give it a narrower
|
|
49
|
+
column rather than a shorter host.
|
|
50
|
+
|
|
41
51
|
## Properties
|
|
42
52
|
|
|
43
53
|
| Property | Type | Default | Description |
|
|
@@ -41,6 +41,21 @@ LLM output example (`block-json` code fence, rendered via `u-element-block`):
|
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
44
|
+
## Sizing
|
|
45
|
+
|
|
46
|
+
The map is **300px tall when nothing constrains it** — that is a default, not a fixed height.
|
|
47
|
+
|
|
48
|
+
**A `max-height` (or `height`) on the host wins**, and the map frame shrinks to fit it:
|
|
49
|
+
|
|
50
|
+
```css
|
|
51
|
+
u-map-block { max-height: 200px; }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Before this was fixed, the frame stayed at 300px regardless — against a 120px host, 180px of the map
|
|
55
|
+
was clipped by the block's `overflow: hidden` with no scrollbar left to reach it.
|
|
56
|
+
|
|
57
|
+
There is no size property or custom property for this — the host is the lever.
|
|
58
|
+
|
|
44
59
|
## Properties
|
|
45
60
|
|
|
46
61
|
| Property | Type | Default | Description |
|