vdc-editor 0.1.198 → 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-IKxccUeP.mjs → BulkSpellChecker-DT2RlF4H.mjs} +6 -6
- package/lib/{BulkSpellChecker-IKxccUeP.mjs.map → BulkSpellChecker-DT2RlF4H.mjs.map} +1 -1
- package/lib/{index-DgdZsemB.mjs → index-CaYoCbLr.mjs} +2748 -2718
- package/lib/{index-DgdZsemB.mjs.map → index-CaYoCbLr.mjs.map} +1 -1
- package/lib/src/components/icons/icons.d.ts +1 -0
- package/lib/src/type.d.ts +3 -0
- package/lib/style.css +1 -1
- package/lib/vdc-editor.mjs +1 -1
- package/lib/vdc-editor.umd.js +56 -56
- 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-IKxccUeP.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]}
|