initUI.ts 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import {i18n} from "../i18n";
  2. import {html2md} from "../sv/html2md";
  3. import {setEditMode} from "../toolbar/EditMode";
  4. import {setContentTheme} from "./setContentTheme";
  5. import {setTheme} from "./setTheme";
  6. declare global {
  7. interface Window {
  8. visualViewport: HTMLElement;
  9. }
  10. }
  11. export const initUI = (vditor: IVditor) => {
  12. vditor.element.innerHTML = "";
  13. vditor.element.classList.add("vditor");
  14. setTheme(vditor);
  15. setContentTheme(vditor.options.preview.markdown.theme, vditor.options.cdn);
  16. if (typeof vditor.options.height === "number") {
  17. vditor.element.style.height = vditor.options.height + "px";
  18. }
  19. if (typeof vditor.options.minHeight === "number") {
  20. vditor.element.style.minHeight = vditor.options.minHeight + "px";
  21. }
  22. if (typeof vditor.options.width === "number") {
  23. vditor.element.style.width = vditor.options.width + "px";
  24. } else {
  25. vditor.element.style.width = vditor.options.width;
  26. }
  27. vditor.element.appendChild(vditor.toolbar.element);
  28. const contentElement = document.createElement("div");
  29. contentElement.className = "vditor-content";
  30. if (vditor.toolbar.elements.outline) {
  31. const outlineElement = document.createElement("div");
  32. outlineElement.className = "vditor-outline";
  33. outlineElement.innerHTML = `<div class="vditor-outline__title">${i18n[vditor.options.lang].outline}</div>
  34. <div class="vditor-outline__content"></div>`;
  35. contentElement.appendChild(outlineElement);
  36. }
  37. contentElement.appendChild(vditor.wysiwyg.element.parentElement);
  38. contentElement.appendChild(vditor.sv.element);
  39. contentElement.appendChild(vditor.ir.element.parentElement);
  40. if (vditor.preview) {
  41. contentElement.appendChild(vditor.preview.element);
  42. }
  43. if (vditor.toolbar.elements.devtools) {
  44. contentElement.appendChild(vditor.devtools.element);
  45. }
  46. if (vditor.upload) {
  47. contentElement.appendChild(vditor.upload.element);
  48. }
  49. if (vditor.options.resize.enable) {
  50. contentElement.appendChild(vditor.resize.element);
  51. }
  52. contentElement.appendChild(vditor.hint.element);
  53. contentElement.appendChild(vditor.tip.element);
  54. vditor.element.appendChild(contentElement);
  55. if (vditor.toolbar.elements.export) {
  56. // for export pdf
  57. vditor.element.insertAdjacentHTML("beforeend",
  58. '<iframe style="width: 100%;height: 0;border: 0"></iframe>');
  59. }
  60. setEditMode(vditor, vditor.options.mode, afterRender(vditor, contentElement));
  61. if (navigator.userAgent.indexOf("iPhone") > -1 && typeof window.visualViewport !== "undefined") {
  62. // https://github.com/Vanessa219/vditor/issues/379
  63. let pendingUpdate = false;
  64. const viewportHandler = (event: Event) => {
  65. if (pendingUpdate) {
  66. return;
  67. }
  68. pendingUpdate = true;
  69. requestAnimationFrame(() => {
  70. pendingUpdate = false;
  71. const layoutViewport = vditor.toolbar.element;
  72. layoutViewport.style.transform = "none";
  73. if (layoutViewport.getBoundingClientRect().top < 0) {
  74. layoutViewport.style.transform = `translate(0, ${-layoutViewport.getBoundingClientRect().top}px)`;
  75. }
  76. });
  77. };
  78. window.visualViewport.addEventListener("scroll", viewportHandler);
  79. window.visualViewport.addEventListener("resize", viewportHandler);
  80. }
  81. };
  82. export const setPadding = (vditor: IVditor) => {
  83. const minPadding = window.innerWidth <= 520 ? 10 : 35;
  84. if (vditor.wysiwyg.element.parentElement.style.display !== "none") {
  85. const padding = (vditor.wysiwyg.element.parentElement.clientWidth
  86. - vditor.options.preview.maxWidth) / 2;
  87. vditor.wysiwyg.element.style.padding = `10px ${Math.max(minPadding, padding)}px`;
  88. }
  89. if (vditor.ir.element.parentElement.style.display !== "none") {
  90. const padding = (vditor.ir.element.parentElement.clientWidth
  91. - vditor.options.preview.maxWidth) / 2;
  92. vditor.ir.element.style.padding = `10px ${Math.max(minPadding, padding)}px`;
  93. }
  94. if ((vditor.element.querySelector(".vditor-preview") as HTMLElement)?.style.display !== "block"
  95. || vditor.currentMode === "sv") {
  96. vditor.toolbar.element.style.paddingLeft = Math.max(5,
  97. parseInt(vditor[vditor.currentMode].element.style.paddingLeft || "0", 10) + 250) + "px";
  98. }
  99. };
  100. export const setTypewriterPosition = (vditor: IVditor) => {
  101. if (!vditor.options.typewriterMode) {
  102. return;
  103. }
  104. let height: number = window.innerHeight;
  105. if (typeof vditor.options.height === "number") {
  106. height = vditor.options.height;
  107. if (typeof vditor.options.minHeight === "number") {
  108. height = Math.max(height, vditor.options.minHeight);
  109. }
  110. height = Math.min(window.innerHeight, height);
  111. }
  112. if (vditor.element.classList.contains("vditor--fullscreen")) {
  113. height = window.innerHeight;
  114. }
  115. // 由于 Firefox padding-bottom bug,只能使用 :after
  116. vditor[vditor.currentMode].element.style.setProperty("--editor-bottom",
  117. ((height - vditor.toolbar.element.offsetHeight) / 2) + "px");
  118. };
  119. const afterRender = (vditor: IVditor, contentElement: HTMLElement) => {
  120. setTypewriterPosition(vditor);
  121. window.addEventListener("resize", () => {
  122. setPadding(vditor);
  123. setTypewriterPosition(vditor);
  124. });
  125. // set default value
  126. let initValue = localStorage.getItem(vditor.options.cache.id);
  127. if (!vditor.options.cache.enable || !initValue) {
  128. if (vditor.options.value) {
  129. initValue = vditor.options.value;
  130. } else if (vditor.originalInnerHTML) {
  131. initValue = html2md(vditor, vditor.originalInnerHTML);
  132. } else if (!vditor.options.cache.enable) {
  133. initValue = "";
  134. }
  135. }
  136. return initValue || "";
  137. };