@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.
Files changed (108) hide show
  1. package/README.md +610 -96
  2. package/angular/README.md +112 -0
  3. package/angular/aeriz-editor.directive.ts +243 -0
  4. package/angular/aeriz-wysiwyg.module.ts +14 -0
  5. package/angular/index.ts +5 -0
  6. package/dist/adapters/jquery.cjs +1 -0
  7. package/dist/adapters/jquery.js +91 -0
  8. package/dist/adapters/react.cjs +1 -0
  9. package/dist/adapters/react.js +66 -0
  10. package/dist/adapters/shared.cjs +1 -0
  11. package/dist/adapters/shared.js +87 -0
  12. package/dist/adapters/svelte.cjs +1 -0
  13. package/dist/adapters/svelte.js +29 -0
  14. package/dist/adapters/vue.cjs +1 -0
  15. package/dist/adapters/vue.js +110 -0
  16. package/dist/adapters/vue2.cjs +1 -0
  17. package/dist/adapters/vue2.js +117 -0
  18. package/dist/adapters/wc.cjs +1 -0
  19. package/dist/adapters/wc.js +207 -0
  20. package/dist/aeriz-wysiwyg-adapter.js +169 -0
  21. package/dist/aeriz-wysiwyg-adapter.min.js +1 -0
  22. package/dist/aeriz-wysiwyg-jquery.js +275 -0
  23. package/dist/aeriz-wysiwyg-jquery.min.js +1 -0
  24. package/dist/aeriz-wysiwyg-wc.js +401 -0
  25. package/dist/aeriz-wysiwyg-wc.min.js +1 -0
  26. package/dist/aeriz-wysiwyg.cjs +6912 -0
  27. package/dist/aeriz-wysiwyg.css +37 -129
  28. package/dist/aeriz-wysiwyg.esm.js +1170 -149
  29. package/dist/aeriz-wysiwyg.esm.min.js +2057 -1209
  30. package/dist/aeriz-wysiwyg.js +1169 -148
  31. package/dist/aeriz-wysiwyg.min.cjs +54 -0
  32. package/dist/aeriz-wysiwyg.min.css +1 -1
  33. package/dist/aeriz-wysiwyg.min.js +44 -13
  34. package/dist/server.cjs +32 -0
  35. package/dist/server.js +666 -0
  36. package/dist-types/adapters/jquery.d.ts +34 -0
  37. package/dist-types/adapters/jquery.d.ts.map +1 -0
  38. package/dist-types/adapters/react.d.ts +28 -0
  39. package/dist-types/adapters/react.d.ts.map +1 -0
  40. package/dist-types/adapters/shared.d.ts +83 -0
  41. package/dist-types/adapters/shared.d.ts.map +1 -0
  42. package/dist-types/adapters/svelte.d.ts +38 -0
  43. package/dist-types/adapters/svelte.d.ts.map +1 -0
  44. package/dist-types/adapters/vue.d.ts +189 -0
  45. package/dist-types/adapters/vue.d.ts.map +1 -0
  46. package/dist-types/adapters/vue2.d.ts +175 -0
  47. package/dist-types/adapters/vue2.d.ts.map +1 -0
  48. package/dist-types/adapters/wc.d.ts +96 -0
  49. package/dist-types/adapters/wc.d.ts.map +1 -0
  50. package/dist-types/cjs/adapters/jquery.d.cts +34 -0
  51. package/dist-types/cjs/adapters/react.d.cts +28 -0
  52. package/dist-types/cjs/adapters/shared.d.cts +83 -0
  53. package/dist-types/cjs/adapters/svelte.d.cts +38 -0
  54. package/dist-types/cjs/adapters/vue.d.cts +189 -0
  55. package/dist-types/cjs/adapters/vue2.d.cts +175 -0
  56. package/dist-types/cjs/adapters/wc.d.cts +96 -0
  57. package/dist-types/cjs/core/AerizEditor.d.cts +357 -0
  58. package/dist-types/cjs/core/AerizViewer.d.cts +61 -0
  59. package/dist-types/cjs/core/block-meta.d.cts +32 -0
  60. package/dist-types/cjs/core/blocks.d.cts +368 -0
  61. package/dist-types/cjs/core/fonts.d.cts +60 -0
  62. package/dist-types/cjs/core/highlight.d.cts +44 -0
  63. package/dist-types/cjs/core/html-mini.d.cts +65 -0
  64. package/dist-types/cjs/core/i18n.d.cts +209 -0
  65. package/dist-types/cjs/core/import-html.d.cts +39 -0
  66. package/dist-types/cjs/core/import-markdown.d.cts +37 -0
  67. package/dist-types/cjs/core/markdown-export.d.cts +30 -0
  68. package/dist-types/cjs/core/plain-text.d.cts +17 -0
  69. package/dist-types/cjs/core/render-string.d.cts +68 -0
  70. package/dist-types/cjs/core/snapshot.d.cts +51 -0
  71. package/dist-types/cjs/index.d.cts +20 -0
  72. package/dist-types/cjs/server/index.d.cts +37 -0
  73. package/dist-types/cjs/types/index.d.cts +61 -0
  74. package/dist-types/cjs/ui/Toolbar.d.cts +21 -0
  75. package/dist-types/cjs/ui/dialogs.d.cts +74 -0
  76. package/dist-types/cjs/ui/icons.d.cts +2 -0
  77. package/dist-types/cjs/ui/popovers.d.cts +70 -0
  78. package/dist-types/core/AerizEditor.d.ts +30 -10
  79. package/dist-types/core/AerizEditor.d.ts.map +1 -1
  80. package/dist-types/core/AerizViewer.d.ts +16 -4
  81. package/dist-types/core/AerizViewer.d.ts.map +1 -1
  82. package/dist-types/core/block-meta.d.ts +32 -0
  83. package/dist-types/core/block-meta.d.ts.map +1 -0
  84. package/dist-types/core/blocks.d.ts +62 -7
  85. package/dist-types/core/blocks.d.ts.map +1 -1
  86. package/dist-types/core/fonts.d.ts +11 -0
  87. package/dist-types/core/fonts.d.ts.map +1 -1
  88. package/dist-types/core/html-mini.d.ts +65 -0
  89. package/dist-types/core/html-mini.d.ts.map +1 -0
  90. package/dist-types/core/import-html.d.ts.map +1 -1
  91. package/dist-types/core/markdown-export.d.ts +30 -0
  92. package/dist-types/core/markdown-export.d.ts.map +1 -0
  93. package/dist-types/core/plain-text.d.ts +17 -0
  94. package/dist-types/core/plain-text.d.ts.map +1 -0
  95. package/dist-types/core/render-string.d.ts +68 -0
  96. package/dist-types/core/render-string.d.ts.map +1 -0
  97. package/dist-types/core/snapshot.d.ts +51 -0
  98. package/dist-types/core/snapshot.d.ts.map +1 -0
  99. package/dist-types/index.d.ts +19 -10
  100. package/dist-types/index.d.ts.map +1 -1
  101. package/dist-types/server/index.d.ts +37 -0
  102. package/dist-types/server/index.d.ts.map +1 -0
  103. package/dist-types/types/index.d.ts +21 -0
  104. package/dist-types/types/index.d.ts.map +1 -1
  105. package/dist-types/ui/Toolbar.d.ts +1 -1
  106. package/dist-types/ui/popovers.d.ts +1 -1
  107. package/dist-types/ui/popovers.d.ts.map +1 -1
  108. package/package.json +213 -58
