qzhuli-markdown-wysiwyg 0.1.21 → 0.1.23

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/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const r=require("vue");var u=typeof document<"u"?document.currentScript:null;const h=`<!doctype html>\r
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const r=require("vue");var u=typeof document<"u"?document.currentScript:null;const p=`<!doctype html>\r
2
2
  <html lang="zh-CN" class="light">\r
3
3
  <head>\r
4
4
  <meta charset="utf-8"/>\r
@@ -331,15 +331,15 @@
331
331
  /* ========================================\r
332
332
  右侧主内容区\r
333
333
  ======================================== */\r
334
- .main-content {
335
- flex: 1;
336
- display: flex;
337
- flex-direction: column;
338
- min-width: 0;
339
- overflow: visible;
340
- background: #f5f7f8;
341
- min-height: 0;
342
- }
334
+ .main-content {\r
335
+ flex: 1;\r
336
+ display: flex;\r
337
+ flex-direction: column;\r
338
+ min-width: 0;\r
339
+ overflow: visible;\r
340
+ background: #f5f7f8;\r
341
+ min-height: 0;\r
342
+ }\r
343
343
  \r
344
344
  /* 顶部工具栏 - 参考设计(全宽通栏) */\r
345
345
  .top-bar {\r
@@ -460,31 +460,56 @@
460
460
  /* ========================================\r
461
461
  格式化工具栏样式\r
462
462
  ======================================== */\r
463
- .format-toolbar {\r
464
- background: #fff;\r
465
- border: 1px solid #e2e8f0;\r
466
- border-radius: 0.75rem;\r
467
- box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);\r
468
- padding: 0.375rem;\r
469
- display: flex;\r
470
- gap: 0.125rem;\r
471
- }\r
463
+ .format-toolbar {
464
+ background: #fff;
465
+ border: 1px solid #e2e8f0;
466
+ border-radius: 0.75rem;
467
+ box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
468
+ padding: 0.375rem;
469
+ display: flex;
470
+ flex-wrap: nowrap;
471
+ align-items: center;
472
+ justify-content: center;
473
+ gap: 0.125rem;
474
+ width: max-content;
475
+ max-width: none;
476
+ transform-origin: center top;
477
+ will-change: transform;
478
+ }
479
+
480
+ .toolbar-separator {
481
+ width: 1px;
482
+ height: 20px;
483
+ flex: 0 0 1px;
484
+ margin: 0 0.25rem;
485
+ background: #e5e7eb;
486
+ border-radius: 9999px;
487
+ }
472
488
  \r
473
489
  /* 工具栏悬浮样式 - 固定在文章板块顶部 */\r
474
- #toolbar-wrapper {\r
475
- position: sticky;\r
476
- top: 0;\r
477
- z-index: 50;\r
478
- background: rgba(245, 247, 248, 0.9);\r
479
- backdrop-filter: blur(8px);\r
480
- -webkit-backdrop-filter: blur(8px);\r
481
- transition: transform 0.2s ease, opacity 0.2s ease;\r
482
- padding: 8px 24px 12px;\r
483
- display: flex;\r
484
- justify-content: center;\r
485
- margin-top: 0;\r
486
- border-radius: 0 0 12px 12px;\r
487
- }\r
490
+ #toolbar-wrapper {
491
+ position: sticky;
492
+ top: 0;
493
+ z-index: 50;
494
+ background: rgba(245, 247, 248, 0.9);
495
+ backdrop-filter: blur(8px);
496
+ -webkit-backdrop-filter: blur(8px);
497
+ transition: transform 0.2s ease, opacity 0.2s ease;
498
+ padding: 8px 24px 12px;
499
+ display: flex;
500
+ justify-content: center;
501
+ align-items: flex-start;
502
+ width: 100%;
503
+ margin-top: 0;
504
+ border-radius: 0 0 12px 12px;
505
+ }
506
+
507
+ @media (max-width: 960px) {
508
+ #toolbar-wrapper {
509
+ padding-left: 0.875rem;
510
+ padding-right: 0.875rem;
511
+ }
512
+ }
488
513
  \r
489
514
  #toolbar-wrapper.toolbar-hidden {\r
490
515
  transform: translateY(-100%);\r
@@ -526,10 +551,10 @@
526
551
  font-weight: 700;\r
527
552
  }\r
528
553
  \r
529
- .format-btn.source-mode-toggle .toggle-label {
530
- letter-spacing: 0.02em;
531
- }
532
-
554
+ .format-btn.source-mode-toggle .toggle-label {\r
555
+ letter-spacing: 0.02em;\r
556
+ }\r
557
+ \r
533
558
  \r
534
559
  /* 行内工具栏 - 选中文字时显示的浮动工具栏 */\r
535
560
  .inline-toolbar {\r
@@ -649,24 +674,31 @@
649
674
  box-shadow: none;
650
675
  }
651
676
 
677
+ body.editor-reading-layout .source-editor-wrap {
678
+ width: 100%;
679
+ min-width: 0;
680
+ max-width: none;
681
+ margin: 0;
682
+ border: 0;
683
+ border-radius: 0;
684
+ box-shadow: none;
685
+ background: transparent;
686
+ }
687
+
652
688
  body.editor-reading-layout #doc-content {
653
- min-height: 100vh;
654
- padding: 2rem 2.5rem;
689
+ min-height: auto;
690
+ padding: 0;
655
691
  }
656
692
 
657
693
  body.editor-reading-layout.write #toolbar-wrapper {
658
- position: fixed;
694
+ position: sticky;
659
695
  top: 0;
660
- left: 0;
661
- right: 0;
662
- background: transparent;
663
- backdrop-filter: none;
664
- -webkit-backdrop-filter: none;
665
696
  box-shadow: none;
666
697
  }
667
698
 
668
- body.editor-reading-layout.write #doc-content {
669
- padding-top: 5.5rem;
699
+ body.editor-reading-layout .source-editor {
700
+ min-height: 320px;
701
+ padding: 0;
670
702
  }
671
703
 
672
704
  body.editor-readonly #toolbar-wrapper,
@@ -683,6 +715,12 @@
683
715
 
684
716
  body.editor-readonly #doc-content {
685
717
  caret-color: transparent;
718
+ padding: 0;
719
+ }
720
+
721
+ body.editor-readonly.source-mode .source-editor {
722
+ min-height: 320px;
723
+ padding: 0;
686
724
  }\r
687
725
  \r
688
726
  .doc-content {\r
@@ -1890,15 +1928,19 @@
1890
1928
  color: #94a3b8;\r
1891
1929
  }\r
1892
1930
  \r
1893
- .dark #toolbar-wrapper {
1894
- background: rgba(18, 18, 18, 0.88);
1895
- box-shadow: 0 10px 30px -24px rgba(0, 0, 0, 0.85);
1896
- }
1897
-
1898
- .dark .sidebar-title {
1899
- color: var(--dm-text-secondary);
1900
- letter-spacing: 0.16em;
1901
- }
1931
+ .dark body.editor-readonly.source-mode .source-editor[readonly] {\r
1932
+ color: #e2e8f0;\r
1933
+ }\r
1934
+ \r
1935
+ .dark #toolbar-wrapper {\r
1936
+ background: rgba(18, 18, 18, 0.88);\r
1937
+ box-shadow: 0 10px 30px -24px rgba(0, 0, 0, 0.85);\r
1938
+ }\r
1939
+ \r
1940
+ .dark .sidebar-title {\r
1941
+ color: var(--dm-text-secondary);\r
1942
+ letter-spacing: 0.16em;\r
1943
+ }\r
1902
1944
  \r
1903
1945
  .dark .toc-item {\r
1904
1946
  color: var(--dm-text-secondary);\r
@@ -2248,9 +2290,10 @@
2248
2290
  box-shadow: inset 0 0 0 1px rgba(96, 165, 250, 0.24);\r
2249
2291
  }\r
2250
2292
  \r
2251
- .dark .format-toolbar .w-px {\r
2252
- background: var(--dm-outline-variant) !important;\r
2253
- }\r
2293
+ .dark .format-toolbar .w-px,
2294
+ .dark .format-toolbar .toolbar-separator {
2295
+ background: var(--dm-outline-variant) !important;
2296
+ }
2254
2297
  \r
