vdc-editor 0.1.199 → 0.1.200
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/lib/{BulkSpellChecker-BmS0mH_S.mjs → BulkSpellChecker-DT2RlF4H.mjs} +6 -6
- package/lib/{BulkSpellChecker-BmS0mH_S.mjs.map → BulkSpellChecker-DT2RlF4H.mjs.map} +1 -1
- package/lib/{index-BAkLSQoP.mjs → index-CaYoCbLr.mjs} +9 -9
- package/lib/{index-BAkLSQoP.mjs.map → index-CaYoCbLr.mjs.map} +1 -1
- package/lib/style.css +1 -1
- package/lib/vdc-editor.mjs +1 -1
- package/lib/vdc-editor.umd.js +20 -20
- package/lib/vdc-editor.umd.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as Z, a as Y, C as be, P as Ce, b as ve, D as ye, d as Ee, _ as Se, e as we, f as Te, S as oe, o as Ie, g as Re, h as Oe, i as Ne, j as We, k as Me, l as He, m as Ae, n as $e } from "./index-
|
|
1
|
+
import { c as Z, a as Y, C as be, P as Ce, b as ve, D as ye, d as Ee, _ as Se, e as we, f as Te, S as oe, o as Ie, g as Re, h as Oe, i as Ne, j as We, k as Me, l as He, m as Ae, n as $e } from "./index-CaYoCbLr.mjs";
|
|
2
2
|
import { defineComponent as P, createElementBlock as v, openBlock as m, createVNode as E, createElementVNode as h, unref as s, ref as L, onMounted as ee, nextTick as le, createCommentVNode as ie, normalizeClass as z, withModifiers as te, toDisplayString as G, normalizeStyle as ae, Fragment as K, renderList as q, createTextVNode as V, createBlock as B, createStaticVNode as Le, withCtx as $, reactive as ce, computed as se, watch as ue, normalizeProps as De, guardReactiveProps as Pe, renderSlot as Be, onUnmounted as re, resolveDynamicComponent as ze } from "vue";
|
|
3
3
|
import { useWindowSize as je, useEventListener as Ge } from "@vueuse/core";
|
|
4
4
|
const U = {
|
|
@@ -246,7 +246,7 @@ const st = ["onClick"], rt = { class: "flex items-center mb-2" }, lt = { class:
|
|
|
246
246
|
var c, f;
|
|
247
247
|
return m(), v("div", {
|
|
248
248
|
key: n,
|
|
249
|
-
class: "border-b border-gray-
|
|
249
|
+
class: "border-b border-gray-400 dark:border-ed-muted pb-5 mb-5 cursor-pointer",
|
|
250
250
|
onClick: (S) => d(x, a.editorsState[x].editor, e)
|
|
251
251
|
}, [
|
|
252
252
|
h("div", rt, [
|
|
@@ -263,7 +263,7 @@ const st = ["onClick"], rt = { class: "flex items-center mb-2" }, lt = { class:
|
|
|
263
263
|
e.correctWord.length ? (m(), v("div", ct, [
|
|
264
264
|
(m(!0), v(K, null, q(e.correctWord, (S, T) => (m(), v("div", {
|
|
265
265
|
key: T,
|
|
266
|
-
class: "font-semibold px-3 py-1.5 rounded bg-gray-
|
|
266
|
+
class: "font-semibold px-3 py-1.5 rounded bg-gray-400 dark:bg-ed-muted flex items-center justify-between"
|
|
267
267
|
}, [
|
|
268
268
|
h("div", ut, G(S), 1),
|
|
269
269
|
h("button", {
|
|
@@ -365,7 +365,7 @@ const vt = /* @__PURE__ */ Se(kt, [["render", Ct]]), yt = { class: "text-xs py-4
|
|
|
365
365
|
class: z(
|
|
366
366
|
s(Y)(
|
|
367
367
|
"border-blue-500 text-blue-500 text-xs px-3 py-2 h-auto hover:bg-white/80 hover:opacity-80 hover:text-blue-500 dark:text-dark-blue-100 dark:hover:bg-dark-blue-400 dark:hover:text-dark-blue-50 dark:hover:border-dark-blue-100",
|
|
368
|
-
i.spellCheckStatus === s(H).LOADING && "text-gray-300 bg-gray-
|
|
368
|
+
i.spellCheckStatus === s(H).LOADING && "text-gray-300 bg-gray-400 border-gray-400 pointer-events-none dark:bg-ed-muted/70 dark:border-ed-muted/70 dark:text-gray-500"
|
|
369
369
|
)
|
|
370
370
|
),
|
|
371
371
|
onClick: p[0] || (p[0] = (A) => r("run-spellcheck"))
|
|
@@ -379,7 +379,7 @@ const vt = /* @__PURE__ */ Se(kt, [["render", Ct]]), yt = { class: "text-xs py-4
|
|
|
379
379
|
class: z(
|
|
380
380
|
s(Y)(
|
|
381
381
|
"border-blue-500 text-white text-xs px-3 py-2 h-auto bg-blue-500 hover:bg-blue-500/80",
|
|
382
|
-
(i.spellCheckStatus !== s(H).HAS_ERROR || i.allWrongWordsMissSuggestions) && "text-gray-300 bg-gray-
|
|
382
|
+
(i.spellCheckStatus !== s(H).HAS_ERROR || i.allWrongWordsMissSuggestions) && "text-gray-300 bg-gray-400 hover:bg-gray-400 pointer-events-none dark:bg-ed-muted/70 dark:text-gray-500"
|
|
383
383
|
)
|
|
384
384
|
),
|
|
385
385
|
onClick: p[1] || (p[1] = (A) => r("replace-all-editor-errors"))
|
|
@@ -684,4 +684,4 @@ const vt = /* @__PURE__ */ Se(kt, [["render", Ct]]), yt = { class: "text-xs py-4
|
|
|
684
684
|
export {
|
|
685
685
|
Mt as default
|
|
686
686
|
};
|
|
687
|
-
//# sourceMappingURL=BulkSpellChecker-
|
|
687
|
+
//# sourceMappingURL=BulkSpellChecker-DT2RlF4H.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BulkSpellChecker-BmS0mH_S.mjs","sources":["../src/constants/bulkSpellChecker.ts","../node_modules/lucide-vue-next/dist/esm/icons/arrow-left-right.js","../node_modules/lucide-vue-next/dist/esm/icons/circle-alert.js","../node_modules/lucide-vue-next/dist/esm/icons/circle-check.js","../src/components/BulkSpellCheckerHelpText.vue","../src/utils/bulkSpellchecker.ts","../src/components/BulkSpellCheckerWrongWordList.vue","../src/components/ui/SpinnerIcon.vue","../src/components/BulkSpellCheckerLoading.vue","../src/components/BulkSpellCheckerContent.vue","../src/hooks/useBulkSpellCheckerStore.ts","../src/components/ui/dialog/DialogTrigger.vue","../src/components/BulkSpellChecker.vue"],"sourcesContent":["export const ERROR_TYPE = {\n SPACING: 1,\n SPELLING: 2,\n}\n\nexport const SPELL_CHECK_CODE = {\n NOTHING_TO_CHANGE: 'NOTHING_TO_CHANGE',\n} as const\n\nexport const SPELL_CHECK_STATUS = {\n LOADING: 'loading',\n HAS_ERROR: 'hasError',\n NO_ERROR: 'noError',\n FAIL: 'fail',\n} as const\n\nexport type SpellCheckStatus = (typeof SPELL_CHECK_STATUS)[keyof typeof SPELL_CHECK_STATUS]\n\nexport const EDITOR_NAME = {\n EDITOR_COMMENT: 'editorComment',\n EDITOR_CONTENT: 'editorContent',\n} as const\n\nexport type EditorName = (typeof EDITOR_NAME)[keyof typeof EDITOR_NAME]\n","/**\n * @license lucide-vue-next v0.439.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ArrowLeftRight = createLucideIcon(\"ArrowLeftRightIcon\", [\n [\"path\", { d: \"M8 3 4 7l4 4\", key: \"9rb6wj\" }],\n [\"path\", { d: \"M4 7h16\", key: \"6tx8e3\" }],\n [\"path\", { d: \"m16 21 4-4-4-4\", key: \"siv7j2\" }],\n [\"path\", { d: \"M20 17H4\", key: \"h6l3hr\" }]\n]);\n\nexport { ArrowLeftRight as default };\n//# sourceMappingURL=arrow-left-right.js.map\n","/**\n * @license lucide-vue-next v0.439.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleAlert = createLucideIcon(\"CircleAlertIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"8\", y2: \"12\", key: \"1pkeuh\" }],\n [\"line\", { x1: \"12\", x2: \"12.01\", y1: \"16\", y2: \"16\", key: \"4dfq90\" }]\n]);\n\nexport { CircleAlert as default };\n//# sourceMappingURL=circle-alert.js.map\n","/**\n * @license lucide-vue-next v0.439.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleCheck = createLucideIcon(\"CircleCheckIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m9 12 2 2 4-4\", key: \"dzmm74\" }]\n]);\n\nexport { CircleCheck as default };\n//# sourceMappingURL=circle-check.js.map\n","<script setup lang=\"ts\">\nimport { cn } from '@/utils'\nimport { ChevronDown } from 'lucide-vue-next'\n\ninterface Props {\n text: string\n}\nconst props = defineProps<Props>()\n\nconst expanded = ref(false)\nconst showButton = ref(false)\nconst helpRef = ref<HTMLElement | null>(null)\n\nfunction toggle() {\n expanded.value = !expanded.value\n}\n\nonMounted(async () => {\n await nextTick()\n if (helpRef.value && helpRef.value.scrollHeight > 32) {\n showButton.value = true\n }\n})\n</script>\n\n<template>\n <div class=\"relative\">\n <div\n ref=\"helpRef\"\n class=\"text-gray-700 dark:text-gray-400 transition-all\"\n :class=\"expanded ? 'max-h-none' : 'max-h-[32px] overflow-hidden'\"\n v-html=\"text\"\n ></div>\n\n <div\n v-if=\"showButton\"\n class=\"\"\n :class=\"\n cn(\n 'w-32 flex items-end justify-end bg-gradient-to-l from-white via-white to-transparent dark:from-ed-background dark:via-ed-background',\n expanded ? 'ml-auto opacity-60' : 'absolute bottom-0 right-0'\n )\n \"\n >\n <button class=\"flex items-center gap-1\" @click.stop=\"toggle\">\n <span class=\"border-b border-gray-500\">{{ expanded ? '접기' : '자세히' }}</span>\n <ChevronDown class=\"w-4 h-4 transition-transform\" :class=\"expanded ? 'rotate-180' : ''\" />\n </button>\n </div>\n </div>\n</template>\n","import { ERROR_TYPE } from '@/constants'\nimport { WrongWordItem } from '@/type'\nimport { Editor } from '@tiptap/core'\nimport { Plugin, PluginKey } from 'prosemirror-state'\nimport { Decoration, DecorationSet } from 'prosemirror-view'\n\nconst HIGHLIGHT_KEY = new PluginKey('bulk-spellcheck-highlight')\n\nfunction createHighlightPlugin(editor: Editor, errors: WrongWordItem[], blockSeparator = '\\n') {\n return new Plugin({\n key: HIGHLIGHT_KEY,\n props: {\n decorations(state) {\n const decos: Decoration[] = []\n const errorColorMap = {\n [ERROR_TYPE.SPACING]: 'bulk-highlight text-blue-500 border-b-2 border-blue-500',\n [ERROR_TYPE.SPELLING]: 'bulk-highlight text-red-500 border-b-2 border-red-500',\n }\n\n errors.forEach(item => {\n const from = findDocPosFromOffset(editor, item.startIndex, blockSeparator)\n const to = findDocPosFromOffset(editor, item.endIndex - 1, blockSeparator) + 1\n\n const errorType = item.errorHelpDtos?.[0]?.errorType\n const className = errorColorMap[errorType ?? -1] || 'bulk-highlight text-green-500 border-b-2 border-green-500' // type integrated\n\n const safeFrom = Math.max(0, Math.min(from, state.doc.content.size))\n const safeTo = Math.max(0, Math.min(to, state.doc.content.size))\n if (safeFrom < safeTo) {\n decos.push(Decoration.inline(safeFrom, safeTo, { class: className }))\n }\n })\n\n return DecorationSet.create(state.doc, decos)\n },\n },\n })\n}\n\nexport function applyHighlights(editor: Editor, errors: WrongWordItem[]) {\n editor.unregisterPlugin(HIGHLIGHT_KEY)\n\n if (!errors.length) return\n\n const plugin = createHighlightPlugin(editor, errors)\n editor.registerPlugin(plugin)\n}\n\nexport function clearHighlights(editor: Editor) {\n if (!editor) return\n\n editor.unregisterPlugin(HIGHLIGHT_KEY)\n}\n\nexport function buildPlainIndexToDocPosMap(editor: Editor, blockSeparator = '\\n') {\n const map: (number | null)[] = []\n let plainIndex = 0\n let firstBlock = true\n\n editor.state.doc.descendants((node, pos) => {\n if (node.isText && node.text) {\n for (let i = 0; i < node.text.length; i++) {\n map[plainIndex++] = pos + i\n }\n }\n\n const nodeName = node.type && (node.type as any).name\n const isHardBreak = nodeName === 'hardBreak' || nodeName === 'hard_break' || nodeName === 'br'\n if (isHardBreak && blockSeparator.length > 0) {\n for (let k = 0; k < blockSeparator.length; k++) {\n map[plainIndex++] = pos\n }\n }\n\n if (node.isBlock) {\n if (!firstBlock && blockSeparator.length > 0) {\n for (let k = 0; k < blockSeparator.length; k++) {\n map[plainIndex++] = pos \n }\n }\n firstBlock = false\n }\n\n return true\n })\n\n return map\n}\n\nexport function findDocPosFromOffset(editor: Editor,offset: number, blockSeparator = '\\n') {\n const map = buildPlainIndexToDocPosMap(editor, blockSeparator)\n if (offset < 0) offset = 0\n if (offset >= map.length) {\n return editor.state.doc.content.size\n }\n const mapped = map[offset]\n if (mapped == null) {\n for (let i = offset; i < map.length; i++) if (map[i] != null) return map[i] as number\n for (let i = offset - 1; i >= 0; i--) if (map[i] != null) return map[i] as number\n return editor.state.doc.content.size\n }\n return mapped as number\n}\n","<script setup lang=\"ts\">\nimport { EDITOR_NAME, EditorName, ERROR_TYPE } from '@/constants'\nimport { ArrowLeftRight } from 'lucide-vue-next'\nimport { Editor } from '@tiptap/core'\nimport { EditorsState, WrongWordItem } from '@/type'\nimport { applyHighlights, findDocPosFromOffset } from '@/utils/bulkSpellchecker'\n\ninterface Props {\n editorsState: EditorsState\n}\nconst props = defineProps<Props>()\n\nfunction getErrorColor(errorType?: number) {\n const errorColorMap = {\n [ERROR_TYPE.SPACING]: 'bg-blue-500',\n [ERROR_TYPE.SPELLING]: 'bg-red-500',\n }\n return errorColorMap[errorType ?? -1] || 'bg-green-500' // integrated\n}\n\nfunction getNoSuggestionText(editor: Editor) {\n return editor?.extensionStorage?.spellchecker?.spellchecker?.uiStrings?.uiStrings || 'No suggestions found'\n}\n\nfunction resetHightlightSection(key: EditorName) {\n if (key === EDITOR_NAME.EDITOR_COMMENT) {\n props.editorsState[EDITOR_NAME.EDITOR_CONTENT].editor?.commands.setTextSelection(0)\n return\n }\n\n if (key === EDITOR_NAME.EDITOR_CONTENT) {\n props.editorsState[EDITOR_NAME.EDITOR_COMMENT].editor?.commands.setTextSelection(0)\n return\n }\n}\n\nfunction scrollToError(key: EditorName, editor: Editor, item: WrongWordItem) {\n if (!editor) return\n\n resetHightlightSection(key)\n\n const from = findDocPosFromOffset(editor, item.startIndex)\n const to = findDocPosFromOffset(editor, item.endIndex - 1) + 1\n\n editor.chain().setTextSelection({ from, to }).focus().run()\n\n const mid = Math.max(0, Math.floor((from + to) / 2))\n const domAtPos = editor.view.domAtPos(mid)\n const maybeNode = domAtPos.node as unknown\n\n let el: HTMLElement | null = null\n\n if (maybeNode instanceof Element) {\n el = maybeNode as HTMLElement\n } else if (maybeNode instanceof Text) {\n el = maybeNode.parentElement\n } else {\n el = (maybeNode as any)?.parentElement ?? (editor.view.dom as HTMLElement)\n }\n\n if (el?.scrollIntoView) {\n el.scrollIntoView({ behavior: 'smooth', block: 'center' })\n }\n}\n\nfunction replaceWithCorrectWord(editor: Editor, errors: WrongWordItem[], item: WrongWordItem, replacement: string) {\n if (!editor) return\n\n const from = findDocPosFromOffset(editor, item.startIndex)\n const to = findDocPosFromOffset(editor, item.endIndex - 1) + 1\n\n const tr = editor.state.tr.insertText(replacement, from, to)\n editor.view.dispatch(tr)\n editor.view.focus()\n\n const delta = replacement.length - (item.wrongWord?.length ?? 0)\n const origStart = item.startIndex\n const origEnd = item.endIndex\n\n for (let i = errors.length - 1; i >= 0; i--) {\n const err = errors[i]\n\n if (err.startIndex >= origStart && err.startIndex < origEnd) {\n errors.splice(i, 1)\n continue\n }\n\n if (err.startIndex > origStart) {\n err.startIndex += delta\n err.endIndex += delta\n }\n }\n\n const idx = errors.indexOf(item)\n if (idx !== -1) errors.splice(idx, 1)\n\n applyHighlights(editor, errors)\n}\n\nconst contentEl = ref<HTMLElement | null>(null)\nconst standardMaxHeight = 450\nconst maxHeight = ref(standardMaxHeight)\nconst { height: windowHeight } = useWindowSize()\n\nfunction computeMaxHeight() {\n const el = contentEl.value\n if (!el) return\n\n const gap = 80\n const rect = el.getBoundingClientRect()\n const availableViewportHeight = windowHeight.value - rect.top - gap\n\n maxHeight.value = standardMaxHeight > availableViewportHeight ? availableViewportHeight : standardMaxHeight\n}\n\nonMounted(() => {\n computeMaxHeight()\n useEventListener(window, 'resize', computeMaxHeight)\n})\n</script>\n\n<template>\n <div ref=\"contentEl\" :style=\"{ maxHeight: `${maxHeight}px` }\" class=\"pr-1 overflow-y-auto\">\n <template v-for=\"(editorData, key) in editorsState\" :key=\"key\">\n <div\n v-for=\"(item, idx) in editorData.wrongWords\"\n :key=\"idx\"\n class=\"border-b border-gray-100 dark:border-ed-muted pb-5 mb-5 cursor-pointer\"\n @click=\"scrollToError(key, editorsState[key].editor as Editor, item)\"\n >\n <div class=\"flex items-center mb-2\">\n <span class=\"w-16 font-medium\">입력 내용</span>\n <div class=\"flex items-center gap-2\">\n <span class=\"w-1.5 h-1.5 rounded-full\" :class=\"getErrorColor(item.errorHelpDtos[0]?.errorType)\"></span>\n <span class=\"break-all whitespace-normal\">{{ item.wrongWord }}</span>\n </div>\n </div>\n\n <div class=\"flex items-center mb-2\">\n <span class=\"w-16 font-medium\">대치어</span>\n <div v-if=\"item.correctWord.length\" class=\"flex-1 space-y-1\">\n <div\n v-for=\"(sub, sidx) in item.correctWord\"\n :key=\"sidx\"\n class=\"font-semibold px-3 py-1.5 rounded bg-gray-100 dark:bg-ed-muted flex items-center justify-between\"\n >\n <div class=\"text-sm\">\n {{ sub }}\n </div>\n <button\n class=\"flex items-center gap-1 text-blue-500\"\n @click.stop=\"replaceWithCorrectWord(editorData.editor as Editor, editorData.wrongWords, item, sub)\"\n >\n <ArrowLeftRight class=\"w-4 h-4\" /> <span>바꾸기</span>\n </button>\n </div>\n </div>\n <div v-else>\n {{ getNoSuggestionText(editorData.editor as Editor) }}\n </div>\n </div>\n\n <div class=\"flex\">\n <span class=\"w-16 font-medium\">도움말</span>\n <div class=\"flex-1\">\n <BulkSpellCheckerHelpText :text=\"item.errorHelpDtos[0]?.errorMessage\" />\n </div>\n </div>\n </div>\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { cn } from '@/utils'\n\ninterface Props {\n fillWhite?: boolean\n class?: string\n}\nconst props = withDefaults(defineProps<Props>(), {\n fillWhite: false,\n class: '',\n})\n</script>\n\n<template>\n <svg :class=\"cn('animate-spin h-5 w-5 mr-0.5', props.class)\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <circle\n v-if=\"fillWhite\"\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n fill=\"#ffffff\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <circle v-else class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path\n class=\"opacity-100\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n</template>\n\n<style scoped></style>\n","<template>\n <div class=\"min-h-[188px] flex flex-col items-center justify-center gap-y-2 text-sm\">\n <SpinnerIcon fill-white class=\"h-10 w-10 text-blue-500\" />\n <div>맞춤법 검사 중입니다</div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { SPELL_CHECK_STATUS, SpellCheckStatus } from '@/constants'\nimport { cn } from '@/utils'\nimport { EditorsState } from '@/type'\n\ninterface Props {\n editorsState: EditorsState,\n spellCheckStatus: SpellCheckStatus\n allWrongWordsMissSuggestions: boolean\n}\nconst props = defineProps<Props>()\n\nconst emit = defineEmits<{\n (e: 'close-modal'): void\n (e: 'run-spellcheck'): void\n (e: 'replace-all-editor-errors'): void\n}>()\n</script>\n\n<template>\n <div class=\"text-xs py-4 px-6\">\n <BulkSpellCheckerLoading v-if=\"spellCheckStatus === SPELL_CHECK_STATUS.LOADING\" />\n <BulkSpellCheckerWrongWordList v-else-if=\"spellCheckStatus === SPELL_CHECK_STATUS.HAS_ERROR\" :editorsState=\"editorsState\" />\n <BulkSpellCheckerNotWrongWord v-else-if=\"spellCheckStatus === SPELL_CHECK_STATUS.NO_ERROR\" />\n <BulkSpellCheckerFail v-else-if=\"spellCheckStatus === SPELL_CHECK_STATUS.FAIL\" />\n\n <div class=\"flex items-center justify-between mt-3\">\n <ul class=\"flex items-cente gap-x-4\">\n <li class=\"flex items-center gap-x-1\"><span class=\"w-1.5 h-1.5 rounded-full bg-red-500\"></span>맞춤법</li>\n <li class=\"flex items-center gap-x-1\"><span class=\"w-1.5 h-1.5 rounded-full bg-blue-500\"></span>띄어쓰기</li>\n <li class=\"flex items-center gap-x-1\"><span class=\"w-1.5 h-1.5 rounded-full bg-green-500\"></span>통합교정</li>\n </ul>\n\n <div class=\"flex gap-x-1\">\n <Button\n variant=\"outline\"\n :class=\"\n cn(\n 'border-blue-500 text-blue-500 text-xs px-3 py-2 h-auto hover:bg-white/80 hover:opacity-80 hover:text-blue-500 dark:text-dark-blue-100 dark:hover:bg-dark-blue-400 dark:hover:text-dark-blue-50 dark:hover:border-dark-blue-100',\n spellCheckStatus === SPELL_CHECK_STATUS.LOADING &&\n 'text-gray-300 bg-gray-100 border-gray-100 pointer-events-none dark:bg-ed-muted/70 dark:border-ed-muted/70 dark:text-gray-500'\n )\n \"\n @click=\"emit('run-spellcheck')\"\n >다시 검사하기</Button\n >\n\n <Button\n :class=\"\n cn(\n 'border-blue-500 text-white text-xs px-3 py-2 h-auto bg-blue-500 hover:bg-blue-500/80',\n (spellCheckStatus !== SPELL_CHECK_STATUS.HAS_ERROR || allWrongWordsMissSuggestions) &&\n 'text-gray-300 bg-gray-100 hover:bg-gray-100 pointer-events-none dark:bg-ed-muted/70 dark:text-gray-500'\n )\n \"\n @click=\"emit('replace-all-editor-errors')\"\n >모두 바꾸기</Button\n >\n </div>\n </div>\n </div>\n</template>\n","import { EDITOR_NAME, EditorName, SPELL_CHECK_CODE, SPELL_CHECK_STATUS, SpellCheckStatus } from '@/constants'\nimport { EditorsState, SpellCheckResponse, WrongWordItem } from '@/type'\nimport { Editor } from '@tiptap/core'\nimport axios from 'axios'\nimport { applyHighlights, clearHighlights, buildPlainIndexToDocPosMap } from '@/utils/bulkSpellchecker'\nimport { SPELLCHECKER_META_LIST } from '@/extensions/SpellChecker/spellchecker-extension'\n\nexport const useBulkSpellCheckerStore = () => {\n const editorsState: EditorsState = reactive({\n [EDITOR_NAME.EDITOR_COMMENT]: {\n editor: null,\n wrongWords: [],\n },\n [EDITOR_NAME.EDITOR_CONTENT]: {\n editor: null,\n wrongWords: [],\n },\n })\n\n function setEditor(editorKey: EditorName, editorInstance: Editor | null) {\n editorsState[editorKey].editor = editorInstance\n }\n\n const spellCheckStatus = ref<SpellCheckStatus>(SPELL_CHECK_STATUS.NO_ERROR)\n\n function resetAllEditorWrongWords() {\n Object.values(editorsState).forEach(editorState => {\n editorState.wrongWords = []\n })\n }\n\n function evaluateStatus(hasFail: boolean, hasError: boolean) {\n if (hasFail) return SPELL_CHECK_STATUS.FAIL\n if (hasError) return SPELL_CHECK_STATUS.HAS_ERROR\n return SPELL_CHECK_STATUS.NO_ERROR\n }\n\n async function handleRunSpellCheck() {\n spellCheckStatus.value = SPELL_CHECK_STATUS.LOADING\n\n let hasError = false\n let hasFail = false\n\n for (const [editorKey, { editor }] of Object.entries(editorsState)) {\n if (!editor) continue\n\n const apiUrl = editor?.extensionManager.extensions.find(ext => ext.name === 'spellchecker')?.options.proofreader\n .api\n const content = editor.getText({ blockSeparator: '\\n' })\n if (!apiUrl || !content) continue\n\n try {\n const { data: response } = await axios.post<SpellCheckResponse>(apiUrl, {\n value: content,\n })\n\n if (!response.success && response.code !== SPELL_CHECK_CODE.NOTHING_TO_CHANGE) {\n hasFail = true\n editorsState[editorKey].wrongWords = []\n continue\n }\n\n if (response.data?.wrongWordResponseDto) {\n hasError = true\n editorsState[editorKey].wrongWords = response.data.wrongWordResponseDto\n continue\n }\n\n editorsState[editorKey].wrongWords = []\n } catch (error) {\n console.error('handleRunSpellCheck error: ', error)\n hasFail = true\n }\n }\n\n spellCheckStatus.value = evaluateStatus(hasFail, hasError)\n }\n\n const countTotalWrongWords = computed(() => {\n return Object.values(editorsState).reduce((sum, { wrongWords }) => {\n return sum + wrongWords.length\n }, 0)\n })\n\n watch(countTotalWrongWords, newVal => {\n if (newVal === 0) {\n spellCheckStatus.value = evaluateStatus(false, false)\n }\n })\n\n const allWrongWordsMissSuggestions = computed(() => {\n const allWrongWords = Object.values(editorsState).flatMap(es => es.wrongWords)\n if (allWrongWords.length === 0) return false\n return allWrongWords.every(w => !Array.isArray(w.correctWord) || w.correctWord.length === 0)\n })\n\n function applyAllEditorHighlightErrors() {\n for (const [_, { editor, wrongWords }] of Object.entries(editorsState)) {\n if (!editor) continue\n applyHighlights(editor as Editor, wrongWords)\n }\n }\n\n function clearAllEditorHighlightErrors() {\n for (const [_, { editor }] of Object.entries(editorsState)) {\n if (!editor) continue\n clearHighlights(editor as Editor)\n }\n }\n\n async function reRunSpellCheckAndHighlight() {\n await handleRunSpellCheck()\n applyAllEditorHighlightErrors()\n }\n\n let isEnableCurrent = true\n function disableSpellCheckRealTime(isEnableSpellCheckRealTime: boolean) {\n isEnableCurrent = isEnableSpellCheckRealTime\n if (!isEnableSpellCheckRealTime) return\n\n for (const [_, { editor }] of Object.entries(editorsState)) {\n if (!editor) continue\n editor.extensionStorage.spellchecker.spellchecker.setEnabledProofreadText(false)\n editor.view.dispatch(editor.state.tr.setMeta(SPELLCHECKER_META_LIST.IS_ACTIVE_SPELLCHECK, false))\n }\n }\n\n function resetEnableSpellCheckRealTime() {\n if (!isEnableCurrent) return\n\n for (const [_, { editor }] of Object.entries(editorsState)) {\n if (!editor) continue\n editor.extensionStorage.spellchecker.spellchecker.setEnabledProofreadText(true)\n editor.view.dispatch(editor.state.tr.setMeta(SPELLCHECKER_META_LIST.IS_ACTIVE_SPELLCHECK, true))\n }\n }\n\n function replaceAllErrors(editor: Editor, errors: WrongWordItem[], blockSeparator = '\\n') {\n if (!editor) return\n if (!errors.length) return\n\n const map = buildPlainIndexToDocPosMap(editor, blockSeparator)\n\n function getMappedPos(offset: number) {\n if (offset < 0) offset = 0\n if (offset >= map.length) return editor.state.doc.content.size\n if (map[offset] != null) return map[offset] as number\n for (let i = offset; i < map.length; i++) if (map[i] != null) return map[i] as number\n for (let i = offset - 1; i >= 0; i--) if (map[i] != null) return map[i] as number\n return editor.state.doc.content.size\n }\n\n const replacements = errors.map(item => {\n const from = getMappedPos(item.startIndex)\n const to = getMappedPos(Math.max(0, item.endIndex - 1)) + 1\n const replacement = item.correctWord?.[0] ?? item.wrongWord\n return { item, from, to, replacement }\n })\n\n const validRepls = replacements.filter(r => typeof r.from === 'number' && typeof r.to === 'number' && r.from < r.to)\n\n if (!validRepls.length) return\n\n validRepls.sort((a, b) => b.from - a.from)\n\n const tr = editor.state.tr\n let lastAppliedFrom = Number.POSITIVE_INFINITY\n const appliedItems = new Set<WrongWordItem>()\n\n for (const r of validRepls) {\n if (r.to > lastAppliedFrom) {\n continue\n }\n\n tr.insertText(r.replacement, r.from, r.to)\n\n appliedItems.add(r.item)\n lastAppliedFrom = r.from\n }\n\n if (appliedItems.size > 0) {\n editor.view.dispatch(tr)\n editor.view.focus()\n }\n\n if (appliedItems.size > 0) {\n errors = errors.filter(e => ![...appliedItems].some(a => a === e))\n }\n\n applyHighlights(editor, errors)\n }\n\n function replaceAllEditorErrors() {\n for (const [_, { editor, wrongWords }] of Object.entries(editorsState)) {\n if (!editor) continue\n replaceAllErrors(editor as Editor, wrongWords)\n }\n }\n\n return {\n editorsState,\n spellCheckStatus,\n countTotalWrongWords,\n allWrongWordsMissSuggestions,\n setEditor,\n resetAllEditorWrongWords,\n disableSpellCheckRealTime,\n resetEnableSpellCheckRealTime,\n applyAllEditorHighlightErrors,\n clearAllEditorHighlightErrors,\n reRunSpellCheckAndHighlight,\n handleRunSpellCheck,\n replaceAllEditorErrors,\n }\n}\n","<script setup lang=\"ts\">\nimport { DialogTrigger, type DialogTriggerProps } from 'radix-vue'\n\nconst props = defineProps<DialogTriggerProps>()\n</script>\n\n<template>\n <DialogTrigger v-bind=\"props\">\n <slot />\n </DialogTrigger>\n</template>\n","<script setup lang=\"ts\">\nimport { EDITOR_NAME } from '@/constants'\nimport { useBulkSpellCheckerStore } from '@/hooks/useBulkSpellCheckerStore'\nimport { Editor } from '@tiptap/core'\nimport { DialogTrigger } from './ui/dialog'\n\ninterface Props {\n editor: Editor\n editorComment?: Editor\n isEnableSpellCheckRealTime: boolean\n}\nconst props = defineProps<Props>()\n\nconst {\n editorsState,\n countTotalWrongWords,\n spellCheckStatus,\n allWrongWordsMissSuggestions,\n setEditor,\n disableSpellCheckRealTime,\n resetEnableSpellCheckRealTime,\n handleRunSpellCheck,\n resetAllEditorWrongWords,\n applyAllEditorHighlightErrors,\n clearAllEditorHighlightErrors,\n reRunSpellCheckAndHighlight,\n replaceAllEditorErrors,\n} = useBulkSpellCheckerStore()\n\nconst isOpenModal = ref(false)\n\nconst dragOffset = reactive({ x: 0, y: 0 })\nconst dragging = ref(false)\nconst offset = { x: 0, y: 0 }\n\nconst onMouseDown = (e: MouseEvent) => {\n dragging.value = true\n offset.x = e.clientX - dragOffset.x\n offset.y = e.clientY - dragOffset.y\n document.addEventListener('mousemove', onMouseMove)\n document.addEventListener('mouseup', onMouseUp)\n}\n\nconst onMouseMove = (e: MouseEvent) => {\n if (!dragging.value) return\n dragOffset.x = e.clientX - offset.x\n dragOffset.y = e.clientY - offset.y\n}\n\nconst onMouseUp = () => {\n dragging.value = false\n document.removeEventListener('mousemove', onMouseMove)\n document.removeEventListener('mouseup', onMouseUp)\n}\n\nonUnmounted(() => {\n document.removeEventListener('mousemove', onMouseMove)\n document.removeEventListener('mouseup', onMouseUp)\n})\n\nconst triggerRef = ref<InstanceType<typeof DialogTrigger> | null>(null)\nconst position = ref({ top: 0, right: 0 })\n\nconst updatePosition = () => {\n if (triggerRef.value) {\n const rect = triggerRef.value.$el.getBoundingClientRect()\n\n position.value = {\n top: rect.bottom + window.scrollY + 5,\n right: window.innerWidth - rect.right - window.scrollX,\n }\n\n dragOffset.x = 0\n dragOffset.y = 0\n }\n}\n\nonMounted(async () => {\n if (props.editorComment) {\n setEditor(EDITOR_NAME.EDITOR_COMMENT, props.editorComment)\n }\n setEditor(EDITOR_NAME.EDITOR_CONTENT, props.editor)\n})\n\nonUnmounted(() => {\n setEditor(EDITOR_NAME.EDITOR_COMMENT, null)\n setEditor(EDITOR_NAME.EDITOR_CONTENT, null)\n})\n\nwatch(isOpenModal, async val => {\n if (val) {\n await nextTick()\n updatePosition()\n disableSpellCheckRealTime(props.isEnableSpellCheckRealTime)\n await handleRunSpellCheck()\n applyAllEditorHighlightErrors()\n } else {\n resetAllEditorWrongWords()\n resetEnableSpellCheckRealTime()\n clearAllEditorHighlightErrors()\n }\n})\n\nconst bulkSpellCheckerBtnConfig = props.editor?.extensionManager.extensions.find(e => e.name === 'spellchecker')\n ?.options.bulkSpellCheckerButton\n</script>\n\n<template>\n <Dialog :open=\"isOpenModal\">\n <DialogTrigger as-child ref=\"triggerRef\" @click=\"isOpenModal = !isOpenModal\">\n <button\n v-if=\"!bulkSpellCheckerBtnConfig\"\n class=\"border-blue-500 text-white text-xs text-nowrap px-3 py-2 h-auto bg-blue-500 hover:bg-blue-500/80 flex items-center rounded\"\n >\n <Icon name=\"checkUnderline\" />맞춤법 일괄 교정\n </button>\n\n <component\n v-else\n :is=\"bulkSpellCheckerBtnConfig.component\"\n :buttonName=\"bulkSpellCheckerBtnConfig.props.buttonName\"\n :icon=\"bulkSpellCheckerBtnConfig.props.icon\"\n :type=\"bulkSpellCheckerBtnConfig.props.type\"\n :disabled=\"bulkSpellCheckerBtnConfig.props.disabled\"\n :iconPosition=\"bulkSpellCheckerBtnConfig.props.iconPosition\"\n :buttonSize=\"bulkSpellCheckerBtnConfig.props.buttonSize\"\n :iconClass=\"bulkSpellCheckerBtnConfig.props.iconClass\"\n />\n </DialogTrigger>\n\n <DialogContent is-overlay-transparent class=\"p-0 gap-0 !animate-none !transition-none dark:border-ed-muted\" as-child>\n <div\n class=\"z-[70]\"\n :style=\"{\n transform: `translate(${dragOffset.x}px, ${dragOffset.y}px)`,\n top: `${position.top}px`,\n right: `${position.right}px`,\n left: 'auto',\n }\"\n >\n <DialogHeader\n class=\"bg-ed-blue-light py-3.5 px-6 rounded-t-[5px] cursor-move text-blue-500 dark:text-dark-blue-100 flex-row items-center justify-between\"\n @mousedown.prevent=\"onMouseDown\"\n >\n <DialogTitle class=\"text-base space-x-2\">\n <span>맞춤법/문법 오류</span>\n <Badge class=\"text-sm bg-blue-500 hover:bg-blue-500 dark:bg-dark-blue-100 px-2\">{{ countTotalWrongWords }}개</Badge></DialogTitle\n >\n\n <DialogClose @click=\"isOpenModal = false\" class=\"text-xs flex items-center gap-x-1\">\n <Icon name=\"Close\" class=\"w-4 h-4\" />{{ $t('editor.close') }}\n </DialogClose>\n </DialogHeader>\n\n <DialogDescription></DialogDescription>\n\n <BulkSpellCheckerContent\n :editorsState=\"editorsState\"\n :spellCheckStatus=\"spellCheckStatus\"\n :allWrongWordsMissSuggestions=\"allWrongWordsMissSuggestions\"\n @close-modal=\"isOpenModal = false\"\n @run-spellcheck=\"reRunSpellCheckAndHighlight\"\n @replace-all-editor-errors=\"(replaceAllEditorErrors(), (isOpenModal = false))\"\n />\n </div>\n </DialogContent>\n </Dialog>\n</template>\n\n<style scoped></style>\n"],"names":["ERROR_TYPE","SPELL_CHECK_CODE","SPELL_CHECK_STATUS","EDITOR_NAME","ArrowLeftRight","createLucideIcon","CircleAlert","CircleCheck","expanded","ref","showButton","helpRef","toggle","onMounted","nextTick","HIGHLIGHT_KEY","PluginKey","createHighlightPlugin","editor","errors","blockSeparator","Plugin","state","decos","errorColorMap","item","from","findDocPosFromOffset","to","errorType","_b","_a","className","safeFrom","safeTo","Decoration","DecorationSet","applyHighlights","plugin","clearHighlights","buildPlainIndexToDocPosMap","map","plainIndex","firstBlock","node","pos","i","nodeName","k","offset","mapped","standardMaxHeight","props","__props","getErrorColor","getNoSuggestionText","_d","_c","resetHightlightSection","key","scrollToError","mid","maybeNode","el","replaceWithCorrectWord","replacement","tr","delta","origStart","origEnd","err","idx","contentEl","maxHeight","windowHeight","useWindowSize","computeMaxHeight","gap","rect","availableViewportHeight","useEventListener","_openBlock","_createElementBlock","_hoisted_1","_createVNode","_component_SpinnerIcon","emit","__emit","useBulkSpellCheckerStore","editorsState","reactive","setEditor","editorKey","editorInstance","spellCheckStatus","resetAllEditorWrongWords","editorState","evaluateStatus","hasFail","hasError","handleRunSpellCheck","apiUrl","ext","content","response","axios","error","countTotalWrongWords","computed","sum","wrongWords","watch","newVal","allWrongWordsMissSuggestions","allWrongWords","es","w","applyAllEditorHighlightErrors","_","clearAllEditorHighlightErrors","reRunSpellCheckAndHighlight","isEnableCurrent","disableSpellCheckRealTime","isEnableSpellCheckRealTime","SPELLCHECKER_META_LIST","resetEnableSpellCheckRealTime","replaceAllErrors","getMappedPos","validRepls","r","a","b","lastAppliedFrom","appliedItems","e","replaceAllEditorErrors","isOpenModal","dragOffset","dragging","onMouseDown","onMouseMove","onMouseUp","onUnmounted","triggerRef","position","updatePosition","val","bulkSpellCheckerBtnConfig"],"mappings":"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","x_google_ignoreList":[1,2,3]}
|
|
1
|
+
{"version":3,"file":"BulkSpellChecker-DT2RlF4H.mjs","sources":["../src/constants/bulkSpellChecker.ts","../node_modules/lucide-vue-next/dist/esm/icons/arrow-left-right.js","../node_modules/lucide-vue-next/dist/esm/icons/circle-alert.js","../node_modules/lucide-vue-next/dist/esm/icons/circle-check.js","../src/components/BulkSpellCheckerHelpText.vue","../src/utils/bulkSpellchecker.ts","../src/components/BulkSpellCheckerWrongWordList.vue","../src/components/ui/SpinnerIcon.vue","../src/components/BulkSpellCheckerLoading.vue","../src/components/BulkSpellCheckerContent.vue","../src/hooks/useBulkSpellCheckerStore.ts","../src/components/ui/dialog/DialogTrigger.vue","../src/components/BulkSpellChecker.vue"],"sourcesContent":["export const ERROR_TYPE = {\n SPACING: 1,\n SPELLING: 2,\n}\n\nexport const SPELL_CHECK_CODE = {\n NOTHING_TO_CHANGE: 'NOTHING_TO_CHANGE',\n} as const\n\nexport const SPELL_CHECK_STATUS = {\n LOADING: 'loading',\n HAS_ERROR: 'hasError',\n NO_ERROR: 'noError',\n FAIL: 'fail',\n} as const\n\nexport type SpellCheckStatus = (typeof SPELL_CHECK_STATUS)[keyof typeof SPELL_CHECK_STATUS]\n\nexport const EDITOR_NAME = {\n EDITOR_COMMENT: 'editorComment',\n EDITOR_CONTENT: 'editorContent',\n} as const\n\nexport type EditorName = (typeof EDITOR_NAME)[keyof typeof EDITOR_NAME]\n","/**\n * @license lucide-vue-next v0.439.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ArrowLeftRight = createLucideIcon(\"ArrowLeftRightIcon\", [\n [\"path\", { d: \"M8 3 4 7l4 4\", key: \"9rb6wj\" }],\n [\"path\", { d: \"M4 7h16\", key: \"6tx8e3\" }],\n [\"path\", { d: \"m16 21 4-4-4-4\", key: \"siv7j2\" }],\n [\"path\", { d: \"M20 17H4\", key: \"h6l3hr\" }]\n]);\n\nexport { ArrowLeftRight as default };\n//# sourceMappingURL=arrow-left-right.js.map\n","/**\n * @license lucide-vue-next v0.439.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleAlert = createLucideIcon(\"CircleAlertIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"8\", y2: \"12\", key: \"1pkeuh\" }],\n [\"line\", { x1: \"12\", x2: \"12.01\", y1: \"16\", y2: \"16\", key: \"4dfq90\" }]\n]);\n\nexport { CircleAlert as default };\n//# sourceMappingURL=circle-alert.js.map\n","/**\n * @license lucide-vue-next v0.439.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleCheck = createLucideIcon(\"CircleCheckIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m9 12 2 2 4-4\", key: \"dzmm74\" }]\n]);\n\nexport { CircleCheck as default };\n//# sourceMappingURL=circle-check.js.map\n","<script setup lang=\"ts\">\nimport { cn } from '@/utils'\nimport { ChevronDown } from 'lucide-vue-next'\n\ninterface Props {\n text: string\n}\nconst props = defineProps<Props>()\n\nconst expanded = ref(false)\nconst showButton = ref(false)\nconst helpRef = ref<HTMLElement | null>(null)\n\nfunction toggle() {\n expanded.value = !expanded.value\n}\n\nonMounted(async () => {\n await nextTick()\n if (helpRef.value && helpRef.value.scrollHeight > 32) {\n showButton.value = true\n }\n})\n</script>\n\n<template>\n <div class=\"relative\">\n <div\n ref=\"helpRef\"\n class=\"text-gray-700 dark:text-gray-400 transition-all\"\n :class=\"expanded ? 'max-h-none' : 'max-h-[32px] overflow-hidden'\"\n v-html=\"text\"\n ></div>\n\n <div\n v-if=\"showButton\"\n class=\"\"\n :class=\"\n cn(\n 'w-32 flex items-end justify-end bg-gradient-to-l from-white via-white to-transparent dark:from-ed-background dark:via-ed-background',\n expanded ? 'ml-auto opacity-60' : 'absolute bottom-0 right-0'\n )\n \"\n >\n <button class=\"flex items-center gap-1\" @click.stop=\"toggle\">\n <span class=\"border-b border-gray-500\">{{ expanded ? '접기' : '자세히' }}</span>\n <ChevronDown class=\"w-4 h-4 transition-transform\" :class=\"expanded ? 'rotate-180' : ''\" />\n </button>\n </div>\n </div>\n</template>\n","import { ERROR_TYPE } from '@/constants'\nimport { WrongWordItem } from '@/type'\nimport { Editor } from '@tiptap/core'\nimport { Plugin, PluginKey } from 'prosemirror-state'\nimport { Decoration, DecorationSet } from 'prosemirror-view'\n\nconst HIGHLIGHT_KEY = new PluginKey('bulk-spellcheck-highlight')\n\nfunction createHighlightPlugin(editor: Editor, errors: WrongWordItem[], blockSeparator = '\\n') {\n return new Plugin({\n key: HIGHLIGHT_KEY,\n props: {\n decorations(state) {\n const decos: Decoration[] = []\n const errorColorMap = {\n [ERROR_TYPE.SPACING]: 'bulk-highlight text-blue-500 border-b-2 border-blue-500',\n [ERROR_TYPE.SPELLING]: 'bulk-highlight text-red-500 border-b-2 border-red-500',\n }\n\n errors.forEach(item => {\n const from = findDocPosFromOffset(editor, item.startIndex, blockSeparator)\n const to = findDocPosFromOffset(editor, item.endIndex - 1, blockSeparator) + 1\n\n const errorType = item.errorHelpDtos?.[0]?.errorType\n const className = errorColorMap[errorType ?? -1] || 'bulk-highlight text-green-500 border-b-2 border-green-500' // type integrated\n\n const safeFrom = Math.max(0, Math.min(from, state.doc.content.size))\n const safeTo = Math.max(0, Math.min(to, state.doc.content.size))\n if (safeFrom < safeTo) {\n decos.push(Decoration.inline(safeFrom, safeTo, { class: className }))\n }\n })\n\n return DecorationSet.create(state.doc, decos)\n },\n },\n })\n}\n\nexport function applyHighlights(editor: Editor, errors: WrongWordItem[]) {\n editor.unregisterPlugin(HIGHLIGHT_KEY)\n\n if (!errors.length) return\n\n const plugin = createHighlightPlugin(editor, errors)\n editor.registerPlugin(plugin)\n}\n\nexport function clearHighlights(editor: Editor) {\n if (!editor) return\n\n editor.unregisterPlugin(HIGHLIGHT_KEY)\n}\n\nexport function buildPlainIndexToDocPosMap(editor: Editor, blockSeparator = '\\n') {\n const map: (number | null)[] = []\n let plainIndex = 0\n let firstBlock = true\n\n editor.state.doc.descendants((node, pos) => {\n if (node.isText && node.text) {\n for (let i = 0; i < node.text.length; i++) {\n map[plainIndex++] = pos + i\n }\n }\n\n const nodeName = node.type && (node.type as any).name\n const isHardBreak = nodeName === 'hardBreak' || nodeName === 'hard_break' || nodeName === 'br'\n if (isHardBreak && blockSeparator.length > 0) {\n for (let k = 0; k < blockSeparator.length; k++) {\n map[plainIndex++] = pos\n }\n }\n\n if (node.isBlock) {\n if (!firstBlock && blockSeparator.length > 0) {\n for (let k = 0; k < blockSeparator.length; k++) {\n map[plainIndex++] = pos \n }\n }\n firstBlock = false\n }\n\n return true\n })\n\n return map\n}\n\nexport function findDocPosFromOffset(editor: Editor,offset: number, blockSeparator = '\\n') {\n const map = buildPlainIndexToDocPosMap(editor, blockSeparator)\n if (offset < 0) offset = 0\n if (offset >= map.length) {\n return editor.state.doc.content.size\n }\n const mapped = map[offset]\n if (mapped == null) {\n for (let i = offset; i < map.length; i++) if (map[i] != null) return map[i] as number\n for (let i = offset - 1; i >= 0; i--) if (map[i] != null) return map[i] as number\n return editor.state.doc.content.size\n }\n return mapped as number\n}\n","<script setup lang=\"ts\">\nimport { EDITOR_NAME, EditorName, ERROR_TYPE } from '@/constants'\nimport { ArrowLeftRight } from 'lucide-vue-next'\nimport { Editor } from '@tiptap/core'\nimport { EditorsState, WrongWordItem } from '@/type'\nimport { applyHighlights, findDocPosFromOffset } from '@/utils/bulkSpellchecker'\n\ninterface Props {\n editorsState: EditorsState\n}\nconst props = defineProps<Props>()\n\nfunction getErrorColor(errorType?: number) {\n const errorColorMap = {\n [ERROR_TYPE.SPACING]: 'bg-blue-500',\n [ERROR_TYPE.SPELLING]: 'bg-red-500',\n }\n return errorColorMap[errorType ?? -1] || 'bg-green-500' // integrated\n}\n\nfunction getNoSuggestionText(editor: Editor) {\n return editor?.extensionStorage?.spellchecker?.spellchecker?.uiStrings?.uiStrings || 'No suggestions found'\n}\n\nfunction resetHightlightSection(key: EditorName) {\n if (key === EDITOR_NAME.EDITOR_COMMENT) {\n props.editorsState[EDITOR_NAME.EDITOR_CONTENT].editor?.commands.setTextSelection(0)\n return\n }\n\n if (key === EDITOR_NAME.EDITOR_CONTENT) {\n props.editorsState[EDITOR_NAME.EDITOR_COMMENT].editor?.commands.setTextSelection(0)\n return\n }\n}\n\nfunction scrollToError(key: EditorName, editor: Editor, item: WrongWordItem) {\n if (!editor) return\n\n resetHightlightSection(key)\n\n const from = findDocPosFromOffset(editor, item.startIndex)\n const to = findDocPosFromOffset(editor, item.endIndex - 1) + 1\n\n editor.chain().setTextSelection({ from, to }).focus().run()\n\n const mid = Math.max(0, Math.floor((from + to) / 2))\n const domAtPos = editor.view.domAtPos(mid)\n const maybeNode = domAtPos.node as unknown\n\n let el: HTMLElement | null = null\n\n if (maybeNode instanceof Element) {\n el = maybeNode as HTMLElement\n } else if (maybeNode instanceof Text) {\n el = maybeNode.parentElement\n } else {\n el = (maybeNode as any)?.parentElement ?? (editor.view.dom as HTMLElement)\n }\n\n if (el?.scrollIntoView) {\n el.scrollIntoView({ behavior: 'smooth', block: 'center' })\n }\n}\n\nfunction replaceWithCorrectWord(editor: Editor, errors: WrongWordItem[], item: WrongWordItem, replacement: string) {\n if (!editor) return\n\n const from = findDocPosFromOffset(editor, item.startIndex)\n const to = findDocPosFromOffset(editor, item.endIndex - 1) + 1\n\n const tr = editor.state.tr.insertText(replacement, from, to)\n editor.view.dispatch(tr)\n editor.view.focus()\n\n const delta = replacement.length - (item.wrongWord?.length ?? 0)\n const origStart = item.startIndex\n const origEnd = item.endIndex\n\n for (let i = errors.length - 1; i >= 0; i--) {\n const err = errors[i]\n\n if (err.startIndex >= origStart && err.startIndex < origEnd) {\n errors.splice(i, 1)\n continue\n }\n\n if (err.startIndex > origStart) {\n err.startIndex += delta\n err.endIndex += delta\n }\n }\n\n const idx = errors.indexOf(item)\n if (idx !== -1) errors.splice(idx, 1)\n\n applyHighlights(editor, errors)\n}\n\nconst contentEl = ref<HTMLElement | null>(null)\nconst standardMaxHeight = 450\nconst maxHeight = ref(standardMaxHeight)\nconst { height: windowHeight } = useWindowSize()\n\nfunction computeMaxHeight() {\n const el = contentEl.value\n if (!el) return\n\n const gap = 80\n const rect = el.getBoundingClientRect()\n const availableViewportHeight = windowHeight.value - rect.top - gap\n\n maxHeight.value = standardMaxHeight > availableViewportHeight ? availableViewportHeight : standardMaxHeight\n}\n\nonMounted(() => {\n computeMaxHeight()\n useEventListener(window, 'resize', computeMaxHeight)\n})\n</script>\n\n<template>\n <div ref=\"contentEl\" :style=\"{ maxHeight: `${maxHeight}px` }\" class=\"pr-1 overflow-y-auto\">\n <template v-for=\"(editorData, key) in editorsState\" :key=\"key\">\n <div\n v-for=\"(item, idx) in editorData.wrongWords\"\n :key=\"idx\"\n class=\"border-b border-gray-400 dark:border-ed-muted pb-5 mb-5 cursor-pointer\"\n @click=\"scrollToError(key, editorsState[key].editor as Editor, item)\"\n >\n <div class=\"flex items-center mb-2\">\n <span class=\"w-16 font-medium\">입력 내용</span>\n <div class=\"flex items-center gap-2\">\n <span class=\"w-1.5 h-1.5 rounded-full\" :class=\"getErrorColor(item.errorHelpDtos[0]?.errorType)\"></span>\n <span class=\"break-all whitespace-normal\">{{ item.wrongWord }}</span>\n </div>\n </div>\n\n <div class=\"flex items-center mb-2\">\n <span class=\"w-16 font-medium\">대치어</span>\n <div v-if=\"item.correctWord.length\" class=\"flex-1 space-y-1\">\n <div\n v-for=\"(sub, sidx) in item.correctWord\"\n :key=\"sidx\"\n class=\"font-semibold px-3 py-1.5 rounded bg-gray-400 dark:bg-ed-muted flex items-center justify-between\"\n >\n <div class=\"text-sm\">\n {{ sub }}\n </div>\n <button\n class=\"flex items-center gap-1 text-blue-500\"\n @click.stop=\"replaceWithCorrectWord(editorData.editor as Editor, editorData.wrongWords, item, sub)\"\n >\n <ArrowLeftRight class=\"w-4 h-4\" /> <span>바꾸기</span>\n </button>\n </div>\n </div>\n <div v-else>\n {{ getNoSuggestionText(editorData.editor as Editor) }}\n </div>\n </div>\n\n <div class=\"flex\">\n <span class=\"w-16 font-medium\">도움말</span>\n <div class=\"flex-1\">\n <BulkSpellCheckerHelpText :text=\"item.errorHelpDtos[0]?.errorMessage\" />\n </div>\n </div>\n </div>\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { cn } from '@/utils'\n\ninterface Props {\n fillWhite?: boolean\n class?: string\n}\nconst props = withDefaults(defineProps<Props>(), {\n fillWhite: false,\n class: '',\n})\n</script>\n\n<template>\n <svg :class=\"cn('animate-spin h-5 w-5 mr-0.5', props.class)\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <circle\n v-if=\"fillWhite\"\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n fill=\"#ffffff\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <circle v-else class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path\n class=\"opacity-100\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n</template>\n\n<style scoped></style>\n","<template>\n <div class=\"min-h-[188px] flex flex-col items-center justify-center gap-y-2 text-sm\">\n <SpinnerIcon fill-white class=\"h-10 w-10 text-blue-500\" />\n <div>맞춤법 검사 중입니다</div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { SPELL_CHECK_STATUS, SpellCheckStatus } from '@/constants'\nimport { cn } from '@/utils'\nimport { EditorsState } from '@/type'\n\ninterface Props {\n editorsState: EditorsState,\n spellCheckStatus: SpellCheckStatus\n allWrongWordsMissSuggestions: boolean\n}\nconst props = defineProps<Props>()\n\nconst emit = defineEmits<{\n (e: 'close-modal'): void\n (e: 'run-spellcheck'): void\n (e: 'replace-all-editor-errors'): void\n}>()\n</script>\n\n<template>\n <div class=\"text-xs py-4 px-6\">\n <BulkSpellCheckerLoading v-if=\"spellCheckStatus === SPELL_CHECK_STATUS.LOADING\" />\n <BulkSpellCheckerWrongWordList v-else-if=\"spellCheckStatus === SPELL_CHECK_STATUS.HAS_ERROR\" :editorsState=\"editorsState\" />\n <BulkSpellCheckerNotWrongWord v-else-if=\"spellCheckStatus === SPELL_CHECK_STATUS.NO_ERROR\" />\n <BulkSpellCheckerFail v-else-if=\"spellCheckStatus === SPELL_CHECK_STATUS.FAIL\" />\n\n <div class=\"flex items-center justify-between mt-3\">\n <ul class=\"flex items-cente gap-x-4\">\n <li class=\"flex items-center gap-x-1\"><span class=\"w-1.5 h-1.5 rounded-full bg-red-500\"></span>맞춤법</li>\n <li class=\"flex items-center gap-x-1\"><span class=\"w-1.5 h-1.5 rounded-full bg-blue-500\"></span>띄어쓰기</li>\n <li class=\"flex items-center gap-x-1\"><span class=\"w-1.5 h-1.5 rounded-full bg-green-500\"></span>통합교정</li>\n </ul>\n\n <div class=\"flex gap-x-1\">\n <Button\n variant=\"outline\"\n :class=\"\n cn(\n 'border-blue-500 text-blue-500 text-xs px-3 py-2 h-auto hover:bg-white/80 hover:opacity-80 hover:text-blue-500 dark:text-dark-blue-100 dark:hover:bg-dark-blue-400 dark:hover:text-dark-blue-50 dark:hover:border-dark-blue-100',\n spellCheckStatus === SPELL_CHECK_STATUS.LOADING &&\n 'text-gray-300 bg-gray-400 border-gray-400 pointer-events-none dark:bg-ed-muted/70 dark:border-ed-muted/70 dark:text-gray-500'\n )\n \"\n @click=\"emit('run-spellcheck')\"\n >다시 검사하기</Button\n >\n\n <Button\n :class=\"\n cn(\n 'border-blue-500 text-white text-xs px-3 py-2 h-auto bg-blue-500 hover:bg-blue-500/80',\n (spellCheckStatus !== SPELL_CHECK_STATUS.HAS_ERROR || allWrongWordsMissSuggestions) &&\n 'text-gray-300 bg-gray-400 hover:bg-gray-400 pointer-events-none dark:bg-ed-muted/70 dark:text-gray-500'\n )\n \"\n @click=\"emit('replace-all-editor-errors')\"\n >모두 바꾸기</Button\n >\n </div>\n </div>\n </div>\n</template>\n","import { EDITOR_NAME, EditorName, SPELL_CHECK_CODE, SPELL_CHECK_STATUS, SpellCheckStatus } from '@/constants'\nimport { EditorsState, SpellCheckResponse, WrongWordItem } from '@/type'\nimport { Editor } from '@tiptap/core'\nimport axios from 'axios'\nimport { applyHighlights, clearHighlights, buildPlainIndexToDocPosMap } from '@/utils/bulkSpellchecker'\nimport { SPELLCHECKER_META_LIST } from '@/extensions/SpellChecker/spellchecker-extension'\n\nexport const useBulkSpellCheckerStore = () => {\n const editorsState: EditorsState = reactive({\n [EDITOR_NAME.EDITOR_COMMENT]: {\n editor: null,\n wrongWords: [],\n },\n [EDITOR_NAME.EDITOR_CONTENT]: {\n editor: null,\n wrongWords: [],\n },\n })\n\n function setEditor(editorKey: EditorName, editorInstance: Editor | null) {\n editorsState[editorKey].editor = editorInstance\n }\n\n const spellCheckStatus = ref<SpellCheckStatus>(SPELL_CHECK_STATUS.NO_ERROR)\n\n function resetAllEditorWrongWords() {\n Object.values(editorsState).forEach(editorState => {\n editorState.wrongWords = []\n })\n }\n\n function evaluateStatus(hasFail: boolean, hasError: boolean) {\n if (hasFail) return SPELL_CHECK_STATUS.FAIL\n if (hasError) return SPELL_CHECK_STATUS.HAS_ERROR\n return SPELL_CHECK_STATUS.NO_ERROR\n }\n\n async function handleRunSpellCheck() {\n spellCheckStatus.value = SPELL_CHECK_STATUS.LOADING\n\n let hasError = false\n let hasFail = false\n\n for (const [editorKey, { editor }] of Object.entries(editorsState)) {\n if (!editor) continue\n\n const apiUrl = editor?.extensionManager.extensions.find(ext => ext.name === 'spellchecker')?.options.proofreader\n .api\n const content = editor.getText({ blockSeparator: '\\n' })\n if (!apiUrl || !content) continue\n\n try {\n const { data: response } = await axios.post<SpellCheckResponse>(apiUrl, {\n value: content,\n })\n\n if (!response.success && response.code !== SPELL_CHECK_CODE.NOTHING_TO_CHANGE) {\n hasFail = true\n editorsState[editorKey].wrongWords = []\n continue\n }\n\n if (response.data?.wrongWordResponseDto) {\n hasError = true\n editorsState[editorKey].wrongWords = response.data.wrongWordResponseDto\n continue\n }\n\n editorsState[editorKey].wrongWords = []\n } catch (error) {\n console.error('handleRunSpellCheck error: ', error)\n hasFail = true\n }\n }\n\n spellCheckStatus.value = evaluateStatus(hasFail, hasError)\n }\n\n const countTotalWrongWords = computed(() => {\n return Object.values(editorsState).reduce((sum, { wrongWords }) => {\n return sum + wrongWords.length\n }, 0)\n })\n\n watch(countTotalWrongWords, newVal => {\n if (newVal === 0) {\n spellCheckStatus.value = evaluateStatus(false, false)\n }\n })\n\n const allWrongWordsMissSuggestions = computed(() => {\n const allWrongWords = Object.values(editorsState).flatMap(es => es.wrongWords)\n if (allWrongWords.length === 0) return false\n return allWrongWords.every(w => !Array.isArray(w.correctWord) || w.correctWord.length === 0)\n })\n\n function applyAllEditorHighlightErrors() {\n for (const [_, { editor, wrongWords }] of Object.entries(editorsState)) {\n if (!editor) continue\n applyHighlights(editor as Editor, wrongWords)\n }\n }\n\n function clearAllEditorHighlightErrors() {\n for (const [_, { editor }] of Object.entries(editorsState)) {\n if (!editor) continue\n clearHighlights(editor as Editor)\n }\n }\n\n async function reRunSpellCheckAndHighlight() {\n await handleRunSpellCheck()\n applyAllEditorHighlightErrors()\n }\n\n let isEnableCurrent = true\n function disableSpellCheckRealTime(isEnableSpellCheckRealTime: boolean) {\n isEnableCurrent = isEnableSpellCheckRealTime\n if (!isEnableSpellCheckRealTime) return\n\n for (const [_, { editor }] of Object.entries(editorsState)) {\n if (!editor) continue\n editor.extensionStorage.spellchecker.spellchecker.setEnabledProofreadText(false)\n editor.view.dispatch(editor.state.tr.setMeta(SPELLCHECKER_META_LIST.IS_ACTIVE_SPELLCHECK, false))\n }\n }\n\n function resetEnableSpellCheckRealTime() {\n if (!isEnableCurrent) return\n\n for (const [_, { editor }] of Object.entries(editorsState)) {\n if (!editor) continue\n editor.extensionStorage.spellchecker.spellchecker.setEnabledProofreadText(true)\n editor.view.dispatch(editor.state.tr.setMeta(SPELLCHECKER_META_LIST.IS_ACTIVE_SPELLCHECK, true))\n }\n }\n\n function replaceAllErrors(editor: Editor, errors: WrongWordItem[], blockSeparator = '\\n') {\n if (!editor) return\n if (!errors.length) return\n\n const map = buildPlainIndexToDocPosMap(editor, blockSeparator)\n\n function getMappedPos(offset: number) {\n if (offset < 0) offset = 0\n if (offset >= map.length) return editor.state.doc.content.size\n if (map[offset] != null) return map[offset] as number\n for (let i = offset; i < map.length; i++) if (map[i] != null) return map[i] as number\n for (let i = offset - 1; i >= 0; i--) if (map[i] != null) return map[i] as number\n return editor.state.doc.content.size\n }\n\n const replacements = errors.map(item => {\n const from = getMappedPos(item.startIndex)\n const to = getMappedPos(Math.max(0, item.endIndex - 1)) + 1\n const replacement = item.correctWord?.[0] ?? item.wrongWord\n return { item, from, to, replacement }\n })\n\n const validRepls = replacements.filter(r => typeof r.from === 'number' && typeof r.to === 'number' && r.from < r.to)\n\n if (!validRepls.length) return\n\n validRepls.sort((a, b) => b.from - a.from)\n\n const tr = editor.state.tr\n let lastAppliedFrom = Number.POSITIVE_INFINITY\n const appliedItems = new Set<WrongWordItem>()\n\n for (const r of validRepls) {\n if (r.to > lastAppliedFrom) {\n continue\n }\n\n tr.insertText(r.replacement, r.from, r.to)\n\n appliedItems.add(r.item)\n lastAppliedFrom = r.from\n }\n\n if (appliedItems.size > 0) {\n editor.view.dispatch(tr)\n editor.view.focus()\n }\n\n if (appliedItems.size > 0) {\n errors = errors.filter(e => ![...appliedItems].some(a => a === e))\n }\n\n applyHighlights(editor, errors)\n }\n\n function replaceAllEditorErrors() {\n for (const [_, { editor, wrongWords }] of Object.entries(editorsState)) {\n if (!editor) continue\n replaceAllErrors(editor as Editor, wrongWords)\n }\n }\n\n return {\n editorsState,\n spellCheckStatus,\n countTotalWrongWords,\n allWrongWordsMissSuggestions,\n setEditor,\n resetAllEditorWrongWords,\n disableSpellCheckRealTime,\n resetEnableSpellCheckRealTime,\n applyAllEditorHighlightErrors,\n clearAllEditorHighlightErrors,\n reRunSpellCheckAndHighlight,\n handleRunSpellCheck,\n replaceAllEditorErrors,\n }\n}\n","<script setup lang=\"ts\">\nimport { DialogTrigger, type DialogTriggerProps } from 'radix-vue'\n\nconst props = defineProps<DialogTriggerProps>()\n</script>\n\n<template>\n <DialogTrigger v-bind=\"props\">\n <slot />\n </DialogTrigger>\n</template>\n","<script setup lang=\"ts\">\nimport { EDITOR_NAME } from '@/constants'\nimport { useBulkSpellCheckerStore } from '@/hooks/useBulkSpellCheckerStore'\nimport { Editor } from '@tiptap/core'\nimport { DialogTrigger } from './ui/dialog'\n\ninterface Props {\n editor: Editor\n editorComment?: Editor\n isEnableSpellCheckRealTime: boolean\n}\nconst props = defineProps<Props>()\n\nconst {\n editorsState,\n countTotalWrongWords,\n spellCheckStatus,\n allWrongWordsMissSuggestions,\n setEditor,\n disableSpellCheckRealTime,\n resetEnableSpellCheckRealTime,\n handleRunSpellCheck,\n resetAllEditorWrongWords,\n applyAllEditorHighlightErrors,\n clearAllEditorHighlightErrors,\n reRunSpellCheckAndHighlight,\n replaceAllEditorErrors,\n} = useBulkSpellCheckerStore()\n\nconst isOpenModal = ref(false)\n\nconst dragOffset = reactive({ x: 0, y: 0 })\nconst dragging = ref(false)\nconst offset = { x: 0, y: 0 }\n\nconst onMouseDown = (e: MouseEvent) => {\n dragging.value = true\n offset.x = e.clientX - dragOffset.x\n offset.y = e.clientY - dragOffset.y\n document.addEventListener('mousemove', onMouseMove)\n document.addEventListener('mouseup', onMouseUp)\n}\n\nconst onMouseMove = (e: MouseEvent) => {\n if (!dragging.value) return\n dragOffset.x = e.clientX - offset.x\n dragOffset.y = e.clientY - offset.y\n}\n\nconst onMouseUp = () => {\n dragging.value = false\n document.removeEventListener('mousemove', onMouseMove)\n document.removeEventListener('mouseup', onMouseUp)\n}\n\nonUnmounted(() => {\n document.removeEventListener('mousemove', onMouseMove)\n document.removeEventListener('mouseup', onMouseUp)\n})\n\nconst triggerRef = ref<InstanceType<typeof DialogTrigger> | null>(null)\nconst position = ref({ top: 0, right: 0 })\n\nconst updatePosition = () => {\n if (triggerRef.value) {\n const rect = triggerRef.value.$el.getBoundingClientRect()\n\n position.value = {\n top: rect.bottom + window.scrollY + 5,\n right: window.innerWidth - rect.right - window.scrollX,\n }\n\n dragOffset.x = 0\n dragOffset.y = 0\n }\n}\n\nonMounted(async () => {\n if (props.editorComment) {\n setEditor(EDITOR_NAME.EDITOR_COMMENT, props.editorComment)\n }\n setEditor(EDITOR_NAME.EDITOR_CONTENT, props.editor)\n})\n\nonUnmounted(() => {\n setEditor(EDITOR_NAME.EDITOR_COMMENT, null)\n setEditor(EDITOR_NAME.EDITOR_CONTENT, null)\n})\n\nwatch(isOpenModal, async val => {\n if (val) {\n await nextTick()\n updatePosition()\n disableSpellCheckRealTime(props.isEnableSpellCheckRealTime)\n await handleRunSpellCheck()\n applyAllEditorHighlightErrors()\n } else {\n resetAllEditorWrongWords()\n resetEnableSpellCheckRealTime()\n clearAllEditorHighlightErrors()\n }\n})\n\nconst bulkSpellCheckerBtnConfig = props.editor?.extensionManager.extensions.find(e => e.name === 'spellchecker')\n ?.options.bulkSpellCheckerButton\n</script>\n\n<template>\n <Dialog :open=\"isOpenModal\">\n <DialogTrigger as-child ref=\"triggerRef\" @click=\"isOpenModal = !isOpenModal\">\n <button\n v-if=\"!bulkSpellCheckerBtnConfig\"\n class=\"border-blue-500 text-white text-xs text-nowrap px-3 py-2 h-auto bg-blue-500 hover:bg-blue-500/80 flex items-center rounded\"\n >\n <Icon name=\"checkUnderline\" />맞춤법 일괄 교정\n </button>\n\n <component\n v-else\n :is=\"bulkSpellCheckerBtnConfig.component\"\n :buttonName=\"bulkSpellCheckerBtnConfig.props.buttonName\"\n :icon=\"bulkSpellCheckerBtnConfig.props.icon\"\n :type=\"bulkSpellCheckerBtnConfig.props.type\"\n :disabled=\"bulkSpellCheckerBtnConfig.props.disabled\"\n :iconPosition=\"bulkSpellCheckerBtnConfig.props.iconPosition\"\n :buttonSize=\"bulkSpellCheckerBtnConfig.props.buttonSize\"\n :iconClass=\"bulkSpellCheckerBtnConfig.props.iconClass\"\n />\n </DialogTrigger>\n\n <DialogContent is-overlay-transparent class=\"p-0 gap-0 !animate-none !transition-none dark:border-ed-muted\" as-child>\n <div\n class=\"z-[70]\"\n :style=\"{\n transform: `translate(${dragOffset.x}px, ${dragOffset.y}px)`,\n top: `${position.top}px`,\n right: `${position.right}px`,\n left: 'auto',\n }\"\n >\n <DialogHeader\n class=\"bg-ed-blue-light py-3.5 px-6 rounded-t-[5px] cursor-move text-blue-500 dark:text-dark-blue-100 flex-row items-center justify-between\"\n @mousedown.prevent=\"onMouseDown\"\n >\n <DialogTitle class=\"text-base space-x-2\">\n <span>맞춤법/문법 오류</span>\n <Badge class=\"text-sm bg-blue-500 hover:bg-blue-500 dark:bg-dark-blue-100 px-2\">{{ countTotalWrongWords }}개</Badge></DialogTitle\n >\n\n <DialogClose @click=\"isOpenModal = false\" class=\"text-xs flex items-center gap-x-1\">\n <Icon name=\"Close\" class=\"w-4 h-4\" />{{ $t('editor.close') }}\n </DialogClose>\n </DialogHeader>\n\n <DialogDescription></DialogDescription>\n\n <BulkSpellCheckerContent\n :editorsState=\"editorsState\"\n :spellCheckStatus=\"spellCheckStatus\"\n :allWrongWordsMissSuggestions=\"allWrongWordsMissSuggestions\"\n @close-modal=\"isOpenModal = false\"\n @run-spellcheck=\"reRunSpellCheckAndHighlight\"\n @replace-all-editor-errors=\"(replaceAllEditorErrors(), (isOpenModal = false))\"\n />\n </div>\n </DialogContent>\n </Dialog>\n</template>\n\n<style scoped></style>\n"],"names":["ERROR_TYPE","SPELL_CHECK_CODE","SPELL_CHECK_STATUS","EDITOR_NAME","ArrowLeftRight","createLucideIcon","CircleAlert","CircleCheck","expanded","ref","showButton","helpRef","toggle","onMounted","nextTick","HIGHLIGHT_KEY","PluginKey","createHighlightPlugin","editor","errors","blockSeparator","Plugin","state","decos","errorColorMap","item","from","findDocPosFromOffset","to","errorType","_b","_a","className","safeFrom","safeTo","Decoration","DecorationSet","applyHighlights","plugin","clearHighlights","buildPlainIndexToDocPosMap","map","plainIndex","firstBlock","node","pos","i","nodeName","k","offset","mapped","standardMaxHeight","props","__props","getErrorColor","getNoSuggestionText","_d","_c","resetHightlightSection","key","scrollToError","mid","maybeNode","el","replaceWithCorrectWord","replacement","tr","delta","origStart","origEnd","err","idx","contentEl","maxHeight","windowHeight","useWindowSize","computeMaxHeight","gap","rect","availableViewportHeight","useEventListener","_openBlock","_createElementBlock","_hoisted_1","_createVNode","_component_SpinnerIcon","emit","__emit","useBulkSpellCheckerStore","editorsState","reactive","setEditor","editorKey","editorInstance","spellCheckStatus","resetAllEditorWrongWords","editorState","evaluateStatus","hasFail","hasError","handleRunSpellCheck","apiUrl","ext","content","response","axios","error","countTotalWrongWords","computed","sum","wrongWords","watch","newVal","allWrongWordsMissSuggestions","allWrongWords","es","w","applyAllEditorHighlightErrors","_","clearAllEditorHighlightErrors","reRunSpellCheckAndHighlight","isEnableCurrent","disableSpellCheckRealTime","isEnableSpellCheckRealTime","SPELLCHECKER_META_LIST","resetEnableSpellCheckRealTime","replaceAllErrors","getMappedPos","validRepls","r","a","b","lastAppliedFrom","appliedItems","e","replaceAllEditorErrors","isOpenModal","dragOffset","dragging","onMouseDown","onMouseMove","onMouseUp","onUnmounted","triggerRef","position","updatePosition","val","bulkSpellCheckerBtnConfig"],"mappings":"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","x_google_ignoreList":[1,2,3]}
|
|
@@ -31679,7 +31679,7 @@ const XK = { class: "flex gap-2 items-center overflow-x-auto overflow-y-hidden [
|
|
|
31679
31679
|
mode: {}
|
|
31680
31680
|
},
|
|
31681
31681
|
setup(t) {
|
|
31682
|
-
const e = sR(() => import("./BulkSpellChecker-
|
|
31682
|
+
const e = sR(() => import("./BulkSpellChecker-DT2RlF4H.mjs")), { t: n } = Jt(), o = t, r = Gt("isEditable", H(!0)), i = ["fontSize", "fontFamily", "superText", "spellchecker", "fontSizeIncreaseDecrease"], s = Y(() => {
|
|
31683
31683
|
const f = [...o.editor.extensionManager.extensions].sort((m, b) => m.name === "superText" ? 1 : b.name === "superText" ? -1 : 0);
|
|
31684
31684
|
let h = [];
|
|
31685
31685
|
for (const m of f) {
|
|
@@ -49263,7 +49263,7 @@ const mre = {
|
|
|
49263
49263
|
}, gre = { className: "text-neutral-500 text-[0.65rem] col-[1/-1] mx-2 mt-2 font-semibold tracking-wider select-none uppercase first:mt-0.5" }, bre = ["onClick"], vre = ["src"], yre = {
|
|
49264
49264
|
key: 1,
|
|
49265
49265
|
class: "p-3"
|
|
49266
|
-
}, wre = { class: "text-xs text-gray-800 dark:text-gray-
|
|
49266
|
+
}, wre = { class: "text-xs text-gray-800 dark:text-gray-400" }, xre = /* @__PURE__ */ W({
|
|
49267
49267
|
__name: "CommandsList",
|
|
49268
49268
|
props: {
|
|
49269
49269
|
editor: {},
|
|
@@ -53819,7 +53819,7 @@ const qse = { class: "flex flex-1" }, K2 = /* @__PURE__ */ W({
|
|
|
53819
53819
|
}), i = (a) => a.id === "spellchecker" ? "!text-ed-blue !bg-white !font-normal rounded [&>div>svg]:w-[19px] [&>div>svg]:h-[19px] h-[26px] gap-x-1 whitespace-nowrap" : a.button.componentProps.customClass, s = (a) => a.id === "spellchecker" ? "Spellchecker" : a.button.componentProps.icon;
|
|
53820
53820
|
return (a, l) => (M(), ge("div", {
|
|
53821
53821
|
id: "tool-bar-format",
|
|
53822
|
-
class: je(g(Ye)("bg-white border border-gray-
|
|
53822
|
+
class: je(g(Ye)("bg-white border border-gray-400 dark:bg-ed-gray-500 dark:border-ed-muted rounded-full shadow-md px-2.5", !r.value.length && "hidden"))
|
|
53823
53823
|
}, [
|
|
53824
53824
|
te("div", Kse, [
|
|
53825
53825
|
(M(!0), ge(nt, null, zt(r.value, (u, d) => {
|
|
@@ -55678,10 +55678,10 @@ const oae = /* @__PURE__ */ MH(nae), Hx = (t, e, n) => {
|
|
|
55678
55678
|
}, rae = {
|
|
55679
55679
|
key: 0,
|
|
55680
55680
|
class: "px-2 min-h-[24px] flex items-center justify-between gap-1 mb-1.5"
|
|
55681
|
-
}, iae = { class: "flex items-center gap-2" }, sae = { class: "
|
|
55681
|
+
}, iae = { class: "flex items-center gap-2" }, sae = { class: "body-small text-gray-600 px-[6px] py-[2px] shrink-0 rounded-[4px] bg-gray-100 !text-gray-600" }, aae = { class: "label-large text-gray-800 line-clamp-1" }, lae = { class: "flex items-center gap-1 shrink-0" }, uae = { class: "mt-[2px]" }, cae = { class: "body-small text-gray-400" }, dae = { class: "border border-gray-50 rounded-md py-[10px] px-4 flex-1 overflow-y-auto" }, fae = { class: "border border-ed-gray rounded-[5px] p-2.5 h-full" }, pae = {
|
|
55682
55682
|
key: 0,
|
|
55683
55683
|
class: "px-2 min-h-[24px] flex items-center justify-between gap-1 mb-1.5"
|
|
55684
|
-
}, hae = { class: "flex items-center gap-2" }, mae = { class: "
|
|
55684
|
+
}, hae = { class: "flex items-center gap-2" }, mae = { class: "body-small text-gray-600 px-[6px] py-[2px] shrink-0 rounded-[4px] bg-blue-50 !text-blue-500" }, gae = { class: "label-large text-gray-800 line-clamp-1" }, bae = { class: "flex items-center gap-1 shrink-0" }, vae = { class: "mt-[2px]" }, yae = { class: "body-small text-gray-400" }, wae = { class: "border border-gray-50 bg-dark-blue-600 rounded-md py-[10px] px-4 flex-1 overflow-y-auto" }, xae = /* @__PURE__ */ W({
|
|
55685
55685
|
__name: "ArticleCompareEditor",
|
|
55686
55686
|
props: {
|
|
55687
55687
|
originalData: {},
|
|
@@ -55743,7 +55743,7 @@ const oae = /* @__PURE__ */ MH(nae), Hx = (t, e, n) => {
|
|
|
55743
55743
|
te("div", uae, [
|
|
55744
55744
|
D(x, {
|
|
55745
55745
|
name: "Clock",
|
|
55746
|
-
class: "w-[13px] h-[13px] text-gray-
|
|
55746
|
+
class: "w-[13px] h-[13px] text-gray-400"
|
|
55747
55747
|
})
|
|
55748
55748
|
]),
|
|
55749
55749
|
te("div", cae, Le((k = (T = b.originalData) == null ? void 0 : T.titleBar) == null ? void 0 : k.time), 1)
|
|
@@ -55803,7 +55803,7 @@ const oae = /* @__PURE__ */ MH(nae), Hx = (t, e, n) => {
|
|
|
55803
55803
|
te("div", vae, [
|
|
55804
55804
|
D(x, {
|
|
55805
55805
|
name: "Clock",
|
|
55806
|
-
class: "w-[13px] h-[13px] text-gray-
|
|
55806
|
+
class: "w-[13px] h-[13px] text-gray-400"
|
|
55807
55807
|
})
|
|
55808
55808
|
]),
|
|
55809
55809
|
te("div", yae, Le((k = (T = b.changedData) == null ? void 0 : T.titleBar) == null ? void 0 : k.time), 1)
|
|
@@ -55842,7 +55842,7 @@ const oae = /* @__PURE__ */ MH(nae), Hx = (t, e, n) => {
|
|
|
55842
55842
|
], 64);
|
|
55843
55843
|
};
|
|
55844
55844
|
}
|
|
55845
|
-
}), ule = /* @__PURE__ */ rs(xae, [["__scopeId", "data-v-
|
|
55845
|
+
}), ule = /* @__PURE__ */ rs(xae, [["__scopeId", "data-v-7c635073"]]), _7 = (t) => {
|
|
55846
55846
|
if (!t) return -1;
|
|
55847
55847
|
const { from: e } = t.state.selection;
|
|
55848
55848
|
let n = 0;
|
|
@@ -56836,4 +56836,4 @@ export {
|
|
|
56836
56836
|
$ae as y,
|
|
56837
56837
|
Rae as z
|
|
56838
56838
|
};
|
|
56839
|
-
//# sourceMappingURL=index-
|
|
56839
|
+
//# sourceMappingURL=index-CaYoCbLr.mjs.map
|