UNPKG

on-codemerge

Version:

A WYSIWYG editor for on-codemerge is a user-friendly interface that allows users to edit and view their code in real time, exactly as it will appear in the final product

3 lines (2 loc) 8.38 kB
/*! on-codemerge v1.3.1 @author Pavel Kuzmin @license MIT @homepage https://s00d.github.io/on-codemerge/ @repository git+https://github.com/s00d/on-codemerge.git Copyright (c) 2026 Pavel Kuzmin - Built on 2026-07-02T13:39:17.947Z */ "use strict";var m=Object.defineProperty;var k=(i,e,t)=>e in i?m(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t;var h=(i,e,t)=>k(i,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const C=require("../ToolbarPlugin/utils.cjs"),x=require("../../icons/spell-check.svg.cjs"),v=require("../../../node_modules/.pnpm/spellchecker-wasm@0.3.3/node_modules/spellchecker-wasm/lib/spellchecker-wasm.wasm.cjs"),S=Object.assign({"./dictionaries/ar.txt":()=>Promise.resolve().then(()=>require("./dictionaries/ar.txt.cjs")).then(i=>i.default),"./dictionaries/cs.txt":()=>Promise.resolve().then(()=>require("./dictionaries/cs.txt.cjs")).then(i=>i.default),"./dictionaries/de.txt":()=>Promise.resolve().then(()=>require("./dictionaries/de.txt.cjs")).then(i=>i.default),"./dictionaries/en.txt":()=>Promise.resolve().then(()=>require("./dictionaries/en.txt.cjs")).then(i=>i.default),"./dictionaries/es.txt":()=>Promise.resolve().then(()=>require("./dictionaries/es.txt.cjs")).then(i=>i.default),"./dictionaries/fr.txt":()=>Promise.resolve().then(()=>require("./dictionaries/fr.txt.cjs")).then(i=>i.default),"./dictionaries/hi.txt":()=>Promise.resolve().then(()=>require("./dictionaries/hi.txt.cjs")).then(i=>i.default),"./dictionaries/id.txt":()=>Promise.resolve().then(()=>require("./dictionaries/id.txt.cjs")).then(i=>i.default),"./dictionaries/it.txt":()=>Promise.resolve().then(()=>require("./dictionaries/it.txt.cjs")).then(i=>i.default),"./dictionaries/ja.txt":()=>Promise.resolve().then(()=>require("./dictionaries/ja.txt.cjs")).then(i=>i.default),"./dictionaries/ko.txt":()=>Promise.resolve().then(()=>require("./dictionaries/ko.txt.cjs")).then(i=>i.default),"./dictionaries/nl.txt":()=>Promise.resolve().then(()=>require("./dictionaries/nl.txt.cjs")).then(i=>i.default),"./dictionaries/pl.txt":()=>Promise.resolve().then(()=>require("./dictionaries/pl.txt.cjs")).then(i=>i.default),"./dictionaries/pt.txt":()=>Promise.resolve().then(()=>require("./dictionaries/pt.txt.cjs")).then(i=>i.default),"./dictionaries/ru.txt":()=>Promise.resolve().then(()=>require("./dictionaries/ru.txt.cjs")).then(i=>i.default),"./dictionaries/th.txt":()=>Promise.resolve().then(()=>require("./dictionaries/th.txt.cjs")).then(i=>i.default),"./dictionaries/tr.txt":()=>Promise.resolve().then(()=>require("./dictionaries/tr.txt.cjs")).then(i=>i.default),"./dictionaries/vi.txt":()=>Promise.resolve().then(()=>require("./dictionaries/vi.txt.cjs")).then(i=>i.default),"./dictionaries/zh.txt":()=>Promise.resolve().then(()=>require("./dictionaries/zh.txt.cjs")).then(i=>i.default)});class b{constructor(){h(this,"name","spellchecker");h(this,"hotkeys",[{keys:"Ctrl+Shift+S",description:"Run spell checker",command:"spellchecker",icon:"🔍✅"}]);h(this,"editor",null);h(this,"toolbarButton",null);h(this,"isSpellCheckEnabled",!1);h(this,"spellChecker",null);h(this,"misspelledWords",new Map);h(this,"lastResults",[])}async initialize(e){this.editor=e,this.addToolbarButton(),this.enableSpellCheck(this.isSpellCheckEnabled),this.editor.on("spellchecker",async()=>{var t,s;this.isSpellCheckEnabled=!this.isSpellCheckEnabled,this.isSpellCheckEnabled&&await this.loadDictionary(((t=this.editor)==null?void 0:t.getLocale())??"en"),this.enableSpellCheck(this.isSpellCheckEnabled),(s=this.toolbarButton)==null||s.classList.toggle("active",this.isSpellCheckEnabled)})}async loadDictionary(e){try{const t=await fetch(v.default),s=S[`./dictionaries/${e}.txt`];if(!s)throw new Error(`Dictionary files for locale ${e} not found`);const l=await s(),n=await fetch(l);if(!t.ok||!n.ok)throw new Error("Failed to load dictionary files");const{SpellcheckerWasm:r}=await Promise.resolve().then(()=>require("../../../_virtual/index.cjs")).then(o=>o.index);this.spellChecker=new r(o=>{this.lastResults=o}),await this.spellChecker.prepareSpellchecker(t,n)}catch(t){console.error("Failed to load dictionary:",t),this.spellChecker=null}}addToolbarButton(){var t,s;const e=(t=this.editor)==null?void 0:t.getToolbar();e&&(this.toolbarButton=C.createToolbarButton({icon:x.default,title:(s=this.editor)==null?void 0:s.t("Spell Check"),onClick:async()=>{var l,n;this.isSpellCheckEnabled=!this.isSpellCheckEnabled,this.isSpellCheckEnabled&&await this.loadDictionary(((l=this.editor)==null?void 0:l.getLocale())??"en"),this.enableSpellCheck(this.isSpellCheckEnabled),(n=this.toolbarButton)==null||n.classList.toggle("active",this.isSpellCheckEnabled)}}),e.appendChild(this.toolbarButton))}enableSpellCheck(e){var s;((s=this.editor)==null?void 0:s.getContainer())&&(e?(this.addSpellCheckListeners(),this.checkAllText()):(this.removeSpellCheckListeners(),this.clearHighlights()))}addSpellCheckListeners(){var t;const e=(t=this.editor)==null?void 0:t.getContainer();e&&(e.addEventListener("input",this.handleInput.bind(this)),e.addEventListener("mouseup",this.handleMouseUp.bind(this)),e.addEventListener("contextmenu",this.handleContextMenu.bind(this)))}removeSpellCheckListeners(){var t;const e=(t=this.editor)==null?void 0:t.getContainer();e&&(e.removeEventListener("input",this.handleInput.bind(this)),e.removeEventListener("mouseup",this.handleMouseUp.bind(this)),e.removeEventListener("contextmenu",this.handleContextMenu.bind(this)))}handleInput(e){this.checkAllText()}handleMouseUp(e){var s,l;const t=(l=(s=this.editor)==null?void 0:s.getTextFormatter())==null?void 0:l.getSelection();if(t&&t.rangeCount>0){const n=t.getRangeAt(0);n.toString()&&this.checkSpelling(n)}}handleContextMenu(e){var s,l;const t=(l=(s=this.editor)==null?void 0:s.getTextFormatter())==null?void 0:l.getSelection();if(t&&t.rangeCount>0){const n=t.getRangeAt(0),r=n.toString();if(r&&this.isMisspelled(r)){e.preventDefault();const o=this.getSpellingSuggestions(r);o.length>0&&this.showContextMenu(e,o,n)}}}checkAllText(){var l;const e=(l=this.editor)==null?void 0:l.getContainer();if(!e)return;this.clearHighlights();const t=document.createTreeWalker(e,NodeFilter.SHOW_TEXT);let s;for(;s=t.nextNode();){const n=s,r=n.textContent;if(r){const o=r.split(/\s+/);let d=0;o.forEach(a=>{if(this.isMisspelled(a)){const c=document.createRange();c.setStart(n,d),c.setEnd(n,d+a.length),this.highlightMisspelledWord(n,c)}d+=a.length+1})}}}checkSpelling(e){const t=e.toString();if(this.isMisspelled(t)){const s=e.startContainer;this.highlightMisspelledWord(s,e)}}isMisspelled(e){return this.spellChecker?(this.lastResults=[],this.spellChecker.checkSpelling(e,{includeUnknown:!0,maxEditDistance:2,verbosity:1,includeSelf:!1}),this.lastResults.length>0):!1}getSpellingSuggestions(e){return this.spellChecker?(this.lastResults=[],this.spellChecker.checkSpelling(e,{includeUnknown:!0,maxEditDistance:2,verbosity:2,includeSelf:!1}),this.lastResults.map(t=>t.term)):[]}highlightMisspelledWord(e,t){var s;(s=e.parentElement)==null||s.classList.add("misspelled-word"),this.misspelledWords.set(e,t)}clearHighlights(){this.misspelledWords.forEach((e,t)=>{var s;(s=t.parentElement)==null||s.classList.remove("misspelled-word")}),this.misspelledWords.clear()}showContextMenu(e,t,s){var p,f;const l=document.createElement("div");l.style.position="fixed",l.style.backgroundColor="#fff",l.style.border="1px solid #ccc",l.style.boxShadow="0 2px 5px rgba(0, 0, 0, 0.2)",l.style.zIndex="1000",l.style.maxHeight="200px",l.style.overflowY="auto",l.style.padding="4px 0";const n=200,r=Math.min(t.length*32,200),o=window.innerWidth,d=window.innerHeight;let a=e.clientY,c=e.clientX;a+r>d&&(a=d-r),c+n>o&&(c=o-n),l.style.top=`${a}px`,l.style.left=`${c}px`,t.forEach(g=>{const u=document.createElement("div");u.style.padding="8px 16px",u.style.cursor="pointer",u.textContent=g,u.addEventListener("click",()=>{this.replaceMisspelledWord(s,g),l.remove()}),l.appendChild(u)}),(p=this.editor)==null||p.getInnerContainer().appendChild(l),(f=this.editor)==null||f.getDOMContext().addEventListener("click",()=>l.remove(),{once:!0})}replaceMisspelledWord(e,t){e.deleteContents(),e.insertNode(document.createTextNode(t)),this.checkAllText()}destroy(){var e;this.enableSpellCheck(!1),(e=this.toolbarButton)==null||e.remove(),this.toolbarButton=null,this.editor=null,this.spellChecker=null}}exports.SpellCheckerPlugin=b;