2255
2298
  .dark .search-replace-bar {\r
2256
2299
  background: rgba(26, 27, 30, 0.94);\r
@@ -2701,35 +2744,35 @@
2701
2744
  <!-- ==========================================\r
2702
2745
  编辑器滚动区域\r
2703
2746
  ========================================== -->\r
2704
- <!-- legacy hidden source toggle anchor removed
2705
- id="source-mode-toggle-anchor"
2706
- class="format-btn source-mode-toggle floating-source-mode-toggle"
2707
- style="display:none"
2708
- type="button"
2709
- onclick="toggleSourceMode()"
2710
- title="鍒囨崲鍒版簮鐮佹ā寮?
2711
- aria-label="鍒囨崲鍒版簮鐮佹ā寮?
2712
- aria-pressed="false"
2713
- >
2714
- <i class="fa-solid fa-code fa-xs"></i>
2715
- <span class="toggle-label">&lt;/&gt;</span>
2716
- -->
2717
-
2718
- <div class="editor-scroll">
2719
- <!-- legacy hidden source toggle container removed
2720
- <button
2721
- id="source-mode-toggle-hidden"
2722
- class="format-btn source-mode-toggle floating-source-mode-toggle"
2723
- type="button"
2724
- onclick="toggleSourceMode()"
2725
- title="閸掑洦宕查崚鐗堢爱閻焦膩瀵?
2726
- aria-label="閸掑洦宕查崚鐗堢爱閻焦膩瀵?
2727
- aria-pressed="false"
2728
- >
2729
- <i class="fa-solid fa-code fa-xs"></i>
2730
- <span class="toggle-label">&lt;/&gt;</span>
2731
- </button>
2732
- -->
2747
+ <!-- legacy hidden source toggle anchor removed\r
2748
+ id="source-mode-toggle-anchor"\r
2749
+ class="format-btn source-mode-toggle floating-source-mode-toggle"\r
2750
+ style="display:none"\r
2751
+ type="button"\r
2752
+ onclick="toggleSourceMode()"\r
2753
+ title="鍒囨崲鍒版簮鐮佹ā寮?\r
2754
+ aria-label="鍒囨崲鍒版簮鐮佹ā寮?\r
2755
+ aria-pressed="false"\r
2756
+ >\r
2757
+ <i class="fa-solid fa-code fa-xs"></i>\r
2758
+ <span class="toggle-label">&lt;/&gt;</span>\r
2759
+ -->\r
2760
+ \r
2761
+ <div class="editor-scroll">\r
2762
+ <!-- legacy hidden source toggle container removed\r
2763
+ <button\r
2764
+ id="source-mode-toggle-hidden"\r
2765
+ class="format-btn source-mode-toggle floating-source-mode-toggle"\r
2766
+ type="button"\r
2767
+ onclick="toggleSourceMode()"\r
2768
+ title="閸掑洦宕查崚鐗堢爱閻焦膩瀵?\r
2769
+ aria-label="閸掑洦宕查崚鐗堢爱閻焦膩瀵?\r
2770
+ aria-pressed="false"\r
2771
+ >\r
2772
+ <i class="fa-solid fa-code fa-xs"></i>\r
2773
+ <span class="toggle-label">&lt;/&gt;</span>\r
2774
+ </button>\r
2775
+ -->\r
2733
2776
  <!-- 格式化工具栏 - 固定在滚动区顶部 -->\r
2734
2777
  <div id="toolbar-wrapper" class="toolbar-wrapper">\r
2735
2778
  <div class="format-toolbar">\r
@@ -2741,8 +2784,8 @@
2741
2784
  <i class="fa-solid fa-redo fa-xs"></i>\r
2742
2785
  </button>\r
2743
2786
  <button\r
2744
- id="source-mode-toggle"
2745
- class="format-btn source-mode-toggle"
2787
+ id="source-mode-toggle"\r
2788
+ class="format-btn source-mode-toggle"\r
2746
2789
  type="button"\r
2747
2790
  onclick="toggleSourceMode()"\r
2748
2791
  title="切换到源码模式"\r
@@ -2752,7 +2795,7 @@
2752
2795
  <i class="fa-solid fa-code fa-xs"></i>\r
2753
2796
  <span class="toggle-label">&lt;/&gt;</span>\r
2754
2797
  </button>\r
2755
- <div class="w-px bg-gray-200 mx-1"></div>
2798
+ <div class="toolbar-separator" aria-hidden="true"></div>
2756
2799
  <!-- 标题按钮 H1-H6 -->\r
2757
2800
  <button class="format-btn" onclick="formatBlock('h1')" title="H1">\r
2758
2801
  <span class="text-xs font-bold">H1</span>\r
@@ -2772,7 +2815,7 @@
2772
2815
  <button class="format-btn" onclick="formatBlock('h6')" title="H6">\r
2773
2816
  <span class="text-xs font-bold">H6</span>\r
2774
2817
  </button>\r
2775
- <div class="w-px bg-gray-200 mx-1"></div>\r
2818
+ <div class="toolbar-separator" aria-hidden="true"></div>
2776
2819
  <!-- 行内格式化按钮 -->\r
2777
2820
  <button class="format-btn" onclick="formatInline('bold')" title="粗体">\r
2778
2821
  <i class="fa-solid fa-bold fa-xs"></i>\r
@@ -2789,7 +2832,7 @@
2789
2832
  <button class="format-btn" onclick="formatInline('mark')" title="高亮">\r
2790
2833
  <i class="fa-solid fa-highlighter fa-xs"></i>\r
2791
2834
  </button>\r
2792
- <div class="w-px bg-gray-200 mx-1"></div>\r
2835
+ <div class="toolbar-separator" aria-hidden="true"></div>
2793
2836
  <!-- 列表按钮 -->\r
2794
2837
  <button class="format-btn" onclick="formatBlock('ul')" title="无序列表">\r
2795
2838
  <i class="fa-solid fa-list fa-xs"></i>\r
@@ -2800,7 +2843,7 @@
2800
2843
  <button class="format-btn" onclick="insertTask()" title="任务列表">\r
2801
2844
  <i class="fa-solid fa-square-check fa-xs"></i>\r
2802
2845
  </button>\r
2803
- <div class="w-px bg-gray-200 mx-1"></div>\r
2846
+ <div class="toolbar-separator" aria-hidden="true"></div>
2804
2847
  <!-- 引用块按钮 -->\r
2805
2848
  <button class="format-btn" onclick="insertBlockquote('primary')" title="引用蓝色">\r
2806
2849
  <i class="fa-solid fa-quote-left fa-xs" style="color: #007bff"></i>\r
@@ -2811,7 +2854,7 @@
2811
2854
  <button class="format-btn" onclick="insertBlockquote('error')" title="引用红色">\r
2812
2855
  <i class="fa-solid fa-quote-left fa-xs" style="color: #ef4444"></i>\r
2813
2856
  </button>\r
2814
- <div class="w-px bg-gray-200 mx-1"></div>\r
2857
+ <div class="toolbar-separator" aria-hidden="true"></div>
2815
2858
  <!-- 其他按钮 -->\r
2816
2859
  <button class="format-btn" onclick="insertCodeBlock()" title="代码块">\r
2817
2860
  <i class="fa-solid fa-file-code fa-xs"></i>\r
@@ -3001,10 +3044,10 @@
3001
3044
  let editorHistoryIndex = -1 // 当前历史索引\r
3002
3045
  let editorHistorySuppress = false // 恢复快照时禁止重新记录历史\r
3003
3046
  let editorHistoryShortcutHandledAt = 0 // 防止 keydown 和 beforeinput 重复触发撤回\r
3004
- let sourceHistory = []
3005
- let sourceHistoryIndex = -1
3006
- let sourceHistorySuppress = false
3007
- let editorHostMode = 'local'
3047
+ let sourceHistory = []\r
3048
+ let sourceHistoryIndex = -1\r
3049
+ let sourceHistorySuppress = false\r
3050
+ let editorHostMode = 'local'\r
3008
3051
  let mentionMenuIndex = 0\r
3009
3052
  let mentionQuery = ''\r
3010
3053
  let mentionSavedRange = null\r
@@ -3013,9 +3056,9 @@
3013
3056
  let mentionMenuResults = []\r
3014
3057
  let mentionUsers = []\r
3015
3058
  let mentionRequestId = 0\r
3016
- let sourceMode = false
3017
- let sourceModeInitialMarkdown = null
3018
- let sourceModeDirty = false
3059
+ let sourceMode = false\r
3060
+ let sourceModeInitialMarkdown = null\r
3061
+ let sourceModeDirty = false\r
3019
3062
  const MAX_EDITOR_HISTORY = 120\r
3020
3063
  let codeBlockCompositionActive = false\r
3021
3064
  let codeBlockCompositionTarget = null\r
@@ -3531,7 +3574,7 @@
3531
3574
  .querySelectorAll('.table-edge-container')\r
3532
3575
  .forEach((el) => el.remove())\r
3533
3576
  // 内联 runtime 启动时先保持空白,等宿主 load-content 后再显示,避免首屏闪动
3534
- c.innerHTML = ''
3577
+ c.innerHTML = ''\r
3535
3578
  decorateHorizontalRules(c)\r
3536
3579
  updateLastEditedTime(null)\r
3537
3580
  // 监听内容变化事件\r
@@ -3909,10 +3952,67 @@
3909
3952
  - Ctrl/Cmd + S: 保存\r
3910
3953
  - / 或 、: 显示斜杠菜单\r
3911
3954
  ======================================== */\r
3955
+ function getReadOnlySelectionText() {\r
3956
+ var text = ''\r
3957
+ if (sourceMode) {\r
3958
+ var textarea = sourceEditor()\r
3959
+ if (textarea) {\r
3960
+ var start = Number(textarea.selectionStart)\r
3961
+ var end = Number(textarea.selectionEnd)\r
3962
+ if (!Number.isNaN(start) && !Number.isNaN(end) && end > start) {\r
3963
+ text = textarea.value.slice(start, end)\r
3964
+ }\r
3965
+ }\r
3966
+ } else {\r
3967
+ text = String(window.getSelection ? window.getSelection().toString() : '')\r
3968
+ }\r
3969
+ \r
3970
+ return String(text || '')\r
3971
+ }\r
3972
+ \r
3973
+ function copyReadOnlySelection(copyEvent) {\r
3974
+ var text = getReadOnlySelectionText()\r
3975
+ if (!text) return false\r
3976
+ \r
3977
+ var clipboard = copyEvent && copyEvent.clipboardData\r
3978
+ if (clipboard && typeof clipboard.setData === 'function') {\r
3979
+ clipboard.setData('text/plain', text)\r
3980
+ return true\r
3981
+ }\r
3982
+ \r
3983
+ if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {\r
3984
+ navigator.clipboard.writeText(text).catch(function () {})\r
3985
+ return true\r
3986
+ }\r
3987
+ \r
3988
+ var temp = document.createElement('textarea')\r
3989
+ temp.value = text\r
3990
+ temp.setAttribute('readonly', 'readonly')\r
3991
+ temp.style.position = 'fixed'\r
3992
+ temp.style.top = '-9999px'\r
3993
+ temp.style.left = '-9999px'\r
3994
+ document.body.appendChild(temp)\r
3995
+ temp.select()\r
3996
+ try {\r
3997
+ document.execCommand('copy')\r
3998
+ } catch (err) {\r
3999
+ document.body.removeChild(temp)\r
4000
+ return false\r
4001
+ }\r
4002
+ document.body.removeChild(temp)\r
4003
+ return true\r
4004
+ }\r
4005
+ \r
3912
4006
  function handleKeydown(e) {\r
3913
4007
  if (editorReadOnly) {\r
3914
4008
  if (e.ctrlKey || e.metaKey) {\r
3915
4009
  const key = String(e.key || '').toLowerCase()\r
4010
+ if (key === 'c') {\r
4011
+ if (copyReadOnlySelection()) {\r
4012
+ e.preventDefault()\r
4013
+ }\r
4014
+ return\r
4015
+ }\r
3916
4016
  if (key === 's' || key === 'b' || key === 'i' || key === 'z' || key === 'y') {\r
3917
4017
  e.preventDefault()\r
3918
4018
  }\r
@@ -3991,25 +4091,25 @@
3991
4091
  }\r
3992
4092
  if (e.ctrlKey || e.metaKey) {\r
3993
4093
  const key = String(e.key || '').toLowerCase()\r
3994
- if (key === 'z' || key === 'y' || (key === 'z' && e.shiftKey)) {
3995
- e.preventDefault()
3996
- e.stopPropagation()
3997
- editorHistoryShortcutHandledAt = Date.now()
3998
- if (key === 'y' || (key === 'z' && e.shiftKey)) {
3999
- if (sourceMode) {
4000
- redoSourceHistory()
4001
- } else {
4002
- redoEditorHistory()
4003
- }
4004
- } else {
4005
- if (sourceMode) {
4006
- undoSourceHistory()
4007
- } else {
4008
- undoEditorHistory()
4009
- }
4010
- }
4011
- return
4012
- }
4094
+ if (key === 'z' || key === 'y' || (key === 'z' && e.shiftKey)) {\r
4095
+ e.preventDefault()\r
4096
+ e.stopPropagation()\r
4097
+ editorHistoryShortcutHandledAt = Date.now()\r
4098
+ if (key === 'y' || (key === 'z' && e.shiftKey)) {\r
4099
+ if (sourceMode) {\r
4100
+ redoSourceHistory()\r
4101
+ } else {\r
4102
+ redoEditorHistory()\r
4103
+ }\r
4104
+ } else {\r
4105
+ if (sourceMode) {\r
4106
+ undoSourceHistory()\r
4107
+ } else {\r
4108
+ undoEditorHistory()\r
4109
+ }\r
4110
+ }\r
4111
+ return\r
4112
+ }\r
4013
4113
  if (key === 'b') {\r
4014
4114
  e.preventDefault()\r
4015
4115
  formatInline('bold')\r
@@ -4576,14 +4676,14 @@
4576
4676
  }\r
4577
4677
  }\r
4578
4678
  \r
4579
- function captureEditorSnapshot(useMemoryFallback = true) {
4580
- const docContent = document.getElementById('doc-content')
4581
- if (!docContent) return null
4582
-
4583
- return {
4584
- html: docContent.innerHTML,
4585
- }
4586
- }
4679
+ function captureEditorSnapshot(useMemoryFallback = true) {\r
4680
+ const docContent = document.getElementById('doc-content')\r
4681
+ if (!docContent) return null\r
4682
+ \r
4683
+ return {\r
4684
+ html: docContent.innerHTML,\r
4685
+ }\r
4686
+ }\r
4587
4687
  \r
4588
4688
  function recordEditorHistory() {\r
4589
4689
  if (editorHistorySuppress || window._loadingContent || editorReadOnly) return\r
@@ -4603,199 +4703,154 @@
4603
4703
  editorHistoryIndex = editorHistory.length - 1\r
4604
4704
  }\r
4605
4705
  \r
4606
- function resetEditorHistory() {
4607
- clearPendingAutoSave()
4608
- setEditorSaveStatus('saved')
4609
-
4610
- const snapshot = captureEditorSnapshot(false)
4611
- editorHistory = snapshot ? [snapshot] : []
4612
- editorHistoryIndex = snapshot ? 0 : -1
4613
- rememberEditorSelection(null)
4614
- }
4615
-
4616
- function captureSourceSnapshot() {
4617
- const textarea = typeof window.sourceEditor === 'function' ? window.sourceEditor() : document.getElementById('markdown-source-editor')
4618
- if (!textarea) return null
4619
-
4620
- return {
4621
- value: textarea.value || '',
4622
- }
4623
- }
4624
-
4625
- function logSourceDebug(stage, extra) {
4626
- const textarea = typeof window.sourceEditor === 'function' ? window.sourceEditor() : document.getElementById('markdown-source-editor')
4627
- const scrollEl = getEditorScrollElement()
4628
- const activeEl = document.activeElement
4629
- console.debug('[source-debug]', stage, {
4630
- sourceMode: !!sourceMode,
4631
- scrollTop: scrollEl ? scrollEl.scrollTop : null,
4632
- textareaScrollTop: textarea ? textarea.scrollTop : null,
4633
- selectionStart: textarea ? textarea.selectionStart : null,
4634
- selectionEnd: textarea ? textarea.selectionEnd : null,
4635
- valueLength: textarea ? (textarea.value || '').length : null,
4636
- activeTag: activeEl ? activeEl.tagName : null,
4637
- activeId: activeEl ? activeEl.id || null : null,
4638
- sourceHistoryIndex,
4639
- sourceHistoryLength: sourceHistory.length,
4640
- ...(extra || {}),
4641
- })
4642
- }
4643
-
4644
- function recordSourceHistory() {
4645
- if (sourceHistorySuppress || window._loadingContent || editorReadOnly) return
4646
-
4647
- const snapshot = captureSourceSnapshot()
4648
- if (!snapshot) return
4649
-
4650
- const current = sourceHistory[sourceHistoryIndex]
4651
- if (current && current.value === snapshot.value) return
4652
-
4653
- sourceHistory = sourceHistory.slice(0, sourceHistoryIndex + 1)
4654
- sourceHistory.push(snapshot)
4655
- if (sourceHistory.length > MAX_EDITOR_HISTORY) {
4656
- const overflow = sourceHistory.length - MAX_EDITOR_HISTORY
4657
- sourceHistory.splice(0, overflow)
4658
- }
4659
- sourceHistoryIndex = sourceHistory.length - 1
4660
- }
4661
-
4662
- function resetSourceHistory() {
4663
- const snapshot = captureSourceSnapshot()
4664
- sourceHistory = snapshot ? [snapshot] : []
4665
- sourceHistoryIndex = snapshot ? 0 : -1
4666
- logSourceDebug('resetSourceHistory', {
4667
- snapshotValueLength: snapshot ? snapshot.value.length : null,
4668
- })
4669
- }
4670
-
4671
- function applySourceHistorySnapshot(snapshot) {
4672
- const textarea = typeof window.sourceEditor === 'function' ? window.sourceEditor() : document.getElementById('markdown-source-editor')
4673
- const scrollEl = getEditorScrollElement()
4674
- if (!snapshot || !textarea) return false
4675
-
4676
- sourceHistorySuppress = true
4677
- try {
4678
- const currentScrollTop = scrollEl ? scrollEl.scrollTop : 0
4679
- logSourceDebug('applySourceHistorySnapshot:start', {
4680
- targetValueLength: (snapshot.value || '').length,
4681
- currentScrollTop,
4682
- })
4683
- textarea.value = snapshot.value || ''
4684
- syncSourceModeDirtyState(textarea.value || '')
4685
- const nextLength = textarea.value.length
4686
- textarea.setSelectionRange(nextLength, nextLength)
4687
- logSourceDebug('applySourceHistorySnapshot:afterSelection', {
4688
- currentScrollTop,
4689
- })
4690
- if (typeof window.syncSourceEditorHeight === 'function') {
4691
- window.syncSourceEditorHeight()
4692
- }
4693
- logSourceDebug('applySourceHistorySnapshot:afterHeightSync', {
4694
- currentScrollTop,
4695
- })
4696
- if (scrollEl) {
4697
- scrollEl.scrollTop = currentScrollTop
4698
- requestAnimationFrame(() => {
4699
- scrollEl.scrollTop = currentScrollTop
4700
- logSourceDebug('applySourceHistorySnapshot:rafRestore', {
4701
- currentScrollTop,
4702
- })
4703
- })
4704
- }
4705
- if (document.activeElement === textarea) {
4706
- textarea.focus({preventScroll: true})
4707
- }
4708
- if (window.updateTOC) window.updateTOC()
4709
- return true
4710
- } finally {
4711
- sourceHistorySuppress = false
4712
- }
4713
- }
4714
-
4715
- function undoSourceHistory() {
4716
- if (editorReadOnly) return false
4717
- if (sourceHistoryIndex <= 0) return false
4718
-
4719
- const targetIndex = sourceHistoryIndex - 1
4720
- const snapshot = sourceHistory[targetIndex]
4721
- if (!snapshot) return false
4722
-
4723
- logSourceDebug('undoSourceHistory:before', {
4724
- targetIndex,
4725
- targetValueLength: (snapshot.value || '').length,
4726
- })
4727
- clearPendingAutoSave()
4728
- if (!applySourceHistorySnapshot(snapshot)) return false
4729
- sourceHistoryIndex = targetIndex
4730
- logSourceDebug('undoSourceHistory:after', {
4731
- targetIndex,
4732
- })
4733
- scheduleAutoSave(true)
4734
- return true
4735
- }
4736
-
4737
- function redoSourceHistory() {
4738
- if (editorReadOnly) return false
4739
- if (sourceHistoryIndex < 0 || sourceHistoryIndex >= sourceHistory.length - 1) return false
4740
-
4741
- const targetIndex = sourceHistoryIndex + 1
4742
- const snapshot = sourceHistory[targetIndex]
4743
- if (!snapshot) return false
4744
-
4745
- logSourceDebug('redoSourceHistory:before', {
4746
- targetIndex,
4747
- targetValueLength: (snapshot.value || '').length,
4748
- })
4749
- clearPendingAutoSave()
4750
- if (!applySourceHistorySnapshot(snapshot)) return false
4751
- sourceHistoryIndex = targetIndex
4752
- logSourceDebug('redoSourceHistory:after', {
4753
- targetIndex,
4754
- })
4755
- scheduleAutoSave(true)
4756
- return true
4757
- }
4758
-
4759
- function handleSourceKeydown(e) {
4760
- if (editorReadOnly) return
4761
- if (!(e.ctrlKey || e.metaKey)) return
4762
-
4763
- const key = String(e.key || '').toLowerCase()
4764
- if (key === 'z') {
4765
- e.preventDefault()
4766
- e.stopPropagation()
4767
- logSourceDebug('handleSourceKeydown:z', {
4768
- shiftKey: !!e.shiftKey,
4769
- })
4770
- if (e.shiftKey) {
4771
- redoSourceHistory()
4772
- } else {
4773
- undoSourceHistory()
4774
- }
4775
- return
4776
- }
4777
- if (key === 'y') {
4778
- e.preventDefault()
4779
- e.stopPropagation()
4780
- logSourceDebug('handleSourceKeydown:y')
4781
- redoSourceHistory()
4782
- return
4783
- }
4784
- if (key === 'b') {
4785
- e.preventDefault()
4786
- formatInline('bold')
4787
- return
4788
- }
4789
- if (key === 'i') {
4790
- e.preventDefault()
4791
- formatInline('italic')
4792
- return
4793
- }
4794
- if (key === 's') {
4795
- e.preventDefault()
4796
- requestHostSave()
4797
- }
4798
- }
4706
+ function resetEditorHistory() {\r
4707
+ clearPendingAutoSave()\r
4708
+ setEditorSaveStatus('saved')\r
4709
+ \r
4710
+ const snapshot = captureEditorSnapshot(false)\r
4711
+ editorHistory = snapshot ? [snapshot] : []\r
4712
+ editorHistoryIndex = snapshot ? 0 : -1\r
4713
+ rememberEditorSelection(null)\r
4714
+ }\r
4715
+ \r
4716
+ function captureSourceSnapshot() {\r
4717
+ const textarea = typeof window.sourceEditor === 'function' ? window.sourceEditor() : document.getElementById('markdown-source-editor')\r
4718
+ if (!textarea) return null\r
4719
+ \r
4720
+ return {\r
4721
+ value: textarea.value || '',\r
4722
+ }\r
4723
+ }\r
4724
+ \r
4725
+ function recordSourceHistory() {\r
4726
+ if (sourceHistorySuppress || window._loadingContent || editorReadOnly) return\r
4727
+ \r
4728
+ const snapshot = captureSourceSnapshot()\r
4729
+ if (!snapshot) return\r
4730
+ \r
4731
+ const current = sourceHistory[sourceHistoryIndex]\r
4732
+ if (current && current.value === snapshot.value) return\r
4733
+ \r
4734
+ sourceHistory = sourceHistory.slice(0, sourceHistoryIndex + 1)\r
4735
+ sourceHistory.push(snapshot)\r
4736
+ if (sourceHistory.length > MAX_EDITOR_HISTORY) {\r
4737
+ const overflow = sourceHistory.length - MAX_EDITOR_HISTORY\r
4738
+ sourceHistory.splice(0, overflow)\r
4739
+ }\r
4740
+ sourceHistoryIndex = sourceHistory.length - 1\r
4741
+ }\r
4742
+ \r
4743
+ function resetSourceHistory() {\r
4744
+ const snapshot = captureSourceSnapshot()\r
4745
+ sourceHistory = snapshot ? [snapshot] : []\r
4746
+ sourceHistoryIndex = snapshot ? 0 : -1\r
4747
+ }\r
4748
+ \r
4749
+ function applySourceHistorySnapshot(snapshot) {\r
4750
+ const textarea = typeof window.sourceEditor === 'function' ? window.sourceEditor() : document.getElementById('markdown-source-editor')\r
4751
+ const scrollEl = getEditorScrollElement()\r
4752
+ if (!snapshot || !textarea) return false\r
4753
+ \r
4754
+ sourceHistorySuppress = true\r
4755
+ try {\r
4756
+ const currentScrollTop = scrollEl ? scrollEl.scrollTop : 0\r
4757
+ textarea.value = snapshot.value || ''\r
4758
+ syncSourceModeDirtyState(textarea.value || '')\r
4759
+ const nextLength = textarea.value.length\r
4760
+ textarea.setSelectionRange(nextLength, nextLength)\r
4761
+ if (typeof window.syncSourceEditorHeight === 'function') {\r
4762
+ window.syncSourceEditorHeight()\r
4763
+ }\r
4764
+ if (scrollEl) {\r
4765
+ scrollEl.scrollTop = currentScrollTop\r
4766
+ requestAnimationFrame(() => {\r
4767
+ scrollEl.scrollTop = currentScrollTop\r
4768
+ })\r
4769
+ }\r
4770
+ if (document.activeElement === textarea) {\r
4771
+ textarea.focus({preventScroll: true})\r
4772
+ }\r
4773
+ if (window.updateTOC) window.updateTOC()\r
4774
+ return true\r
4775
+ } finally {\r
4776
+ sourceHistorySuppress = false\r
4777
+ }\r
4778
+ }\r
4779
+ \r
4780
+ function undoSourceHistory() {\r
4781
+ if (editorReadOnly) return false\r
4782
+ if (sourceHistoryIndex <= 0) return false\r
4783
+ \r
4784
+ const targetIndex = sourceHistoryIndex - 1\r
4785
+ const snapshot = sourceHistory[targetIndex]\r
4786
+ if (!snapshot) return false\r
4787
+ \r
4788
+ clearPendingAutoSave()\r
4789
+ if (!applySourceHistorySnapshot(snapshot)) return false\r
4790
+ sourceHistoryIndex = targetIndex\r
4791
+ scheduleAutoSave(true)\r
4792
+ return true\r
4793
+ }\r
4794
+ \r
4795
+ function redoSourceHistory() {\r
4796
+ if (editorReadOnly) return false\r
4797
+ if (sourceHistoryIndex < 0 || sourceHistoryIndex >= sourceHistory.length - 1) return false\r
4798
+ \r
4799
+ const targetIndex = sourceHistoryIndex + 1\r
4800
+ const snapshot = sourceHistory[targetIndex]\r
4801
+ if (!snapshot) return false\r
4802
+ \r
4803
+ clearPendingAutoSave()\r
4804
+ if (!applySourceHistorySnapshot(snapshot)) return false\r
4805
+ sourceHistoryIndex = targetIndex\r
4806
+ scheduleAutoSave(true)\r
4807
+ return true\r
4808
+ }\r
4809
+ \r
4810
+ function handleSourceKeydown(e) {\r
4811
+ if (editorReadOnly) {\r
4812
+ if ((e.ctrlKey || e.metaKey) && String(e.key || '').toLowerCase() === 'c') {\r
4813
+ if (copyReadOnlySelection()) {\r
4814
+ e.preventDefault()\r
4815
+ e.stopPropagation()\r
4816
+ }\r
4817
+ }\r
4818
+ return\r
4819
+ }\r
4820
+ if (!(e.ctrlKey || e.metaKey)) return\r
4821
+ \r
4822
+ const key = String(e.key || '').toLowerCase()\r
4823
+ if (key === 'z') {\r
4824
+ e.preventDefault()\r
4825
+ e.stopPropagation()\r
4826
+ if (e.shiftKey) {\r
4827
+ redoSourceHistory()\r
4828
+ } else {\r
4829
+ undoSourceHistory()\r
4830
+ }\r
4831
+ return\r
4832
+ }\r
4833
+ if (key === 'y') {\r
4834
+ e.preventDefault()\r
4835
+ e.stopPropagation()\r
4836
+ redoSourceHistory()\r
4837
+ return\r
4838
+ }\r
4839
+ if (key === 'b') {\r
4840
+ e.preventDefault()\r
4841
+ formatInline('bold')\r
4842
+ return\r
4843
+ }\r
4844
+ if (key === 'i') {\r
4845
+ e.preventDefault()\r
4846
+ formatInline('italic')\r
4847
+ return\r
4848
+ }\r
4849
+ if (key === 's') {\r
4850
+ e.preventDefault()\r
4851
+ requestHostSave()\r
4852
+ }\r
4853
+ }\r
4799
4854
  \r
4800
4855
  function refreshEditorAfterContentChange() {\r
4801
4856
  const docContent = document.getElementById('doc-content')\r
@@ -4808,31 +4863,31 @@
4808
4863
  if (window.updateTOC) window.updateTOC()\r
4809
4864
  }\r
4810
4865
  \r
4811
- function applyEditorHistorySnapshot(snapshot) {
4812
- if (!snapshot) return false
4813
-
4814
- const docContent = document.getElementById('doc-content')
4815
- const scrollEl = getEditorScrollElement()
4816
- if (!docContent) return false
4817
-
4818
- editorHistorySuppress = true
4819
- try {
4820
- const currentScrollTop = scrollEl ? scrollEl.scrollTop : 0
4821
- clearReadOnlyArtifacts()
4822
- docContent.innerHTML = snapshot.html
4823
- refreshEditorAfterContentChange()
4824
- syncEditorReadOnlyState()
4825
- rememberEditorSelection(null)
4826
- if (scrollEl) {
4827
- scrollEl.scrollTop = currentScrollTop
4828
- requestAnimationFrame(() => {
4829
- scrollEl.scrollTop = currentScrollTop
4830
- })
4831
- }
4832
- return true
4833
- } finally {
4834
- editorHistorySuppress = false
4835
- }
4866
+ function applyEditorHistorySnapshot(snapshot) {\r
4867
+ if (!snapshot) return false\r
4868
+ \r
4869
+ const docContent = document.getElementById('doc-content')\r
4870
+ const scrollEl = getEditorScrollElement()\r
4871
+ if (!docContent) return false\r
4872
+ \r
4873
+ editorHistorySuppress = true\r
4874
+ try {\r
4875
+ const currentScrollTop = scrollEl ? scrollEl.scrollTop : 0\r
4876
+ clearReadOnlyArtifacts()\r
4877
+ docContent.innerHTML = snapshot.html\r
4878
+ refreshEditorAfterContentChange()\r
4879
+ syncEditorReadOnlyState()\r
4880
+ rememberEditorSelection(null)\r
4881
+ if (scrollEl) {\r
4882
+ scrollEl.scrollTop = currentScrollTop\r
4883
+ requestAnimationFrame(() => {\r
4884
+ scrollEl.scrollTop = currentScrollTop\r
4885
+ })\r
4886
+ }\r
4887
+ return true\r
4888
+ } finally {\r
4889
+ editorHistorySuppress = false\r
4890
+ }\r
4836
4891
  }\r
4837
4892
  \r
4838
4893
  function undoEditorHistory() {\r
@@ -6128,19 +6183,19 @@
6128
6183
  /* ========================================\r
6129
6184
  撤销 / 重做\r
6130
6185
  ======================================== */\r
6131
- function undo() {
6132
- if (sourceMode) {
6133
- undoSourceHistory()
6134
- return
6135
- }
6136
- document.execCommand('undo')
6137
- scheduleAutoSave()
6138
- }
6139
- function redo() {
6140
- if (sourceMode) {
6141
- redoSourceHistory()
6142
- return
6143
- }
6186
+ function undo() {\r
6187
+ if (sourceMode) {\r
6188
+ undoSourceHistory()\r
6189
+ return\r
6190
+ }\r
6191
+ document.execCommand('undo')\r
6192
+ scheduleAutoSave()\r
6193
+ }\r
6194
+ function redo() {\r
6195
+ if (sourceMode) {\r
6196
+ redoSourceHistory()\r
6197
+ return\r
6198
+ }\r
6144
6199
  document.execCommand('redo')\r
6145
6200
  scheduleAutoSave()\r
6146
6201
  }\r
@@ -7758,24 +7813,24 @@
7758
7813
  '<span class="flex items-center gap-1 text-emerald-500"><span class="w-1.5 h-1.5 bg-emerald-500 rounded-full"></span>已同步</span>'\r
7759
7814
  }\r
7760
7815
  \r
7761
- function notifyHostContentChange() {
7762
- if (window._loadingContent || editorReadOnly) return
7763
-
7764
- const markdown = getCurrentEditorMarkdown()
7765
- if (markdown === null || !window.parent) return
7766
-
7767
- window.parent.postMessage({type: 'content-change', content: markdown}, '*')
7768
- }
7769
-
7770
- function syncSourceModeDirtyState(currentValue) {
7771
- if (sourceModeInitialMarkdown === null) {
7772
- sourceModeDirty = false
7773
- return false
7774
- }
7775
-
7776
- sourceModeDirty = String(currentValue || '') !== String(sourceModeInitialMarkdown || '')
7777
- return sourceModeDirty
7778
- }
7816
+ function notifyHostContentChange() {\r
7817
+ if (window._loadingContent || editorReadOnly) return\r
7818
+ \r
7819
+ const markdown = getCurrentEditorMarkdown()\r
7820
+ if (markdown === null || !window.parent) return\r
7821
+ \r
7822
+ window.parent.postMessage({type: 'content-change', content: markdown}, '*')\r
7823
+ }\r
7824
+ \r
7825
+ function syncSourceModeDirtyState(currentValue) {\r
7826
+ if (sourceModeInitialMarkdown === null) {\r
7827
+ sourceModeDirty = false\r
7828
+ return false\r
7829
+ }\r
7830
+ \r
7831
+ sourceModeDirty = String(currentValue || '') !== String(sourceModeInitialMarkdown || '')\r
7832
+ return sourceModeDirty\r
7833
+ }\r
7779
7834
  \r
7780
7835
  window.getCurrentEditorMarkdown = getCurrentEditorMarkdown\r
7781
7836
  window.clearPendingAutoSave = clearPendingAutoSave\r
@@ -7821,10 +7876,22 @@
7821
7876
 
7822
7877
  function syncEditorReadOnlyState() {
7823
7878
  const docContent = document.getElementById('doc-content')
7879
+ const textarea = document.getElementById('markdown-source-editor')
7880
+ const toggle = document.getElementById('source-mode-toggle')
7824
7881
  if (docContent) {
7825
7882
  docContent.setAttribute('contenteditable', editorReadOnly ? 'false' : 'true')
7826
7883
  docContent.setAttribute('aria-readonly', editorReadOnly ? 'true' : 'false')
7827
7884
  }
7885
+ if (textarea) {
7886
+ textarea.readOnly = !!editorReadOnly
7887
+ textarea.setAttribute('aria-readonly', editorReadOnly ? 'true' : 'false')
7888
+ }
7889
+ if (toggle) {
7890
+ toggle.classList.toggle('is-active', sourceMode)
7891
+ toggle.setAttribute('aria-pressed', sourceMode ? 'true' : 'false')
7892
+ toggle.setAttribute('title', sourceMode ? '切换到渲染模式' : '切换到源码模式')
7893
+ toggle.setAttribute('aria-label', sourceMode ? '切换到渲染模式' : '切换到源码模式')
7894
+ }
7828
7895
  applyEditorViewModeClasses()
7829
7896
  }
7830
7897
 
@@ -11707,40 +11774,40 @@
11707
11774
  return headings\r
11708
11775
  }\r
11709
11776
  \r
11710
- function getCurrentTocEntries() {
11711
- if (sourceMode) {
11712
- const textarea = document.getElementById('markdown-source-editor')
11713
- return collectSourceModeHeadings(textarea ? textarea.value : '')
11714
- }
11777
+ function getCurrentTocEntries() {\r
11778
+ if (sourceMode) {\r
11779
+ const textarea = document.getElementById('markdown-source-editor')\r
11780
+ return collectSourceModeHeadings(textarea ? textarea.value : '')\r
11781
+ }\r
11715
11782
  \r
11716
11783
  const content = document.getElementById('doc-content')\r
11717
11784
  if (!content) return []\r
11718
11785
  \r
11719
- return Array.from(content.querySelectorAll('h1,h2,h3,h4,h5,h6')).map((heading, index) => {
11720
- if (!heading.id) heading.id = 'heading-' + index
11721
- return {
11722
- level: parseInt(heading.tagName[1]),
11723
- text: heading.textContent || '',
11786
+ return Array.from(content.querySelectorAll('h1,h2,h3,h4,h5,h6')).map((heading, index) => {\r
11787
+ if (!heading.id) heading.id = 'heading-' + index\r
11788
+ return {\r
11789
+ level: parseInt(heading.tagName[1]),\r
11790
+ text: heading.textContent || '',\r
11724
11791
  element: heading,\r
11725
11792
  lineIndex: index,\r
11726
- }
11727
- })
11728
- }
11729
-
11730
- function revealToolbarForSourceMode() {
11731
- const toolbarWrapper = document.getElementById('toolbar-wrapper')
11732
- if (editorReadOnly || !toolbarWrapper) return
11733
- clearTimeout(hideToolbarTimer)
11734
- hideToolbarTimer = setTimeout(() => {
11735
- toolbarWrapper.classList.remove('toolbar-hidden')
11736
- toolbarHidden = false
11737
- }, 100)
11738
- }
11739
-
11740
- const sourceTextarea = document.getElementById('markdown-source-editor')
11741
- if (sourceTextarea) {
11742
- sourceTextarea.addEventListener('click', revealToolbarForSourceMode)
11743
- }
11793
+ }\r
11794
+ })\r
11795
+ }\r
11796
+ \r
11797
+ function revealToolbarForSourceMode() {\r
11798
+ const toolbarWrapper = document.getElementById('toolbar-wrapper')\r
11799
+ if (editorReadOnly || !toolbarWrapper) return\r
11800
+ clearTimeout(hideToolbarTimer)\r
11801
+ hideToolbarTimer = setTimeout(() => {\r
11802
+ toolbarWrapper.classList.remove('toolbar-hidden')\r
11803
+ toolbarHidden = false\r
11804
+ }, 100)\r
11805
+ }\r
11806
+ \r
11807
+ const sourceTextarea = document.getElementById('markdown-source-editor')\r
11808
+ if (sourceTextarea) {\r
11809
+ sourceTextarea.addEventListener('click', revealToolbarForSourceMode)\r
11810
+ }\r
11744
11811
  \r
11745
11812
  function updateTOC() {\r
11746
11813
  const tocNav = document.getElementById('toc-nav')\r
@@ -11806,9 +11873,9 @@
11806
11873
  })\r
11807
11874
  }\r
11808
11875
  \r
11809
- if (sourceTextarea) {
11810
- sourceTextarea.addEventListener('click', revealToolbarForSourceMode)
11811
- }
11876
+ if (sourceTextarea) {\r
11877
+ sourceTextarea.addEventListener('click', revealToolbarForSourceMode)\r
11878
+ }\r
11812
11879
  \r
11813
11880
  editorScroll.addEventListener('scroll', () => {\r
11814
11881
  const scrollTop = editorScroll.scrollTop\r
@@ -11860,27 +11927,71 @@
11860
11927
  window.scrollToHeading = scrollToHeading\r
11861
11928
  window.initTableFeatures = initTableFeatures\r
11862
11929
  window.initImagePreview = initImagePreview\r
11863
- })()
11864
- <\/script>
11865
- <script>
11866
- (function () {\r
11867
- var loadingFromHost = false\r
11868
- \r
11869
- function editorContent() {\r
11870
- return document.getElementById('doc-content')\r
11871
- }\r
11930
+ })()\r
11931
+ <\/script>\r
11932
+ <script>\r
11933
+ (function () {
11934
+ var loadingFromHost = false
11935
+ var toolbarScaleFrame = null
11936
+ var toolbarScaleResizeObserver = null
11937
+
11938
+ function editorContent() {
11939
+ return document.getElementById('doc-content')
11940
+ }
11872
11941
  \r
11873
11942
  function sourceEditor() {\r
11874
11943
  return document.getElementById('markdown-source-editor')\r
11875
11944
  }\r
11876
11945
  \r
11877
- function editorScroll() {\r
11878
- return document.querySelector('.editor-scroll')\r
11879
- }\r
11880
- \r
11881
- function revealToolbarForSourceMode() {\r
11882
- var toolbarWrapper = document.getElementById('toolbar-wrapper')\r
11883
- if (editorReadOnly || !toolbarWrapper) return\r
11946
+ function editorScroll() {
11947
+ return document.querySelector('.editor-scroll')
11948
+ }
11949
+
11950
+ function syncToolbarScale() {
11951
+ var toolbarWrapper = document.getElementById('toolbar-wrapper')
11952
+ var toolbar = toolbarWrapper ? toolbarWrapper.querySelector('.format-toolbar') : null
11953
+ if (!toolbarWrapper || !toolbar) return
11954
+
11955
+ toolbar.style.transform = 'scale(1)'
11956
+
11957
+ var availableWidth = Math.max(toolbarWrapper.clientWidth, 0)
11958
+ var naturalWidth = Math.max(toolbar.scrollWidth, 0)
11959
+ var scale = naturalWidth > 0 ? Math.min(1, availableWidth / naturalWidth) : 1
11960
+
11961
+ toolbar.style.transform = 'scale(' + scale + ')'
11962
+ toolbarWrapper.style.minHeight = Math.ceil(toolbar.offsetHeight * scale) + 'px'
11963
+ }
11964
+
11965
+ function scheduleToolbarScale() {
11966
+ if (toolbarScaleFrame !== null) cancelAnimationFrame(toolbarScaleFrame)
11967
+ toolbarScaleFrame = requestAnimationFrame(function () {
11968
+ toolbarScaleFrame = null
11969
+ syncToolbarScale()
11970
+ })
11971
+ }
11972
+
11973
+ function initToolbarResponsiveScale() {
11974
+ var toolbarWrapper = document.getElementById('toolbar-wrapper')
11975
+ var toolbar = toolbarWrapper ? toolbarWrapper.querySelector('.format-toolbar') : null
11976
+ if (!toolbarWrapper || !toolbar) return
11977
+
11978
+ if (toolbarScaleResizeObserver) {
11979
+ toolbarScaleResizeObserver.disconnect()
11980
+ }
11981
+
11982
+ if (typeof ResizeObserver === 'function') {
11983
+ toolbarScaleResizeObserver = new ResizeObserver(scheduleToolbarScale)
11984
+ toolbarScaleResizeObserver.observe(toolbarWrapper)
11985
+ toolbarScaleResizeObserver.observe(toolbar)
11986
+ }
11987
+
11988
+ window.addEventListener('resize', scheduleToolbarScale)
11989
+ scheduleToolbarScale()
11990
+ }
11991
+
11992
+ function revealToolbarForSourceMode() {
11993
+ var toolbarWrapper = document.getElementById('toolbar-wrapper')
11994
+ if (editorReadOnly || !toolbarWrapper) return
11884
11995
  clearTimeout(hideToolbarTimer)\r
11885
11996
  hideToolbarTimer = setTimeout(function () {\r
11886
11997
  toolbarWrapper.classList.remove('toolbar-hidden')\r
@@ -11888,18 +11999,18 @@
11888
11999
  }, 100)\r
11889
12000
  }\r
11890
12001
  \r
11891
- function syncSourceEditorHeight() {
11892
- var textarea = sourceEditor()
11893
- var scrollEl = editorScroll()
11894
- if (!textarea) return
11895
-
11896
- if (textarea.offsetParent === null && !sourceMode) return
11897
-
11898
- var previousScrollTop = scrollEl ? scrollEl.scrollTop : 0
11899
- textarea.style.height = 'auto'
11900
- textarea.style.height = Math.max(textarea.scrollHeight, 320) + 'px'
11901
- if (scrollEl) scrollEl.scrollTop = previousScrollTop
11902
- }
12002
+ function syncSourceEditorHeight() {\r
12003
+ var textarea = sourceEditor()\r
12004
+ var scrollEl = editorScroll()\r
12005
+ if (!textarea) return\r
12006
+ \r
12007
+ if (textarea.offsetParent === null && !sourceMode) return\r
12008
+ \r
12009
+ var previousScrollTop = scrollEl ? scrollEl.scrollTop : 0\r
12010
+ textarea.style.height = 'auto'\r
12011
+ textarea.style.height = Math.max(textarea.scrollHeight, 320) + 'px'\r
12012
+ if (scrollEl) scrollEl.scrollTop = previousScrollTop\r
12013
+ }\r
11903
12014
  \r
11904
12015
  function renderMarkdownToRichEditor(markdown, options) {\r
11905
12016
  var docContent = editorContent()\r
@@ -11910,25 +12021,26 @@
11910
12021
  hydrateMentionTokens(docContent)\r
11911
12022
  \r
11912
12023
  if (window.initCodeHighlight) window.initCodeHighlight()\r
11913
- if (window.initTableFeatures) window.initTableFeatures()\r
11914
- if (window.initImagePreview) window.initImagePreview()\r
11915
- if (window.updateTOC) window.updateTOC()\r
11916
- syncSourceEditorHeight()\r
11917
- syncEditorReadOnlyState()\r
11918
- \r
11919
- if (options && options.resetHistory !== false && window.resetEditorHistory) {\r
11920
- window.resetEditorHistory()\r
11921
- }\r
12024
+ if (window.initTableFeatures) window.initTableFeatures()
12025
+ if (window.initImagePreview) window.initImagePreview()
12026
+ if (window.updateTOC) window.updateTOC()
12027
+ syncSourceEditorHeight()
12028
+ syncEditorReadOnlyState()
12029
+ scheduleToolbarScale()
12030
+
12031
+ if (options && options.resetHistory !== false && window.resetEditorHistory) {
12032
+ window.resetEditorHistory()
12033
+ }
11922
12034
  }\r
11923
12035
  \r
11924
- function syncSourceModeUi() {
11925
- var toggle = document.getElementById('source-mode-toggle')
11926
- var textarea = sourceEditor()
11927
- document.body.classList.toggle('source-mode', sourceMode)
11928
-
11929
- if (toggle) {
11930
- toggle.classList.toggle('is-active', sourceMode)
11931
- toggle.setAttribute('aria-pressed', sourceMode ? 'true' : 'false')
12036
+ function syncSourceModeUi() {\r
12037
+ var toggle = document.getElementById('source-mode-toggle')\r
12038
+ var textarea = sourceEditor()\r
12039
+ document.body.classList.toggle('source-mode', sourceMode)\r
12040
+ \r
12041
+ if (toggle) {\r
12042
+ toggle.classList.toggle('is-active', sourceMode)\r
12043
+ toggle.setAttribute('aria-pressed', sourceMode ? 'true' : 'false')\r
11932
12044
  toggle.setAttribute('title', sourceMode ? '切换到渲染模式' : '切换到源码模式')\r
11933
12045
  toggle.setAttribute('aria-label', sourceMode ? '切换到渲染模式' : '切换到源码模式')\r
11934
12046
  }\r
@@ -11939,11 +12051,11 @@
11939
12051
  }\r
11940
12052
  }\r
11941
12053
  \r
11942
- function setSourceMode(nextMode, options) {
11943
- var textarea = sourceEditor()
11944
- var docContent = editorContent()
11945
- var scrollEl = editorScroll()
11946
- if (!textarea || !docContent) return
12054
+ function setSourceMode(nextMode, options) {\r
12055
+ var textarea = sourceEditor()\r
12056
+ var docContent = editorContent()\r
12057
+ var scrollEl = editorScroll()\r
12058
+ if (!textarea || !docContent) return\r
11947
12059
  \r
11948
12060
  var targetMode = !!nextMode\r
11949
12061
  if (sourceMode === targetMode) {\r
@@ -11953,7 +12065,7 @@
11953
12065
  \r
11954
12066
  clearPendingAutoSave()\r
11955
12067
  var previousScrollTop = scrollEl ? scrollEl.scrollTop : 0\r
11956
-
12068
+ \r
11957
12069
  if (targetMode) {
11958
12070
  textarea.value = getCurrentEditorMarkdown() || ''
11959
12071
  sourceModeInitialMarkdown = textarea.value || ''
@@ -11964,11 +12076,12 @@
11964
12076
  if (window.updateTOC) window.updateTOC()
11965
12077
  requestAnimationFrame(function () {
11966
12078
  syncSourceEditorHeight()
12079
+ scheduleToolbarScale()
11967
12080
  if (scrollEl) scrollEl.scrollTop = previousScrollTop
11968
12081
  if (!editorReadOnly && (!options || options.focus !== false)) {
11969
12082
  try {
11970
- textarea.focus({preventScroll: true})
11971
- } catch (err) {
12083
+ textarea.focus({preventScroll: true})\r
12084
+ } catch (err) {\r
11972
12085
  textarea.focus()\r
11973
12086
  }\r
11974
12087
  }\r
@@ -11976,28 +12089,29 @@
11976
12089
  return\r
11977
12090
  }\r
11978
12091
  \r
11979
- loadingFromHost = true
11980
- window._loadingContent = true
11981
- var sourceMarkdown = textarea.value || ''
11982
- var sourceWasModified = syncSourceModeDirtyState(sourceMarkdown)
11983
- sourceMode = false
12092
+ loadingFromHost = true\r
12093
+ window._loadingContent = true\r
12094
+ var sourceMarkdown = textarea.value || ''\r
12095
+ var sourceWasModified = syncSourceModeDirtyState(sourceMarkdown)\r
12096
+ sourceMode = false\r
11984
12097
  renderMarkdownToRichEditor(sourceMarkdown, {resetHistory: true})
11985
12098
  syncSourceModeUi()
11986
12099
  requestAnimationFrame(function () {
11987
12100
  loadingFromHost = false
11988
12101
  window._loadingContent = false
12102
+ scheduleToolbarScale()
11989
12103
  if (scrollEl) scrollEl.scrollTop = previousScrollTop
11990
12104
  if ((!options || options.notify !== false) && sourceWasModified && window.parent) {
11991
12105
  window.parent.postMessage({type: 'content-change', content: sourceMarkdown}, '*')
11992
- }
11993
- if (!editorReadOnly && (!options || options.focus !== false)) {
11994
- focusEditorContent()
11995
- }
11996
- sourceModeInitialMarkdown = sourceMarkdown
11997
- sourceModeDirty = false
11998
- resetSourceHistory()
11999
- })
12000
- }
12106
+ }\r
12107
+ if (!editorReadOnly && (!options || options.focus !== false)) {\r
12108
+ focusEditorContent()\r
12109
+ }\r
12110
+ sourceModeInitialMarkdown = sourceMarkdown\r
12111
+ sourceModeDirty = false\r
12112
+ resetSourceHistory()\r
12113
+ })\r
12114
+ }\r
12001
12115
  \r
12002
12116
  function toggleSourceMode() {\r
12003
12117
  if (editorReadOnly) {\r
@@ -12005,11 +12119,55 @@
12005
12119
  return\r
12006
12120
  }\r
12007
12121
  setSourceMode(!sourceMode)\r
12008
- }\r
12009
- \r
12010
- window.toggleSourceMode = toggleSourceMode\r
12011
- \r
12012
- function focusEditorContent() {\r
12122
+ }
12123
+
12124
+ window.toggleSourceMode = toggleSourceMode
12125
+
12126
+ function emitHostContentHeight() {
12127
+ if (!window.parent) return
12128
+ const body = document.body
12129
+ const docEl = document.documentElement
12130
+ const nextHeight = Math.max(
12131
+ body ? body.scrollHeight : 0,
12132
+ body ? body.offsetHeight : 0,
12133
+ docEl ? docEl.scrollHeight : 0,
12134
+ docEl ? docEl.offsetHeight : 0,
12135
+ )
12136
+ window.parent.postMessage({type: 'content-height-change', value: nextHeight}, '*')
12137
+ }
12138
+
12139
+ function scheduleHostContentHeightSync() {
12140
+ requestAnimationFrame(emitHostContentHeight)
12141
+ }
12142
+
12143
+ const hostHeightResizeObserver = typeof ResizeObserver === 'function'
12144
+ ? new ResizeObserver(scheduleHostContentHeightSync)
12145
+ : null
12146
+ const hostHeightMutationObserver = typeof MutationObserver === 'function'
12147
+ ? new MutationObserver(scheduleHostContentHeightSync)
12148
+ : null
12149
+
12150
+ requestAnimationFrame(function () {
12151
+ if (hostHeightResizeObserver) {
12152
+ hostHeightResizeObserver.observe(document.documentElement)
12153
+ if (document.body) {
12154
+ hostHeightResizeObserver.observe(document.body)
12155
+ }
12156
+ }
12157
+ if (hostHeightMutationObserver && document.body) {
12158
+ hostHeightMutationObserver.observe(document.body, {
12159
+ attributes: true,
12160
+ childList: true,
12161
+ characterData: true,
12162
+ subtree: true,
12163
+ })
12164
+ }
12165
+ window.addEventListener('resize', scheduleHostContentHeightSync)
12166
+ scheduleHostContentHeightSync()
12167
+ })
12168
+ initToolbarResponsiveScale()
12169
+
12170
+ function focusEditorContent() {
12013
12171
  var docContent = editorContent()\r
12014
12172
  if (sourceMode) {\r
12015
12173
  var textarea = sourceEditor()\r
@@ -12041,19 +12199,19 @@
12041
12199
  }\r
12042
12200
  }\r
12043
12201
  \r
12044
- function applySourceTextUpdate(nextValue, selectionStart, selectionEnd) {
12045
- var state = getSourceSelection()
12046
- if (!state) return
12047
-
12048
- state.textarea.value = nextValue
12049
- syncSourceModeDirtyState(nextValue)
12050
- state.textarea.focus({preventScroll: true})
12051
- state.textarea.setSelectionRange(selectionStart, selectionEnd)
12052
- syncSourceEditorHeight()
12053
- if (window.updateTOC) window.updateTOC()
12054
- recordSourceHistory()
12055
- scheduleAutoSave()
12056
- }
12202
+ function applySourceTextUpdate(nextValue, selectionStart, selectionEnd) {\r
12203
+ var state = getSourceSelection()\r
12204
+ if (!state) return\r
12205
+ \r
12206
+ state.textarea.value = nextValue\r
12207
+ syncSourceModeDirtyState(nextValue)\r
12208
+ state.textarea.focus({preventScroll: true})\r
12209
+ state.textarea.setSelectionRange(selectionStart, selectionEnd)\r
12210
+ syncSourceEditorHeight()\r
12211
+ if (window.updateTOC) window.updateTOC()\r
12212
+ recordSourceHistory()\r
12213
+ scheduleAutoSave()\r
12214
+ }\r
12057
12215
  \r
12058
12216
  function replaceSourceSelection(replacement, selectionStart, selectionEnd) {\r
12059
12217
  var state = getSourceSelection()\r
@@ -12244,73 +12402,60 @@
12244
12402
  })\r
12245
12403
  }\r
12246
12404
  \r
12247
- function loadContent(content, filename, path, options) {
12248
- var docContent = editorContent()
12249
- var textarea = sourceEditor()
12250
- var scrollEl = editorScroll()
12251
- if (!docContent) return
12252
-
12253
- loadingFromHost = true
12254
- window._loadingContent = true
12255
-
12256
- var restoreView = !!(options && options.restoreView)
12257
- var targetScrollTop = options && typeof options.scrollPosition === 'number'
12258
- ? Number(options.scrollPosition) || 0
12259
- : null
12260
- var cursorInfo = restoreView ? null : getCursorCharOffset()
12261
- var markdown = content || ''
12262
- renderMarkdownToRichEditor(markdown, {resetHistory: false})
12263
- if (textarea) {
12264
- textarea.value = markdown
12265
- sourceModeInitialMarkdown = markdown
12266
- sourceModeDirty = false
12267
- resetSourceHistory()
12268
- textarea.setSelectionRange(0, 0)
12269
- logSourceDebug('loadContent:afterTextareaReset', {
12270
- restoreView,
12271
- targetScrollTop,
12272
- markdownLength: markdown.length,
12273
- })
12274
- if (sourceMode) {
12275
- requestAnimationFrame(function () {
12276
- syncSourceEditorHeight()
12277
- if (scrollEl && targetScrollTop !== null) {
12278
- scrollEl.scrollTop = targetScrollTop
12279
- }
12280
- logSourceDebug('loadContent:sourceModeRaf', {
12281
- restoreView,
12282
- targetScrollTop,
12283
- })
12284
- })
12285
- }
12286
- }
12405
+ function loadContent(content, filename, path, options) {\r
12406
+ var docContent = editorContent()\r
12407
+ var textarea = sourceEditor()\r
12408
+ var scrollEl = editorScroll()\r
12409
+ if (!docContent) return\r
12410
+ \r
12411
+ loadingFromHost = true\r
12412
+ window._loadingContent = true\r
12413
+ \r
12414
+ var restoreView = !!(options && options.restoreView)\r
12415
+ var targetScrollTop = options && typeof options.scrollPosition === 'number'\r
12416
+ ? Number(options.scrollPosition) || 0\r
12417
+ : null\r
12418
+ var cursorInfo = restoreView ? null : getCursorCharOffset()\r
12419
+ var markdown = content || ''\r
12420
+ renderMarkdownToRichEditor(markdown, {resetHistory: false})\r
12421
+ if (textarea) {\r
12422
+ textarea.value = markdown\r
12423
+ sourceModeInitialMarkdown = markdown\r
12424
+ sourceModeDirty = false\r
12425
+ resetSourceHistory()\r
12426
+ textarea.setSelectionRange(0, 0)\r
12427
+ if (sourceMode) {\r
12428
+ requestAnimationFrame(function () {\r
12429
+ syncSourceEditorHeight()\r
12430
+ if (scrollEl && targetScrollTop !== null) {\r
12431
+ scrollEl.scrollTop = targetScrollTop\r
12432
+ }\r
12433
+ })\r
12434
+ }\r
12435
+ }\r
12287
12436
  docContent.setAttribute('data-filename', filename || '')\r
12288
- docContent.setAttribute('data-initial-path', path || filename || '')
12289
- setTitleFromFilename(filename || '')
12290
-
12437
+ docContent.setAttribute('data-initial-path', path || filename || '')\r
12438
+ setTitleFromFilename(filename || '')\r
12439
+ \r
12291
12440
  syncEditorReadOnlyState()
12292
12441
  document.body.classList.remove('editor-booting')
12293
- if (scrollEl && targetScrollTop !== null) {
12294
- scrollEl.scrollTop = targetScrollTop
12295
- }
12296
- if (!sourceMode && !restoreView) {
12297
- setCursorByCharOffset(cursorInfo)
12298
- focusEditorContent()
12299
- }
12300
- if (window.resetEditorHistory) window.resetEditorHistory()
12301
-
12302
- requestAnimationFrame(function () {
12303
- if (scrollEl && targetScrollTop !== null) {
12304
- scrollEl.scrollTop = targetScrollTop
12305
- }
12306
- logSourceDebug('loadContent:finalRaf', {
12307
- restoreView,
12308
- targetScrollTop,
12309
- })
12310
- loadingFromHost = false
12311
- window._loadingContent = false
12312
- })
12313
- }
12442
+ if (scrollEl && targetScrollTop !== null) {\r
12443
+ scrollEl.scrollTop = targetScrollTop\r
12444
+ }\r
12445
+ if (!sourceMode && !restoreView) {\r
12446
+ setCursorByCharOffset(cursorInfo)\r
12447
+ focusEditorContent()\r
12448
+ }\r
12449
+ if (window.resetEditorHistory) window.resetEditorHistory()\r
12450
+ \r
12451
+ requestAnimationFrame(function () {\r
12452
+ if (scrollEl && targetScrollTop !== null) {\r
12453
+ scrollEl.scrollTop = targetScrollTop\r
12454
+ }\r
12455
+ loadingFromHost = false\r
12456
+ window._loadingContent = false\r
12457
+ })\r
12458
+ }\r
12314
12459
  \r
12315
12460
  function notifyContentChange() {\r
12316
12461
  if (loadingFromHost || window._loadingContent) return\r
@@ -12335,13 +12480,13 @@
12335
12480
  window.addEventListener('message', function (event) {\r
12336
12481
  if (!event.data || typeof event.data !== 'object') return\r
12337
12482
  \r
12338
- if (event.data.type === 'load-content') {
12339
- loadContent(event.data.content || '', event.data.filename || '', event.data.path || '', {
12340
- scrollPosition: event.data.scrollPosition,
12341
- restoreView: !!event.data.restoreView,
12342
- })
12343
- return
12344
- }
12483
+ if (event.data.type === 'load-content') {\r
12484
+ loadContent(event.data.content || '', event.data.filename || '', event.data.path || '', {\r
12485
+ scrollPosition: event.data.scrollPosition,\r
12486
+ restoreView: !!event.data.restoreView,\r
12487
+ })\r
12488
+ return\r
12489
+ }\r
12345
12490
  \r
12346
12491
  if (event.data.type === 'apply-settings') {
12347
12492
  if (typeof event.data.theme === 'string') {
@@ -12367,69 +12512,68 @@
12367
12512
  return\r
12368
12513
  }\r
12369
12514
  \r
12370
- if (event.data.type === 'apply-scroll') {
12371
- var scrollEl = editorScroll()
12372
- if (scrollEl) scrollEl.scrollTop = Number(event.data.position) || 0
12373
- return
12374
- }
12375
- })
12515
+ if (event.data.type === 'apply-scroll') {\r
12516
+ var scrollEl = editorScroll()\r
12517
+ if (scrollEl) scrollEl.scrollTop = Number(event.data.position) || 0\r
12518
+ return\r
12519
+ }\r
12520
+ })\r
12376
12521
  \r
12377
- document.addEventListener('DOMContentLoaded', function () {
12378
- var docContent = editorContent()
12379
- var scrollEl = editorScroll()
12380
- var textarea = sourceEditor()
12522
+ document.addEventListener('DOMContentLoaded', function () {\r
12523
+ var docContent = editorContent()\r
12524
+ var scrollEl = editorScroll()\r
12525
+ var textarea = sourceEditor()\r
12381
12526
  \r
12382
12527
  if (docContent) {\r
12383
12528
  docContent.addEventListener('input', notifyContentChange)\r
12384
12529
  }\r
12385
12530
  \r
12386
- if (textarea) {
12387
- textarea.addEventListener('click', function () {
12388
- revealToolbarForSourceMode()
12389
- })
12390
- textarea.addEventListener('keydown', handleSourceKeydown)
12391
- textarea.addEventListener('select', function () {
12392
- if (!sourceMode) return
12393
- logSourceDebug('textarea:select')
12394
- })
12395
- textarea.addEventListener('input', function () {
12396
- if (editorReadOnly) return
12397
- syncSourceModeDirtyState(textarea.value || '')
12398
- requestAnimationFrame(function () {
12399
- syncSourceEditorHeight()
12400
- if (window.updateTOC) window.updateTOC()
12401
- })
12402
- recordSourceHistory()
12403
- scheduleAutoSave()
12404
- })
12405
- }
12531
+ if (textarea) {\r
12532
+ textarea.addEventListener('click', function () {\r
12533
+ revealToolbarForSourceMode()\r
12534
+ })\r
12535
+ textarea.addEventListener('copy', function (event) {\r
12536
+ if (!editorReadOnly) return\r
12537
+ if (copyReadOnlySelection(event)) {\r
12538
+ event.preventDefault()\r
12539
+ }\r
12540
+ })\r
12541
+ textarea.addEventListener('keydown', handleSourceKeydown)\r
12542
+ textarea.addEventListener('input', function () {\r
12543
+ if (editorReadOnly) return\r
12544
+ syncSourceModeDirtyState(textarea.value || '')\r
12545
+ requestAnimationFrame(function () {\r
12546
+ syncSourceEditorHeight()\r
12547
+ if (window.updateTOC) window.updateTOC()\r
12548
+ })\r
12549
+ recordSourceHistory()\r
12550
+ scheduleAutoSave()\r
12551
+ })\r
12552
+ }\r
12406
12553
  \r
12407
- if (scrollEl) {
12408
- var scrollTimer = null
12409
- scrollEl.addEventListener('scroll', function () {
12410
- if (sourceMode) {
12411
- logSourceDebug('editorScroll:scroll')
12412
- }
12413
- clearTimeout(scrollTimer)
12414
- scrollTimer = setTimeout(notifyScrollPosition, 100)
12415
- })
12416
- }
12417
- syncSourceModeUi()
12418
- window.parent.postMessage({type: 'editor-ready'}, '*')
12419
- })
12420
-
12421
- window.sourceEditor = sourceEditor
12422
- window.syncSourceEditorHeight = syncSourceEditorHeight
12423
- window.revealToolbarForSourceMode = revealToolbarForSourceMode
12424
- window.getSourceSelection = getSourceSelection
12425
- window.applySourceTextUpdate = applySourceTextUpdate
12426
- window.replaceSourceSelection = replaceSourceSelection
12427
- window.wrapSourceSelection = wrapSourceSelection
12428
- window.transformSelectedSourceLines = transformSelectedSourceLines
12429
- window.sourceTogglePrefix = sourceTogglePrefix
12430
- window.sourceInsertBlock = sourceInsertBlock
12431
- })()
12432
- <\/script>
12554
+ if (scrollEl) {\r
12555
+ var scrollTimer = null\r
12556
+ scrollEl.addEventListener('scroll', function () {\r
12557
+ clearTimeout(scrollTimer)\r
12558
+ scrollTimer = setTimeout(notifyScrollPosition, 100)\r
12559
+ })\r
12560
+ }\r
12561
+ syncSourceModeUi()\r
12562
+ window.parent.postMessage({type: 'editor-ready'}, '*')\r
12563
+ })\r
12564
+ \r
12565
+ window.sourceEditor = sourceEditor\r
12566
+ window.syncSourceEditorHeight = syncSourceEditorHeight\r
12567
+ window.revealToolbarForSourceMode = revealToolbarForSourceMode\r
12568
+ window.getSourceSelection = getSourceSelection\r
12569
+ window.applySourceTextUpdate = applySourceTextUpdate\r
12570
+ window.replaceSourceSelection = replaceSourceSelection\r
12571
+ window.wrapSourceSelection = wrapSourceSelection\r
12572
+ window.transformSelectedSourceLines = transformSelectedSourceLines\r
12573
+ window.sourceTogglePrefix = sourceTogglePrefix\r
12574
+ window.sourceInsertBlock = sourceInsertBlock\r
12575
+ })()\r
12576
+ <\/script>\r
12433
12577
  <script>\r
