leksy-editor 2.6.0 → 3.0.0-beta.1
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/README.md +58 -3
- package/backend.d.ts +2 -0
- package/dist/backend/index.js +2 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/index.mjs +2 -0
- package/dist/backend/index.mjs.map +1 -0
- package/dist/index.css +2 -0
- package/dist/index.css.map +1 -0
- package/dist/index.js +478 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +478 -0
- package/dist/index.mjs.map +1 -0
- package/index.d.ts +2 -0
- package/package.json +30 -4
- package/types/backend.d.ts +89 -0
- package/types/index.d.ts +200 -0
- package/constant.js +0 -967
- package/contribution.md +0 -57
- package/gallery.js +0 -107
- package/index.js +0 -1028
- package/plugin.js +0 -1355
- package/style.css +0 -721
- package/tab.js +0 -709
- package/utilities.js +0 -4359
package/README.md
CHANGED
|
@@ -111,6 +111,7 @@ const app = createApp({
|
|
|
111
111
|
| `enableFindAndReplace` | To enabled find and replace feature|
|
|
112
112
|
| `customTooltip` | Customize tooltip according to your need, set using key-value pair|
|
|
113
113
|
| `customIcon` | Customize icon according to your need, set using key-value pair|
|
|
114
|
+
| `additionalFonts` | Includes custom fonts to extend the available font options|
|
|
114
115
|
|
|
115
116
|
### CSS Customization
|
|
116
117
|
|
|
@@ -193,14 +194,68 @@ Similarly, Pexels and Tenor can be integrated using `pexels` and `tenor` plugins
|
|
|
193
194
|
| `updateCssVariables()` | To update cssVariables. |
|
|
194
195
|
| `updateLabels()` | To update label. |
|
|
195
196
|
| `getLocalCursor()` | Return local cursor position |
|
|
196
|
-
| `
|
|
197
|
-
| `onLocalCursorChange()` | Trigger when local cursor change. |
|
|
198
|
-
| `onLocalSyncChanges()` | Trigger on content change, returns in chunks. |
|
|
197
|
+
| `onLocalSyncChanges()` | Trigger on content and local cursor change, returns in chunks. |
|
|
199
198
|
| `applyRemoteSyncChanges()` | Apply remote chunks. |
|
|
200
199
|
| `setDisabled()` | Pass true/false to disable/enable editor. |
|
|
201
200
|
| `getCurrentTab()` | To fetch current tab data. |
|
|
202
201
|
| `parseTabFromHTML(html)` | Creates a temporary tab-like object from an HTML string. |
|
|
203
202
|
| `compare(tabs1, tabs2)` | Compare tabs and return in Boolean. |
|
|
203
|
+
| `initRuntimeDoms(runtimeDoms)` | Seeds in-memory DOMs for tabs from a `{ tabId: html }` map. |
|
|
204
|
+
| `reloadRuntimeDom(content, runtimeDoms)` | Clears all runtime DOMs and rebuilds them from fresh content, optionally seeding from a `{ tabId: html }` map.
|
|
205
|
+
| `showChangeHighlight(highlights)` | Highlights changed nodes for per-user attribution. Accepts an array of `{ tabId, route, color, userName }`;
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
## LeksyEditorBackend
|
|
209
|
+
|
|
210
|
+
`LeksyEditorBackend` is the server-side counterpart used for collaborative editing. It holds authoritative document state in memory, applies remote diffs with JSDOM, tracks a monotonic change sequence for reconnect/replay, manages version history, and handles autosave and idle cleanup.
|
|
211
|
+
|
|
212
|
+
It is exported as a class. Call `create(options)` **once** in your application to get a shared instance, and import that instance everywhere else (e.g. via a small service wrapper) so all socket handlers operate on the same in-memory document state.
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
### Usage
|
|
216
|
+
|
|
217
|
+
```js
|
|
218
|
+
const LeksyEditorBackend = require('leksy-editor/backend');
|
|
219
|
+
|
|
220
|
+
const LeksyEditor = LeksyEditorBackend.create({
|
|
221
|
+
autoSaveMs: 30 * 60 * 1000,
|
|
222
|
+
cleanMs: 2 * 60 * 1000
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
LeksyEditor.onSave(async ({ documentId, content, metadata, updatedBy }) => {
|
|
226
|
+
// persist content
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
LeksyEditor.onVersionFinalize(async ({ documentId, versionId, startSnapshot, version, metadata }) => {
|
|
230
|
+
// store finalized version
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Create Options
|
|
236
|
+
|
|
237
|
+
| Option | Description |
|
|
238
|
+
|--------|-------------|
|
|
239
|
+
| `autoSaveMs` | Interval in milliseconds between automatic saves of a dirty document. Defaults to 30 minutes. |
|
|
240
|
+
| `cleanMs` | Interval period in milliseconds after the last user leaves before the document is saved, finalized, and cleared from memory. Defaults to 2 minutes. |
|
|
241
|
+
|
|
242
|
+
### Functions
|
|
243
|
+
|
|
244
|
+
| Function | Description |
|
|
245
|
+
|----------|-------------|
|
|
246
|
+
| `user.add({ documentId, userId, connectionId })` | Registers a user connection for a document, starting it in memory if needed. |
|
|
247
|
+
| `user.remove({ documentId, userId, connectionId })` | Removes a connection; returns collaboration events (e.g. cursor removal). |
|
|
248
|
+
| `content.get(documentId)` | Returns `{ content, isLoaded }` for a document. |
|
|
249
|
+
| `content.set(documentId, content, metadata, options)` | Sets or replaces a document's content. Pass `{ isRestore: true }` on restore so reconnecting clients reload. |
|
|
250
|
+
| `content.getRuntimeDoms(documentId)` | Returns the in-memory runtime DOMs for each tab. |
|
|
251
|
+
| `changes.apply(documentId, userId, message)` | Applies an incoming change (diff, tab structure, cursor, tab create) and returns the new sequence. |
|
|
252
|
+
| `changes.getSince(documentId, sequence)` | Returns changes after a sequence for replay, or `null` when the client must reload. |
|
|
253
|
+
| `changes.getCurrentSequence(documentId)` | Returns the document's current sequence number. |
|
|
254
|
+
| `isActive(documentId)` | Returns whether the document is currently held in memory. |
|
|
255
|
+
| `save(documentId)` | Saves content (via `onSave`) and finalizes the in-progress version. |
|
|
256
|
+
| `restore(documentId, snapshot, changes)` | Rebuilds a version by replaying diffs on a snapshot, then replaces live content. |
|
|
257
|
+
| `onSave(fn)` | Registers the persistence callback invoked on save. |
|
|
258
|
+
| `onVersionFinalize(fn)` | Registers the callback invoked when a version is finalized. |
|
|
204
259
|
|
|
205
260
|
## License
|
|
206
261
|
|
package/backend.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var D=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var M=Object.prototype.hasOwnProperty;var V=(y,f)=>{for(var p in f)D(y,p,{get:f[p],enumerable:!0})},z=(y,f,p,g)=>{if(f&&typeof f=="object"||typeof f=="function")for(let i of E(f))!M.call(y,i)&&i!==p&&D(y,i,{get:()=>f[i],enumerable:!(g=C(f,i))||g.enumerable});return y};var U=y=>z(D({},"__esModule",{value:!0}),y);var F={};V(F,{create:()=>L,default:()=>O});module.exports=U(F);var q=require("jsdom"),b=require("diff-dom"),w=class{static create(f={}){let p=f.autoSaveMs??18e5,g=f.cleanMs??120*1e3,i={documents:new Map,onSave:null,onVersionFinalize:null,async addUser({documentId:t,userId:n,connectionId:c}){if(!i.documents.has(t)){let a=T(t);i.documents.set(t,a)}let e=i.documents.get(t);e.lifecycle.saveTimer||(e.lifecycle.saveTimer=setInterval(()=>{i.save(t)},p)),e.lifecycle.cleanupTimer&&(clearTimeout(e.lifecycle.cleanupTimer),e.lifecycle.cleanupTimer=null);let s=String(n);e.users.active.has(s)||e.users.active.set(s,{connections:new Set,lastSequence:e.sequence}),e.users.active.get(s).connections.add(c),e.lifecycle.lastActiveAt=Date.now()},async removeUser({documentId:t,userId:n,connectionId:c}){let e=i.documents.get(t),s=[];if(!e)return;let a=String(n),m=e.users.active.get(a);if(m)return m.connections.delete(c),m.connections.size===0&&(e.users.active.delete(a),s.push({type:"cursor:remove",userId:n})),e.lifecycle.lastActiveAt=Date.now(),e.users.active.size===0&&(e.lifecycle.cleanupTimer=setTimeout(async()=>{e.users.active.size===0&&(await i.save(t),await i.finalizeVersion(t),clearInterval(e.lifecycle.saveTimer),e.lifecycle.saveTimer=null,i.documents.delete(t))},g)),{collabEvents:s}},getContent(t){let n=i.documents.get(t);return{content:(n==null?void 0:n.content)??null,isLoaded:!!(n!=null&&n.content)}},setContent(t,n,c={},e={}){i.documents.has(t)||i.documents.set(t,T(t));let s=i.documents.get(t);s.content=n,s.metadata=c,s.lifecycle.dirty=e.dirty??!1,s.lifecycle.lastActiveAt=Date.now(),s.history=null,s.runtimeDom={},e.isRestore&&(s.sequence++,s.changes.log.push({sequence:s.sequence,type:"restore",timestamp:Date.now()}))},getSince(t,n){let c=i.documents.get(t);if(!c)return null;let e=c.changes.log.filter(s=>s.sequence>n).sort((s,a)=>s.sequence-a.sequence);return e.length===0&&n<c.sequence||e.some(s=>s.type==="restore")?null:e},getCurrentSequence(t){var n;return((n=i.documents.get(t))==null?void 0:n.sequence)??0},isActive(t){return i.documents.has(t)},async applyChange(t,n,c){var m;let e=i.documents.get(t);if(!e||!e.content)return;if(c.type!=="cursor:open"&&c.type!=="tabs:create"&&(e.lastEditedBy=n),c.type==="tabs:create"){e.runtimeDom[c.tabId]||(e.runtimeDom[c.tabId]=new q.JSDOM(c.editorHTML)),(!e.content||e.content.length===0)&&(e.content=[{tabTitle:"Tab 1",tabId:c.tabId,content:"",children:[]}]);return}if(c.type==="diff"&&((m=c.diff)!=null&&m.diffs)){let d=c.diff.diffs.filter(r=>!(r.action==="modifyAttribute"&&["contenteditable","spellcheck","class"].includes(r.name)));if(!d.length)return;let u=e.runtimeDom[c.tabId];if(u){let r=u.window.document.body.firstElementChild;new b.DiffDOM({document:r.ownerDocument}).apply(r,d);let v=A(e.content,c.tabId);v&&(v.content=r.innerHTML)}c.diff.diffs=d}if(e.history||(e.history={versionId:crypto.randomUUID(),startedAt:Date.now(),endedAt:null,fromSequence:e.sequence,toSequence:e.sequence,users:[n],changes:[],startSnapshot:JSON.parse(JSON.stringify(e.content))}),c.type==="tabs:structure"){let d=new Map,u=h=>{h.forEach(o=>{var l;d.set(o.tabId,o),(l=o.children)!=null&&l.length&&u(o.children)})};u(e.content||[]);let r=h=>h.map(o=>{let l=d.get(o.tabId);return{...o,content:(l==null?void 0:l.content)??o.content??"",children:r(o.children||[])}}),S=new Set,v=h=>{h.forEach(o=>{var l;S.add(o.tabId),(l=o.children)!=null&&l.length&&v(o.children)})};v(c.tabs),Object.keys(e.runtimeDom||{}).forEach(h=>{S.has(h)||delete e.runtimeDom[h]}),e.content=r(c.tabs)}let s=new Set(["diff","tabs:structure"]),a=e.history;return a&&s.has(c.type)&&(a.toSequence=e.sequence+1,a.endedAt=Date.now(),a.users.map(d=>d.toString()).includes(String(n))||a.users.push(n),a.changes.push({sequence:e.sequence+1,userId:n,timestamp:Date.now(),type:c.type,message:c})),s.has(c.type)?(e.sequence++,e.changes.log.push({sequence:e.sequence,userId:n,timestamp:Date.now(),type:c.type,message:c}),e.lifecycle.dirty=!0,e.sequence):(e.lifecycle.lastActiveAt=Date.now(),null)},async save(t){var c;let n=i.documents.get(t);if(!(!n||!n.content||!n.lifecycle.dirty)&&!n.lifecycle.isSaving){n.lifecycle.isSaving=!0;try{await((c=i.onSave)==null?void 0:c.call(i,{documentId:t,content:n.content,updatedBy:n.lastEditedBy,metadata:n.metadata})),n.lifecycle.dirty=!1,n.changes.log.length>1e3&&(n.changes.log=n.changes.log.slice(-1e3)),await i.finalizeVersion(t),n.lifecycle.saveTimer&&(clearInterval(n.lifecycle.saveTimer),n.lifecycle.saveTimer=setInterval(()=>{i.save(t)},p))}finally{n.lifecycle.isSaving=!1}}},async finalizeVersion(t){var e;let n=i.documents.get(t);if(!n)return;let c=n.history;if(!c||c.changes.length===0){n.history=null;return}c.endedAt=Date.now(),await((e=i.onVersionFinalize)==null?void 0:e.call(i,{documentId:t,versionId:c.versionId,startSnapshot:c.startSnapshot,version:c,metadata:n.metadata})),n.history=null},async restoreVersion(t,n,c){var m,d;let e=n.map(u=>({...u})),s=(c||[]).sort((u,r)=>u.sequence-r.sequence);for(let u of s){if(u.type!=="diff")continue;let r=e.find(l=>l.tabId===u.message.tabId);if(!r)continue;let v=new q.JSDOM(`<div class="content-editable">${r.content}</div>`).window.document.body.firstElementChild,h=new b.DiffDOM({document:v.ownerDocument}),o=(((m=u.message.diff)==null?void 0:m.diffs)||[]).filter(l=>!(l.action==="modifyAttribute"&&["contenteditable","spellcheck","class"].includes(l.name)));o.length&&(h.apply(v,o),r.content=v.innerHTML)}let a=i.documents.get(t);return await i.save(t),i.setContent(t,e,(d=i.documents.get(t))==null?void 0:d.metadata,{dirty:!0,isRestore:!0}),e}},T=t=>({id:t,content:null,runtimeDom:{},sequence:0,metadata:{},changes:{log:[]},history:null,users:{active:new Map},lifecycle:{lastActiveAt:Date.now(),saveTimer:null,dirty:!1,isSaving:!1,cleanupTimer:null}}),A=(t,n)=>{var c;for(let e of t){if(e.tabId===n)return e;if((c=e.children)!=null&&c.length){let s=A(e.children,n);if(s)return s}}return null};return{user:{add:t=>i.addUser(t),remove:t=>i.removeUser(t)},content:{get:t=>i.getContent(t),set:(t,n,c,e)=>i.setContent(t,n,c,e),getRuntimeDoms:t=>{let n=i.documents.get(t);return n?n.runtimeDom:{}}},changes:{apply:(t,n,c)=>i.applyChange(t,n,c),getSince:(t,n)=>i.getSince(t,n),getCurrentSequence:t=>i.getCurrentSequence(t)},isActive:t=>i.isActive(t),save:t=>i.save(t),onSave:t=>{i.onSave=t},onVersionFinalize:t=>{i.onVersionFinalize=t},restore:(t,n,c)=>i.restoreVersion(t,n,c)}}},L=(...y)=>w.create(...y);var O=w;0&&(module.exports={create});
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/backend/index.js"],"sourcesContent":["import { JSDOM } from 'jsdom';\nimport { DiffDOM } from 'diff-dom';\n\nclass LeksyEditorBackend {\n\n static create(options = {}) {\n\n const AUTO_SAVE_MS = options.autoSaveMs ?? 30 * 60 * 1000 \n const CLEAN_MS = options.cleanMs ?? 2 * 60 * 1000 \n\n /**\n * Internal state\n */\n const core = {\n documents: new Map(),\n onSave: null,\n onVersionFinalize: null,\n\n async addUser({ documentId, userId, connectionId }) {\n if (!core.documents.has(documentId)) {\n const doc = createDocumentState(documentId)\n core.documents.set(documentId, doc)\n }\n const doc = core.documents.get(documentId)\n\n if (!doc.lifecycle.saveTimer) {\n doc.lifecycle.saveTimer = setInterval(() => {\n core.save(documentId)\n }, AUTO_SAVE_MS)\n }\n if (doc.lifecycle.cleanupTimer) {\n clearTimeout(doc.lifecycle.cleanupTimer)\n doc.lifecycle.cleanupTimer = null\n }\n const userKey = String(userId)\n\n if (!doc.users.active.has(userKey)) {\n doc.users.active.set(userKey, {\n connections: new Set(),\n lastSequence: doc.sequence\n })\n }\n\n doc.users.active.get(userKey).connections.add(connectionId)\n doc.lifecycle.lastActiveAt = Date.now()\n },\n\n async removeUser({ documentId, userId, connectionId }) {\n const doc = core.documents.get(documentId)\n const collabEvents = []\n\n if (!doc) return\n const userKey = String(userId)\n\n const user = doc.users.active.get(userKey)\n if (!user) return\n\n\n user.connections.delete(connectionId)\n\n if (user.connections.size === 0) {\n doc.users.active.delete(userKey)\n collabEvents.push({\n type: 'cursor:remove',\n userId\n });\n }\n\n doc.lifecycle.lastActiveAt = Date.now()\n\n if (doc.users.active.size === 0) {\n doc.lifecycle.cleanupTimer = setTimeout(async () => {\n if (doc.users.active.size === 0) {\n await core.save(documentId)\n await core.finalizeVersion(documentId)\n clearInterval(doc.lifecycle.saveTimer)\n doc.lifecycle.saveTimer = null\n core.documents.delete(documentId)\n }\n }, CLEAN_MS)\n }\n return { collabEvents };\n },\n\n getContent(documentId) {\n const doc = core.documents.get(documentId)\n return {\n content: doc?.content ?? null,\n isLoaded: !!doc?.content\n }\n },\n\n setContent(documentId, content, metadata = {}, options = {}) {\n if (!core.documents.has(documentId)) {\n core.documents.set(documentId, createDocumentState(documentId))\n }\n const doc = core.documents.get(documentId)\n doc.content = content\n doc.metadata = metadata\n doc.lifecycle.dirty = options.dirty ?? false\n doc.lifecycle.lastActiveAt = Date.now()\n doc.history = null\n doc.runtimeDom = {}\n\n if (options.isRestore) {\n doc.sequence++\n doc.changes.log.push({\n sequence: doc.sequence,\n type: 'restore',\n timestamp: Date.now()\n })\n }\n },\n\n getSince(documentId, sequence) {\n const doc = core.documents.get(documentId)\n if (!doc) return null\n\n const changes = doc.changes.log.filter(c => c.sequence > sequence).sort((a, b) => a.sequence - b.sequence)\n\n // if no changes found but sequence is behind\n // means log was cleared by a save tell client to do full reload\n if (changes.length === 0 && sequence < doc.sequence) return null\n if (changes.some(c => c.type === 'restore')) return null\n\n return changes\n },\n\n getCurrentSequence(documentId) {\n return core.documents.get(documentId)?.sequence ?? 0\n },\n\n isActive(documentId) {\n return core.documents.has(documentId)\n },\n\n async applyChange(documentId, userId, message) {\n const doc = core.documents.get(documentId);\n if (!doc || !doc.content) {\n return;\n }\n if (message.type !== 'cursor:open' && message.type !== 'tabs:create') {\n doc.lastEditedBy = userId\n }\n if (message.type === 'tabs:create') {\n if (!doc.runtimeDom[message.tabId]) {\n doc.runtimeDom[message.tabId] = new JSDOM(\n message.editorHTML\n );\n }\n if (!doc.content || doc.content.length === 0) {\n doc.content = [{\n tabTitle: 'Tab 1',\n tabId: message.tabId,\n content: '',\n children: []\n }]\n }\n\n return;\n }\n\n if (message.type === 'diff' && message.diff?.diffs) {\n const meaningfulDiffs = message.diff.diffs.filter(diff =>\n !(diff.action === 'modifyAttribute' &&\n ['contenteditable', 'spellcheck', 'class'].includes(diff.name))\n )\n if (!meaningfulDiffs.length) return\n\n const runtimeDom = doc.runtimeDom[message.tabId];\n if (runtimeDom) {\n\n const editor = runtimeDom.window.document.body.firstElementChild;\n const ddInstance = new DiffDOM({ document: editor.ownerDocument });\n ddInstance.apply(editor, meaningfulDiffs);\n const tab = findTab(doc.content, message.tabId);\n if (tab) tab.content = editor.innerHTML;\n }\n message.diff.diffs = meaningfulDiffs\n }\n\n if (!doc.history) {\n doc.history = {\n versionId: crypto.randomUUID(),\n startedAt: Date.now(),\n endedAt: null,\n fromSequence: doc.sequence,\n toSequence: doc.sequence,\n users: [userId],\n changes: [],\n startSnapshot: JSON.parse(JSON.stringify(doc.content))\n };\n }\n\n if (message.type === 'tabs:structure') {\n const existingTabs = new Map();\n\n const flattenTabs = (tabs) => {\n tabs.forEach(tab => {\n existingTabs.set(tab.tabId, tab);\n if (tab.children?.length) {\n flattenTabs(tab.children);\n }\n });\n };\n\n flattenTabs(doc.content || []);\n\n const buildTree = (tabs) => {\n return tabs.map(tab => {\n const existing = existingTabs.get(tab.tabId);\n return {\n ...tab,\n content: existing?.content ?? tab.content ?? '',\n children: buildTree(tab.children || [])\n };\n });\n };\n\n const incomingIds = new Set();\n\n const collectIds = (tabs) => {\n tabs.forEach(tab => {\n incomingIds.add(tab.tabId);\n\n if (tab.children?.length) {\n collectIds(tab.children);\n }\n });\n };\n\n collectIds(message.tabs);\n\n Object.keys(doc.runtimeDom || {}).forEach(tabId => {\n if (!incomingIds.has(tabId)) {\n delete doc.runtimeDom[tabId];\n }\n });\n doc.content = buildTree(message.tabs);\n }\n\n const REPLAYABLE_EVENTS = new Set(['diff', 'tabs:structure']);\n\n const version = doc.history\n\n if (version && REPLAYABLE_EVENTS.has(message.type)) {\n version.toSequence = doc.sequence + 1\n version.endedAt = Date.now()\n\n if (!version.users.map(id => id.toString()).includes(String(userId))) {\n version.users.push(userId)\n }\n version.changes.push({\n sequence: doc.sequence + 1,\n userId,\n timestamp: Date.now(),\n type: message.type,\n message\n })\n }\n\n if (REPLAYABLE_EVENTS.has(message.type)) {\n doc.sequence++;\n doc.changes.log.push({\n sequence: doc.sequence,\n userId,\n timestamp: Date.now(),\n type: message.type,\n message\n });\n\n doc.lifecycle.dirty = true;\n return doc.sequence;\n }\n\n doc.lifecycle.lastActiveAt = Date.now();\n\n return null;\n },\n\n async save(documentId) {\n const doc = core.documents.get(documentId)\n if (!doc || !doc.content || !doc.lifecycle.dirty) return\n if (doc.lifecycle.isSaving) return\n doc.lifecycle.isSaving = true\n\n try {\n\n await core.onSave?.({ documentId, content: doc.content, updatedBy: doc.lastEditedBy, metadata: doc.metadata });\n doc.lifecycle.dirty = false\n if (doc.changes.log.length > 1000) {\n doc.changes.log = doc.changes.log.slice(-1000)\n }\n await core.finalizeVersion(documentId)\n if (doc.lifecycle.saveTimer) {\n clearInterval(doc.lifecycle.saveTimer)\n doc.lifecycle.saveTimer = setInterval(\n () => { core.save(documentId) },\n AUTO_SAVE_MS)\n }\n } finally {\n doc.lifecycle.isSaving = false\n }\n },\n\n async finalizeVersion(documentId) {\n\n const doc = core.documents.get(documentId)\n if (!doc) return\n\n const version = doc.history\n\n if (!version || version.changes.length === 0) {\n doc.history = null\n return\n }\n version.endedAt = Date.now()\n\n await core.onVersionFinalize?.({\n documentId,\n versionId: version.versionId,\n startSnapshot: version.startSnapshot,\n version,\n metadata: doc.metadata\n\n })\n doc.history = null\n },\n\n async restoreVersion(documentId, snapshot, changes) {\n const restoredContent = snapshot.map(tab => ({ ...tab }))\n const sortedChanges = (changes || []).sort((a, b) => a.sequence - b.sequence)\n\n for (const change of sortedChanges) {\n if (change.type !== 'diff') continue\n const tab = restoredContent.find(t => t.tabId === change.message.tabId)\n if (!tab) continue\n\n const dom = new JSDOM(`<div class=\"content-editable\">${tab.content}</div>`)\n const editor = dom.window.document.body.firstElementChild\n const ddInstance = new DiffDOM({ document: editor.ownerDocument })\n\n const meaningfulDiffs = (change.message.diff?.diffs || []).filter(diff =>\n !(diff.action === 'modifyAttribute' &&\n ['contenteditable', 'spellcheck', 'class'].includes(diff.name))\n )\n if (meaningfulDiffs.length) {\n ddInstance.apply(editor, meaningfulDiffs)\n tab.content = editor.innerHTML\n }\n }\n const doc = core.documents.get(documentId)\n await core.save(documentId)\n core.setContent(documentId, restoredContent, core.documents.get(documentId)?.metadata, { dirty: true, isRestore: true })\n\n return restoredContent\n }\n }\n\n /**\n * Internal functions\n */\n\n const createDocumentState = (documentId) => {\n return {\n id: documentId,\n content: null,\n runtimeDom: {},\n sequence: 0,\n metadata: {},\n changes: {\n log: [],\n },\n history: null,\n users: {\n active: new Map()\n },\n\n lifecycle: {\n lastActiveAt: Date.now(),\n saveTimer: null,\n dirty: false,\n isSaving: false,\n cleanupTimer: null\n }\n }\n }\n\n const findTab = (tabs, tabId) => {\n for (const tab of tabs) {\n if (tab.tabId === tabId) return tab\n if (tab.children?.length) {\n const found = findTab(tab.children, tabId)\n if (found) return found\n }\n }\n return null\n }\n\n /**\n * Public API \n */\n\n return {\n user: {\n add: (params) => core.addUser(params),//\n remove: (params) => core.removeUser(params),//\n },\n content: {\n get: (documentId) => core.getContent(documentId),//\n set: (documentId, content, metadata, options) => core.setContent(documentId, content, metadata, options),\n getRuntimeDoms: (documentId) => {\n const doc = core.documents.get(documentId)\n if (!doc) return {}\n return doc.runtimeDom\n }\n },\n changes: {\n apply: (documentId, userId, message) => core.applyChange(documentId, userId, message),\n getSince: (documentId, sequence) => core.getSince(documentId, sequence),\n getCurrentSequence: (documentId) => core.getCurrentSequence(documentId)\n },\n isActive: (documentId) => core.isActive(documentId),\n save: (documentId) => core.save(documentId),\n onSave: (fn) => { core.onSave = fn },\n onVersionFinalize: (fn) => { core.onVersionFinalize = fn },\n restore: (documentId, snapshot, changes) => core.restoreVersion(documentId, snapshot, changes)\n }\n }\n}\n\nconst create = (...args) => LeksyEditorBackend.create(...args)\n\nexport {\n create,\n}\nexport default LeksyEditorBackend\n"],"mappings":"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","names":["backend_exports","__export","create","backend_default","__toCommonJS","import_jsdom","import_diff_dom","LeksyEditorBackend","options","AUTO_SAVE_MS","CLEAN_MS","core","documentId","userId","connectionId","doc","createDocumentState","userKey","collabEvents","user","content","metadata","sequence","changes","c","a","b","_a","message","meaningfulDiffs","diff","runtimeDom","editor","tab","findTab","existingTabs","flattenTabs","tabs","buildTree","existing","incomingIds","collectIds","tabId","REPLAYABLE_EVENTS","version","id","snapshot","_b","restoredContent","sortedChanges","change","t","ddInstance","found","params","fn","args","backend_default","LeksyEditorBackend"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{JSDOM as q}from"jsdom";import{DiffDOM as b}from"diff-dom";var v=class{static create(g={}){let S=g.autoSaveMs??18e5,T=g.cleanMs??120*1e3,i={documents:new Map,onSave:null,onVersionFinalize:null,async addUser({documentId:t,userId:n,connectionId:c}){if(!i.documents.has(t)){let a=w(t);i.documents.set(t,a)}let e=i.documents.get(t);e.lifecycle.saveTimer||(e.lifecycle.saveTimer=setInterval(()=>{i.save(t)},S)),e.lifecycle.cleanupTimer&&(clearTimeout(e.lifecycle.cleanupTimer),e.lifecycle.cleanupTimer=null);let s=String(n);e.users.active.has(s)||e.users.active.set(s,{connections:new Set,lastSequence:e.sequence}),e.users.active.get(s).connections.add(c),e.lifecycle.lastActiveAt=Date.now()},async removeUser({documentId:t,userId:n,connectionId:c}){let e=i.documents.get(t),s=[];if(!e)return;let a=String(n),y=e.users.active.get(a);if(y)return y.connections.delete(c),y.connections.size===0&&(e.users.active.delete(a),s.push({type:"cursor:remove",userId:n})),e.lifecycle.lastActiveAt=Date.now(),e.users.active.size===0&&(e.lifecycle.cleanupTimer=setTimeout(async()=>{e.users.active.size===0&&(await i.save(t),await i.finalizeVersion(t),clearInterval(e.lifecycle.saveTimer),e.lifecycle.saveTimer=null,i.documents.delete(t))},T)),{collabEvents:s}},getContent(t){let n=i.documents.get(t);return{content:(n==null?void 0:n.content)??null,isLoaded:!!(n!=null&&n.content)}},setContent(t,n,c={},e={}){i.documents.has(t)||i.documents.set(t,w(t));let s=i.documents.get(t);s.content=n,s.metadata=c,s.lifecycle.dirty=e.dirty??!1,s.lifecycle.lastActiveAt=Date.now(),s.history=null,s.runtimeDom={},e.isRestore&&(s.sequence++,s.changes.log.push({sequence:s.sequence,type:"restore",timestamp:Date.now()}))},getSince(t,n){let c=i.documents.get(t);if(!c)return null;let e=c.changes.log.filter(s=>s.sequence>n).sort((s,a)=>s.sequence-a.sequence);return e.length===0&&n<c.sequence||e.some(s=>s.type==="restore")?null:e},getCurrentSequence(t){var n;return((n=i.documents.get(t))==null?void 0:n.sequence)??0},isActive(t){return i.documents.has(t)},async applyChange(t,n,c){var y;let e=i.documents.get(t);if(!e||!e.content)return;if(c.type!=="cursor:open"&&c.type!=="tabs:create"&&(e.lastEditedBy=n),c.type==="tabs:create"){e.runtimeDom[c.tabId]||(e.runtimeDom[c.tabId]=new q(c.editorHTML)),(!e.content||e.content.length===0)&&(e.content=[{tabTitle:"Tab 1",tabId:c.tabId,content:"",children:[]}]);return}if(c.type==="diff"&&((y=c.diff)!=null&&y.diffs)){let f=c.diff.diffs.filter(r=>!(r.action==="modifyAttribute"&&["contenteditable","spellcheck","class"].includes(r.name)));if(!f.length)return;let u=e.runtimeDom[c.tabId];if(u){let r=u.window.document.body.firstElementChild;new b({document:r.ownerDocument}).apply(r,f);let h=D(e.content,c.tabId);h&&(h.content=r.innerHTML)}c.diff.diffs=f}if(e.history||(e.history={versionId:crypto.randomUUID(),startedAt:Date.now(),endedAt:null,fromSequence:e.sequence,toSequence:e.sequence,users:[n],changes:[],startSnapshot:JSON.parse(JSON.stringify(e.content))}),c.type==="tabs:structure"){let f=new Map,u=d=>{d.forEach(o=>{var l;f.set(o.tabId,o),(l=o.children)!=null&&l.length&&u(o.children)})};u(e.content||[]);let r=d=>d.map(o=>{let l=f.get(o.tabId);return{...o,content:(l==null?void 0:l.content)??o.content??"",children:r(o.children||[])}}),m=new Set,h=d=>{d.forEach(o=>{var l;m.add(o.tabId),(l=o.children)!=null&&l.length&&h(o.children)})};h(c.tabs),Object.keys(e.runtimeDom||{}).forEach(d=>{m.has(d)||delete e.runtimeDom[d]}),e.content=r(c.tabs)}let s=new Set(["diff","tabs:structure"]),a=e.history;return a&&s.has(c.type)&&(a.toSequence=e.sequence+1,a.endedAt=Date.now(),a.users.map(f=>f.toString()).includes(String(n))||a.users.push(n),a.changes.push({sequence:e.sequence+1,userId:n,timestamp:Date.now(),type:c.type,message:c})),s.has(c.type)?(e.sequence++,e.changes.log.push({sequence:e.sequence,userId:n,timestamp:Date.now(),type:c.type,message:c}),e.lifecycle.dirty=!0,e.sequence):(e.lifecycle.lastActiveAt=Date.now(),null)},async save(t){var c;let n=i.documents.get(t);if(!(!n||!n.content||!n.lifecycle.dirty)&&!n.lifecycle.isSaving){n.lifecycle.isSaving=!0;try{await((c=i.onSave)==null?void 0:c.call(i,{documentId:t,content:n.content,updatedBy:n.lastEditedBy,metadata:n.metadata})),n.lifecycle.dirty=!1,n.changes.log.length>1e3&&(n.changes.log=n.changes.log.slice(-1e3)),await i.finalizeVersion(t),n.lifecycle.saveTimer&&(clearInterval(n.lifecycle.saveTimer),n.lifecycle.saveTimer=setInterval(()=>{i.save(t)},S))}finally{n.lifecycle.isSaving=!1}}},async finalizeVersion(t){var e;let n=i.documents.get(t);if(!n)return;let c=n.history;if(!c||c.changes.length===0){n.history=null;return}c.endedAt=Date.now(),await((e=i.onVersionFinalize)==null?void 0:e.call(i,{documentId:t,versionId:c.versionId,startSnapshot:c.startSnapshot,version:c,metadata:n.metadata})),n.history=null},async restoreVersion(t,n,c){var y,f;let e=n.map(u=>({...u})),s=(c||[]).sort((u,r)=>u.sequence-r.sequence);for(let u of s){if(u.type!=="diff")continue;let r=e.find(l=>l.tabId===u.message.tabId);if(!r)continue;let h=new q(`<div class="content-editable">${r.content}</div>`).window.document.body.firstElementChild,d=new b({document:h.ownerDocument}),o=(((y=u.message.diff)==null?void 0:y.diffs)||[]).filter(l=>!(l.action==="modifyAttribute"&&["contenteditable","spellcheck","class"].includes(l.name)));o.length&&(d.apply(h,o),r.content=h.innerHTML)}let a=i.documents.get(t);return await i.save(t),i.setContent(t,e,(f=i.documents.get(t))==null?void 0:f.metadata,{dirty:!0,isRestore:!0}),e}},w=t=>({id:t,content:null,runtimeDom:{},sequence:0,metadata:{},changes:{log:[]},history:null,users:{active:new Map},lifecycle:{lastActiveAt:Date.now(),saveTimer:null,dirty:!1,isSaving:!1,cleanupTimer:null}}),D=(t,n)=>{var c;for(let e of t){if(e.tabId===n)return e;if((c=e.children)!=null&&c.length){let s=D(e.children,n);if(s)return s}}return null};return{user:{add:t=>i.addUser(t),remove:t=>i.removeUser(t)},content:{get:t=>i.getContent(t),set:(t,n,c,e)=>i.setContent(t,n,c,e),getRuntimeDoms:t=>{let n=i.documents.get(t);return n?n.runtimeDom:{}}},changes:{apply:(t,n,c)=>i.applyChange(t,n,c),getSince:(t,n)=>i.getSince(t,n),getCurrentSequence:t=>i.getCurrentSequence(t)},isActive:t=>i.isActive(t),save:t=>i.save(t),onSave:t=>{i.onSave=t},onVersionFinalize:t=>{i.onVersionFinalize=t},restore:(t,n,c)=>i.restoreVersion(t,n,c)}}},E=(...p)=>v.create(...p);var M=v;export{E as create,M as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/backend/index.js"],"sourcesContent":["import { JSDOM } from 'jsdom';\nimport { DiffDOM } from 'diff-dom';\n\nclass LeksyEditorBackend {\n\n static create(options = {}) {\n\n const AUTO_SAVE_MS = options.autoSaveMs ?? 30 * 60 * 1000 \n const CLEAN_MS = options.cleanMs ?? 2 * 60 * 1000 \n\n /**\n * Internal state\n */\n const core = {\n documents: new Map(),\n onSave: null,\n onVersionFinalize: null,\n\n async addUser({ documentId, userId, connectionId }) {\n if (!core.documents.has(documentId)) {\n const doc = createDocumentState(documentId)\n core.documents.set(documentId, doc)\n }\n const doc = core.documents.get(documentId)\n\n if (!doc.lifecycle.saveTimer) {\n doc.lifecycle.saveTimer = setInterval(() => {\n core.save(documentId)\n }, AUTO_SAVE_MS)\n }\n if (doc.lifecycle.cleanupTimer) {\n clearTimeout(doc.lifecycle.cleanupTimer)\n doc.lifecycle.cleanupTimer = null\n }\n const userKey = String(userId)\n\n if (!doc.users.active.has(userKey)) {\n doc.users.active.set(userKey, {\n connections: new Set(),\n lastSequence: doc.sequence\n })\n }\n\n doc.users.active.get(userKey).connections.add(connectionId)\n doc.lifecycle.lastActiveAt = Date.now()\n },\n\n async removeUser({ documentId, userId, connectionId }) {\n const doc = core.documents.get(documentId)\n const collabEvents = []\n\n if (!doc) return\n const userKey = String(userId)\n\n const user = doc.users.active.get(userKey)\n if (!user) return\n\n\n user.connections.delete(connectionId)\n\n if (user.connections.size === 0) {\n doc.users.active.delete(userKey)\n collabEvents.push({\n type: 'cursor:remove',\n userId\n });\n }\n\n doc.lifecycle.lastActiveAt = Date.now()\n\n if (doc.users.active.size === 0) {\n doc.lifecycle.cleanupTimer = setTimeout(async () => {\n if (doc.users.active.size === 0) {\n await core.save(documentId)\n await core.finalizeVersion(documentId)\n clearInterval(doc.lifecycle.saveTimer)\n doc.lifecycle.saveTimer = null\n core.documents.delete(documentId)\n }\n }, CLEAN_MS)\n }\n return { collabEvents };\n },\n\n getContent(documentId) {\n const doc = core.documents.get(documentId)\n return {\n content: doc?.content ?? null,\n isLoaded: !!doc?.content\n }\n },\n\n setContent(documentId, content, metadata = {}, options = {}) {\n if (!core.documents.has(documentId)) {\n core.documents.set(documentId, createDocumentState(documentId))\n }\n const doc = core.documents.get(documentId)\n doc.content = content\n doc.metadata = metadata\n doc.lifecycle.dirty = options.dirty ?? false\n doc.lifecycle.lastActiveAt = Date.now()\n doc.history = null\n doc.runtimeDom = {}\n\n if (options.isRestore) {\n doc.sequence++\n doc.changes.log.push({\n sequence: doc.sequence,\n type: 'restore',\n timestamp: Date.now()\n })\n }\n },\n\n getSince(documentId, sequence) {\n const doc = core.documents.get(documentId)\n if (!doc) return null\n\n const changes = doc.changes.log.filter(c => c.sequence > sequence).sort((a, b) => a.sequence - b.sequence)\n\n // if no changes found but sequence is behind\n // means log was cleared by a save tell client to do full reload\n if (changes.length === 0 && sequence < doc.sequence) return null\n if (changes.some(c => c.type === 'restore')) return null\n\n return changes\n },\n\n getCurrentSequence(documentId) {\n return core.documents.get(documentId)?.sequence ?? 0\n },\n\n isActive(documentId) {\n return core.documents.has(documentId)\n },\n\n async applyChange(documentId, userId, message) {\n const doc = core.documents.get(documentId);\n if (!doc || !doc.content) {\n return;\n }\n if (message.type !== 'cursor:open' && message.type !== 'tabs:create') {\n doc.lastEditedBy = userId\n }\n if (message.type === 'tabs:create') {\n if (!doc.runtimeDom[message.tabId]) {\n doc.runtimeDom[message.tabId] = new JSDOM(\n message.editorHTML\n );\n }\n if (!doc.content || doc.content.length === 0) {\n doc.content = [{\n tabTitle: 'Tab 1',\n tabId: message.tabId,\n content: '',\n children: []\n }]\n }\n\n return;\n }\n\n if (message.type === 'diff' && message.diff?.diffs) {\n const meaningfulDiffs = message.diff.diffs.filter(diff =>\n !(diff.action === 'modifyAttribute' &&\n ['contenteditable', 'spellcheck', 'class'].includes(diff.name))\n )\n if (!meaningfulDiffs.length) return\n\n const runtimeDom = doc.runtimeDom[message.tabId];\n if (runtimeDom) {\n\n const editor = runtimeDom.window.document.body.firstElementChild;\n const ddInstance = new DiffDOM({ document: editor.ownerDocument });\n ddInstance.apply(editor, meaningfulDiffs);\n const tab = findTab(doc.content, message.tabId);\n if (tab) tab.content = editor.innerHTML;\n }\n message.diff.diffs = meaningfulDiffs\n }\n\n if (!doc.history) {\n doc.history = {\n versionId: crypto.randomUUID(),\n startedAt: Date.now(),\n endedAt: null,\n fromSequence: doc.sequence,\n toSequence: doc.sequence,\n users: [userId],\n changes: [],\n startSnapshot: JSON.parse(JSON.stringify(doc.content))\n };\n }\n\n if (message.type === 'tabs:structure') {\n const existingTabs = new Map();\n\n const flattenTabs = (tabs) => {\n tabs.forEach(tab => {\n existingTabs.set(tab.tabId, tab);\n if (tab.children?.length) {\n flattenTabs(tab.children);\n }\n });\n };\n\n flattenTabs(doc.content || []);\n\n const buildTree = (tabs) => {\n return tabs.map(tab => {\n const existing = existingTabs.get(tab.tabId);\n return {\n ...tab,\n content: existing?.content ?? tab.content ?? '',\n children: buildTree(tab.children || [])\n };\n });\n };\n\n const incomingIds = new Set();\n\n const collectIds = (tabs) => {\n tabs.forEach(tab => {\n incomingIds.add(tab.tabId);\n\n if (tab.children?.length) {\n collectIds(tab.children);\n }\n });\n };\n\n collectIds(message.tabs);\n\n Object.keys(doc.runtimeDom || {}).forEach(tabId => {\n if (!incomingIds.has(tabId)) {\n delete doc.runtimeDom[tabId];\n }\n });\n doc.content = buildTree(message.tabs);\n }\n\n const REPLAYABLE_EVENTS = new Set(['diff', 'tabs:structure']);\n\n const version = doc.history\n\n if (version && REPLAYABLE_EVENTS.has(message.type)) {\n version.toSequence = doc.sequence + 1\n version.endedAt = Date.now()\n\n if (!version.users.map(id => id.toString()).includes(String(userId))) {\n version.users.push(userId)\n }\n version.changes.push({\n sequence: doc.sequence + 1,\n userId,\n timestamp: Date.now(),\n type: message.type,\n message\n })\n }\n\n if (REPLAYABLE_EVENTS.has(message.type)) {\n doc.sequence++;\n doc.changes.log.push({\n sequence: doc.sequence,\n userId,\n timestamp: Date.now(),\n type: message.type,\n message\n });\n\n doc.lifecycle.dirty = true;\n return doc.sequence;\n }\n\n doc.lifecycle.lastActiveAt = Date.now();\n\n return null;\n },\n\n async save(documentId) {\n const doc = core.documents.get(documentId)\n if (!doc || !doc.content || !doc.lifecycle.dirty) return\n if (doc.lifecycle.isSaving) return\n doc.lifecycle.isSaving = true\n\n try {\n\n await core.onSave?.({ documentId, content: doc.content, updatedBy: doc.lastEditedBy, metadata: doc.metadata });\n doc.lifecycle.dirty = false\n if (doc.changes.log.length > 1000) {\n doc.changes.log = doc.changes.log.slice(-1000)\n }\n await core.finalizeVersion(documentId)\n if (doc.lifecycle.saveTimer) {\n clearInterval(doc.lifecycle.saveTimer)\n doc.lifecycle.saveTimer = setInterval(\n () => { core.save(documentId) },\n AUTO_SAVE_MS)\n }\n } finally {\n doc.lifecycle.isSaving = false\n }\n },\n\n async finalizeVersion(documentId) {\n\n const doc = core.documents.get(documentId)\n if (!doc) return\n\n const version = doc.history\n\n if (!version || version.changes.length === 0) {\n doc.history = null\n return\n }\n version.endedAt = Date.now()\n\n await core.onVersionFinalize?.({\n documentId,\n versionId: version.versionId,\n startSnapshot: version.startSnapshot,\n version,\n metadata: doc.metadata\n\n })\n doc.history = null\n },\n\n async restoreVersion(documentId, snapshot, changes) {\n const restoredContent = snapshot.map(tab => ({ ...tab }))\n const sortedChanges = (changes || []).sort((a, b) => a.sequence - b.sequence)\n\n for (const change of sortedChanges) {\n if (change.type !== 'diff') continue\n const tab = restoredContent.find(t => t.tabId === change.message.tabId)\n if (!tab) continue\n\n const dom = new JSDOM(`<div class=\"content-editable\">${tab.content}</div>`)\n const editor = dom.window.document.body.firstElementChild\n const ddInstance = new DiffDOM({ document: editor.ownerDocument })\n\n const meaningfulDiffs = (change.message.diff?.diffs || []).filter(diff =>\n !(diff.action === 'modifyAttribute' &&\n ['contenteditable', 'spellcheck', 'class'].includes(diff.name))\n )\n if (meaningfulDiffs.length) {\n ddInstance.apply(editor, meaningfulDiffs)\n tab.content = editor.innerHTML\n }\n }\n const doc = core.documents.get(documentId)\n await core.save(documentId)\n core.setContent(documentId, restoredContent, core.documents.get(documentId)?.metadata, { dirty: true, isRestore: true })\n\n return restoredContent\n }\n }\n\n /**\n * Internal functions\n */\n\n const createDocumentState = (documentId) => {\n return {\n id: documentId,\n content: null,\n runtimeDom: {},\n sequence: 0,\n metadata: {},\n changes: {\n log: [],\n },\n history: null,\n users: {\n active: new Map()\n },\n\n lifecycle: {\n lastActiveAt: Date.now(),\n saveTimer: null,\n dirty: false,\n isSaving: false,\n cleanupTimer: null\n }\n }\n }\n\n const findTab = (tabs, tabId) => {\n for (const tab of tabs) {\n if (tab.tabId === tabId) return tab\n if (tab.children?.length) {\n const found = findTab(tab.children, tabId)\n if (found) return found\n }\n }\n return null\n }\n\n /**\n * Public API \n */\n\n return {\n user: {\n add: (params) => core.addUser(params),//\n remove: (params) => core.removeUser(params),//\n },\n content: {\n get: (documentId) => core.getContent(documentId),//\n set: (documentId, content, metadata, options) => core.setContent(documentId, content, metadata, options),\n getRuntimeDoms: (documentId) => {\n const doc = core.documents.get(documentId)\n if (!doc) return {}\n return doc.runtimeDom\n }\n },\n changes: {\n apply: (documentId, userId, message) => core.applyChange(documentId, userId, message),\n getSince: (documentId, sequence) => core.getSince(documentId, sequence),\n getCurrentSequence: (documentId) => core.getCurrentSequence(documentId)\n },\n isActive: (documentId) => core.isActive(documentId),\n save: (documentId) => core.save(documentId),\n onSave: (fn) => { core.onSave = fn },\n onVersionFinalize: (fn) => { core.onVersionFinalize = fn },\n restore: (documentId, snapshot, changes) => core.restoreVersion(documentId, snapshot, changes)\n }\n }\n}\n\nconst create = (...args) => LeksyEditorBackend.create(...args)\n\nexport {\n create,\n}\nexport default LeksyEditorBackend\n"],"mappings":"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","names":["JSDOM","DiffDOM","LeksyEditorBackend","options","AUTO_SAVE_MS","CLEAN_MS","core","documentId","userId","connectionId","doc","createDocumentState","userKey","collabEvents","user","content","metadata","sequence","changes","c","a","b","_a","message","meaningfulDiffs","diff","runtimeDom","editor","tab","findTab","existingTabs","flattenTabs","tabs","buildTree","existing","incomingIds","collectIds","tabId","REPLAYABLE_EVENTS","version","id","snapshot","_b","restoredContent","sortedChanges","change","t","ddInstance","found","params","fn","create","args","backend_default","LeksyEditorBackend"]}
|
package/dist/index.css
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
.leksy-editor-container *,*:before,*:after{box-sizing:border-box}.leksy-editor-container body,.leksy-editor-container p,.leksy-editor-container ul,.leksy-editor-container ol,.leksy-editor-container li{margin:0;padding:0;color:#000;font-weight:400}.leksy-editor-container button{appearance:auto;text-rendering:auto;color:unset;letter-spacing:normal;word-spacing:normal;line-height:normal;text-transform:none;text-indent:0px;text-shadow:none;display:inline-block;text-align:center;align-items:center;cursor:pointer;box-sizing:border-box;background-color:unset;padding-block:unset;border-width:0px;border-style:outset;border-color:unset;border-image:initial}.leksy-editor-container{width:100%;min-height:400px;border:1px solid black;border-radius:6px;display:flex;flex-direction:column;position:relative}.leksy-editor-container.fullscreen{position:fixed;top:0;left:0;height:100vh;background-color:#fff;z-index:1000;border-radius:0}.leksy-editor-toolbar{padding:6px;border-bottom:1px solid black;background-color:#f8f8ff;flex:0 1 auto;display:flex;flex-wrap:wrap;border-radius:6px 6px 0 0;align-items:center}.leksy-editor-toolbar-items{outline:1px solid gray;display:flex;border-radius:4px;margin:2px}.leksy-editor-toolbar-items span{font-size:14px;white-space:nowrap}.leksy-editor-toolbar-item{margin:1px;padding:6px 0;height:34px;width:34px;background:transparent;border-radius:4px;position:relative;user-select:none;vertical-align:top;font-size:1rem;cursor:pointer;outline:0px;text-align:center;transition:.3s}.leksy-editor-toolbar-item.active{color:#4592ff;fill:#4592ff}.leksy-editor-toolbar-item.disabled{cursor:not-allowed;color:#bdbdbd;fill:#bdbdbd}.leksy-editor-toolbar-item svg{width:14px;height:14px}.leksy-editor-toolbar-item.select{padding:0 8px;width:unset}.leksy-editor-toolbar-item.button-select{border-radius:4px 0 0 4px;margin-right:0}.leksy-editor-toolbar-item.select.button-select{padding:0;border-radius:0 4px 4px 0;margin-left:0;margin-right:1px}.leksy-editor-toolbar-item.select.button-select svg{width:18px;height:18px}.leksy-editor-toolbar-item.reset-color,.leksy-editor-toolbar-item.color{width:unset;padding:4px 8px}.leksy-editor-toolbar-item.color input{border:none;width:25px;height:25px;background:none}.leksy-editor-toolbar-item.color div{display:inline}.leksy-editor-toolbar-item:hover{background-color:#d3d3d3;border:pink}.leksy-editor-toolbar-item:hover:after{opacity:1;visibility:visible}.leksy-editor-toolbar-item:after{content:attr(data-title);position:fixed;top:var(--leksy-editor-top, 0);left:var(--leksy-editor-left, 0);opacity:0;visibility:hidden;transition:opacity .3s,visibility .3s;background-color:gray;box-shadow:0 0 24px #0003;color:#000;padding:5px 10px;border-radius:5px;transform:translate(-50%);white-space:nowrap;z-index:1;pointer-events:none;font-size:.875rem}.leksy-editor-toolbar-table{display:grid;grid-template-columns:repeat(10,20px);grid-template-rows:repeat(10,20px)}.leksy-editor-toolbar-table .cell{width:16px;height:16px;border:1px solid gray;background-color:#d3d3d3}.leksy-editor-toolbar-table .cell.selected{background-color:#0c8}.leksy-editor-placeholder{user-select:none;opacity:.5;padding:4px;position:absolute}.leksy-editor-resize-items{margin-top:4px;width:235px}.leksy-editor-resize-item{margin:1px;padding:6px;height:34px;background:transparent;border-radius:4px;position:relative;user-select:none;vertical-align:top;font-size:1rem;cursor:pointer;outline:0px;text-align:center}.leksy-editor-resize-item svg{width:15px}.leksy-editor-resize-item:hover{background-color:#d3d3d3;border:pink}.leksy-editor-resize-item:hover:after{opacity:1;visibility:visible}.leksy-editor-resize-item:not([data-title]):after,.leksy-editor-resize-item[data-title=""]:after{display:none}.leksy-editor-resize-item:after{content:attr(data-title);position:absolute;opacity:0;visibility:hidden;transition:opacity .3s,visibility .3s;background-color:gray;box-shadow:0 0 24px #0003;color:#000;padding:5px 10px;border-radius:5px;bottom:-90%;left:60%;transform:translate(-50%);white-space:nowrap;z-index:1;pointer-events:none;font-size:.875rem}.leksy-editor-dropdown-content{display:none;position:absolute;min-width:160px;box-shadow:0 4px 12px #00000026;border-radius:6px;overflow:hidden;padding:4px;z-index:2000;background-color:#fff}.leksy-editor-dropdown-content>button{display:block;width:100%;margin:0;text-align:left;padding:8px 16px;cursor:pointer;white-space:nowrap;transition:.3s;border-radius:6px}.leksy-editor-dropdown-content>button svg{width:10px;margin-right:2px}.leksy-editor-dropdown-content>button:hover{background-color:#28a745;color:#fff}.leksy-editor-dropdown-content.gallery{width:266px;height:350px;padding:0;overflow-y:auto}.leksy-editor-dropdown-content.gallery img{width:100%}.leksy-editor-dropdown-content.gallery input{width:100%;line-height:1.5rem;padding:2px 8px;border:1px solid #ccc;border-radius:6px;transition:all .3s ease-in-out;box-shadow:0 2px 4px #0000001a;font-size:14px;position:sticky;top:0}.leksy-editor-dropdown-content.gallery input:focus{border-color:#4592ff;box-shadow:0 4px 8px #4592ff4d;outline:none}.leksy-editor-dropdown-content.category{width:300px;height:350px;padding:6px;overflow-y:auto;user-select:none}.leksy-editor-dropdown-content.category div{font-weight:700;margin-top:8px;margin-bottom:4px}.leksy-editor-dropdown-content.category span{padding:4px;cursor:pointer}.leksy-editor-dropdown-content.mention{width:250px;height:350px;padding:6px;overflow-y:auto;user-select:none}.leksy-editor-dropdown-content.mention input{width:100%;line-height:1.5rem;margin:4px 0}.leksy-editor-dropdown-content.mention button{display:block;width:100%;margin:0;text-align:left;padding:8px 16px;cursor:pointer;white-space:nowrap}.leksy-editor-dropdown-content.mention button:hover{background-color:green}.leksy-editor-popover-content{display:none;position:absolute;min-width:160px;box-shadow:0 0 10px gray;border-radius:6px;padding:4px;z-index:2000;background-color:#fff}.leksy-editor-popover-tabs{display:flex;background:#f1f1f1;border-bottom:1px solid #ccc}button.leksy-editor-popover-tab{padding:8px 12px;border:none;background:transparent;cursor:pointer}button.leksy-editor-popover-tab.active{border-bottom:2px solid black;font-weight:700}.leksy-editor-popover-tabs .leksy-editor-popover-tab:not(:last-child){border-right:1px solid #ccc}.leksy-editor-codeview{flex:1 1 auto;padding:4px;background-color:#1f1f1f;color:#74bed8;border:0;outline:0;display:none;resize:none;height:400px}.leksy-editor-stepper{height:24px;border-top:1px solid black;border-radius:0 0 4px 4px;background-color:#f8f8ff;padding:2px 5px;text-transform:uppercase;display:flex;justify-content:space-between;font-size:14px;user-select:none}.leksy-editor-stepper .breadcrumb{list-style:none;display:flex;overflow:hidden;justify-content:end}.leksy-editor-stepper .breadcrumb li{margin-left:5px}.leksy-editor-stepper .breadcrumb li:after{content:">";margin-left:5px}.leksy-editor-stepper .breadcrumb li:last-child:after{content:""}.leksy-editor-modal{position:fixed;z-index:100;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:#00000080}.leksy-editor-modal.leksy-editor-draggable-modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:inherit;width:fit-content;height:inherit}.leksy-editor-modal-content{margin:10% auto;border:1px solid #898f9f;max-width:500px;border-radius:12px}.leksy-editor-modal.leksy-editor-draggable-modal .leksy-editor-modal-content{margin:unset;width:fit-content}.leksy-editor-modal-header{padding:1.25rem;display:flex;align-items:center;justify-content:space-between;background-color:#fff;border-bottom:1px solid #d4d5d8;border-radius:12px 12px 0 0;overflow:hidden}.leksy-editor-modal-body{background-color:#fff;padding:1.5rem;width:100%}.leksy-editor-modal-body .warning{color:red}.leksy-editor-modal-footer{background-color:#f2f2f3;padding:1.25rem;display:flex;justify-content:flex-end;gap:12px;border-radius:0 0 12px 12px;width:100%}.leksy-editor-modal input{width:100%;font-size:1rem;padding:10px 12px;border:1px solid #ccc;border-radius:6px;outline:none;transition:all .3s ease-in-out;color:#333}.leksy-editor-modal input:focus{border-color:#4592ff;background-color:#fff}.leksy-editor-modal input::placeholder{color:#bdbdbd}.leksy-editor-modal input:hover{border-color:#555}.leksy-editor-modal button.submit{height:2rem;padding:.75rem 1rem;background-color:#00b377;display:flex;align-items:center;justify-content:center;flex-direction:row;text-align:center;text-decoration:none;cursor:pointer;border:1px solid hsl(160,100%,40%);border-radius:6px;color:#fff;white-space:nowrap;gap:.5rem;transition:.5s;font-size:1rem}.leksy-editor-preview-modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:#000000b9;display:block;align-items:center;justify-content:center;z-index:1000}.leksy-editor-preview-modal-content{height:100%;padding:20px;border-radius:8px;box-shadow:0 4px 6px #0000001a;position:relative;text-align:center}.leksy-editor-preview-modal-close{position:absolute;top:10px;right:20px;cursor:pointer;color:#fff;font-size:20px}.leksy-editor-preview-modal-close svg{width:28px}.leksy-editor-preview-modal-body{display:flex;height:100%;width:100%;align-items:center;justify-content:center}.leksy-editor-preview-modal-body img{object-fit:contain;max-width:90%;max-height:90%}.leksy-editor-spinner{animation:leksy-editor-rotate 1s linear infinite;margin-right:8px;vertical-align:middle}.leksy-editor-spinner .leksy-editor-path{stroke:#fff;stroke-linecap:round;animation:leksy-editor-dash 1.5s ease-in-out infinite}.leksy-editor-upload-img-box{height:180px;border:2px dashed #d1d5db;border-radius:12px;background:#f9fafb;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:border-color .2s ease}.leksy-editor-upload-img-box:hover{border-color:gray}.leksy-editor-upload-img-preview-box{height:180px;border:2px solid grey;margin-bottom:8px;border-radius:8px}.leksy-editor-upload-img-preview{width:100%;height:100%;border-radius:8px;object-fit:cover;object-position:top}.leksy-editor-find-and-replace-modal-tab-btn{background:transparent;border:none;cursor:pointer;font-size:16px;padding:0;color:var(--primary)}.leksy-editor-find-and-replace-modal-tab-btn.active{font-weight:700;border-bottom:2px solid black}.leksy-editor-find-and-replace-modal-label{padding-left:4px;margin-bottom:10px}.leksy-editor-find-and-replace-modal-count{position:absolute;right:8px;top:50%;transform:translateY(-50%);font-size:12px;color:#585555;pointer-events:none;user-select:none}@keyframes leksy-editor-rotate{to{transform:rotate(360deg)}}@keyframes leksy-editor-dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}to{stroke-dasharray:90,150;stroke-dashoffset:-124}}
|
|
2
|
+
/*# sourceMappingURL=index.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/style.css"],"sourcesContent":[".leksy-editor-container *,\n*:before,\n*:after {\n box-sizing: border-box;\n}\n\n.leksy-editor-container body,\n.leksy-editor-container p,\n.leksy-editor-container ul,\n.leksy-editor-container ol,\n.leksy-editor-container li {\n margin: 0;\n padding: 0;\n color: black;\n font-weight: normal;\n}\n\n.leksy-editor-container button {\n appearance: auto;\n text-rendering: auto;\n color: unset;\n letter-spacing: normal;\n word-spacing: normal;\n line-height: normal;\n text-transform: none;\n text-indent: 0px;\n text-shadow: none;\n display: inline-block;\n text-align: center;\n align-items: center;\n cursor: pointer;\n box-sizing: border-box;\n background-color: unset;\n padding-block: unset;\n border-width: 0px;\n border-style: outset;\n border-color: unset;\n border-image: initial;\n}\n\n.leksy-editor-container {\n width: 100%;\n min-height: 400px;\n border: 1px solid black;\n border-radius: 6px;\n display: flex;\n flex-direction: column;\n position: relative;\n}\n\n.leksy-editor-container.fullscreen {\n position: fixed;\n top: 0;\n left: 0;\n height: 100vh;\n background-color: white;\n z-index: 1000;\n border-radius: 0px;\n}\n\n.leksy-editor-toolbar {\n padding: 6px;\n border-bottom: 1px solid black;\n background-color: ghostwhite;\n flex: 0 1 auto;\n display: flex;\n flex-wrap: wrap;\n border-radius: 6px 6px 0px 0px;\n align-items: center;\n}\n\n.leksy-editor-toolbar-items {\n outline: 1px solid gray;\n display: flex;\n border-radius: 4px;\n margin: 2px;\n}\n\n.leksy-editor-toolbar-items span {\n font-size: 14px;\n white-space: nowrap;\n}\n\n.leksy-editor-toolbar-item {\n margin: 1px;\n padding: 6px 0;\n height: 34px;\n width: 34px;\n background: transparent;\n border-radius: 4px;\n position: relative;\n user-select: none;\n vertical-align: top;\n font-size: 1rem;\n cursor: pointer;\n outline: 0px;\n text-align: center;\n transition: .3s;\n}\n\n.leksy-editor-toolbar-item.active {\n color: #4592ff;\n fill: #4592ff;\n}\n\n.leksy-editor-toolbar-item.disabled {\n cursor: not-allowed;\n color: #bdbdbd;\n fill: #bdbdbd;\n}\n\n.leksy-editor-toolbar-item svg {\n width: 14px;\n height: 14px;\n}\n\n.leksy-editor-toolbar-item.select {\n padding: 0 8px;\n width: unset;\n}\n\n.leksy-editor-toolbar-item.button-select {\n border-radius: 4px 0 0 4px;\n margin-right: 0;\n}\n\n.leksy-editor-toolbar-item.select.button-select {\n padding: 0;\n border-radius: 0 4px 4px 0;\n margin-left: 0;\n margin-right: 1px;\n}\n\n.leksy-editor-toolbar-item.select.button-select svg {\n width: 18px;\n height: 18px;\n}\n\n.leksy-editor-toolbar-item.reset-color {\n width: unset;\n padding: 4px 8px;\n}\n\n.leksy-editor-toolbar-item.color {\n width: unset;\n padding: 4px 8px;\n}\n\n.leksy-editor-toolbar-item.color input {\n border: none;\n width: 25px;\n height: 25px;\n background: none;\n}\n\n.leksy-editor-toolbar-item.color div {\n display: inline;\n}\n\n.leksy-editor-toolbar-item:hover {\n background-color: lightgrey;\n border: pink;\n}\n\n.leksy-editor-toolbar-item:hover::after {\n opacity: 1;\n visibility: visible;\n}\n\n.leksy-editor-toolbar-item::after {\n content: attr(data-title);\n position: fixed;\n top: var(--leksy-editor-top, 0);\n left: var(--leksy-editor-left, 0);\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s, visibility 0.3s;\n background-color: gray;\n box-shadow: 0px 0px 24px rgba(0, 0, 0, 0.2);\n color: black;\n padding: 5px 10px;\n border-radius: 5px;\n transform: translateX(-50%);\n white-space: nowrap;\n z-index: 1;\n pointer-events: none;\n font-size: 0.875rem;\n}\n\n.leksy-editor-toolbar-table {\n display: grid;\n grid-template-columns: repeat(10, 20px);\n grid-template-rows: repeat(10, 20px);\n}\n\n.leksy-editor-toolbar-table .cell {\n width: 16px;\n height: 16px;\n border: 1px solid gray;\n background-color: lightgray;\n}\n\n.leksy-editor-toolbar-table .cell.selected {\n background-color: #0c8;\n}\n\n.leksy-editor-placeholder {\n user-select: none;\n opacity: 0.5;\n padding: 4px;\n position: absolute;\n}\n\n.leksy-editor-resize-items {\n margin-top: 4px;\n width: 235px;\n}\n\n.leksy-editor-resize-item {\n margin: 1px;\n padding: 6px;\n height: 34px;\n background: transparent;\n border-radius: 4px;\n position: relative;\n user-select: none;\n vertical-align: top;\n font-size: 1rem;\n cursor: pointer;\n outline: 0px;\n text-align: center;\n}\n\n.leksy-editor-resize-item svg {\n width: 15px;\n}\n\n.leksy-editor-resize-item:hover {\n background-color: lightgrey;\n border: pink;\n}\n\n.leksy-editor-resize-item:hover::after {\n opacity: 1;\n visibility: visible;\n}\n\n.leksy-editor-resize-item:not([data-title])::after,\n.leksy-editor-resize-item[data-title=\"\"]::after {\n display: none;\n}\n\n.leksy-editor-resize-item::after {\n content: attr(data-title);\n position: absolute;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s, visibility 0.3s;\n background-color: gray;\n box-shadow: 0px 0px 24px rgba(0, 0, 0, 0.2);\n color: black;\n padding: 5px 10px;\n border-radius: 5px;\n bottom: -90%;\n left: 60%;\n transform: translateX(-50%);\n white-space: nowrap;\n z-index: 1;\n pointer-events: none;\n font-size: 0.875rem;\n}\n\n.leksy-editor-dropdown-content {\n display: none;\n position: absolute;\n min-width: 160px;\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.15);\n border-radius: 6px;\n overflow: hidden;\n padding: 4px;\n z-index: 2000;\n background-color: white;\n}\n\n.leksy-editor-dropdown-content>button {\n display: block;\n width: 100%;\n margin: 0;\n text-align: left;\n padding: 8px 16px;\n cursor: pointer;\n white-space: nowrap;\n transition: .3s;\n border-radius: 6px;\n}\n\n.leksy-editor-dropdown-content>button svg {\n width: 10px;\n margin-right: 2px;\n}\n\n.leksy-editor-dropdown-content>button:hover {\n background-color: #28a745;\n color: #fff;\n}\n\n.leksy-editor-dropdown-content.gallery {\n width: 266px;\n height: 350px;\n padding: 0;\n overflow-y: auto;\n}\n\n.leksy-editor-dropdown-content.gallery img {\n width: 100%;\n}\n\n.leksy-editor-dropdown-content.gallery input {\n width: 100%;\n line-height: 1.5rem;\n padding: 2px 8px;\n border: 1px solid #ccc;\n border-radius: 6px;\n transition: all 0.3s ease-in-out;\n box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);\n font-size: 14px;\n position: sticky;\n top: 0;\n}\n\n.leksy-editor-dropdown-content.gallery input:focus {\n border-color: #4592ff;\n box-shadow: 0px 4px 8px rgba(69, 146, 255, 0.3);\n outline: none;\n}\n\n\n.leksy-editor-dropdown-content.category {\n width: 300px;\n height: 350px;\n padding: 6px;\n overflow-y: auto;\n user-select: none;\n}\n\n.leksy-editor-dropdown-content.category div {\n font-weight: bold;\n margin-top: 8px;\n margin-bottom: 4px;\n}\n\n.leksy-editor-dropdown-content.category span {\n padding: 4px;\n cursor: pointer;\n}\n\n.leksy-editor-dropdown-content.mention {\n width: 250px;\n height: 350px;\n padding: 6px;\n overflow-y: auto;\n user-select: none;\n}\n\n.leksy-editor-dropdown-content.mention input {\n width: 100%;\n line-height: 1.5rem;\n margin: 4px 0;\n}\n\n.leksy-editor-dropdown-content.mention button {\n display: block;\n width: 100%;\n margin: 0;\n text-align: left;\n padding: 8px 16px;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.leksy-editor-dropdown-content.mention button:hover {\n background-color: green;\n}\n\n.leksy-editor-popover-content {\n display: none;\n position: absolute;\n min-width: 160px;\n box-shadow: 0 0 10px 0 grey;\n border-radius: 6px;\n padding: 4px;\n z-index: 2000;\n background-color: white;\n}\n\n.leksy-editor-popover-tabs {\n display: flex;\n background: #f1f1f1;\n border-bottom: 1px solid #ccc;\n}\n\nbutton.leksy-editor-popover-tab {\n padding: 8px 12px;\n border: none;\n background: transparent;\n cursor: pointer;\n}\n\nbutton.leksy-editor-popover-tab.active {\n border-bottom: 2px solid black;\n font-weight: bold;\n}\n\n.leksy-editor-popover-tabs .leksy-editor-popover-tab:not(:last-child) {\n border-right: 1px solid #ccc;\n}\n\n.leksy-editor-codeview {\n flex: 1 1 auto;\n padding: 4px;\n background-color: #1f1f1f;\n color: #74bed8;\n border: 0;\n outline: 0;\n display: none;\n resize: none;\n height: 400px;\n}\n\n.leksy-editor-stepper {\n height: 24px;\n border-top: 1px solid black;\n border-radius: 0 0 4px 4px;\n background-color: ghostwhite;\n padding: 2px 5px;\n text-transform: uppercase;\n display: flex;\n justify-content: space-between;\n font-size: 14px;\n user-select: none;\n /* Remove the last breadcrumb's slash */\n}\n\n.leksy-editor-stepper .breadcrumb {\n list-style: none;\n display: flex;\n overflow: hidden;\n justify-content: end;\n}\n\n.leksy-editor-stepper .breadcrumb li {\n margin-left: 5px;\n}\n\n.leksy-editor-stepper .breadcrumb li::after {\n content: \">\";\n margin-left: 5px;\n}\n\n.leksy-editor-stepper .breadcrumb li:last-child::after {\n content: \"\";\n}\n\n.leksy-editor-modal {\n position: fixed;\n z-index: 100;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n overflow: auto;\n background-color: rgba(0, 0, 0, 0.5);\n}\n\n.leksy-editor-modal.leksy-editor-draggable-modal {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n background: inherit;\n width: fit-content;\n height: inherit;\n}\n\n.leksy-editor-modal-content {\n margin: 10% auto;\n border: 1px solid #898f9f;\n max-width: 500px;\n border-radius: 12px;\n}\n\n.leksy-editor-modal.leksy-editor-draggable-modal .leksy-editor-modal-content {\n margin: unset;\n width: fit-content;\n}\n\n.leksy-editor-modal-header {\n padding: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: space-between;\n background-color: #fff;\n border-bottom: 1px solid #d4d5d8;\n border-radius: 12px 12px 0 0;\n overflow: hidden;\n}\n\n.leksy-editor-modal-body {\n background-color: #fff;\n padding: 1.5rem;\n width: 100%;\n}\n\n.leksy-editor-modal-body .warning {\n color: red;\n}\n\n.leksy-editor-modal-footer {\n background-color: #f2f2f3;\n padding: 1.25rem;\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n border-radius: 0 0 12px 12px;\n width: 100%;\n}\n\n.leksy-editor-modal input {\n width: 100%;\n font-size: 1rem;\n padding: 10px 12px;\n border: 1px solid #ccc;\n border-radius: 6px;\n outline: none;\n transition: all 0.3s ease-in-out;\n color: #333;\n}\n\n.leksy-editor-modal input:focus {\n border-color: #4592ff;\n background-color: #fff;\n}\n\n.leksy-editor-modal input::placeholder {\n color: #bdbdbd;\n}\n\n.leksy-editor-modal input:hover {\n border-color: #555;\n}\n\n.leksy-editor-modal button.submit {\n height: 2rem;\n padding: 0.75rem 1rem;\n background-color: hsl(160, 100%, 35%);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: row;\n text-align: center;\n text-decoration: none;\n cursor: pointer;\n border: 1px solid hsl(160, 100%, 40%);\n border-radius: 6px;\n color: hsl(0, 0%, 100%);\n white-space: nowrap;\n gap: 0.5rem;\n transition: 500ms;\n font-size: 1rem;\n}\n\n/* Overlay styling */\n.leksy-editor-preview-modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.726);\n /* Dark semi-transparent background */\n display: block;\n /* Hidden by default */\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n\n/* Modal content styling */\n.leksy-editor-preview-modal-content {\n height: 100%;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n position: relative;\n text-align: center;\n}\n\n/* Close button styling */\n.leksy-editor-preview-modal-close {\n position: absolute;\n top: 10px;\n right: 20px;\n cursor: pointer;\n color: white;\n font-size: 20px;\n}\n\n.leksy-editor-preview-modal-close svg {\n width: 28px;\n}\n\n/* Modal body styling */\n.leksy-editor-preview-modal-body {\n display: flex;\n height: 100%;\n width: 100%;\n align-items: center;\n justify-content: center;\n}\n\n.leksy-editor-preview-modal-body img {\n object-fit: contain;\n max-width: 90%;\n max-height: 90%;\n}\n\n.leksy-editor-spinner {\n animation: leksy-editor-rotate 1s linear infinite;\n margin-right: 8px;\n vertical-align: middle;\n}\n\n.leksy-editor-spinner .leksy-editor-path {\n stroke: white;\n stroke-linecap: round;\n animation: leksy-editor-dash 1.5s ease-in-out infinite;\n}\n\n.leksy-editor-upload-img-box {\n height: 180px;\n border: 2px dashed #d1d5db;\n border-radius: 12px;\n background: #f9fafb;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: border-color 0.2s ease;\n}\n\n.leksy-editor-upload-img-box:hover {\n border-color: gray;\n}\n\n.leksy-editor-upload-img-preview-box {\n height: 180px;\n border: 2px solid grey;\n margin-bottom: 8px;\n border-radius: 8px;\n}\n\n.leksy-editor-upload-img-preview {\n width: 100%;\n height: 100%;\n border-radius: 8px;\n object-fit: cover;\n object-position: top;\n}\n\n.leksy-editor-find-and-replace-modal-tab-btn {\n background: transparent;\n border: none;\n cursor: pointer;\n font-size: 16px;\n padding: 0;\n color: var(--primary);\n}\n\n.leksy-editor-find-and-replace-modal-tab-btn.active {\n font-weight: bold;\n border-bottom: 2px solid black;\n}\n\n.leksy-editor-find-and-replace-modal-label {\n padding-left: 4px;\n margin-bottom: 10px;\n}\n\n.leksy-editor-find-and-replace-modal-count {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n font-size: 12px;\n color: #585555;\n pointer-events: none;\n user-select: none;\n}\n\n@keyframes leksy-editor-rotate {\n 100% {\n transform: rotate(360deg);\n }\n}\n\n@keyframes leksy-editor-dash {\n 0% {\n stroke-dasharray: 1, 150;\n stroke-dashoffset: 0;\n }\n\n 50% {\n stroke-dasharray: 90, 150;\n stroke-dashoffset: -35;\n }\n\n 100% {\n stroke-dasharray: 90, 150;\n stroke-dashoffset: -124;\n }\n}"],"mappings":"AAAA,CAAC,uBAAuB,EACxB,CAAC,QACD,CAAC,OACG,WAAY,UAChB,CAEA,CANC,uBAMuB,KACxB,CAPC,uBAOuB,EACxB,CARC,uBAQuB,GACxB,CATC,uBASuB,GACxB,CAVC,uBAUuB,GAVxB,OAWY,EAXZ,QAYa,EACT,MAAO,KACP,YAAa,GACjB,CAEA,CAjBC,uBAiBuB,OACpB,WAAY,KACZ,eAAgB,KAChB,MAAO,MACP,eAAgB,OAChB,aAAc,OACd,YAAa,OACb,eAAgB,KAChB,YAAa,IACb,YAAa,KACb,QAAS,aACT,WAAY,OACZ,YAAa,OACb,OAAQ,QACR,WAAY,WACZ,iBAAkB,MAClB,cAAe,MACf,aAAc,IACd,aAAc,OACd,aAAc,MACd,aAAc,OAClB,CAEA,CAxCC,uBAyCG,MAAO,KACP,WAAY,MACZ,OAAQ,IAAI,MAAM,MA3CtB,cA4CmB,IACf,QAAS,KACT,eAAgB,OAChB,SAAU,QACd,CAEA,CAlDC,sBAkDsB,CAAC,WACpB,SAAU,MACV,IAAK,EACL,KAAM,EACN,OAAQ,MACR,iBAAkB,KAClB,QAAS,KAxDb,cAyDmB,CACnB,CAEA,CAAC,qBA5DD,QA6Da,IACT,cAAe,IAAI,MAAM,MACzB,iBAAkB,QAClB,KAAM,EAAE,EAAE,KACV,QAAS,KACT,UAAW,KAlEf,cAmEmB,IAAI,IAAI,EAAI,EAC3B,YAAa,MACjB,CAEA,CAAC,2BACG,QAAS,IAAI,MAAM,KACnB,QAAS,KAzEb,cA0EmB,IA1EnB,OA2EY,GACZ,CAEA,CAPC,2BAO2B,KACxB,UAAW,KACX,YAAa,MACjB,CAEA,CAAC,0BAnFD,OAoFY,IApFZ,QAqFa,IAAI,EACb,OAAQ,KACR,MAAO,KACP,WAAY,YAxFhB,cAyFmB,IACf,SAAU,SACV,YAAa,KACb,eAAgB,IAChB,UAAW,KACX,OAAQ,QACR,QAAS,IACT,WAAY,OACZ,WAAY,GAChB,CAEA,CAjBC,yBAiByB,CAAC,OACvB,MAAO,QACP,KAAM,OACV,CAEA,CAtBC,yBAsByB,CAAC,SACvB,OAAQ,YACR,MAAO,QACP,KAAM,OACV,CAEA,CA5BC,0BA4B0B,IACvB,MAAO,KACP,OAAQ,IACZ,CAEA,CAjCC,yBAiCyB,CAAC,OApH3B,QAqHa,EAAE,IACX,MAAO,KACX,CAEA,CAtCC,yBAsCyB,CAAC,cAzH3B,cA0HmB,IAAI,EAAE,EAAE,IACvB,aAAc,CAClB,CAEA,CA3CC,yBA2CyB,CAVC,MAUM,CALN,cAzH3B,QA+Ha,EA/Hb,cAgImB,EAAE,IAAI,IAAI,EACzB,YAAa,EACb,aAAc,GAClB,CAEA,CAlDC,yBAkDyB,CAjBC,MAiBM,CAZN,cAYqB,IAC5C,MAAO,KACP,OAAQ,IACZ,CAEA,CAvDC,yBAuDyB,CAAC,YAK3B,CA5DC,yBA4DyB,CAAC,MAJvB,MAAO,MA3IX,QA4Ia,IAAI,GACjB,CAOA,CAjEC,yBAiEyB,CALC,MAKM,MAC7B,OAAQ,KACR,MAAO,KACP,OAAQ,KACR,WAAY,IAChB,CAEA,CAxEC,yBAwEyB,CAZC,MAYM,IAC7B,QAAS,MACb,CAEA,CA5EC,yBA4EyB,OACtB,iBAAkB,QAClB,OAAQ,IACZ,CAEA,CAjFC,yBAiFyB,MAAM,OAC5B,QAAS,EACT,WAAY,OAChB,CAEA,CAtFC,yBAsFyB,OACtB,QAAS,KAAK,YACd,SAAU,MACV,IAAK,IAAI,kBAAkB,EAAE,GAC7B,KAAM,IAAI,mBAAmB,EAAE,GAC/B,QAAS,EACT,WAAY,OACZ,WAAY,QAAQ,GAAI,CAAE,WAAW,IACrC,iBAAkB,KAClB,WAAY,EAAI,EAAI,KAAK,MACzB,MAAO,KAnLX,QAoLa,IAAI,KApLjB,cAqLmB,IACf,UAAW,UAAW,MACtB,YAAa,OACb,QAAS,EACT,eAAgB,KAChB,UAAW,OACf,CAEA,CAAC,2BACG,QAAS,KACT,sBAAuB,OAAO,EAAE,CAAE,MAClC,mBAAoB,OAAO,EAAE,CAAE,KACnC,CAEA,CANC,2BAM2B,CAAC,KACzB,MAAO,KACP,OAAQ,KACR,OAAQ,IAAI,MAAM,KAClB,iBAAkB,OACtB,CAEA,CAbC,2BAa2B,CAPC,IAOI,CAAC,SAC9B,iBAAkB,IACtB,CAEA,CAAC,yBACG,YAAa,KACb,QAAS,GAhNb,QAiNa,IACT,SAAU,QACd,CAEA,CAAC,0BACG,WAAY,IACZ,MAAO,KACX,CAEA,CAAC,yBA1ND,OA2NY,IA3NZ,QA4Na,IACT,OAAQ,KACR,WAAY,YA9NhB,cA+NmB,IACf,SAAU,SACV,YAAa,KACb,eAAgB,IAChB,UAAW,KACX,OAAQ,QACR,QAAS,IACT,WAAY,MAChB,CAEA,CAfC,yBAeyB,IACtB,MAAO,IACX,CAEA,CAnBC,wBAmBwB,OACrB,iBAAkB,QAClB,OAAQ,IACZ,CAEA,CAxBC,wBAwBwB,MAAM,OAC3B,QAAS,EACT,WAAY,OAChB,CAEA,CA7BC,wBA6BwB,KAAK,CAAC,YAAY,OAC3C,CA9BC,wBA8BwB,CAAC,cAAc,OACpC,QAAS,IACb,CAEA,CAlCC,wBAkCwB,OACrB,QAAS,KAAK,YACd,SAAU,SACV,QAAS,EACT,WAAY,OACZ,WAAY,QAAQ,GAAI,CAAE,WAAW,IACrC,iBAAkB,KAClB,WAAY,EAAI,EAAI,KAAK,MACzB,MAAO,KApQX,QAqQa,IAAI,KArQjB,cAsQmB,IACf,OAAQ,KACR,KAAM,IACN,UAAW,UAAW,MACtB,YAAa,OACb,QAAS,EACT,eAAgB,KAChB,UAAW,OACf,CAEA,CAAC,8BACG,QAAS,KACT,SAAU,SACV,UAAW,MACX,WAAY,EAAI,IAAI,KAAK,UApR7B,cAqRmB,IACf,SAAU,OAtRd,QAuRa,IACT,QAAS,KACT,iBAAkB,IACtB,CAEA,CAZC,6BAY6B,CAAC,OAC3B,QAAS,MACT,MAAO,KA9RX,OA+RY,EACR,WAAY,KAhShB,QAiSa,IAAI,KACb,OAAQ,QACR,YAAa,OACb,WAAY,IApShB,cAqSmB,GACnB,CAEA,CAxBC,6BAwB6B,CAAC,OAAO,IAClC,MAAO,KACP,aAAc,GAClB,CAEA,CA7BC,6BA6B6B,CAAC,MAAM,OACjC,iBAAkB,QAClB,MAAO,IACX,CAEA,CAlCC,6BAkC6B,CAAC,QAC3B,MAAO,MACP,OAAQ,MApTZ,QAqTa,EACT,WAAY,IAChB,CAEA,CAzCC,6BAyC6B,CAPC,QAOQ,IACnC,MAAO,IACX,CAEA,CA7CC,6BA6C6B,CAXC,QAWQ,MACnC,MAAO,KACP,YAAa,OA/TjB,QAgUa,IAAI,IACb,OAAQ,IAAI,MAAM,KAjUtB,cAkUmB,IACf,WAAY,IAAI,IAAK,YACrB,WAAY,EAAI,IAAI,IAAI,UACxB,UAAW,KACX,SAAU,OACV,IAAK,CACT,CAEA,CA1DC,6BA0D6B,CAxBC,QAwBQ,KAAK,OACxC,aAAc,QACd,WAAY,EAAI,IAAI,IAAI,UACxB,QAAS,IACb,CAGA,CAjEC,6BAiE6B,CAAC,SAC3B,MAAO,MACP,OAAQ,MAnVZ,QAoVa,IACT,WAAY,KACZ,YAAa,IACjB,CAEA,CAzEC,6BAyE6B,CARC,SAQS,IACpC,YAAa,IACb,WAAY,IACZ,cAAe,GACnB,CAEA,CA/EC,6BA+E6B,CAdC,SAcS,KA/VxC,QAgWa,IACT,OAAQ,OACZ,CAEA,CApFC,6BAoF6B,CAAC,QAC3B,MAAO,MACP,OAAQ,MAtWZ,QAuWa,IACT,WAAY,KACZ,YAAa,IACjB,CAEA,CA5FC,6BA4F6B,CARC,QAQQ,MACnC,MAAO,KACP,YAAa,OA9WjB,OA+WY,IAAI,CAChB,CAEA,CAlGC,6BAkG6B,CAdC,QAcQ,OACnC,QAAS,MACT,MAAO,KApXX,OAqXY,EACR,WAAY,KAtXhB,QAuXa,IAAI,KACb,OAAQ,QACR,YAAa,MACjB,CAEA,CA5GC,6BA4G6B,CAxBC,QAwBQ,MAAM,OACzC,iBAAkB,KACtB,CAEA,CAAC,6BACG,QAAS,KACT,SAAU,SACV,UAAW,MACX,WAAY,EAAE,EAAE,KAAO,KApY3B,cAqYmB,IArYnB,QAsYa,IACT,QAAS,KACT,iBAAkB,IACtB,CAEA,CAAC,0BACG,QAAS,KACT,WAAY,QACZ,cAAe,IAAI,MAAM,IAC7B,CAEA,MAAM,CAAC,yBAjZP,QAkZa,IAAI,KACb,OAAQ,KACR,WAAY,YACZ,OAAQ,OACZ,CAEA,MAAM,CAPC,wBAOwB,CApTJ,OAqTvB,cAAe,IAAI,MAAM,MACzB,YAAa,GACjB,CAEA,CAlBC,0BAkB0B,CAZpB,wBAY6C,KAAK,aACrD,aAAc,IAAI,MAAM,IAC5B,CAEA,CAAC,sBACG,KAAM,EAAE,EAAE,KAlad,QAmaa,IACT,iBAAkB,QAClB,MAAO,QACP,OAAQ,EACR,QAAS,EACT,QAAS,KACT,OAAQ,KACR,OAAQ,KACZ,CAEA,CAAC,qBACG,OAAQ,KACR,WAAY,IAAI,MAAM,MA/a1B,cAgbmB,EAAE,EAAE,IAAI,IACvB,iBAAkB,QAjbtB,QAkba,IAAI,IACb,eAAgB,UAChB,QAAS,KACT,gBAAiB,cACjB,UAAW,KACX,YAAa,IAEjB,CAEA,CAdC,qBAcqB,CAAC,WACnB,WAAY,KACZ,QAAS,KACT,SAAU,OACV,gBAAiB,GACrB,CAEA,CArBC,qBAqBqB,CAPC,WAOW,GAC9B,YAAa,GACjB,CAEA,CAzBC,qBAyBqB,CAXC,WAWW,EAAE,OAChC,QAAS,IACT,YAAa,GACjB,CAEA,CA9BC,qBA8BqB,CAhBC,WAgBW,EAAE,WAAW,OAC3C,QAAS,EACb,CAEA,CAAC,mBACG,SAAU,MACV,QAAS,IACT,KAAM,EACN,IAAK,EACL,MAAO,KACP,OAAQ,KACR,SAAU,KACV,iBAAkB,SACtB,CAEA,CAXC,kBAWkB,CAAC,6BAChB,SAAU,MACV,IAAK,IACL,KAAM,IACN,UAAW,UAAU,IAAI,CAAE,MAC3B,WAAY,QACZ,MAAO,YACP,OAAQ,OACZ,CAEA,CAAC,2BApeD,OAqeY,IAAI,KACZ,OAAQ,IAAI,MAAM,QAClB,UAAW,MAvef,cAwemB,IACnB,CAEA,CA5BC,kBA4BkB,CAjBC,6BAiB6B,CAPhD,2BAQG,OAAQ,MACR,MAAO,WACX,CAEA,CAAC,0BAhfD,QAifa,QACT,QAAS,KACT,YAAa,OACb,gBAAiB,cACjB,iBAAkB,KAClB,cAAe,IAAI,MAAM,QAtf7B,cAufmB,KAAK,KAAK,EAAE,EAC3B,SAAU,MACd,CAEA,CAAC,wBACG,iBAAkB,KA5ftB,QA6fa,OACT,MAAO,IACX,CAEA,CANC,wBAMwB,CAAC,QACtB,MAAO,GACX,CAEA,CAAC,0BACG,iBAAkB,QAtgBtB,QAugBa,QACT,QAAS,KACT,gBAAiB,SACjB,IAAK,KA1gBT,cA2gBmB,EAAE,EAAE,KAAK,KACxB,MAAO,IACX,CAEA,CAhEC,mBAgEmB,MAChB,MAAO,KACP,UAAW,KAjhBf,QAkhBa,KAAK,KACd,OAAQ,IAAI,MAAM,KAnhBtB,cAohBmB,IACf,QAAS,KACT,WAAY,IAAI,IAAK,YACrB,MAAO,IACX,CAEA,CA3EC,mBA2EmB,KAAK,OACrB,aAAc,QACd,iBAAkB,IACtB,CAEA,CAhFC,mBAgFmB,KAAK,cACrB,MAAO,OACX,CAEA,CApFC,mBAoFmB,KAAK,OACrB,aAAc,IAClB,CAEA,CAxFC,mBAwFmB,MAAM,CAAC,OACvB,OAAQ,KAxiBZ,QAyiBa,OAAQ,KACjB,iBAAkB,QAClB,QAAS,KACT,YAAa,OACb,gBAAiB,OACjB,eAAgB,IAChB,WAAY,OACZ,gBAAiB,KACjB,OAAQ,QACR,OAAQ,IAAI,MAAM,IAAI,GAAG,CAAE,IAAI,CAAE,KAljBrC,cAmjBmB,IACf,MAAO,KACP,YAAa,OACb,IAAK,MACL,WAAY,IACZ,UAAW,IACf,CAGA,CAAC,mCACG,SAAU,MACV,IAAK,EACL,KAAM,EACN,MAAO,KACP,OAAQ,KACR,WAAY,UAEZ,QAAS,MAET,YAAa,OACb,gBAAiB,OACjB,QAAS,IACb,CAGA,CAAC,mCACG,OAAQ,KA7kBZ,QA8kBa,KA9kBb,cA+kBmB,IACf,WAAY,EAAE,IAAI,IAAI,UACtB,SAAU,SACV,WAAY,MAChB,CAGA,CAAC,iCACG,SAAU,SACV,IAAK,KACL,MAAO,KACP,OAAQ,QACR,MAAO,KACP,UAAW,IACf,CAEA,CATC,iCASiC,IAC9B,MAAO,IACX,CAGA,CAAC,gCACG,QAAS,KACT,OAAQ,KACR,MAAO,KACP,YAAa,OACb,gBAAiB,MACrB,CAEA,CARC,gCAQgC,IAC7B,WAAY,QACZ,UAAW,IACX,WAAY,GAChB,CAEA,CAAC,qBACG,UAAW,oBAAoB,GAAG,OAAO,SACzC,aAAc,IACd,eAAgB,MACpB,CAEA,CANC,qBAMqB,CAAC,kBACnB,OAAQ,KACR,eAAgB,MAChB,UAAW,kBAAkB,KAAK,YAAY,QAClD,CAEA,CAAC,4BACG,OAAQ,MACR,OAAQ,IAAI,OAAO,QAhoBvB,cAioBmB,KACf,WAAY,QACZ,QAAS,KACT,YAAa,OACb,gBAAiB,OACjB,OAAQ,QACR,WAAY,aAAa,IAAK,IAClC,CAEA,CAZC,2BAY2B,OACxB,aAAc,IAClB,CAEA,CAAC,oCACG,OAAQ,MACR,OAAQ,IAAI,MAAM,KAClB,cAAe,IAjpBnB,cAkpBmB,GACnB,CAEA,CAAC,gCACG,MAAO,KACP,OAAQ,KAvpBZ,cAwpBmB,IACf,WAAY,MACZ,gBAAiB,GACrB,CAEA,CAAC,4CACG,WAAY,YACZ,OAAQ,KACR,OAAQ,QACR,UAAW,KAjqBf,QAkqBa,EACT,MAAO,IAAI,UACf,CAEA,CATC,2CAS2C,CAlkBjB,OAmkBvB,YAAa,IACb,cAAe,IAAI,MAAM,KAC7B,CAEA,CAAC,0CACG,aAAc,IACd,cAAe,IACnB,CAEA,CAAC,0CACG,SAAU,SACV,MAAO,IACP,IAAK,IACL,UAAW,WAAW,MACtB,UAAW,KACX,MAAO,QACP,eAAgB,KAChB,YAAa,IACjB,CAEA,WAxEe,oBAyEX,GACI,UAAW,OAAO,OACtB,CACJ,CAEA,WAtEe,kBAuEX,GACI,iBAAkB,CAAC,CAAE,IACrB,kBAAmB,CACvB,CAEA,IACI,iBAAkB,EAAE,CAAE,IACtB,kBAAmB,GACvB,CAEA,GACI,iBAAkB,EAAE,CAAE,IACtB,kBAAmB,IACvB,CACJ","names":[]}
|