@@ -42,7 +42,6 @@
42
42
  --aw-primary-hover: #8ad6ff;
43
43
  --aw-divider: rgba(100, 200, 255, 0.12);
44
44
  }
45
-
46
45
  .aeriz-wysiwyg {
47
46
  font-family: var(--aw-font);
48
47
  background-color: var(--aw-bg);
@@ -78,18 +77,15 @@
78
77
  /* ─── 뷰어 모드 ─────────────────────────────────────────────────────
79
78
  AerizViewer 는 컨텐츠 길이만큼 자연스럽게 늘어난다 (스크롤 / 고정 높이 X).
80
79
  에디터 기본 규칙을 viewer 클래스가 좁게 덮어쓴다. */
81
-
82
80
  .aeriz-wysiwyg-viewer {
83
81
  height: auto;
84
82
  min-height: 0;
85
83
  }
86
-
87
84
  .aeriz-wysiwyg-viewer .aw-content-wrap {
88
85
  flex: 0 0 auto;
89
86
  overflow: visible;
90
87
  min-height: 0;
91
88
  }
92
-
93
89
  .aeriz-wysiwyg-viewer .aw-content {
94
90
  min-height: 0;
95
91
  }
@@ -100,17 +96,16 @@
100
96
  position: absolute;
101
97
  top: 0;
102
98
  left: 0;
103
- width: 24px;
99
+ width: 20px;
104
100
  height: 100%;
105
101
  pointer-events: none;
106
102
  z-index: 2;
107
103
  }
108
104
 
109
105
  /* 블록별 컨트롤 그룹 — 드래그 핸들 + 단락 추가 버튼을 세로로 묶는다. */
110
-
111
106
  .aw-block-controls {
112
107
  position: absolute;
113
- left: 4px;
108
+ left: 3px;
114
109
  display: flex;
115
110
  flex-direction: column;
116
111
  gap: 0;
@@ -118,19 +113,19 @@
118
113
  opacity: 0;
119
114
  transition: opacity 0.12s ease;
120
115
  }
121
-
122
116
  .aw-content-wrap:hover .aw-block-controls {
123
117
  opacity: 0.45;
124
118
  }
125
-
126
119
  .aw-block-controls:hover {
127
120
  opacity: 1;
128
121
  }
129
122
 
123
+ /* 높이는 AerizEditor.positionHandle 의 HANDLE_HEIGHT 와 짝을 이룬다 —
124
+ 한쪽만 바꾸면 짧은 블록(hr) 위에서 핸들의 수직 정렬이 어긋난다. */
130
125
  .aw-block-handle,
131
126
  .aw-block-add {
132
- width: 18px;
133
- height: 22px;
127
+ width: 14px;
128
+ height: 18px;
134
129
  display: inline-flex;
135
130
  align-items: center;
136
131
  justify-content: center;
@@ -145,13 +140,12 @@
145
140
  cursor: pointer;
146
141
  transition: color 0.12s, background-color 0.12s, border-color 0.12s;
147
142
  }