12434
12578
  (function () {\r
12435
12579
  var wikiDocuments = []\r
@@ -14519,4 +14663,4 @@
14519
14663
  <\/script>\r
14520
14664
  </body>\r
14521
14665
  </html>\r
14522
- `,q="qzhuli-markdown-wysiwyg",k="markdown-editor-wysiwyg.html",X=`./editor/${k}`,_=`editor/${k}`,G=`node_modules/${q}/dist/editor/${k}`,$="__QZHULI_MARKDOWN_WYSIWYG_RUNTIME_URL__",AA='meta[name="qzhuli-markdown-wysiwyg-runtime-url"]',V=/\/node_modules\/\.vite\/deps\/[^/?#]*qzhuli-markdown-wysiwyg[^/?#]*\.js(?:[?#].*)?$/i,g=(t,i)=>{const o=String(i||"").trim();!o||t.includes(o)||t.push(o)},eA=()=>typeof window>"u"?"":String(window[$]||"").trim(),nA=()=>{if(typeof document>"u")return"";const t=document.querySelector(AA);return String((t==null?void 0:t.getAttribute("content"))||"").trim()},rA=()=>new URL(X,typeof document>"u"?require("url").pathToFileURL(__filename).href:u&&u.tagName.toUpperCase()==="SCRIPT"&&u.src||new URL("index.cjs",document.baseURI).href).href,tA=()=>typeof document>"u"||!document.baseURI?"":new URL(_,document.baseURI).href,aA=()=>typeof document>"u"||!document.baseURI?"":new URL(G,document.baseURI).href,iA=()=>{const t=String((typeof document>"u"?require("url").pathToFileURL(__filename).href:u&&u.tagName.toUpperCase()==="SCRIPT"&&u.src||new URL("index.cjs",document.baseURI).href)||"").trim();return!t||!V.test(t)?"":t.replace(V,`/${G}`)},H=t=>String(t||"").trim().length>0,Y=t=>{const i=[];return g(i,t),i.length>0||(g(i,eA()),g(i,nA()),g(i,iA()),g(i,aA()),g(i,tA()),g(i,rA())),i},oA=t=>{if(typeof window>"u")return!1;try{return new URL(t,window.location.href).origin===window.location.origin}catch{return!1}},sA=async t=>{const i=String(t||"").trim();if(!i)return!1;if(typeof window>"u"||typeof fetch!="function"||!oA(i))return!0;try{const o=await fetch(i,{method:"HEAD",cache:"no-store",credentials:"same-origin"});if(o.ok)return!0;if(o.status!==405&&o.status!==501)return!1}catch{}try{return(await fetch(i,{method:"GET",cache:"no-store",credentials:"same-origin"})).ok}catch{return!1}},lA=t=>Y(t)[0]||"",cA=["src","srcdoc","title"],D=r.defineComponent({name:"MarkdownEditorWysiwyg",__name:"MarkdownEditorWysiwyg",props:{modelValue:{default:""},readOnly:{type:Boolean,default:!1},viewMode:{},theme:{default:"system"},filename:{default:""},path:{default:""},runtimeUrl:{default:""},iframeTitle:{default:"Markdown WYSIWYG editor"},atUserList:{default:()=>[]}},emits:["update:modelValue","change","ready","scroll","get-at-list","at-who","mention-click","file-save"],setup(t,{expose:i,emit:o}){const a=t,l=o,C=r.ref(null),Q=r.getCurrentInstance(),F=()=>{var A;const e=(A=Q==null?void 0:Q.subTree)==null?void 0:A.el;C.value=e instanceof HTMLIFrameElement?e:null},c=r.ref(!1),U=r.ref(0),d=r.ref(""),M=r.ref(""),B=r.ref(0),p=r.ref(a.modelValue??""),x=r.ref(a.filename??""),y=r.ref(a.path??""),w=r.ref(0),z=r.computed(()=>P(a.atUserList)),j=r.computed(()=>h.trim().length>0),v=r.computed(()=>!H(a.runtimeUrl)&&j.value),W=r.computed(()=>a.viewMode?a.viewMode:a.readOnly?"readonly":"default"),T=r.computed(()=>Y(a.runtimeUrl)),N=r.computed(()=>a.viewMode?a.viewMode:a.readOnly?"readonly":v.value?"write":W.value),I=async()=>{const e=w.value+1;if(w.value=e,v.value){d.value="",M.value=h;return}const A=T.value;if(A.length===0){d.value="",M.value="";return}if(M.value="",H(a.runtimeUrl)){d.value=A[0]||"";return}for(const n of A){const s=await sA(n);if(w.value!==e)return;if(s){d.value=n;return}}d.value=A[0]||""},m=e=>{var A,n;(n=(A=C.value)==null?void 0:A.contentWindow)==null||n.postMessage(e,"*")},E=(e,A)=>{if(typeof e=="string"){const f=e.trim();return{id:f||A,name:f,displayName:f,label:f,subtitle:"",keywords:[],searchTerms:[]}}const n=String(e.name||e.displayName||e.label||"").trim(),s=String(e.displayName||e.label||e.name||"").trim(),b=String(e.subtitle||"").trim();return{id:e.id??n??s??A,name:n||s,displayName:s||n,label:s||n,avatar:String(e.avatar||"").trim(),subtitle:b,keywords:Array.isArray(e.keywords)?[...e.keywords]:[],searchTerms:Array.isArray(e.searchTerms)?[...e.searchTerms]:[]}},P=(e=[])=>e.map((A,n)=>E(A,n)),L=()=>{const e=a.modelValue??"",A=a.filename??"",n=a.path??"";m({type:"load-content",content:e,filename:A,path:n}),p.value=e,x.value=A,y.value=n},R=()=>{m({type:"apply-settings",theme:a.theme,readOnly:N.value==="readonly",viewMode:N.value})},K=()=>{m({type:"set-host-mode",mode:"external"})},J=(e=B.value)=>{m({type:"set-at-list",requestId:e,users:z.value})},O=()=>{c.value&&(K(),L(),R(),J())},Z=()=>{c.value=!1,B.value=0,w.value+=1,U.value+=1,I()},S=e=>{if(C.value&&e.source!==C.value.contentWindow||!e.data||typeof e.data!="object")return;const A=e.data;if(A.type==="editor-ready"){c.value=!0,l("ready"),O();return}if(A.type==="get-at-list"){const n=Number(A.requestId)||Date.now();B.value=n;const s={requestId:n,query:String(A.query||"")};l("get-at-list",s);return}if(A.type==="at-who"){if(!A.user)return;const n={requestId:Number(A.requestId)||B.value||Date.now(),value:String(A.value||""),user:E(A.user,0)};l("at-who",n);return}if(A.type==="mention-click"){if(!A.user)return;const n={value:String(A.value||""),user:E(A.user,0)};l("mention-click",n);return}if(A.type==="file-save"){const n={content:String(A.content??""),filename:String(A.filename??a.filename??""),path:String(A.path??a.path??"")};l("file-save",n);return}if(A.type==="content-change"){const n=A.content??"";p.value=n,l("update:modelValue",n),l("change",n);return}A.type==="scroll-position"&&l("scroll",Number(A.position)||0)};return r.watch(T,()=>{c.value=!1,B.value=0,I()},{deep:!0}),r.watch(()=>[a.modelValue,a.filename,a.path],([e,A,n])=>{if(!c.value)return;const s=e??"",b=A??"",f=n??"";s===p.value&&b===x.value&&f===y.value||L()}),r.watch(()=>[a.readOnly,a.viewMode,a.theme],()=>{c.value&&R()}),r.watch(z,()=>{c.value&&J()},{deep:!0}),i({reload:Z,postMessage:m}),r.onMounted(()=>{F(),window.addEventListener("message",S),I()}),r.onUpdated(()=>{F()}),r.onBeforeUnmount(()=>{w.value+=1,window.removeEventListener("message",S)}),(e,A)=>(r.openBlock(),r.createElementBlock("iframe",{key:U.value,src:d.value||void 0,srcdoc:M.value||void 0,title:t.iframeTitle,class:"markdown-editor-wysiwyg-frame",style:{display:"block",width:"100%",height:"100%",border:"0"}},null,8,cA))}}),gA=()=>h,dA={install(t){t.component("MarkdownEditorWysiwyg",D)}};exports.MarkdownEditorWysiwyg=D;exports.MarkdownEditorWysiwygPlugin=dA;exports.default=D;exports.embeddedRuntimeHtml=h;exports.getEmbeddedRuntimeHtml=gA;exports.resolveEditorRuntimeUrl=lA;exports.resolveEditorRuntimeUrls=Y;
14666
+ `,_="qzhuli-markdown-wysiwyg",D="markdown-editor-wysiwyg.html",$=`./editor/${D}`,AA=`editor/${D}`,j=`node_modules/${_}/dist/editor/${D}`,eA="__QZHULI_MARKDOWN_WYSIWYG_RUNTIME_URL__",nA='meta[name="qzhuli-markdown-wysiwyg-runtime-url"]',H=/\/node_modules\/\.vite\/deps\/[^/?#]*qzhuli-markdown-wysiwyg[^/?#]*\.js(?:[?#].*)?$/i,g=(t,i)=>{const o=String(i||"").trim();!o||t.includes(o)||t.push(o)},rA=()=>typeof window>"u"?"":String(window[eA]||"").trim(),tA=()=>{if(typeof document>"u")return"";const t=document.querySelector(nA);return String((t==null?void 0:t.getAttribute("content"))||"").trim()},aA=()=>new URL($,typeof document>"u"?require("url").pathToFileURL(__filename).href:u&&u.tagName.toUpperCase()==="SCRIPT"&&u.src||new URL("index.cjs",document.baseURI).href).href,iA=()=>typeof document>"u"||!document.baseURI?"":new URL(AA,document.baseURI).href,oA=()=>typeof document>"u"||!document.baseURI?"":new URL(j,document.baseURI).href,sA=()=>{const t=String((typeof document>"u"?require("url").pathToFileURL(__filename).href:u&&u.tagName.toUpperCase()==="SCRIPT"&&u.src||new URL("index.cjs",document.baseURI).href)||"").trim();return!t||!H.test(t)?"":t.replace(H,`/${j}`)},G=t=>String(t||"").trim().length>0,F=t=>{const i=[];return g(i,t),i.length>0||(g(i,rA()),g(i,tA()),g(i,sA()),g(i,oA()),g(i,iA()),g(i,aA())),i},lA=t=>{if(typeof window>"u")return!1;try{return new URL(t,window.location.href).origin===window.location.origin}catch{return!1}},cA=async t=>{const i=String(t||"").trim();if(!i)return!1;if(typeof window>"u"||typeof fetch!="function"||!lA(i))return!0;try{const o=await fetch(i,{method:"HEAD",cache:"no-store",credentials:"same-origin"});if(o.ok)return!0;if(o.status!==405&&o.status!==501)return!1}catch{}try{return(await fetch(i,{method:"GET",cache:"no-store",credentials:"same-origin"})).ok}catch{return!1}},gA=t=>F(t)[0]||"",dA=["src","srcdoc","title"],U=r.defineComponent({name:"MarkdownEditorWysiwyg",__name:"MarkdownEditorWysiwyg",props:{modelValue:{default:""},readOnly:{type:Boolean,default:!1},viewMode:{},theme:{default:"system"},filename:{default:""},path:{default:""},runtimeUrl:{default:""},iframeTitle:{default:"Markdown WYSIWYG editor"},atUserList:{default:()=>[]}},emits:["update:modelValue","change","ready","scroll","get-at-list","at-who","mention-click","file-save"],setup(t,{expose:i,emit:o}){const a=t,l=o,C=r.ref(null),I=r.getCurrentInstance(),x=()=>{var A;const e=(A=I==null?void 0:I.subTree)==null?void 0:A.el;C.value=e instanceof HTMLIFrameElement?e:null},c=r.ref(!1),y=r.ref(0),d=r.ref(""),M=r.ref(""),h=r.ref(0),B=r.ref(0),E=r.ref(a.modelValue??""),z=r.ref(a.filename??""),v=r.ref(a.path??""),w=r.ref(0),T=r.computed(()=>O(a.atUserList)),W=r.computed(()=>p.trim().length>0),Q=r.computed(()=>!G(a.runtimeUrl)&&W.value),P=r.computed(()=>a.viewMode?a.viewMode:a.readOnly?"readonly":"default"),N=r.computed(()=>F(a.runtimeUrl)),L=r.computed(()=>a.viewMode?a.viewMode:a.readOnly?"readonly":Q.value?"write":P.value),K=r.computed(()=>({display:"block",width:"100%",height:Q.value&&h.value>0?`${h.value}px`:"100%",border:"0"})),b=async()=>{const e=w.value+1;if(w.value=e,Q.value){d.value="",M.value=p;return}const A=N.value;if(A.length===0){d.value="",M.value="";return}if(M.value="",G(a.runtimeUrl)){d.value=A[0]||"";return}for(const n of A){const s=await cA(n);if(w.value!==e)return;if(s){d.value=n;return}}d.value=A[0]||""},m=e=>{var A,n;(n=(A=C.value)==null?void 0:A.contentWindow)==null||n.postMessage(e,"*")},k=(e,A)=>{if(typeof e=="string"){const f=e.trim();return{id:f||A,name:f,displayName:f,label:f,subtitle:"",keywords:[],searchTerms:[]}}const n=String(e.name||e.displayName||e.label||"").trim(),s=String(e.displayName||e.label||e.name||"").trim(),Y=String(e.subtitle||"").trim();return{id:e.id??n??s??A,name:n||s,displayName:s||n,label:s||n,avatar:String(e.avatar||"").trim(),subtitle:Y,keywords:Array.isArray(e.keywords)?[...e.keywords]:[],searchTerms:Array.isArray(e.searchTerms)?[...e.searchTerms]:[]}},O=(e=[])=>e.map((A,n)=>k(A,n)),R=()=>{const e=a.modelValue??"",A=a.filename??"",n=a.path??"";m({type:"load-content",content:e,filename:A,path:n}),E.value=e,z.value=A,v.value=n},J=()=>{m({type:"apply-settings",theme:a.theme,readOnly:L.value==="readonly",viewMode:L.value})},Z=()=>{m({type:"set-host-mode",mode:"external"})},S=(e=B.value)=>{m({type:"set-at-list",requestId:e,users:T.value})},q=()=>{c.value&&(Z(),R(),J(),S())},X=()=>{c.value=!1,h.value=0,B.value=0,w.value+=1,y.value+=1,b()},V=e=>{if(C.value&&e.source!==C.value.contentWindow||!e.data||typeof e.data!="object")return;const A=e.data;if(A.type==="editor-ready"){c.value=!0,l("ready"),q();return}if(A.type==="content-height-change"){if(!Q.value)return;h.value=Math.max(Number(A.value)||0,320);return}if(A.type==="get-at-list"){const n=Number(A.requestId)||Date.now();B.value=n;const s={requestId:n,query:String(A.query||"")};l("get-at-list",s);return}if(A.type==="at-who"){if(!A.user)return;const n={requestId:Number(A.requestId)||B.value||Date.now(),value:String(A.value||""),user:k(A.user,0)};l("at-who",n);return}if(A.type==="mention-click"){if(!A.user)return;const n={value:String(A.value||""),user:k(A.user,0)};l("mention-click",n);return}if(A.type==="file-save"){const n={content:String(A.content??""),filename:String(A.filename??a.filename??""),path:String(A.path??a.path??"")};l("file-save",n);return}if(A.type==="content-change"){const n=A.content??"";E.value=n,l("update:modelValue",n),l("change",n);return}A.type==="scroll-position"&&l("scroll",Number(A.position)||0)};return r.watch(N,()=>{c.value=!1,B.value=0,b()},{deep:!0}),r.watch(()=>[a.modelValue,a.filename,a.path],([e,A,n])=>{if(!c.value)return;const s=e??"",Y=A??"",f=n??"";s===E.value&&Y===z.value&&f===v.value||R()}),r.watch(()=>[a.readOnly,a.viewMode,a.theme],()=>{c.value&&J()}),r.watch(T,()=>{c.value&&S()},{deep:!0}),i({reload:X,postMessage:m}),r.onMounted(()=>{x(),window.addEventListener("message",V),b()}),r.onUpdated(()=>{x()}),r.onBeforeUnmount(()=>{w.value+=1,window.removeEventListener("message",V)}),(e,A)=>(r.openBlock(),r.createElementBlock("iframe",{key:y.value,src:d.value||void 0,srcdoc:M.value||void 0,title:t.iframeTitle,class:"markdown-editor-wysiwyg-frame",style:r.normalizeStyle(K.value)},null,12,dA))}}),fA=()=>p,uA={install(t){t.component("MarkdownEditorWysiwyg",U)}};exports.MarkdownEditorWysiwyg=U;exports.MarkdownEditorWysiwygPlugin=uA;exports.default=U;exports.embeddedRuntimeHtml=p;exports.getEmbeddedRuntimeHtml=fA;exports.resolveEditorRuntimeUrl=gA;exports.resolveEditorRuntimeUrls=F;