@aeriz/wysiwyg 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +610 -96
- package/angular/README.md +112 -0
- package/angular/aeriz-editor.directive.ts +243 -0
- package/angular/aeriz-wysiwyg.module.ts +14 -0
- package/angular/index.ts +5 -0
- package/dist/adapters/jquery.cjs +1 -0
- package/dist/adapters/jquery.js +91 -0
- package/dist/adapters/react.cjs +1 -0
- package/dist/adapters/react.js +66 -0
- package/dist/adapters/shared.cjs +1 -0
- package/dist/adapters/shared.js +87 -0
- package/dist/adapters/svelte.cjs +1 -0
- package/dist/adapters/svelte.js +29 -0
- package/dist/adapters/vue.cjs +1 -0
- package/dist/adapters/vue.js +110 -0
- package/dist/adapters/vue2.cjs +1 -0
- package/dist/adapters/vue2.js +117 -0
- package/dist/adapters/wc.cjs +1 -0
- package/dist/adapters/wc.js +207 -0
- package/dist/aeriz-wysiwyg-adapter.js +169 -0
- package/dist/aeriz-wysiwyg-adapter.min.js +1 -0
- package/dist/aeriz-wysiwyg-jquery.js +275 -0
- package/dist/aeriz-wysiwyg-jquery.min.js +1 -0
- package/dist/aeriz-wysiwyg-wc.js +401 -0
- package/dist/aeriz-wysiwyg-wc.min.js +1 -0
- package/dist/aeriz-wysiwyg.cjs +6912 -0
- package/dist/aeriz-wysiwyg.css +37 -129
- package/dist/aeriz-wysiwyg.esm.js +1170 -149
- package/dist/aeriz-wysiwyg.esm.min.js +2057 -1209
- package/dist/aeriz-wysiwyg.js +1169 -148
- package/dist/aeriz-wysiwyg.min.cjs +54 -0
- package/dist/aeriz-wysiwyg.min.css +1 -1
- package/dist/aeriz-wysiwyg.min.js +44 -13
- package/dist/server.cjs +32 -0
- package/dist/server.js +666 -0
- package/dist-types/adapters/jquery.d.ts +34 -0
- package/dist-types/adapters/jquery.d.ts.map +1 -0
- package/dist-types/adapters/react.d.ts +28 -0
- package/dist-types/adapters/react.d.ts.map +1 -0
- package/dist-types/adapters/shared.d.ts +83 -0
- package/dist-types/adapters/shared.d.ts.map +1 -0
- package/dist-types/adapters/svelte.d.ts +38 -0
- package/dist-types/adapters/svelte.d.ts.map +1 -0
- package/dist-types/adapters/vue.d.ts +189 -0
- package/dist-types/adapters/vue.d.ts.map +1 -0
- package/dist-types/adapters/vue2.d.ts +175 -0
- package/dist-types/adapters/vue2.d.ts.map +1 -0
- package/dist-types/adapters/wc.d.ts +96 -0
- package/dist-types/adapters/wc.d.ts.map +1 -0
- package/dist-types/cjs/adapters/jquery.d.cts +34 -0
- package/dist-types/cjs/adapters/react.d.cts +28 -0
- package/dist-types/cjs/adapters/shared.d.cts +83 -0
- package/dist-types/cjs/adapters/svelte.d.cts +38 -0
- package/dist-types/cjs/adapters/vue.d.cts +189 -0
- package/dist-types/cjs/adapters/vue2.d.cts +175 -0
- package/dist-types/cjs/adapters/wc.d.cts +96 -0
- package/dist-types/cjs/core/AerizEditor.d.cts +357 -0
- package/dist-types/cjs/core/AerizViewer.d.cts +61 -0
- package/dist-types/cjs/core/block-meta.d.cts +32 -0
- package/dist-types/cjs/core/blocks.d.cts +368 -0
- package/dist-types/cjs/core/fonts.d.cts +60 -0
- package/dist-types/cjs/core/highlight.d.cts +44 -0
- package/dist-types/cjs/core/html-mini.d.cts +65 -0
- package/dist-types/cjs/core/i18n.d.cts +209 -0
- package/dist-types/cjs/core/import-html.d.cts +39 -0
- package/dist-types/cjs/core/import-markdown.d.cts +37 -0
- package/dist-types/cjs/core/markdown-export.d.cts +30 -0
- package/dist-types/cjs/core/plain-text.d.cts +17 -0
- package/dist-types/cjs/core/render-string.d.cts +68 -0
- package/dist-types/cjs/core/snapshot.d.cts +51 -0
- package/dist-types/cjs/index.d.cts +20 -0
- package/dist-types/cjs/server/index.d.cts +37 -0
- package/dist-types/cjs/types/index.d.cts +61 -0
- package/dist-types/cjs/ui/Toolbar.d.cts +21 -0
- package/dist-types/cjs/ui/dialogs.d.cts +74 -0
- package/dist-types/cjs/ui/icons.d.cts +2 -0
- package/dist-types/cjs/ui/popovers.d.cts +70 -0
- package/dist-types/core/AerizEditor.d.ts +30 -10
- package/dist-types/core/AerizEditor.d.ts.map +1 -1
- package/dist-types/core/AerizViewer.d.ts +16 -4
- package/dist-types/core/AerizViewer.d.ts.map +1 -1
- package/dist-types/core/block-meta.d.ts +32 -0
- package/dist-types/core/block-meta.d.ts.map +1 -0
- package/dist-types/core/blocks.d.ts +62 -7
- package/dist-types/core/blocks.d.ts.map +1 -1
- package/dist-types/core/fonts.d.ts +11 -0
- package/dist-types/core/fonts.d.ts.map +1 -1
- package/dist-types/core/html-mini.d.ts +65 -0
- package/dist-types/core/html-mini.d.ts.map +1 -0
- package/dist-types/core/import-html.d.ts.map +1 -1
- package/dist-types/core/markdown-export.d.ts +30 -0
- package/dist-types/core/markdown-export.d.ts.map +1 -0
- package/dist-types/core/plain-text.d.ts +17 -0
- package/dist-types/core/plain-text.d.ts.map +1 -0
- package/dist-types/core/render-string.d.ts +68 -0
- package/dist-types/core/render-string.d.ts.map +1 -0
- package/dist-types/core/snapshot.d.ts +51 -0
- package/dist-types/core/snapshot.d.ts.map +1 -0
- package/dist-types/index.d.ts +19 -10
- package/dist-types/index.d.ts.map +1 -1
- package/dist-types/server/index.d.ts +37 -0
- package/dist-types/server/index.d.ts.map +1 -0
- package/dist-types/types/index.d.ts +21 -0
- package/dist-types/types/index.d.ts.map +1 -1
- package/dist-types/ui/Toolbar.d.ts +1 -1
- package/dist-types/ui/popovers.d.ts +1 -1
- package/dist-types/ui/popovers.d.ts.map +1 -1
- package/package.json +213 -58
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import type { EditorOptions, SerializeHtmlOptions } from '../types/index.cjs';
|
|
2
|
+
import { Toolbar } from '../ui/Toolbar.cjs';
|
|
3
|
+
import type { Block, BlockAttrs, BlockKind, BlockSnapshot } from './blocks.cjs';
|
|
4
|
+
export type { Block, BlockAttrs, BlockKind, BlockMatch, BlockSnapshot, BlockType, ClassifyResult, HeadingLevel, } from './blocks.cjs';
|
|
5
|
+
export interface InlineState {
|
|
6
|
+
bold: boolean;
|
|
7
|
+
italic: boolean;
|
|
8
|
+
underline: boolean;
|
|
9
|
+
strike: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface EditorState {
|
|
12
|
+
blocks: Block[];
|
|
13
|
+
activeBlockId: string | null;
|
|
14
|
+
inline: InlineState;
|
|
15
|
+
}
|
|
16
|
+
export type EditorStateListener = (state: EditorState) => void;
|
|
17
|
+
export declare class AerizEditor {
|
|
18
|
+
readonly root: HTMLDivElement;
|
|
19
|
+
readonly content: HTMLDivElement;
|
|
20
|
+
readonly toolbar: Toolbar | null;
|
|
21
|
+
private readonly contentWrap;
|
|
22
|
+
private readonly handlesLayer;
|
|
23
|
+
private readonly dropIndicator;
|
|
24
|
+
private readonly handles;
|
|
25
|
+
private readonly blockLabelPill;
|
|
26
|
+
private readonly statusBar;
|
|
27
|
+
private readonly statusBlockEl;
|
|
28
|
+
private readonly statusBlocksEl;
|
|
29
|
+
private readonly statusCharsEl;
|
|
30
|
+
private readonly statusSourceEl;
|
|
31
|
+
private readonly options;
|
|
32
|
+
private readonly observer;
|
|
33
|
+
private readonly blockIds;
|
|
34
|
+
private readonly idFor;
|
|
35
|
+
private readonly listeners;
|
|
36
|
+
private readonly handleSelectionChange;
|
|
37
|
+
private readonly handleResize;
|
|
38
|
+
private state;
|
|
39
|
+
private destroyed;
|
|
40
|
+
private syncQueued;
|
|
41
|
+
private lastSerialized;
|
|
42
|
+
/** 사용자가 색 다이얼로그에서 직접 고른 색상의 LRU. 에디터 인스턴스 메모리에만 유지. */
|
|
43
|
+
private recentCustomColors;
|
|
44
|
+
constructor(options: EditorOptions);
|
|
45
|
+
/**
|
|
46
|
+
* 본문 HTML 을 반환한다.
|
|
47
|
+
*
|
|
48
|
+
* 두 가지 스타일 전략을 지원한다 (`options.styles`, 기본값은 생성 시
|
|
49
|
+
* `EditorOptions.htmlStyles`, 그것도 없으면 `'inline'`).
|
|
50
|
+
*
|
|
51
|
+
* - `'inline'` — 호출 시점의 테마 변수(--aw-primary 등) 를 읽어 블록 단위
|
|
52
|
+
* 인라인 스타일에 베이크한다. 스타일시트 없이 어디에 붙여도(이메일 본문,
|
|
53
|
+
* 다른 페이지) 에디터에서 보이는 그대로 렌더된다.
|
|
54
|
+
* - `'class'` — 테마 스타일을 베이크하지 않고 `aw-block-*` / `aw-align-*`
|
|
55
|
+
* 클래스만 남긴다. `style` 속성을 지우는 서버 sanitizer 아래에서 서식을
|
|
56
|
+
* 보존해야 할 때 쓴다. 출력은 `aeriz-wysiwyg.min.css` 를 로드한 페이지의
|
|
57
|
+
* `.aeriz-wysiwyg > .aw-content` 안에 넣는 것을 전제로 한다.
|
|
58
|
+
*
|
|
59
|
+
* 어느 쪽이든 에디터 내부 DOM 은 변형되지 않으며(clone 트리에 적용),
|
|
60
|
+
* data-block-kind / data-block-focused 같은 에디터 전용 속성과 리사이즈
|
|
61
|
+
* 핸들 · 정렬 컨트롤 같은 편집 보조 마크업은 출력에서 제거된다.
|
|
62
|
+
* data-block-id 는 보존.
|
|
63
|
+
*/
|
|
64
|
+
getHTML(options?: SerializeHtmlOptions): string;
|
|
65
|
+
/** 가공 없는 원본 innerHTML. 직렬화 검증/디버그 용도. */
|
|
66
|
+
getRawHTML(): string;
|
|
67
|
+
setHTML(html: string): void;
|
|
68
|
+
focus(): void;
|
|
69
|
+
setTheme(theme: 'light' | 'dark'): void;
|
|
70
|
+
getState(): EditorState;
|
|
71
|
+
getBlocks(): Block[];
|
|
72
|
+
/**
|
|
73
|
+
* 본문 블록들을 직렬화 가능한 BlockSnapshot 배열로 반환한다.
|
|
74
|
+
* AerizViewer.setBlocks(snapshots) 가 받아 동일한 트리를 렌더할 수 있다.
|
|
75
|
+
*/
|
|
76
|
+
serialize(): BlockSnapshot[];
|
|
77
|
+
/**
|
|
78
|
+
* data-block-id 로 본문에서 블록을 찾아 반환. 없으면 null.
|
|
79
|
+
*/
|
|
80
|
+
findBlockById(id: string): Block | null;
|
|
81
|
+
getActiveBlock(): Block | null;
|
|
82
|
+
/**
|
|
83
|
+
* 블록 유형을 변경/추가한다.
|
|
84
|
+
* - `targetBlockId` 지정 시 그 id 의 블록을 강제 대상으로 한다 (다이얼로그
|
|
85
|
+
* 확인 등으로 선택이 다른 곳으로 넘어간 뒤에도 원래 블록을 정확히 변환).
|
|
86
|
+
* - 미지정 시 현재 active block 사용. 둘 다 없으면 본문 끝에 새 블록 추가.
|
|
87
|
+
*/
|
|
88
|
+
setBlockType(kind: BlockKind, attrs?: BlockAttrs, targetBlockId?: string): void;
|
|
89
|
+
private replaceBlock;
|
|
90
|
+
private appendBlock;
|
|
91
|
+
onStateChange(listener: EditorStateListener): () => void;
|
|
92
|
+
destroy(): void;
|
|
93
|
+
/**
|
|
94
|
+
* DOM 변화 후 호출되는 reconcile 진입점.
|
|
95
|
+
* 누락된 data-block-id 를 채우고, 자기 쓰기로 발생한 옵저버 레코드를
|
|
96
|
+
* takeRecords 로 흡수한 뒤 onChange + queueSync.
|
|
97
|
+
*/
|
|
98
|
+
private flush;
|
|
99
|
+
private handleToolbarAction;
|
|
100
|
+
/**
|
|
101
|
+
* 인라인 마크(bold/italic/underline/strike) 토글. 활성 블록의 allowedMarks
|
|
102
|
+
* 에 포함되지 않은 마크면 무시. styleWithCSS=true 모드로 deprecated 태그
|
|
103
|
+
* (<b>/<i>/<u>) 대신 `<span style="font-weight:bold">` 형태가 만들어진다.
|
|
104
|
+
*
|
|
105
|
+
* 'strike' 는 execCommand 표준 명령명이 'strikeThrough'.
|
|
106
|
+
*/
|
|
107
|
+
private applyMark;
|
|
108
|
+
/**
|
|
109
|
+
* 색상 선택기에서 받은 색을 LRU 에 누적하고 selection 에 적용한다.
|
|
110
|
+
* `command` 가 'foreColor' 면 글자색, 'hiliteColor' 면 글 배경색.
|
|
111
|
+
*/
|
|
112
|
+
private handleColorPick;
|
|
113
|
+
/**
|
|
114
|
+
* selection 에 색상을 적용. styleWithCSS=true 모드로 `<span style="color:…">`
|
|
115
|
+
* 또는 `<span style="background-color:…">` 형태가 만들어진다.
|
|
116
|
+
* `null` 은 '기본색' — 'inherit' 으로 부모 색을 따라가도록.
|
|
117
|
+
*/
|
|
118
|
+
private applyColor;
|
|
119
|
+
/**
|
|
120
|
+
* 정렬을 활성 블록(또는 표 셀) 에 적용한다.
|
|
121
|
+
*
|
|
122
|
+
* execCommand('justify*') 는 일부 브라우저에서 blockquote 안의 <p> 에 적용
|
|
123
|
+
* 시 blockquote 를 <div style="text-align:..."> 로 바꿔버리는 잘 알려진
|
|
124
|
+
* 버그가 있어 직접 DOM 조작으로 대체한다.
|
|
125
|
+
*
|
|
126
|
+
* 적용 대상:
|
|
127
|
+
* paragraph / heading → element 자체
|
|
128
|
+
* blockquote → 안의 <p> (없으면 자기 자신)
|
|
129
|
+
* table 단일 셀 → 캐럿이 들어 있는 td/th
|
|
130
|
+
* table 다중 셀 마킹 → 각 cell.style.textAlign 일괄
|
|
131
|
+
*/
|
|
132
|
+
private applyAlign;
|
|
133
|
+
/** 캐럿이 들어 있는 표 셀(td/th) 반환. 표 밖이면 null. */
|
|
134
|
+
private getActiveTableCell;
|
|
135
|
+
/**
|
|
136
|
+
* 현재 활성 셀(들) 을 반환한다.
|
|
137
|
+
* 1순위: 커스텀 드래그-셀렉션으로 마킹된 `.aw-cell-selected` 셀들
|
|
138
|
+
* 2순위: 브라우저 selection range 가 가리키는 표 셀(들)
|
|
139
|
+
* 3순위: 캐럿이 들어 있는 단일 셀
|
|
140
|
+
*/
|
|
141
|
+
private getSelectedTableCells;
|
|
142
|
+
private cellSelStart;
|
|
143
|
+
private cellSelDrag;
|
|
144
|
+
private handleCellSelStart;
|
|
145
|
+
private handleCellSelMove;
|
|
146
|
+
private handleCellSelEnd;
|
|
147
|
+
/** `.aw-cell-selected` 마킹을 모두 제거. */
|
|
148
|
+
private clearCellSelection;
|
|
149
|
+
/**
|
|
150
|
+
* 표 셀 배열 각각에 `cell.style.fontSize` 를 직접 설정. Range API 의 wrap
|
|
151
|
+
* 경로(셀 중첩 버그 발생) 를 우회하기 위한 안전한 다중 셀 적용 경로.
|
|
152
|
+
*/
|
|
153
|
+
private applyFontSizeToCells;
|
|
154
|
+
/**
|
|
155
|
+
* 캡처해 둔 셀(들) 에 배경색을 일괄 적용. null 이면 inline background-color
|
|
156
|
+
* 제거. `<th>` 의 stylesheet 배경(0,1,2 specificity) 보다 inline + !important
|
|
157
|
+
* 가 항상 우선하도록 setProperty('important') 로 박는다.
|
|
158
|
+
*/
|
|
159
|
+
private applyCellBgToCells;
|
|
160
|
+
/** 표 편집 드롭다운에서 받은 액션을 분기 실행. */
|
|
161
|
+
private runTableMenu;
|
|
162
|
+
/** 활성 셀의 행 위/아래에 새 행 삽입. 같은 열 수, 빈 td 로 채움. */
|
|
163
|
+
private insertRow;
|
|
164
|
+
/** 활성 셀이 속한 열의 좌/우에 새 열 삽입. 모든 행에 빈 td 추가. */
|
|
165
|
+
private insertColumn;
|
|
166
|
+
/** 활성 셀의 행 전체 삭제. 마지막 행이면 보존(빈 표 회피). */
|
|
167
|
+
private deleteRow;
|
|
168
|
+
/**
|
|
169
|
+
* 코드 블록 input 마다 호출되는 debounced rehighlight. 활성 블록이 codeBlock
|
|
170
|
+
* 이고 data-language 가 설정돼 있을 때만 동작 — 타이핑 멈춘 뒤 300ms 후 1 회.
|
|
171
|
+
*/
|
|
172
|
+
private codeHighlightTimer;
|
|
173
|
+
private scheduleCodeHighlight;
|
|
174
|
+
/**
|
|
175
|
+
* code 블록의 언어를 변경하고 즉시 highlight 를 다시 적용. 캐럿 위치는
|
|
176
|
+
* 텍스트 offset 으로 보존.
|
|
177
|
+
*/
|
|
178
|
+
private applyCodeLanguage;
|
|
179
|
+
/**
|
|
180
|
+
* `<code>` element 의 텍스트를 highlight 후 innerHTML 로 갱신. 셀렉션이
|
|
181
|
+
* code 안에 있다면 textContent offset 으로 caret 위치 보존.
|
|
182
|
+
*/
|
|
183
|
+
private rehighlightCode;
|
|
184
|
+
/**
|
|
185
|
+
* 본문에서 모든 codeBlock 을 순회하며 highlight 적용. setHTML / 초기 로드
|
|
186
|
+
* / 외부 import 후 호출.
|
|
187
|
+
*/
|
|
188
|
+
private rehighlightAllCodeBlocks;
|
|
189
|
+
/** 활성 셀의 열 전체 삭제. 마지막 열이면 보존(빈 표 회피). */
|
|
190
|
+
private deleteColumn;
|
|
191
|
+
/**
|
|
192
|
+
* 마우스 이동 시 셀 우/하 가장자리에서 col-resize / row-resize 커서 표시.
|
|
193
|
+
* 드래그 진행 중에는 별도 핸들러가 cursor 를 관리하므로 skip.
|
|
194
|
+
*/
|
|
195
|
+
private handleTableCursor;
|
|
196
|
+
private tableResize;
|
|
197
|
+
/**
|
|
198
|
+
* 셀 가장자리 / 이미지·유튜브 리사이즈 핸들 mousedown 진입점.
|
|
199
|
+
* - 셀: 우(col-resize) / 하(row-resize) 가장자리 6px 영역
|
|
200
|
+
* - 이미지·유튜브: 우하단 `.aw-resize-handle` element (corner resize)
|
|
201
|
+
*/
|
|
202
|
+
private handleTableResizeStart;
|
|
203
|
+
private handleTableResizeMove;
|
|
204
|
+
/**
|
|
205
|
+
* 이미지/유튜브 좌상단 정렬 컨트롤 클릭 핸들러. data-align 에 따라 wrapper
|
|
206
|
+
* 의 marginLeft / marginRight 를 조정 — left/center/right.
|
|
207
|
+
*/
|
|
208
|
+
private handleBlockAlignClick;
|
|
209
|
+
/**
|
|
210
|
+
* 이미지 / 유튜브 wrapper 의 너비를 드래그로 조정. 높이는 자동 (이미지는
|
|
211
|
+
* 종횡비 유지, 유튜브는 CSS aspect-ratio 16/9). mouseup 에서 cursor 복귀
|
|
212
|
+
* + flush.
|
|
213
|
+
*
|
|
214
|
+
* 너비는 본문 안쪽 폭을 상한으로 한다. 상한이 없으면 오른쪽으로 계속 끌 때
|
|
215
|
+
* wrapper 가 본문보다 넓어지고, 그만큼 에디터 전체가 가로로 늘어난다
|
|
216
|
+
* (드래그를 멈춰도 늘어난 상태가 남는다).
|
|
217
|
+
*/
|
|
218
|
+
private startBlockResize;
|
|
219
|
+
/**
|
|
220
|
+
* 본문의 padding 을 제외한 실제 컨텐츠 폭. 블록 리사이즈의 상한이다.
|
|
221
|
+
* 에디터가 아주 좁을 때도 최소 폭은 확보되도록 하한을 둔다.
|
|
222
|
+
*/
|
|
223
|
+
private contentInnerWidth;
|
|
224
|
+
private currentTheme;
|
|
225
|
+
/**
|
|
226
|
+
* 선택 영역에 글꼴을 적용한다.
|
|
227
|
+
* `styleWithCSS=true` 모드의 execCommand('fontName') 가 `<font face=…>` 대신
|
|
228
|
+
* `<span style="font-family: …">` 를 생성하도록 강제한다. selection 이
|
|
229
|
+
* 비어 있으면(캐럿만) 다음 입력 글꼴이 결정된다(브라우저 기본 동작).
|
|
230
|
+
*/
|
|
231
|
+
private applyFontFamily;
|
|
232
|
+
/**
|
|
233
|
+
* 현재 selection 의 anchor 노드 기준 computed font-family 를 읽어 알려진
|
|
234
|
+
* FONT_FAMILIES id 와 매칭. 글꼴 드롭다운의 active 표시에 사용.
|
|
235
|
+
*/
|
|
236
|
+
private detectActiveFontId;
|
|
237
|
+
/**
|
|
238
|
+
* 선택 영역에 글자 크기를 적용한다. execCommand('fontSize') 는 1~7 만 받기
|
|
239
|
+
* 때문에 px 적용을 위해 Range API 로 직접 `<span style="font-size: Xpx">`
|
|
240
|
+
* wrap 한다.
|
|
241
|
+
*
|
|
242
|
+
* **다중 셀 선택**(커스텀 마킹 또는 셀 경계를 넘는 browser range) 의 경우엔
|
|
243
|
+
* Range.extractContents 가 셀들을 묶어 한 셀 안에 끼워넣는 셀 중첩 버그가
|
|
244
|
+
* 있어 — 셀별로 `cell.style.fontSize` 를 직접 설정하는 안전한 경로를 사용.
|
|
245
|
+
*/
|
|
246
|
+
private applyFontSize;
|
|
247
|
+
/**
|
|
248
|
+
* 현재 selection 의 anchor 노드 기준 computed font-size 를 px 정수로 읽어
|
|
249
|
+
* FONT_SIZES 의 값과 일치할 때만 반환. 글자 크기 드롭다운의 active 표시에
|
|
250
|
+
* 사용.
|
|
251
|
+
*/
|
|
252
|
+
private detectActiveFontSize;
|
|
253
|
+
/**
|
|
254
|
+
* 블록 유형 드롭다운을 열어 사용자 선택 결과를 처리한다.
|
|
255
|
+
* 툴바의 blockType 버튼 / 활성 블록 라벨 pill 양쪽 진입점이 동일한 분기
|
|
256
|
+
* 로직(리치 블록 다이얼로그 분기 + targetId 보존) 을 공유한다.
|
|
257
|
+
*/
|
|
258
|
+
private openBlockTypeMenu;
|
|
259
|
+
/**
|
|
260
|
+
* 링크 다이얼로그를 열어 URL/텍스트를 받은 뒤 linkCard 블록으로 변환/추가.
|
|
261
|
+
* 표시 텍스트가 비어 있으면 URL 을 텍스트로 사용. `targetId` 가 있으면
|
|
262
|
+
* 그 id 의 블록을 정확히 변환 대상으로 삼는다.
|
|
263
|
+
*/
|
|
264
|
+
private openLinkDialogAndApply;
|
|
265
|
+
/**
|
|
266
|
+
* 이미지 다이얼로그(임베드/URL/업로드)를 열어 src 를 받은 뒤 image 블록으로
|
|
267
|
+
* 변환/추가.
|
|
268
|
+
*/
|
|
269
|
+
private openImageDialogAndApply;
|
|
270
|
+
/**
|
|
271
|
+
* 유튜브 다이얼로그를 열어 URL 을 받고, 영상 ID 를 추출해 youtube 블록으로
|
|
272
|
+
* 변환/추가. 잘못된 URL 이면 무시.
|
|
273
|
+
*/
|
|
274
|
+
private openYouTubeDialogAndApply;
|
|
275
|
+
/**
|
|
276
|
+
* HTML 가져오기 다이얼로그를 열어 사용자가 고른 HTML 을 iframe 으로 로드/
|
|
277
|
+
* 처리한 뒤 본문에 element 들을 삽입한다.
|
|
278
|
+
*
|
|
279
|
+
* - `targetId` 가 있으면 그 블록 바로 뒤에 삽입, 없으면 본문 끝에 append.
|
|
280
|
+
* - 삽입된 element 는 MutationObserver flush 가 새 data-block-id 를 발급.
|
|
281
|
+
*/
|
|
282
|
+
private openImportHtmlDialogAndApply;
|
|
283
|
+
/**
|
|
284
|
+
* Markdown 가져오기 다이얼로그를 열어 사용자가 입력한 markdown 을 파싱해
|
|
285
|
+
* 본문에 element 들을 삽입한다. importHtml 과 동일한 삽입 정책을 따른다.
|
|
286
|
+
*/
|
|
287
|
+
private openMarkdownImportDialogAndApply;
|
|
288
|
+
/**
|
|
289
|
+
* 파일 첨부 다이얼로그(URL/업로드)를 열어 src 를 받은 뒤 file 블록으로
|
|
290
|
+
* 변환/추가. src 가 비어 있으면 무시. 파일명이 없으면 URL 의 마지막
|
|
291
|
+
* segment 를 fallback 으로 사용.
|
|
292
|
+
*/
|
|
293
|
+
private openFileAttachmentDialogAndApply;
|
|
294
|
+
/**
|
|
295
|
+
* 파일 업로드 핸들러를 결정. onFileUpload 가 우선, 없으면 fileUploadUrl 에
|
|
296
|
+
* multipart/form-data POST 후 응답 JSON 의 `url` 필드를 사용. 둘 다 없으면
|
|
297
|
+
* undefined → 다이얼로그 업로드 탭 비활성.
|
|
298
|
+
*/
|
|
299
|
+
private resolveFileUploadFn;
|
|
300
|
+
/**
|
|
301
|
+
* 이미지 업로드 핸들러를 결정. options.onImageUpload 가 우선이며, 없으면
|
|
302
|
+
* options.imageUploadUrl 로 multipart/form-data POST 후 응답 JSON 의
|
|
303
|
+
* `url` 필드를 사용. 둘 다 없으면 undefined → 다이얼로그 업로드 탭 비활성.
|
|
304
|
+
*/
|
|
305
|
+
private resolveImageUploadFn;
|
|
306
|
+
/**
|
|
307
|
+
* `src` 의 이미지를 figure>img 블록으로 본문에 삽입.
|
|
308
|
+
* 활성 블록이 있으면 그 블록을 image 로 변환, 없으면 본문 끝에 추가.
|
|
309
|
+
*/
|
|
310
|
+
private insertImageBlock;
|
|
311
|
+
private queueSync;
|
|
312
|
+
private sync;
|
|
313
|
+
private handleKeyDown;
|
|
314
|
+
/**
|
|
315
|
+
* 활성 블록 뒤에 새 빈 단락을 만들고 캐럿을 그 안에 둔다.
|
|
316
|
+
* 인용구 / 코드 블록의 Enter 탈출 동작에 사용.
|
|
317
|
+
*/
|
|
318
|
+
private exitBlockOnEnter;
|
|
319
|
+
private syncBlockHandles;
|
|
320
|
+
private repositionHandles;
|
|
321
|
+
private positionHandle;
|
|
322
|
+
private createBlockHandle;
|
|
323
|
+
/**
|
|
324
|
+
* `blockId` 의 블록 뒤에 빈 단락을 삽입하고 캐럿을 그 단락으로 이동.
|
|
325
|
+
* MutationObserver flush 가 새 단락에 신규 data-block-id 를 발급한다.
|
|
326
|
+
*/
|
|
327
|
+
private insertParagraphAfter;
|
|
328
|
+
private handleDragOver;
|
|
329
|
+
private handleDrop;
|
|
330
|
+
private handleDragLeave;
|
|
331
|
+
private findDropTarget;
|
|
332
|
+
private showDropIndicator;
|
|
333
|
+
private hideDropIndicator;
|
|
334
|
+
/**
|
|
335
|
+
* 본문 블록들에 data-block-kind / data-block-label 을 갱신하고,
|
|
336
|
+
* 활성 블록에 data-block-focused 를 표기한다. CSS 가 이 속성을 읽어
|
|
337
|
+
* 포커스 인디케이터와 라벨 태그를 그린다.
|
|
338
|
+
*
|
|
339
|
+
* 자기 쓰기로 발생한 attributes 레코드는 takeRecords 로 흡수.
|
|
340
|
+
*/
|
|
341
|
+
/**
|
|
342
|
+
* 활성 블록 위쪽에 떠 있는 인터랙티브 라벨 pill 갱신.
|
|
343
|
+
* - 활성 블록이 없으면 숨김
|
|
344
|
+
* - 활성 블록의 라벨 텍스트로 갱신, 위치를 블록 상단에 맞춤
|
|
345
|
+
* - 클릭 시 openBlockTypeDropdown 가 열려 블록 유형을 즉시 변경 가능
|
|
346
|
+
*/
|
|
347
|
+
private syncBlockLabelPill;
|
|
348
|
+
/**
|
|
349
|
+
* 하단 Status Bar 갱신.
|
|
350
|
+
* - 좌측: 활성 블록 라벨 + id (없으면 — )
|
|
351
|
+
* - 우측: 총 블록 수, 본문 글자 수(공백 제외)
|
|
352
|
+
*/
|
|
353
|
+
private syncStatusBar;
|
|
354
|
+
private syncBlockMarkers;
|
|
355
|
+
private applyToolbarState;
|
|
356
|
+
}
|
|
357
|
+
// (소스맵은 CJS 선언 사본에서 제외됨 — scripts/finalize-types.mjs)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { HtmlStyleMode, SerializeHtmlOptions } from '../types/index.cjs';
|
|
2
|
+
import type { Block, BlockSnapshot } from './blocks.cjs';
|
|
3
|
+
export interface ViewerOptions {
|
|
4
|
+
/** 마운트할 호스트 element */
|
|
5
|
+
element: HTMLElement;
|
|
6
|
+
/** 초기 블록 상태 (1차 입력 경로). HTML 이 아닌 상태 모델을 사용. */
|
|
7
|
+
initialBlocks?: BlockSnapshot[];
|
|
8
|
+
/** 초기 테마 */
|
|
9
|
+
theme?: 'light' | 'dark';
|
|
10
|
+
/** `getHTML()` 의 스타일 전략. 기본 `'inline'`. */
|
|
11
|
+
htmlStyles?: HtmlStyleMode;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 편집 불가 모드의 읽기 전용 뷰어.
|
|
15
|
+
*
|
|
16
|
+
* 입력은 HTML 문자열이 아닌 BlockSnapshot 배열(상태 모델)이다.
|
|
17
|
+
* 각 snapshot 은 BlockType 레지스트리를 통해 새 element 로 렌더되며, 결과는
|
|
18
|
+
* AerizEditor 와 같은 `.aeriz-wysiwyg .aw-content` 트리에 들어가 동일한
|
|
19
|
+
* CSS 규칙(테마 변수 포함)이 그대로 적용된다.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const editor = new AerizEditor({ element: editorMount });
|
|
23
|
+
* const viewer = new AerizViewer({ element: viewerMount });
|
|
24
|
+
* editor.onStateChange(() => viewer.setBlocks(editor.serialize()));
|
|
25
|
+
*/
|
|
26
|
+
export declare class AerizViewer {
|
|
27
|
+
readonly root: HTMLDivElement;
|
|
28
|
+
readonly content: HTMLDivElement;
|
|
29
|
+
private readonly blockIds;
|
|
30
|
+
private readonly idFor;
|
|
31
|
+
/**
|
|
32
|
+
* 생성 시 받은 options 객체를 그대로 들고 있는다. `htmlStyles` 를 여기서
|
|
33
|
+
* 매번 다시 읽으므로, 호출자가 이 객체를 갱신하면 재생성 없이 출력 전략이
|
|
34
|
+
* 바뀐다 (AerizEditor 와 같은 규약).
|
|
35
|
+
*/
|
|
36
|
+
private readonly options;
|
|
37
|
+
private destroyed;
|
|
38
|
+
constructor(options: ViewerOptions);
|
|
39
|
+
/**
|
|
40
|
+
* BlockSnapshot 배열로부터 본문을 다시 렌더한다.
|
|
41
|
+
* 동일한 BlockType 레지스트리로 element 를 만들어 채우므로 외부 HTML 파싱
|
|
42
|
+
* 경로를 거치지 않는다.
|
|
43
|
+
*/
|
|
44
|
+
setBlocks(blocks: BlockSnapshot[]): void;
|
|
45
|
+
/** 현재 본문의 BlockSnapshot 배열을 반환한다. */
|
|
46
|
+
getBlocks(): BlockSnapshot[];
|
|
47
|
+
/** 임의의 노드를 받아 그 노드가 속한 블록을 반환한다. 본문 밖이면 null. */
|
|
48
|
+
getBlockOf(node: Node): Block | null;
|
|
49
|
+
/**
|
|
50
|
+
* 본문 HTML 을 반환한다. 전략은 `AerizEditor.getHTML()` 과 동일하다.
|
|
51
|
+
*
|
|
52
|
+
* - `'inline'` (기본) — 외부 컨텍스트(이메일, 다른 페이지의 HTML 영역 등)
|
|
53
|
+
* 에서도 동일한 시각으로 보이도록 portable 인라인 스타일을 베이크한다.
|
|
54
|
+
* - `'class'` — 클래스만 남긴다. `style` 속성을 지우는 sanitizer 대응.
|
|
55
|
+
*/
|
|
56
|
+
getHTML(options?: SerializeHtmlOptions): string;
|
|
57
|
+
setTheme(theme: 'light' | 'dark'): void;
|
|
58
|
+
destroy(): void;
|
|
59
|
+
private listBlocksInternal;
|
|
60
|
+
}
|
|
61
|
+
// (소스맵은 CJS 선언 사본에서 제외됨 — scripts/finalize-types.mjs)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 블록 렌더링에 쓰이는 순수 헬퍼와 상수.
|
|
3
|
+
*
|
|
4
|
+
* DOM 을 참조하지 않는다. 브라우저 렌더 경로(`blocks.ts`) 와 DOM 없는 문자열
|
|
5
|
+
* 렌더 경로(`render-string.ts`) 가 **같은** 값을 쓰도록 여기 한 곳에 둔다.
|
|
6
|
+
* 두 경로가 갈라지면 서버 재렌더 결과와 에디터 출력이 미묘하게 달라지므로,
|
|
7
|
+
* 양쪽이 공유해야 하는 것은 반드시 이 모듈로 올린다.
|
|
8
|
+
*/
|
|
9
|
+
/** 바이트 수를 사람이 읽는 크기 문자열로. */
|
|
10
|
+
export declare function formatBytes(bytes: number): string;
|
|
11
|
+
/** 표시용 짧은 타입 라벨. 파일명 확장자 우선, 없으면 MIME subtype. */
|
|
12
|
+
export declare function fileExtensionLabel(name?: string, mime?: string): string;
|
|
13
|
+
/** URL 의 hostname (subdomain 포함) 만 추출. 실패 시 빈 문자열. */
|
|
14
|
+
export declare function hostnameFromUrl(url: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Google 의 무료 favicon 서비스 URL 을 반환. CORS / 인증 불필요. URL 파싱
|
|
17
|
+
* 실패 시 빈 문자열.
|
|
18
|
+
*/
|
|
19
|
+
export declare function defaultFaviconUrl(url: string): string;
|
|
20
|
+
/** 파일 첨부 카드 좌측 문서 아이콘. */
|
|
21
|
+
export declare const FILE_ICON_SVG: string;
|
|
22
|
+
/** 파일 첨부 카드 우측 다운로드 아이콘. */
|
|
23
|
+
export declare const FILE_ACTION_SVG: string;
|
|
24
|
+
/** 유튜브 iframe 의 `allow` 목록. */
|
|
25
|
+
export declare const YOUTUBE_IFRAME_ALLOW = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture";
|
|
26
|
+
/** 유튜브 임베드 base URL. 쿠키를 덜 쓰는 nocookie 도메인을 사용한다. */
|
|
27
|
+
export declare const YOUTUBE_EMBED_BASE = "https://www.youtube-nocookie.com/embed/";
|
|
28
|
+
/** 파일명이 없는 첨부의 기본 표시 이름. */
|
|
29
|
+
export declare const FILE_FALLBACK_NAME = "\uD30C\uC77C";
|
|
30
|
+
/** 블록의 안정 식별자를 담는 속성명. */
|
|
31
|
+
export declare const BLOCK_ID_ATTR = "data-block-id";
|
|
32
|
+
// (소스맵은 CJS 선언 사본에서 제외됨 — scripts/finalize-types.mjs)
|