148
-
149
143
  .aw-block-handle { cursor: grab; }
150
144
 
151
145
  .aw-block-handle svg,
152
146
  .aw-block-add svg {
153
- width: 12px;
154
- height: 14px;
147
+ width: 10px;
148
+ height: 11px;
155
149
  }
156
150
 
157
151
  .aw-block-handle:hover,
@@ -232,7 +226,6 @@
232
226
  }
233
227
 
234
228
  /* status bar 안의 작은 아이콘 액션 버튼 (undo/redo 등) */
235
-
236
229
  .aw-status-action {
237
230
  appearance: none;
238
231
  cursor: pointer;
@@ -249,18 +242,15 @@
249
242
  flex-shrink: 0;
250
243
  transition: color 0.12s, background-color 0.12s, border-color 0.12s;
251
244
  }
252
-
253
245
  .aw-status-action svg {
254
246
  width: 13px;
255
247
  height: 13px;
256
248
  }
257
-
258
249
  .aw-status-action:hover {
259
250
  color: var(--aw-btn-active-fg, var(--aw-primary));
260
251
  background-color: var(--aw-btn-hover-bg);
261
252
  border-color: var(--aw-border);
262
253
  }
263
-
264
254
  .aw-status-action:active {
265
255
  background-color: var(--aw-btn-active-bg);
266
256
  }
@@ -285,7 +275,6 @@
285
275
  /* ─── 인터랙티브 블록 라벨 pill ───────────────────────────────────────
286
276
  활성 블록 위에 떠 있는 작은 버튼. 정적 ::before pseudo 라벨을 대체하며
287
277
  클릭 시 블록 유형 드롭다운을 열어 마이크로 인터랙션으로 유형 변경. */
288
-
289
278
  .aw-block-label-pill {
290
279
  position: absolute;
291
280
  z-index: 4;
@@ -309,20 +298,17 @@
309
298
  transition: transform 0.12s ease, background-color 0.12s, color 0.12s,
310
299
  box-shadow 0.12s;
311
300
  }
312
-
313
301
  .aw-block-label-pill::after {
314
302
  content: '▾';
315
303
  font-size: 9px;
316
304
  opacity: 0.7;
317
305
  }
318
-
319
306
  .aw-block-label-pill:hover {
320
307
  background: var(--aw-primary);
321
308
  color: var(--aw-bg);
322
309
  transform: translateY(-1px);
323
310
  box-shadow: 0 2px 6px color-mix(in srgb, var(--aw-primary) 35%, transparent);
324
311
  }
325
-
326
312
  .aw-block-label-pill:active {
327
313
  transform: translateY(0);
328
314
  }
@@ -348,11 +334,26 @@
348
334
  .aw-content > p {
349
335
  margin: 0 0 0.8em 0;
350
336
  }
351
-
352
337
  .aw-content > p:last-child {
353
338
  margin-bottom: 0;
354
339
  }
355
340
 
341
+ /* 정렬 클래스 — getHTML({ styles: 'class' }) 출력이 style="text-align:…" 대신
342
+ 사용한다. style 속성을 제거하는 서버 sanitizer 를 통과해도 정렬이 남는다.
343
+ 에디터 자체는 계속 인라인 style 로 정렬하므로 편집 중 동작에는 영향이 없다. */
344
+ .aw-content .aw-align-left {
345
+ text-align: left;
346
+ }
347
+ .aw-content .aw-align-center {
348
+ text-align: center;
349
+ }
350
+ .aw-content .aw-align-right {
351
+ text-align: right;
352
+ }
353
+ .aw-content .aw-align-justify {
354
+ text-align: justify;
355
+ }
356
+
356
357
  .aw-content h1,
357
358
  .aw-content h2,
358
359
  .aw-content h3 {
@@ -361,11 +362,8 @@
361
362
  padding-bottom: 0.25em;
362
363
  border-bottom: 1px solid var(--aw-border);
363
364
  }
364
-
365
365
  .aw-content h1 { font-size: 1.875rem; line-height: 1.3; }
366
-
367
366
  .aw-content h2 { font-size: 1.5rem; line-height: 1.35; }
368
-
369
367
  .aw-content h3 { font-size: 1.25rem; line-height: 1.4; }
370
368
 
