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

83 lines (82 loc) 18.5 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 A=Object.defineProperty;var S=(s,e,l)=>e in s?A(s,e,{enumerable:!0,configurable:!0,writable:!0,value:l}):s[e]=l;var d=(s,e,l)=>S(s,typeof e!="symbol"?e+"":e,l);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const T=require("../../../core/ui/ContextMenu.cjs"),C=require("../commands/AddRowCommand.cjs"),b=require("../commands/AddColumnCommand.cjs"),M=require("../commands/DeleteRowCommand.cjs"),E=require("../commands/DeleteColumnCommand.cjs"),z=require("../commands/DeleteTableCommand.cjs"),D=require("../commands/StyleTableCellCommand.cjs"),I=require("../commands/CopyTableCommand.cjs"),p=require("../commands/MergeCellsCommand.cjs"),w=require("../commands/SplitCellCommand.cjs"),q=require("../commands/SetCellBorderCommand.cjs"),u=require("../commands/InsertCellCommand.cjs"),R=require("../commands/FormatCellCommand.cjs"),L=require("../commands/ShowTablePropertiesCommand.cjs"),H=require("../commands/ExportTableCommand.cjs"),P=require("../commands/ImportTableCommand.cjs"),N=require("../commands/SortTableCommand.cjs"),O=require("../commands/ResizeColumnsCommand.cjs"),V=require("../commands/SelectAllCommand.cjs"),F=require("../commands/CopyCellCommand.cjs"),j=require("../commands/CutCellCommand.cjs"),B=require("../commands/PasteCellCommand.cjs"),Q=require("../commands/DeleteCellContentCommand.cjs"),J=require("../commands/SelectRowCommand.cjs"),$=require("../commands/SelectColumnCommand.cjs"),U=require("../commands/AutoFitCommand.cjs"),W=require("../commands/ClearTableCommand.cjs"),X=require("../commands/DeleteCellCommand.cjs"),v=require("./LazyTableModal.cjs"),Z=require("../../../icons/copy.svg.cjs"),_=require("../../../icons/delete-table.svg.cjs"),G=require("../../../icons/delete-row.svg.cjs"),K=require("../../../icons/delete-column.svg.cjs"),Y=require("../../../core/ui/PopupManager.cjs"),c={arrowUp:"↑",arrowDown:"↓",arrowLeft:"←",arrowRight:"→"},f="🟰",k="✂️",h="🎨",y="📤",g="📥",x="🔄";class ee{constructor(e){d(this,"contextMenu");d(this,"activeCell",null);d(this,"popupManager");d(this,"colorPicker",null);d(this,"editor");this.editor=e,this.contextMenu=new T.ContextMenu(e,[{type:"group",groupTitle:e.t("Insert"),subMenu:[{title:e.t("Add Row"),icon:"➕",subMenu:[{title:e.t("Add Row Above"),icon:c.arrowUp,action:"add-row-above",onClick:()=>this.executeAction("add-row-above"),hotkey:"Ctrl+Shift+↑"},{title:e.t("Add Row Below"),icon:c.arrowDown,action:"add-row-below",onClick:()=>this.executeAction("add-row-below"),hotkey:"Ctrl+Shift+↓"}]},{title:e.t("Add Column"),icon:"➕",subMenu:[{title:e.t("Add Column Left"),icon:c.arrowLeft,action:"add-col-left",onClick:()=>this.executeAction("add-col-left"),hotkey:"Ctrl+Shift+←"},{title:e.t("Add Column Right"),icon:c.arrowRight,action:"add-col-right",onClick:()=>this.executeAction("add-col-right"),hotkey:"Ctrl+Shift+→"}]},{title:e.t("Insert Cell"),icon:"➕",subMenu:[{title:e.t("Insert Cell Left"),icon:c.arrowLeft,action:"insert-cell-left",onClick:()=>this.executeAction("insert-cell-left"),hotkey:"Alt+Shift+←"},{title:e.t("Insert Cell Right"),icon:c.arrowRight,action:"insert-cell-right",onClick:()=>this.executeAction("insert-cell-right"),hotkey:"Alt+Shift+→"},{title:e.t("Insert Cell Above"),icon:c.arrowUp,action:"insert-cell-top",onClick:()=>this.executeAction("insert-cell-top"),hotkey:"Alt+Shift+↑"},{title:e.t("Insert Cell Below"),icon:c.arrowDown,action:"insert-cell-bottom",onClick:()=>this.executeAction("insert-cell-bottom"),hotkey:"Alt+Shift+↓"}]}]},{type:"divider"},{type:"group",groupTitle:e.t("Delete"),subMenu:[{title:e.t("Delete Elements"),icon:"🗑️",subMenu:[{title:e.t("Delete Row"),icon:G.default,action:"delete-row",onClick:()=>this.executeAction("delete-row"),variant:"danger",hotkey:"Delete"},{title:e.t("Delete Column"),icon:K.default,action:"delete-col",onClick:()=>this.executeAction("delete-col"),variant:"danger",hotkey:"Backspace"},{title:e.t("Clear Cell"),icon:"🧹",action:"clear-cell",onClick:()=>this.executeAction("clear-cell"),variant:"warning",hotkey:"Ctrl+Shift+Backspace"},{title:e.t("Delete Cell"),icon:"🗑️",action:"delete-cell",onClick:()=>this.executeAction("delete-cell"),variant:"danger",hotkey:"Delete"},{title:e.t("Delete Table"),icon:_.default,action:"delete-table",onClick:()=>this.executeAction("delete-table"),variant:"danger",hotkey:"Ctrl+Delete"}]}]},{type:"divider"},{type:"group",groupTitle:e.t("Table Operations"),subMenu:[{title:e.t("Clipboard Operations"),icon:"📋",subMenu:[{title:e.t("Copy Table"),icon:Z.default,action:"copy-table",onClick:()=>this.executeAction("copy-table"),hotkey:"Ctrl+C"},{title:e.t("Copy Cell"),icon:"📋",action:"copy-cell",onClick:()=>this.executeAction("copy-cell"),hotkey:"Alt+Shift+C"},{title:e.t("Cut Cell"),icon:"✂️",action:"cut-cell",onClick:()=>this.executeAction("cut-cell"),hotkey:"Ctrl+X"},{title:e.t("Paste Cell"),icon:"📋",action:"paste-cell",onClick:()=>this.executeAction("paste-cell"),hotkey:"Ctrl+V"}]},{title:e.t("Cell Operations"),icon:"🔗",subMenu:[{title:e.t("Merge Cells"),icon:f,subMenu:[{title:e.t("Merge Horizontally"),icon:"↔",action:"merge-cells-horizontal",onClick:()=>this.executeAction("merge-cells-horizontal"),hotkey:"Ctrl+Shift+Z"},{title:e.t("Merge Vertically"),icon:"↕",action:"merge-cells-vertical",onClick:()=>this.executeAction("merge-cells-vertical"),hotkey:"Ctrl+Shift+V"}]},{title:e.t("Split Cell"),icon:k,subMenu:[{title:e.t("Split Horizontally"),icon:"⇹",action:"split-cell-horizontal",onClick:()=>this.executeAction("split-cell-horizontal"),hotkey:"Alt+Shift+H"},{title:e.t("Split Vertically"),icon:"⇳",action:"split-cell-vertical",onClick:()=>this.executeAction("split-cell-vertical"),hotkey:"Alt+Shift+V"}]}]}]},{type:"divider"},{type:"group",groupTitle:e.t("Selection"),subMenu:[{title:e.t("Select Elements"),icon:"☑️",subMenu:[{title:e.t("Select All"),icon:"☑️",action:"select-all",onClick:()=>this.executeAction("select-all"),hotkey:"Ctrl+A"},{title:e.t("Select Row"),icon:"➡️",action:"select-row",onClick:()=>this.executeAction("select-row"),hotkey:"Ctrl+Shift+R"},{title:e.t("Select Column"),icon:"⬇️",action:"select-column",onClick:()=>this.executeAction("select-column"),hotkey:"Alt+Shift+Col"}]}]},{type:"divider"},{type:"group",groupTitle:e.t("Table Management"),subMenu:[{title:e.t("Format"),icon:h,subMenu:[{title:e.t("Format Cell"),icon:h,action:"format-cell",onClick:()=>this.executeAction("format-cell"),hotkey:"Ctrl+F"},{title:e.t("Table Properties"),icon:"⚙️",action:"table-properties",onClick:()=>this.executeAction("table-properties"),hotkey:"Ctrl+Shift+P"}]},{title:e.t("Table Tools"),icon:"🔧",subMenu:[{title:e.t("Sort Table"),icon:"📈",action:"sort-table",onClick:()=>this.executeAction("sort-table"),hotkey:"Ctrl+S"},{title:e.t("Resize Columns"),icon:"📏",action:"resize-columns",onClick:()=>this.executeAction("resize-columns"),hotkey:"Ctrl+R"},{title:e.t("Auto Fit"),icon:"🔧",action:"auto-fit",onClick:()=>this.executeAction("auto-fit"),hotkey:"Ctrl+Shift+A"}]},{title:e.t("Data"),icon:"📊",subMenu:[{title:e.t("Import/Export"),icon:"📊",subMenu:[{title:e.t("Export Table"),icon:y,action:"export-table",onClick:()=>this.executeAction("export-table"),variant:"success",hotkey:"Ctrl+E"},{title:e.t("Import Table"),icon:g,action:"import-table",onClick:()=>this.executeAction("import-table"),variant:"success",hotkey:"Ctrl+I"}]},{title:e.t("Edit Lazy Table"),icon:x,action:"edit-lazy-table",onClick:()=>this.executeAction("edit-lazy-table"),variant:"success",hotkey:"Ctrl+L"},{title:e.t("Fill Table"),icon:"📥",action:"fill-table",onClick:()=>this.executeAction("fill-table"),variant:"success",hotkey:"Ctrl+F"},{title:e.t("Clear Table"),icon:"🧹",action:"clear-table",onClick:()=>this.executeAction("clear-table"),variant:"warning",hotkey:"Ctrl+Shift+Delete"}]}]},{type:"divider"},{type:"custom",customHTML:`<input type="color" class="table-color-picker" title="${e.t("Background Color")}">`}],{maxHeight:350,maxWidth:280,animation:!0,closeOnClickOutside:!0,closeOnEscape:!0}),this.popupManager=new Y.PopupManager(e,{title:e.t("Set Cell Border"),closeOnClickOutside:!0,buttons:[{label:e.t("Confirm"),variant:"primary",onClick:()=>this.handleBorderConfirm()},{label:e.t("Cancel"),variant:"secondary",onClick:()=>this.popupManager.hide()}]}),this.setupColorPicker()}handleBorderConfirm(){const e=this.popupManager.getValue("border-style");e&&this.activeCell&&new q.SetCellBorderCommand(this.activeCell,e).execute(),this.popupManager.hide()}setupColorPicker(){this.colorPicker=this.contextMenu.getElement().querySelector(".table-color-picker"),this.colorPicker&&(this.colorPicker.addEventListener("input",e=>{this.activeCell&&new D.StyleTableCellCommand(this.activeCell,{backgroundColor:e.target.value}).execute()}),this.colorPicker.addEventListener("contextmenu",e=>e.stopPropagation()))}executeAction(e){if(!this.activeCell)return;const l=this.activeCell.closest(".html-editor-table");if(!l||!(l instanceof HTMLElement))return;let t=null;switch(e){case"add-row-above":t=new C.AddRowCommand(l,this.activeCell,!0);break;case"add-row-below":t=new C.AddRowCommand(l,this.activeCell,!1);break;case"add-col-left":t=new b.AddColumnCommand(l,this.activeCell,!0);break;case"add-col-right":t=new b.AddColumnCommand(l,this.activeCell,!1);break;case"insert-cell-left":t=new u.InsertCellCommand(this.editor,this.activeCell,"left");break;case"insert-cell-right":t=new u.InsertCellCommand(this.editor,this.activeCell,"right");break;case"insert-cell-top":t=new u.InsertCellCommand(this.editor,this.activeCell,"top");break;case"insert-cell-bottom":t=new u.InsertCellCommand(this.editor,this.activeCell,"bottom");break;case"delete-row":t=new M.DeleteRowCommand(l,this.activeCell);break;case"delete-col":t=new E.DeleteColumnCommand(l,this.activeCell);break;case"delete-table":t=new z.DeleteTableCommand(l);break;case"copy-table":t=new I.CopyTableCommand(l);break;case"merge-cells-horizontal":t=new p.MergeCellsCommand(l,this.activeCell,"horizontal");break;case"merge-cells-vertical":t=new p.MergeCellsCommand(l,this.activeCell,"vertical");break;case"split-cell-horizontal":t=new w.SplitCellCommand(l,this.activeCell,"horizontal");break;case"split-cell-vertical":t=new w.SplitCellCommand(l,this.activeCell,"vertical");break;case"format-cell":t=new R.FormatCellCommand(this.editor,this.activeCell);break;case"table-properties":t=new L.ShowTablePropertiesCommand(this.editor,l);break;case"export-table":t=new H.ExportTableCommand(this.editor,l);break;case"import-table":t=new P.ImportTableCommand(this.editor);break;case"sort-table":t=new N.SortTableCommand(this.editor,l);break;case"resize-columns":t=new O.ResizeColumnsCommand(this.editor,l);break;case"select-all":t=new V.SelectAllCommand(this.editor,l);break;case"copy-cell":t=new F.CopyCellCommand(this.editor,this.activeCell);break;case"cut-cell":t=new j.CutCellCommand(this.editor,this.activeCell);break;case"paste-cell":t=new B.PasteCellCommand(this.editor,this.activeCell);break;case"delete-cell":t=new X.DeleteCellCommand(this.editor,this.activeCell);break;case"select-row":t=new J.SelectRowCommand(this.editor,this.activeCell);break;case"select-column":t=new $.SelectColumnCommand(this.editor,this.activeCell);break;case"auto-fit":t=new U.AutoFitCommand(this.editor,l);break;case"clear-table":t=new W.ClearTableCommand(this.editor,l);break;case"clear-cell":t=new Q.DeleteCellContentCommand(this.editor,this.activeCell);break;case"edit-lazy-table":this.editLazyTable(l),this.contextMenu.hide();break;case"fill-table":this.fillTable(l),this.contextMenu.hide();break}t&&t.execute()}editLazyTable(e){const l={url:e.getAttribute("data-lazy-url")||"",format:e.getAttribute("data-lazy-format")||"json",hasHeaders:e.getAttribute("data-lazy-headers")!=="false",delimiter:e.getAttribute("data-lazy-delimiter")||",",tableId:e.id||"",isEdit:!0,onSave:a=>{var r;a.url&&e.setAttribute("data-lazy-url",a.url),a.format&&e.setAttribute("data-lazy-format",a.format),a.delimiter&&e.setAttribute("data-lazy-delimiter",a.delimiter),a.hasHeaders!==void 0&&e.setAttribute("data-lazy-headers",String(a.hasHeaders)),a.tableId&&(e.id=a.tableId);const o=e.nextElementSibling;o&&o.tagName==="SCRIPT"&&o.remove();const i=document.createElement("script");i.type="text/javascript",i.textContent=this.generateLazyScript(e.id,{url:e.getAttribute("data-lazy-url")||"",format:e.getAttribute("data-lazy-format")||"json",hasHeaders:e.getAttribute("data-lazy-headers")!=="false",delimiter:e.getAttribute("data-lazy-delimiter")||","}),(r=e.parentNode)==null||r.insertBefore(i,e.nextSibling),setTimeout(()=>{const n=document.createElement("script");n.textContent=i.textContent,document.head.appendChild(n),document.head.removeChild(n)},100)}};new v.LazyTableModal(this.editor,document.createRange(),l).show()}fillTable(e){new v.LazyTableModal(this.editor,document.createRange(),{isFillMode:!0,onSave:t=>{this.loadAndFillTable(e,t)}}).show()}async loadAndFillTable(e,l){try{e.innerHTML='<div class="table-row"><div class="table-cell" style="text-align:center;padding:20px;">Загрузка данных...</div></div>';const t=await fetch(l.url);if(!t.ok)throw new Error(`HTTP ${t.status}`);let a;if(l.format==="json")a=await t.json();else{const o=await t.text();a=this.parseCSV(o,l.delimiter||",")}this.renderTableData(e,a,l.format,l.hasHeaders)}catch(t){e.innerHTML=`<div class="table-row"><div class="table-cell" style="text-align:center;padding:20px;color:#e74c3c;">Ошибка загрузки: ${t instanceof Error?t.message:"Неизвестная ошибка"}</div></div>`}}parseCSV(e,l){return e.trim().split(` `).map(a=>{const o=[];let i="",r=!1;for(let n=0;n<a.length;n++){const m=a[n];m==='"'?r=!r:m===l&&!r?(o.push(i.trim()),i=""):i+=m}return o.push(i.trim()),o})}renderTableData(e,l,t,a){e.innerHTML="",t==="json"?this.renderJSONData(e,l):this.renderCSVData(e,l,a)}renderJSONData(e,l){if(!Array.isArray(l)||!l.length){e.innerHTML='<div class="table-row"><div class="table-cell">Нет данных</div></div>';return}const t=Object.keys(l[0]),a=document.createElement("div");a.className="table-header-row",t.forEach(o=>{const i=document.createElement("div");i.className="table-header-cell",i.textContent=o,a.appendChild(i)}),e.appendChild(a),l.forEach(o=>{const i=document.createElement("div");i.className="table-row",t.forEach(r=>{const n=document.createElement("div");n.className="table-cell",n.textContent=o[r]||"",i.appendChild(n)}),e.appendChild(i)})}renderCSVData(e,l,t){l.forEach((a,o)=>{const i=document.createElement("div");i.className=o===0&&t?"table-header-row":"table-row",a.forEach(r=>{const n=document.createElement("div");n.className=o===0&&t?"table-header-cell":"table-cell",n.textContent=r,i.appendChild(n)}),e.appendChild(i)})}generateLazyScript(e,l){return` (function() { var table = document.getElementById('${e}'); if (!table) return; var url = table.getAttribute('data-lazy-url'); var format = table.getAttribute('data-lazy-format'); var delimiter = table.getAttribute('data-lazy-delimiter') || ','; var hasHeaders = table.getAttribute('data-lazy-headers') !== 'false'; function showLoading() { table.innerHTML = '<div class="table-row"><div class="table-cell" style="text-align:center;padding:20px;">Загрузка данных...</div></div>'; } function showError(msg) { table.innerHTML = '<div class="table-row"><div class="table-cell" style="text-align:center;padding:20px;color:#e74c3c;">Ошибка загрузки: ' + msg + '</div></div>'; } function parseCSV(csv, delimiter) { var rows = csv.trim().split('\\n'); return rows.map(function(row) { var result = [], current = '', inQuotes = false; for (var i = 0; i < row.length; i++) { var char = row[i]; if (char === '"') inQuotes = !inQuotes; else if (char === delimiter && !inQuotes) { result.push(current.trim()); current = ''; } else current += char; } result.push(current.trim()); return result; }); } function renderCSV(data, hasHeaders) { table.innerHTML = ''; data.forEach(function(row, rowIndex) { var rowDiv = document.createElement('div'); rowDiv.className = rowIndex === 0 && hasHeaders ? 'table-header-row' : 'table-row'; row.forEach(function(cellData) { var cell = document.createElement('div'); cell.className = rowIndex === 0 && hasHeaders ? 'table-header-cell' : 'table-cell'; cell.textContent = cellData; rowDiv.appendChild(cell); }); table.appendChild(rowDiv); }); } function renderJSON(data) { table.innerHTML = ''; if (!Array.isArray(data) || !data.length) { table.innerHTML = '<div class="table-row"><div class="table-cell">Нет данных</div></div>'; return; } var headers = Object.keys(data[0]); var headerRow = document.createElement('div'); headerRow.className = 'table-header-row'; headers.forEach(function(header) { var cell = document.createElement('div'); cell.className = 'table-header-cell'; cell.textContent = header; headerRow.appendChild(cell); }); table.appendChild(headerRow); data.forEach(function(row) { var rowDiv = document.createElement('div'); rowDiv.className = 'table-row'; headers.forEach(function(header) { var cell = document.createElement('div'); cell.className = 'table-cell'; cell.textContent = row[header] || ''; rowDiv.appendChild(cell); }); table.appendChild(rowDiv); }); } showLoading(); fetch(url).then(function(resp) { if (!resp.ok) throw new Error('HTTP ' + resp.status); return format === 'json' ? resp.json() : resp.text(); }).then(function(data) { if (format === 'json') renderJSON(data); else renderCSV(parseCSV(data, delimiter), hasHeaders); }).catch(function(e) { showError(e.message); }); })(); `}show(e,l,t){this.activeCell=e,this.contextMenu.show(e,l,t)}hide(){this.contextMenu.hide()}destroy(){this.contextMenu.destroy(),this.popupManager.destroy()}}exports.TableContextMenu=ee;exports.exportIcon=y;exports.formatIcon=h;exports.importIcon=g;exports.lazyIcon=x;exports.mergeIcon=f;exports.navigationIcons=c;exports.splitIcon=k;