371
369
  .aw-content blockquote {
@@ -393,7 +391,6 @@
393
391
  /* 코드 블록 우상단의 언어 라벨 — `<code data-language="javascript">` 의
394
392
  * data-language 가 있을 때만 표시. attr() 로 자동 동기화돼 별도 JS 갱신
395
393
  * 불필요. 사용자가 드롭다운으로 언어 변경 시 CSS 가 즉시 반영. */
396
-
397
394
  .aw-content > pre > code[data-language]:not([data-language=""])::before {
398
395
  content: attr(data-language);
399
396
  position: absolute;
@@ -418,48 +415,30 @@
418
415
  padding: 0.15em 0.4em;
419
416
  border-radius: 3px;
420
417
  }
421
-
422
418
  .aw-content pre code {
423
419
  background: transparent;
424
420
  padding: 0;
425
421
  }
426
422
 
427
423
  /* ─── Syntax highlight 토큰 색 (자체 highlight.ts 출력) ──────────── */
428
-
429
424
  .aw-content pre code .hl-keyword { color: #c678dd; font-weight: 600; }
430
-
431
425
  .aw-content pre code .hl-string { color: #98c379; }
432
-
433
426
  .aw-content pre code .hl-number { color: #d19a66; }
434
-
435
427
  .aw-content pre code .hl-comment { color: var(--aw-fg-muted); font-style: italic; }
436
-
437
428
  .aw-content pre code .hl-fn { color: #61afef; }
438
-
439
429
  .aw-content pre code .hl-builtin { color: #56b6c2; }
440
-
441
430
  .aw-content pre code .hl-tag { color: #e06c75; }
442
-
443
431
  .aw-content pre code .hl-attr { color: #d19a66; }
444
-
445
432
  .aw-content pre code .hl-prop { color: #61afef; }
446
-
447
433
  .aw-content pre code .hl-punct { color: var(--aw-fg-muted); }
448
434
 
449
435
  /* light 테마 보정 */
450
-
451
436
  .aeriz-wysiwyg[data-theme='light'] .aw-content pre code .hl-keyword { color: #a626a4; }
452
-
453
437
  .aeriz-wysiwyg[data-theme='light'] .aw-content pre code .hl-string { color: #50a14f; }
454
-
455
438
  .aeriz-wysiwyg[data-theme='light'] .aw-content pre code .hl-number { color: #986801; }
456
-
457
439
  .aeriz-wysiwyg[data-theme='light'] .aw-content pre code .hl-fn { color: #4078f2; }
458
-
459
440
  .aeriz-wysiwyg[data-theme='light'] .aw-content pre code .hl-builtin { color: #0184bc; }
460
-
461
441
  .aeriz-wysiwyg[data-theme='light'] .aw-content pre code .hl-tag { color: #e45649; }
462
-
463
442
  .aeriz-wysiwyg[data-theme='light'] .aw-content pre code .hl-prop { color: #4078f2; }
464
443
 
465
444
  .aw-content ul,
@@ -491,7 +470,6 @@
491
470
  }
492
471
 
493
472
  /* ─── 유튜브 임베드 (16:9 반응형 컨테이너) ──────────────────── */
494
-
495
473
  .aw-content > div.aw-youtube-embed {
496
474
  position: relative;
497
475
  width: 100%;
@@ -502,7 +480,6 @@
502
480
  background: #000;
503
481
  border: 1px solid var(--aw-border);
504
482
  }
505
-
506
483
  .aw-content > div.aw-youtube-embed iframe {
507
484
  position: absolute;
508
485
  inset: 0;
@@ -513,7 +490,6 @@
513
490
  }
514
491
 
515
492
  /* ─── 파일 첨부 (다운로드 카드) ──────────────────── */
516
-
517
493
  .aw-content > a.aw-file-attachment {
518
494
  display: flex;
519
495
  align-items: center;
@@ -529,12 +505,10 @@
529
505
  cursor: pointer;
530
506
  user-select: none;
531
507
  }
532
-
533
508
  .aw-content > a.aw-file-attachment:hover {
534
509
  background: color-mix(in srgb, var(--aw-fg) 5%, var(--aw-bg));
535
510
  border-color: color-mix(in srgb, var(--aw-primary) 40%, var(--aw-border));
536
511
  }
537
-
538
512
  .aw-content > a.aw-file-attachment .aw-file-icon {
539
513
  flex: 0 0 auto;
540
514
  display: inline-flex;
@@ -546,12 +520,10 @@
546
520
  background: color-mix(in srgb, var(--aw-primary) 12%, transparent);
547
521
  color: var(--aw-primary);
548
522
  }
549
-
550
523
  .aw-content > a.aw-file-attachment .aw-file-icon svg {
551
524
  width: 20px;
552
525
  height: 20px;
553
526
  }
554
-
555
527
  .aw-content > a.aw-file-attachment .aw-file-meta {
556
528
  flex: 1 1 auto;
557
529
  min-width: 0;
@@ -559,7 +531,6 @@
559
531
  flex-direction: column;
560
532
  gap: 2px;
561
533
  }
562
-
563
534
  .aw-content > a.aw-file-attachment .aw-file-name {
564
535
  font-weight: 600;
565
536
  font-size: 0.95rem;
@@ -567,14 +538,12 @@
567
538
  word-break: break-all;
568
539
  line-height: 1.3;
569
540
  }
570
-
571
541
  .aw-content > a.aw-file-attachment .aw-file-info {
572
542
  font-size: 0.75rem;
573
543
  color: var(--aw-fg-muted);
574
544
  font-family: var(--aw-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
575
545
  letter-spacing: 0.02em;
576
546
  }
577
-
578
547
  .aw-content > a.aw-file-attachment .aw-file-action {
579
548
  flex: 0 0 auto;
580
549
  display: inline-flex;
@@ -584,18 +553,15 @@
584
553
  justify-content: center;
585
554
  color: var(--aw-fg-muted);
586
555
  }
587
-
588
556
  .aw-content > a.aw-file-attachment .aw-file-action svg {
589
557
  width: 18px;
590
558
  height: 18px;
591
559
  }
592
-
593
560
  .aw-content > a.aw-file-attachment:hover .aw-file-action {
594
561
  color: var(--aw-primary);
595
562
  }
596
563
 
597
564
  /* ─── 링크 카드 (Open Graph 스타일 미리보기) ──────────────────── */
598
-
599
565
  .aw-content > a.aw-link-card {
600
566
  display: flex;
601
567
  align-items: stretch;
@@ -610,14 +576,12 @@
610
576
  overflow: hidden;
611
577
  transition: border-color 0.12s, background-color 0.12s;
612
578
  }
613
-
614
579
  .aw-content > a.aw-link-card:hover {
615
580
  border-color: var(--aw-primary);
616
581
  background-color: color-mix(in srgb, var(--aw-primary) 9%, var(--aw-bg));
617
582
  }
618
583
 
619
584
  /* 좌측 og:image 썸네일 — 있을 때만. */
620
-
621
585
  .aw-content > a.aw-link-card > .aw-link-card-image {
622
586
  flex: 0 0 auto;
623
587
  width: 120px;
@@ -628,7 +592,6 @@
628
592
  }
629
593
 
630
594
  /* 우측 본문 — title / desc / url 행. */
631
-
632
595
  .aw-content > a.aw-link-card > .aw-link-card-body {
633
596
  flex: 1 1 auto;
634
597
  min-width: 0;
@@ -637,7 +600,6 @@
637
600
  gap: 4px;
638
601
  padding: 12px 14px;
639
602
  }
640
-
641
603
  .aw-content > a.aw-link-card .aw-link-card-title {
642
604
  font-weight: 600;
643
605
  font-size: 1rem;
@@ -648,7 +610,6 @@
648
610
  -webkit-box-orient: vertical;
649
611
  overflow: hidden;
650
612
  }
651
-
652
613
  .aw-content > a.aw-link-card .aw-link-card-desc {
653
614
  font-size: 0.85rem;
654
615
  line-height: 1.4;
@@ -658,7 +619,6 @@
658
619
  -webkit-box-orient: vertical;
659
620
  overflow: hidden;
660
621
  }
661
-
662
622
  .aw-content > a.aw-link-card .aw-link-card-url {
663
623
  display: flex;
664
624
  align-items: center;
@@ -669,7 +629,6 @@
669
629
  font-family: var(--aw-font-mono);
670
630
  word-break: break-all;
671
631
  }
672
-
673
632
  .aw-content > a.aw-link-card .aw-link-card-favicon {
674
633
  flex: 0 0 auto;
675
634
  width: 14px;
@@ -677,7 +636,6 @@
677
636
  border-radius: 2px;
678
637
  background: transparent;
679
638
  }
680
-
681
639
  .aw-content > a.aw-link-card .aw-link-card-url-text {
682
640
  flex: 1 1 auto;
683
641
  min-width: 0;
@@ -691,7 +649,6 @@
691
649
  width: 100%;
692
650
  margin: 1em 0;
693
651
  }
694
-
695
652
  .aw-content table td,
696
653
  .aw-content table th {
697
654
  border: 1px solid var(--aw-border);
@@ -701,35 +658,43 @@
701
658
  /* td/th 의 inline background-color 가 overflow 자식에 가려지지 않도록 */
702
659
  background-clip: padding-box;
703
660
  }
704
-
705
661
  .aw-content table th {
706
662
  background-color: color-mix(in srgb, var(--aw-fg) 5%, var(--aw-bg));
707
663
  font-weight: 600;
708
664
  }
709
665
 
710
666
  /* 커스텀 드래그-셀렉션으로 마킹된 표 셀 — 다중 선택 시각 강조. */
711
-
712
667
  .aw-content table td.aw-cell-selected,
713
668
  .aw-content table th.aw-cell-selected {
714
669
  outline: 2px solid var(--aw-primary);
715
670
  outline-offset: -2px;
716
671
  background-color: color-mix(in srgb, var(--aw-primary) 18%, transparent) !important;
717
672
  }
718
-
719
673
  .aeriz-wysiwyg-viewer .aw-cell-selected {
720
674
  outline: none;
721
675
  background-color: revert !important;
722
676
  }
723
677
 
724
678
  /* ─── 리사이즈 핸들 + 정렬 컨트롤 (이미지·유튜브) ──────────────────── */
725
-
726
679
  .aw-content > figure,
727
680
  .aw-content > div.aw-youtube-embed {
728
681
  position: relative;
682
+ /* 인라인 width 가 본문보다 커도 넘치지 않게 막는다. 드래그 리사이즈는
683
+ JS 에서 본문 폭으로 상한을 두지만, 외부에서 들어온 값(HTML 가져오기,
684
+ 예전에 더 넓은 화면에서 저장된 스냅샷)까지 막아 주는 건 이 규칙이다.
685
+ 이게 없으면 본문이 가로로 넓어지면서 에디터 전체가 늘어난다. */
686
+ max-width: 100%;
729
687
  }
730
688
 
731
- /* 좌상단 정렬 컨트롤 — 좌/중/우 3 버튼. hover 시 fade-in. */
689
+ /* figure 의 좌우 여백을 0 으로 명시한다.
690
+ 브라우저 UA 기본값은 `figure { margin: 1em 40px }` 인데, getHTML() 이
691
+ 베이크하는 portable 스타일은 `margin: 1em 0` 이다. 그대로 두면 에디터에서는
692
+ 80px 좁게 보이고 내보낸 HTML 에서는 넓게 보이는 WYSIWYG 불일치가 생긴다. */
693
+ .aw-content > figure {
694
+ margin: 1em 0;
695
+ }
732
696
 
697
+ /* 좌상단 정렬 컨트롤 — 좌/중/우 3 버튼. hover 시 fade-in. */
733
698
  .aw-block-align-controls {
734
699
  position: absolute;
735
700
  top: 6px;
@@ -744,13 +709,11 @@
744
709
  transition: opacity 0.12s;
745
710
  user-select: none;
746
711
  }
747
-
748
712
  .aw-content > figure:hover .aw-block-align-controls,
749
713
  .aw-content > div.aw-youtube-embed:hover .aw-block-align-controls,
750
714
  .aw-resizing .aw-block-align-controls {
751
715
  opacity: 1;
752
716
  }
753
-
754
717
  .aw-block-align-btn {
755
718
  width: 22px;
756
719
  height: 22px;
@@ -764,16 +727,13 @@
764
727
  border-radius: 3px;
765
728
  padding: 0;
766
729
  }
767
-
768
730
  .aw-block-align-btn:hover {
769
731
  background: rgba(255, 255, 255, 0.18);
770
732
  }
771
-
772
733
  .aw-block-align-btn svg {
773
734
  width: 14px;
774
735
  height: 14px;
775
736
  }
776
-
777
737
  .aw-resize-handle {
778
738
  position: absolute;
779
739
  right: -1px;
@@ -789,13 +749,11 @@
789
749
  opacity: 0;
790
750
  transition: opacity 0.12s, transform 0.08s;
791
751
  }
792
-
793
752
  .aw-content > figure:hover .aw-resize-handle,
794
753
  .aw-content > div.aw-youtube-embed:hover .aw-resize-handle,
795
754
  .aw-resizing .aw-resize-handle {
796
755
  opacity: 1;
797
756
  }
798
-
799
757
  .aw-resize-handle:hover {
800
758
  transform: scale(1.15);
801
759
  }
@@ -803,24 +761,20 @@
803
761
  /* 유튜브 임베드는 iframe 안에 자체 워터마크/컨트롤이 있어 코너에 핸들을 두면
804
762
  * 클릭이 충돌한다. embed 안쪽 우하단에 약간 들여서 배치 — YouTube 자체 UI
805
763
  * 영역과 약간 떨어진 위치. */
806
-
807
764
  .aw-content > div.aw-youtube-embed > .aw-resize-handle {
808
765
  right: 0px;
809
766
  bottom: -15px;
810
767
  }
811
-
812
768
  .aw-resizing {
813
769
  user-select: none;
814
770
  }
815
771
 
816
772
  /* 뷰어(읽기 전용) 모드에서는 편집용 컨트롤(리사이즈 핸들 / 정렬 컨트롤) 을
817
773
  * 모두 숨긴다. AerizViewer.root 의 className 'aeriz-wysiwyg-viewer' 를 타겟. */
818
-
819
774
  .aeriz-wysiwyg-viewer .aw-resize-handle,
820
775
  .aeriz-wysiwyg-viewer .aw-block-align-controls {
821
776
  display: none !important;
822
777
  }
823
-
824
778
  .aw-toolbar {
825
779
  display: flex;
826
780
  align-items: center;
@@ -910,7 +864,6 @@
910
864
  width: 100%;
911
865
  height: 100%;
912
866
  }
913
-
914
867
  /*
915
868
  * Dialog / popover 는 .aeriz-wysiwyg 의 자식이 아닌 document.body 에 attach
916
869
  * 되므로 에디터의 CSS 변수를 직접 받지 못한다. 대신 자기 자신에
@@ -1015,9 +968,7 @@
1015
968
  color: var(--d-fg-muted);
1016
969
  transition: background-color 0.12s, color 0.12s;
1017
970
  }
1018
-
1019
971
  .aw-dialog-close:hover { background-color: var(--d-hover-bg); color: var(--d-fg); }
1020
-
1021
972
  .aw-dialog-close svg { width: 18px; height: 18px; }
1022
973
 
1023
974
  .aw-dialog-body {
@@ -1034,7 +985,6 @@
1034
985
  }
1035
986
 
1036
987
  .aw-field { display: flex; flex-direction: column; gap: 6px; }
1037
-
1038
988
  .aw-field-label { font-size: 13px; font-weight: 600; color: var(--d-fg); }
1039
989
 
1040
990
  .aw-input {
@@ -1049,7 +999,6 @@
1049
999
  color: var(--d-input-fg);
1050
1000
  background-color: var(--d-input-bg);
1051
1001
  }
1052
-
1053
1002
  .aw-input:focus {
1054
1003
  border-color: var(--d-primary);
1055
1004
  box-shadow: 0 0 0 3px var(--d-primary-soft);
@@ -1069,7 +1018,6 @@
1069
1018
  color: var(--d-fg);
1070
1019
  cursor: pointer; user-select: none;
1071
1020
  }
1072
-
1073
1021
  .aw-checkbox input { width: 16px; height: 16px; accent-color: var(--d-primary); }
1074
1022
 
1075
1023
  .aw-btn {
@@ -1082,17 +1030,13 @@
1082
1030
  font-family: inherit;
1083
1031
  transition: background-color 0.12s, border-color 0.12s, color 0.12s;
1084
1032
  }
1085
-
1086
1033
  .aw-btn-primary { background-color: var(--d-primary); color: var(--d-on-primary); }
1087
-
1088
1034
  .aw-btn-primary:hover { background-color: var(--d-primary-hover); }
1089
-
1090
1035
  .aw-btn-ghost {
1091
1036
  background-color: transparent;
1092
1037
  color: var(--d-fg);
1093
1038
  border-color: var(--d-border-strong);
1094
1039
  }
1095
-
1096
1040
  .aw-btn-ghost:hover { background-color: var(--d-hover-bg); }
1097
1041
 
1098
1042
  .aw-tabs {
@@ -1100,7 +1044,6 @@
1100
1044
  border-bottom: 1px solid var(--d-border);
1101
1045
  margin: -4px -4px 8px;
1102
1046
  }
1103
-
1104
1047
  .aw-tab {
1105
1048
  padding: 8px 14px;
1106
1049
  background: transparent;
@@ -1113,11 +1056,8 @@
1113
1056
  cursor: pointer;
1114
1057
  transition: color 0.12s, border-color 0.12s;
1115
1058
  }
1116
-
1117
1059
  .aw-tab:hover { color: var(--d-fg); }
1118
-
1119
1060
  .aw-tab-active { color: var(--d-primary); border-bottom-color: var(--d-primary); }
1120
-
1121
1061
  .aw-tab-disabled,
1122
1062
  .aw-tab[disabled] {
1123
1063
  opacity: 0.4;
@@ -1125,7 +1065,6 @@
1125
1065
  text-decoration: line-through;
1126
1066
  color: var(--d-fg-muted);
1127
1067
  }
1128
-
1129
1068
  .aw-tab-disabled:hover,
1130
1069
  .aw-tab[disabled]:hover { color: var(--d-fg-muted); }
1131
1070
 
@@ -1160,17 +1099,13 @@
1160
1099
  transition: border-color 0.12s, background-color 0.12s, color 0.12s;
1161
1100
  background-color: var(--d-input-bg);
1162
1101
  }
1163
-
1164
1102
  .aw-dropzone:hover {
1165
1103
  border-color: var(--d-primary);
1166
1104
  background-color: var(--d-hover-bg);
1167
1105
  color: var(--d-primary);
1168
1106
  }
1169
-
1170
1107
  .aw-dropzone svg { width: 36px; height: 36px; }
1171
-
1172
1108
  .aw-dropzone-text { font-size: 13px; line-height: 1.5; }
1173
-
1174
1109
  .aw-dropzone-loading { opacity: 0.6; pointer-events: none; }
1175
1110
 
1176
1111
  .aw-preview {
@@ -1191,7 +1126,6 @@
1191
1126
  width: max-content;
1192
1127
  margin: 0 auto;
1193
1128
  }
1194
-
1195
1129
  .aw-table-cell {
1196
1130
  background-color: var(--d-input-bg);
1197
1131
  border: 1px solid var(--d-border-strong);
@@ -1199,12 +1133,10 @@
1199
1133
  cursor: pointer;
1200
1134
  transition: background-color 0.08s;
1201
1135
  }
1202
-
1203
1136
  .aw-table-cell-active {
1204
1137
  background-color: var(--d-primary-soft);
1205
1138
  border-color: var(--d-primary);
1206
1139
  }
1207
-
1208
1140
  .aw-table-status {
1209
1141
  text-align: center;
1210
1142
  font-size: 13px;
@@ -1249,7 +1181,6 @@
1249
1181
  padding: 0;
1250
1182
  transition: transform 0.08s;
1251
1183
  }
1252
-
1253
1184
  .aw-color-swatch:hover { transform: scale(1.15); }
1254
1185
 
1255
1186
  .aw-color-section {
@@ -1260,7 +1191,6 @@
1260
1191
  font-weight: 700;
1261
1192
  padding: 6px 2px 4px;
1262
1193
  }
1263
-
1264
1194
  .aw-color-section + .aw-color-grid { margin-bottom: 4px; }
1265
1195
 
1266
1196
  .aw-popover-action {
@@ -1278,7 +1208,6 @@
1278
1208
  margin-top: 4px;
1279
1209
  position: relative;
1280
1210
  }
1281
-
1282
1211
  .aw-popover-action:hover { background-color: var(--d-hover-bg); }
1283
1212
 
1284
1213
  .aw-popover-item {
@@ -1296,7 +1225,6 @@
1296
1225
  font-family: inherit;
1297
1226
  font-size: 12.5px;
1298
1227
  }
1299
-
1300
1228
  .aw-popover-item:hover { background-color: var(--d-hover-bg); }
1301
1229
 
1302
1230
  .aw-popover-item-glyph {
@@ -1311,7 +1239,6 @@
1311
1239
  font-size: 10px;
1312
1240
  font-weight: 700;
1313
1241
  }
1314
-
1315
1242
  .aw-popover-item-glyph svg { width: 11px; height: 11px; }
1316
1243
 
1317
1244
  .aw-popover-item-label { flex: 1; min-width: 0; }
@@ -1323,7 +1250,6 @@
1323
1250
  align-items: center; justify-content: center;
1324
1251
  gap: 0;
1325
1252
  }
1326
-
1327
1253
  .aw-popover-item-icon svg { width: 18px; height: 18px; }
1328
1254
 
1329
1255
  .aw-popover-divider {
@@ -1334,33 +1260,28 @@
1334
1260
 
1335
1261
  /* 블록 유형 드롭다운 — 항목이 많아 세로로 길어지지 않도록 2 컬럼 그리드.
1336
1262
  * 섹션 구분 divider 는 grid-column 으로 두 컬럼을 모두 가로지른다. */
1337
-
1338
1263
  .aw-block-type-popover {
1339
1264
  display: grid;
1340
1265
  grid-template-columns: repeat(2, minmax(150px, 1fr));
1341
1266
  column-gap: 2px;
1342
1267
  min-width: 320px;
1343
1268
  }
1344
-
1345
1269
  .aw-block-type-popover .aw-popover-divider {
1346
1270
  grid-column: 1 / -1;
1347
1271
  }
1348
1272
 
1349
1273
  /* 글꼴 드롭다운 — 라벨(작게) + '가A' 미리보기(글꼴 자체) 두 영역. */
1350
-
1351
1274
  .aw-font-family-popover {
1352
1275
  min-width: 180px;
1353
1276
  max-height: 360px;
1354
1277
  overflow-y: auto;
1355
1278
  }
1356
-
1357
1279
  .aw-font-family-item {
1358
1280
  padding: 4px 8px;
1359
1281
  display: flex;
1360
1282
  align-items: center;
1361
1283
  gap: 8px;
1362
1284
  }
1363
-
1364
1285
  .aw-font-family-name {
1365
1286
  flex: 1 1 auto;
1366
1287
  min-width: 0;
@@ -1371,7 +1292,6 @@
1371
1292
  overflow: hidden;
1372
1293
  text-overflow: ellipsis;
1373
1294
  }
1374
-
1375
1295
  .aw-font-family-preview {
1376
1296
  flex: 0 0 auto;
1377
1297
  font-size: 13px;
@@ -1381,29 +1301,24 @@
1381
1301
  }
1382
1302
 
1383
1303
  /* 표 편집 드롭다운 — 행/열 추가·삭제 텍스트 항목 */
1384
-
1385
1304
  .aw-table-menu-popover {
1386
1305
  min-width: 160px;
1387
1306
  }
1388
-
1389
1307
  .aw-table-menu-item {
1390
1308
  font-size: 12px;
1391
1309
  padding: 6px 10px;
1392
1310
  }
1393
1311
 
1394
1312
  /* 글자 크기 드롭다운 — 한 줄당 px 라벨이 그 크기로 렌더되는 컴팩트 리스트 */
1395
-
1396
1313
  .aw-font-size-popover {
1397
1314
  min-width: 80px;
1398
1315
  max-height: 320px;
1399
1316
  overflow-y: auto;
1400
1317
  }
1401
-
1402
1318
  .aw-font-size-item {
1403
1319
  padding: 2px 10px;
1404
1320
  justify-content: space-between;
1405
1321
  }
1406
-
1407
1322
  .aw-font-size-label {
1408
1323
  font-size: 11px;
1409
1324
  color: var(--d-fg);
@@ -1415,7 +1330,6 @@
1415
1330
  background-color: color-mix(in srgb, var(--d-primary) 14%, transparent);
1416
1331
  color: var(--d-primary);
1417
1332
  }
1418
-
1419
1333
  .aw-popover-item-active::after {
1420
1334
  content: '✓';
1421
1335
  margin-left: auto;
@@ -1429,18 +1343,15 @@
1429
1343
  }
1430
1344
 
1431
1345
  /* 표 삽입 드롭다운 — 호버에 따라 동적으로 늘어나는 셀 그리드 */
1432
-
1433
1346
  .aw-table-popover {
1434
1347
  padding: 10px;
1435
1348
  min-width: auto;
1436
1349
  }
1437
-
1438
1350
  .aw-table-picker-grid {
1439
1351
  display: grid;
1440
1352
  gap: 2px;
1441
1353
  margin-bottom: 6px;
1442
1354
  }
1443
-
1444
1355
  .aw-table-picker-grid .aw-table-cell {
1445
1356
  width: 18px;
1446
1357
  height: 18px;
@@ -1450,12 +1361,10 @@
1450
1361
  cursor: pointer;
1451
1362
  transition: background-color 0.06s, border-color 0.06s;
1452
1363
  }
1453
-
1454
1364
  .aw-table-picker-grid .aw-table-cell.aw-table-cell-active {
1455
1365
  background-color: var(--d-primary-soft);
1456
1366
  border-color: var(--d-primary);
1457
1367
  }
1458
-
1459
1368
  .aw-table-popover .aw-table-status {
1460
1369
  text-align: center;
1461
1370
  font-size: 12px;
@@ -1472,7 +1381,6 @@
1472
1381
  padding: 4px 8px;
1473
1382
  font-weight: 700;
1474
1383
  }
1475
-
1476
1384
  .aw-coming-soon-popover .aw-popover-empty {
1477
1385
  padding: 10px 8px;
1478
1386
  font-size: 13px;