@phenix1024/editor 0.1.0 → 0.2.0

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.
@@ -1 +1,59 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));let c=require("@tiptap/core"),l=require("@tiptap/starter-kit");l=s(l,1);let u=require("@tiptap/extension-underline");u=s(u,1);let d=require("@tiptap/extension-link");d=s(d,1);let f=require("@tiptap/extension-image");f=s(f,1);let p=require("@tiptap/extension-placeholder");p=s(p,1);let m=require("@tiptap/extension-table"),h=require("@tiptap/extension-table-row"),g=require("@tiptap/extension-table-header"),_=require("@tiptap/extension-table-cell"),v=require("@tiptap/extension-heading");v=s(v,1);let y=require("@tiptap/pm/state"),b=require("@tiptap/pm/view"),x=require("jszip");x=s(x,1);var S=c.Mark.create({name:`label`,inclusive:!1,addAttributes(){return{label:{default:`highlight`,parseHTML:e=>e.dataset.label??`highlight`,renderHTML:e=>({"data-label":e.label})}}},parseHTML(){return[{tag:`mark[data-label]`},{tag:`mark`}]},renderHTML({HTMLAttributes:e}){return[`mark`,e,0]}});function C(){return{fieldId:{default:``,parseHTML:e=>e.getAttribute(`data-ophx-field`)??``,renderHTML:e=>({"data-ophx-field":e.fieldId??``})},fieldLabel:{default:null,parseHTML:e=>e.getAttribute(`data-ophx-label`),renderHTML:e=>e.fieldLabel?{"data-ophx-label":e.fieldLabel}:{}},required:{default:!1,parseHTML:e=>e.getAttribute(`data-ophx-required`)===`true`,renderHTML:e=>e.required?{"data-ophx-required":`true`}:{}}}}var w=/^[A-Za-z0-9._-]+$/,T=c.Node.create({name:`ophxInlineField`,priority:1e3,group:`inline`,inline:!0,content:`text*`,defining:!0,addAttributes:C,parseHTML(){return[{tag:`span.ophx-field[contenteditable="true"][data-ophx-field]`,priority:1e3}]},renderHTML({HTMLAttributes:e}){return[`span`,{...e,class:`ophx-field`,contenteditable:`true`},0]}}),E=c.Node.create({name:`ophxBlockField`,priority:1e3,group:`block`,content:`text*`,defining:!0,addAttributes(){return{...C(),tagName:{default:`div`,parseHTML:e=>e.tagName.toLowerCase(),renderHTML:()=>({})}}},parseHTML(){return[{tag:`p.ophx-field[contenteditable="true"][data-ophx-field]`,priority:1e3},{tag:`div.ophx-field[contenteditable="true"][data-ophx-field]`,priority:1e3}]},renderHTML({node:e,HTMLAttributes:t}){return[e.attrs.tagName===`p`?`p`:`div`,{...t,class:`ophx-field`,contenteditable:`true`},0]}}),D=c.Mark.create({name:`ophxReadonlyInline`,inclusive:!1,addAttributes(){return{className:{default:null,parseHTML:e=>e.getAttribute(`class`),renderHTML:e=>e.className?{class:e.className}:{}}}},parseHTML(){return[{tag:`span[contenteditable="false"]`,priority:100}]},renderHTML({HTMLAttributes:e}){return[`span`,{...e,contenteditable:`false`},0]}}),O=c.Node.create({name:`ophxReadonlyBlock`,priority:1e3,group:`block`,content:`block*`,defining:!0,isolating:!0,addAttributes(){return{id:{default:null,parseHTML:e=>e.getAttribute(`id`),renderHTML:e=>e.id?{id:e.id}:{}},className:{default:null,parseHTML:e=>e.getAttribute(`class`),renderHTML:e=>e.className?{class:e.className}:{}},title:{default:null,parseHTML:e=>e.getAttribute(`title`),renderHTML:e=>e.title?{title:e.title}:{}}}},parseHTML(){return[{tag:`div[contenteditable="false"]`,priority:1e3}]},renderHTML({HTMLAttributes:e}){return[`div`,{...e,contenteditable:`false`},0]}}),k=new y.PluginKey(`ophxHeadingCollapse`),A=v.default.extend({addAttributes(){return{...this.parent?.(),collapsed:{default:!1,parseHTML:e=>e.dataset.collapsed===`true`,renderHTML:e=>e.collapsed?{"data-collapsed":`true`}:{}}}},addProseMirrorPlugins(){return[new y.Plugin({key:k,props:{decorations(e){let t=[],n=null;return e.doc.forEach((e,r)=>{if(e.type.name===`heading`){let i=Number(e.attrs.level);n!==null&&i<=n&&(n=null),n!==null&&t.push(b.Decoration.node(r,r+e.nodeSize,{class:`ophx-collapsed-content`})),e.attrs.collapsed&&(n=i)}else n!==null&&t.push(b.Decoration.node(r,r+e.nodeSize,{class:`ophx-collapsed-content`}))}),b.DecorationSet.create(e.doc,t)}}})]}}),j=new y.PluginKey(`ophxTextSearch`),M=c.Extension.create({name:`ophxSearch`,addStorage(){return{query:``}},addCommands(){return{setSearchQuery:e=>({tr:t,dispatch:n})=>(this.storage.query=e,n?.(t.setMeta(j,e)),!0)}},addProseMirrorPlugins(){let e=this;return[new y.Plugin({key:j,state:{init:(t,n)=>N(n.doc,e.storage.query),apply:(t,n,r,i)=>{let a=t.getMeta(j);return a!==void 0&&(e.storage.query=a),!t.docChanged&&a===void 0?n:N(i.doc,e.storage.query)}},props:{decorations(e){return j.getState(e)}}})]}});function N(e,t){if(!t.trim())return b.DecorationSet.empty;let n=[],r=t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),i=new RegExp(r,`gi`);return e.descendants((e,t)=>{if(e.isText&&e.text){i.lastIndex=0;for(let r of e.text.matchAll(i))r.index!==void 0&&n.push(b.Decoration.inline(t+r.index,t+r.index+r[0].length,{class:`ophx-search-match`}))}}),b.DecorationSet.create(e,n)}var P=c.Extension.create({name:`ophxWysiwymRules`,addProseMirrorPlugins(){return[new y.Plugin({props:{handleTextInput(e,t,n,r){return r===` `&&/\s/.test(e.state.doc.textBetween(Math.max(0,t-1),t))},handleKeyDown(e,t){if(t.key!==`Enter`||t.shiftKey)return!1;let{$from:n}=e.state.selection;if(!n.parent.isTextblock||n.parent.content.size!==0||n.depth===0)return!1;let r=n.index(n.depth-1),i=n.node(n.depth-1);return[i.maybeChild(r-1),i.maybeChild(r+1)].some(e=>e?.isTextblock&&e.content.size===0)}}})]}}),F=c.Extension.create({name:`ophxIndentation`,addGlobalAttributes(){return[{types:[`paragraph`,`heading`],attributes:{indent:{default:0,parseHTML:e=>Number(e.dataset.indent??0),renderHTML:e=>e.indent?{"data-indent":String(e.indent)}:{}}}}]}}),I=c.Extension.create({name:`ophxEditability`,addGlobalAttributes(){return[{types:[`paragraph`,`heading`,`blockquote`,`codeBlock`,`bulletList`,`orderedList`,`listItem`,`horizontalRule`,`image`,`table`,`tableRow`,`tableHeader`,`tableCell`,`bold`,`italic`,`underline`,`strike`,`link`,`label`],attributes:{contenteditable:{default:null,parseHTML:e=>{let t=e.getAttribute(`contenteditable`);return t===`true`||t===`false`?t:null},renderHTML:e=>e.contenteditable?{contenteditable:e.contenteditable}:{}}}}]}});function L(e){return w.test(e)}var R=class{editor;constructor(e){this.editor=new c.Editor({element:e.element,content:e.content??`<p></p>`,editable:e.editable??!0,extensions:[l.default.configure({heading:!1,underline:!1,link:!1}),A.configure({levels:[1,2,3,4,5,6]}),u.default,d.default.configure({openOnClick:!1,autolink:!0,linkOnPaste:!0}),f.default.configure({allowBase64:!0,inline:!1}),m.Table.configure({resizable:!0}),h.TableRow,g.TableHeader,_.TableCell,T,E,O,D,S,F,I,M,P,p.default.configure({placeholder:e.placeholder??`Начните писать…`}),...e.extensions??[]],editorProps:{attributes:{class:`ophx-editor-surface`,spellcheck:`true`,lang:`ru`,"aria-label":`Редактор документа`}},onUpdate:e.onUpdate})}getHTML(){return this.editor.getHTML()}getJSON(){return this.editor.getJSON()}setContent(e){this.editor.commands.setContent(e,{emitUpdate:!1})}setSearchQuery(e){this.editor.commands.setSearchQuery(e)}getFields(){let e=Array.from(this.editor.view.dom.querySelectorAll(`[data-ophx-field]`)).filter(e=>{let t=e.getAttribute(`data-ophx-field`)??``;return e.classList.contains(`ophx-field`)&&e.getAttribute(`contenteditable`)===`true`&&L(t)}),t=new Map;for(let n of e){let e=n.getAttribute(`data-ophx-field`);t.set(e,(t.get(e)??0)+1)}return e.filter(e=>t.get(e.getAttribute(`data-ophx-field`))===1).map(e=>({id:e.getAttribute(`data-ophx-field`),label:e.getAttribute(`data-ophx-label`),required:e.getAttribute(`data-ophx-required`)===`true`,value:e.textContent??``}))}getMissingRequiredFields(){return this.getFields().filter(e=>e.required&&!e.value.trim())}destroy(){this.editor.destroy()}},ee=[{action:`bold`,label:`B`,title:`Жирный (⌘/Ctrl+B)`},{action:`italic`,label:`I`,title:`Курсив (⌘/Ctrl+I)`},{action:`underline`,label:`U`,title:`Подчёркнутый (⌘/Ctrl+U)`},{action:`strike`,label:`S̶`,title:`Зачёркнутый`},{action:`bullet`,label:`• Список`,title:`Маркированный список`},{action:`ordered`,label:`1. Список`,title:`Нумерованный список`},{action:`outdent`,label:`← Отступ`,title:`Уменьшить отступ`},{action:`indent`,label:`Отступ →`,title:`Увеличить отступ`},{action:`link`,label:`Ссылка`,title:`Добавить ссылку`},{action:`image`,label:`Изображение`,title:`Вставить изображение`},{action:`table`,label:`Таблица`,title:`Вставить таблицу`},{action:`collapse`,label:`Свернуть`,title:`Свернуть/развернуть раздел`},{action:`label`,label:`Метка`,title:`Выделить текст меткой`},{action:`toc`,label:`Содержание`,title:`Содержание документа`},{action:`undo`,label:`↶`,title:`Отменить (⌘/Ctrl+Z)`},{action:`redo`,label:`↷`,title:`Повторить (⌘/Ctrl+Shift+Z)`}];function te(e,t,n={}){e.classList.add(`ophx-toolbar`),e.replaceChildren();let r=document.createElement(`select`);r.className=`ophx-toolbar__style`,r.setAttribute(`aria-label`,`Стиль текста`),r.innerHTML=`<option value="p">Обычный текст</option><option value="1">Заголовок 1</option><option value="2">Заголовок 2</option><option value="3">Заголовок 3</option>`,r.addEventListener(`change`,()=>{let e=Number(r.value),n=t.chain().focus();r.value===`p`?n.setParagraph().run():n.setHeading({level:e}).run()}),e.append(r);let i=new Map;for(let n of ee){let r=document.createElement(`button`);r.type=`button`,r.className=`ophx-toolbar__button`,r.dataset.action=n.action,r.textContent=n.label,r.title=n.title,r.setAttribute(`aria-label`,n.title),r.addEventListener(`mousedown`,e=>e.preventDefault()),r.addEventListener(`click`,()=>z(n.action,t,o,s)),i.set(n.action,r),e.append(r)}let a=document.createElement(`input`);a.type=`search`,a.className=`ophx-toolbar__search`,a.placeholder=`Поиск…`,a.setAttribute(`aria-label`,`Поиск по тексту`),a.addEventListener(`input`,()=>t.commands.setSearchQuery(a.value)),a.addEventListener(`keydown`,e=>{e.key===`Escape`&&(a.value=``,t.commands.setSearchQuery(``),t.commands.focus())}),e.append(a);let o=document.createElement(`input`);o.type=`file`,o.accept=`image/*`,o.hidden=!0,o.addEventListener(`change`,()=>{let e=o.files?.[0];if(e){if(n.onInsertImage)n.onInsertImage(e);else{let n=new FileReader;n.addEventListener(`load`,()=>{typeof n.result==`string`&&t.chain().focus().setImage({src:n.result,alt:e.name}).run()}),n.readAsDataURL(e)}}o.value=``}),e.append(o);let s=document.createElement(`nav`);s.className=`ophx-toc`,s.setAttribute(`aria-label`,`Содержание документа`),s.hidden=!0,e.append(s);let c=()=>{i.get(`undo`).disabled=!t.can().undo(),i.get(`redo`).disabled=!t.can().redo(),i.get(`bold`).classList.toggle(`is-active`,t.isActive(`bold`)),i.get(`italic`).classList.toggle(`is-active`,t.isActive(`italic`)),i.get(`underline`).classList.toggle(`is-active`,t.isActive(`underline`)),i.get(`strike`).classList.toggle(`is-active`,t.isActive(`strike`));let e=t.getAttributes(`heading`).level;r.value=e?String(e):(t.isActive(`paragraph`),`p`),s.replaceChildren(),t.state.doc.descendants((e,n)=>{if(e.type.name!==`heading`)return;let r=document.createElement(`button`);r.type=`button`,r.className=`ophx-toc__item`,r.style.paddingInlineStart=`${Math.max(0,Number(e.attrs.level)-1)*12}px`,r.textContent=e.textContent||`Без названия`,r.addEventListener(`mousedown`,e=>e.preventDefault()),r.addEventListener(`click`,()=>{t.commands.setTextSelection(n+1),t.commands.focus(),t.commands.scrollIntoView()}),s.append(r)})};return t.on(`transaction`,c),t.on(`selectionUpdate`,c),c(),()=>{t.off(`transaction`,c),t.off(`selectionUpdate`,c),e.replaceChildren(),e.classList.remove(`ophx-toolbar`)}}function z(e,t,n,r){let i=t.chain().focus();switch(e){case`bold`:i.toggleBold().run();break;case`italic`:i.toggleItalic().run();break;case`underline`:i.toggleUnderline().run();break;case`strike`:i.toggleStrike().run();break;case`bullet`:i.toggleBulletList().run();break;case`ordered`:i.toggleOrderedList().run();break;case`indent`:B(t,1);break;case`outdent`:B(t,-1);break;case`link`:{let e=t.getAttributes(`link`).href,n=window.prompt(`Адрес ссылки`,e??`https://`);if(n===null)return;n.trim()?i.extendMarkRange(`link`).setLink({href:n.trim()}).run():i.extendMarkRange(`link`).unsetLink().run();break}case`image`:n.click();break;case`table`:i.insertTable({rows:3,cols:3,withHeaderRow:!0}).run();break;case`collapse`:{if(!t.isActive(`heading`))return;let e=!!t.getAttributes(`heading`).collapsed;i.updateAttributes(`heading`,{collapsed:!e}).run();break}case`label`:{let e=window.prompt(`Название метки`,`важно`);e?.trim()&&i.setMark(`label`,{label:e.trim()}).run();break}case`toc`:r.hidden=!r.hidden;break;case`undo`:i.undo().run();break;case`redo`:i.redo().run()}}function B(e,t){let{$from:n}=e.state.selection;if(n.parent.type.name===`listItem`){let n=e.chain().focus();t>0?n.sinkListItem(`listItem`).run():n.liftListItem(`listItem`).run();return}let r=n.parent.type.name;if(r!==`paragraph`&&r!==`heading`)return;let i=Number(e.getAttributes(r).indent??0);e.chain().focus().updateAttributes(r,{indent:Math.max(0,Math.min(8,i+t))}).run()}var V={avif:`image/avif`,bmp:`image/bmp`,gif:`image/gif`,ico:`image/x-icon`,jpeg:`image/jpeg`,jpg:`image/jpeg`,png:`image/png`,svg:`image/svg+xml`,tif:`image/tiff`,tiff:`image/tiff`,webp:`image/webp`};async function H(e,t={}){let n=new x.default,r=new DOMParser().parseFromString(e,`text/html`);K(r);let i=q(t.filename??t.title??`Документ`),a=t.title??r.title??i,o=t.assets??{},s=new Set(Object.keys(o).map(Y)),c=0;for(let e of Array.from(r.querySelectorAll(`img[src]`))){let t=e.getAttribute(`src`)?.trim();if(!t||/^https?:\/\//i.test(t)||/^data:(?!image\/)/i.test(t))continue;if(/^data:image\//i.test(t)||/^blob:/i.test(t)){try{let r=await fetch(t);if(!r.ok)throw Error(`Не удалось прочитать изображение: ${t}`);let i=await r.blob();if(!i.type.startsWith(`image/`))throw Error(`Вложение с data/blob URL не является изображением`);let a=`image-${++c}.${Q(i.type,t)}`;for(;s.has(a);)a=`image-${++c}.${Q(i.type,t)}`;n.file(a,i),s.add(a),e.setAttribute(`src`,encodeURIComponent(a))}catch(e){throw Error(`Не удалось добавить изображение в архив ophx`,{cause:e})}continue}let r=Y(t);if(!J(r))throw Error(`Путь изображения должен быть простым именем файла: ${t}`);let i=o[r];if(!i&&!s.has(r))throw Error(`Для локального изображения «${r}» не передан файл media`);i&&n.file(r,i),e.setAttribute(`src`,encodeURIComponent(r))}let l=G(t.styles??{});for(let[e,t]of Object.entries(l))n.file(e,t);let u=Object.keys(l).map(e=>`<link rel="stylesheet" href="${$(encodeURIComponent(e))}">`).join(``),d=r.documentElement.lang||`ru`,f=t.bodyContentEditable?` contenteditable="${t.bodyContentEditable}"`:``,p=`<!doctype html>\n<html lang="${$(d)}"><head><meta charset="utf-8"><title>${$(a)}</title>${u}</head><body${f}>${r.body.innerHTML}</body></html>`;return n.file(`${i}.html`,p),n.generateAsync({type:`blob`,mimeType:`application/zip`,compression:`DEFLATE`,compressionOptions:{level:6}})}async function U(e){await Z(e);let t;try{t=await x.default.loadAsync(e)}catch(e){throw Error(`Не удалось прочитать ZIP-архив .ophx (шифрование и неподдерживаемые ZIP-режимы не поддерживаются)`,{cause:e})}if(Object.values(t.files).some(e=>e.dir||/[\\/]/.test(e.name)))throw Error(`В текущей версии .ophx все файлы должны находиться плоским списком в корне архива`);let n=Object.values(t.files).filter(e=>!e.dir),r=n.filter(e=>e.name.toLowerCase().endsWith(`.html`));if(r.length!==1)throw r.length===0&&n.some(e=>e.name.toLowerCase().endsWith(`.xml`))?Error(`Обнаружен устаревший XML-вариант ophx; поддерживается только версия v2 с HTML5 внутри ZIP`):Error(`В архиве должен быть ровно один HTML-файл в корне; найдено: ${r.length}`);let i=r[0],a=i.name.slice(0,-5),o=`name`in e&&typeof e.name==`string`?e.name:``;if(/\.ophx$/i.test(o)&&o.replace(/\.ophx$/i,``)!==a)throw Error(`Имя HTML-файла «${i.name}» должно совпадать с именем архива «${o}»`);let s=await i.async(`string`);if(!/^\s*<!doctype\s+html\b/i.test(s))throw Error(`Основной файл .ophx должен начинаться с <!doctype html>`);let c=new DOMParser().parseFromString(s,`text/html`);if(c.querySelector(`head meta[charset]`)?.getAttribute(`charset`)?.toLowerCase()!==`utf-8`)throw Error(`В <head> документа требуется <meta charset="utf-8">`);let l={};for(let e of Array.from(c.querySelectorAll(`head link[rel~="stylesheet"][href]`))){let n=e.getAttribute(`href`)?.trim();if(!n)continue;if(X(n))throw Error(`CSS должен быть встроенным плоским файлом архива: ${n}`);let r=Y(n);if(!J(r)||!r.toLowerCase().endsWith(`.css`))throw Error(`Ссылка на стиль должна указывать на плоский .css-файл: ${n}`);let i=t.file(r);if(!i)throw Error(`Файл стиля «${r}» отсутствует в архиве`);l[r]=await i.async(`string`)}for(let e of Array.from(c.querySelectorAll(`img[src]`))){let n=e.getAttribute(`src`)?.trim();if(!n||X(n))continue;let r=Y(n);if(!J(r))throw Error(`Ссылка на изображение должна быть простым именем файла: ${n}`);let i=t.file(r);if(!i)throw Error(`Файл изображения «${r}» отсутствует в архиве`);let a=await i.async(`base64`),o=r.split(`.`).pop()?.toLowerCase()??``,s=V[o]??(o?`image/${o}`:`application/octet-stream`);e.setAttribute(`src`,`data:${s};base64,${a}`)}let u=c.body.getAttribute(`contenteditable`);if(u===`false`)for(let e of Array.from(c.body.children))e.hasAttribute(`contenteditable`)||e.setAttribute(`contenteditable`,`false`);ne(c);let d=Object.entries(l);return{html:c.body.innerHTML,title:c.title||a,filename:a,styles:l,css:d[0]?.[1]??``,bodyContentEditable:u===`true`||u===`false`?u:void 0}}function W(e,t){let n=URL.createObjectURL(e),r=window.document.createElement(`a`);r.href=n,r.download=t,r.click(),window.setTimeout(()=>URL.revokeObjectURL(n),0)}function G(e){let t={};for(let[n,r]of Object.entries(e)){let e=Y(n);if(!J(e)||!e.toLowerCase().endsWith(`.css`))throw Error(`Имя файла стиля должно быть плоским и оканчиваться на .css: ${n}`);if(Object.hasOwn(t,e))throw Error(`Повторяется имя файла стиля: ${e}`);t[e]=r}return t}function K(e){let t=Array.from(e.querySelectorAll(`[data-ophx-field], .ophx-field`)),n=new Set;for(let e of t){let t=e.getAttribute(`data-ophx-field`)??``,r=e.tagName.toLowerCase();if(!e.classList.contains(`ophx-field`)||e.getAttribute(`contenteditable`)!==`true`)throw Error(`Каждое поле должно иметь класс ophx-field и contenteditable="true"`);if(![`span`,`div`,`p`].includes(r)||!/^[A-Za-z0-9._-]+$/.test(t))throw Error(`Некорректная обёртка или идентификатор поля: ${t||`(пусто)`}`);if(n.has(t))throw Error(`Идентификатор поля должен быть уникальным: ${t}`);if(e.parentElement?.closest(`[data-ophx-field]`))throw Error(`Поля не могут быть вложенными: ${t}`);n.add(t)}}function q(e){let t=e.trim().replace(/\.(?:ophx|html)$/i,``);if(!t)return`Документ`;if(!J(t)||/[\u0000-\u001f]/.test(t))throw Error(`Имя .ophx должно быть простым именем файла без каталогов`);return t}function J(e){return!!e&&e!==`.`&&e!==`..`&&!/[\\/]/.test(e)}function Y(e){try{return decodeURIComponent(e)}catch{throw Error(`Некорректное percent-экранирование в имени ресурса: ${e}`)}}function X(e){return/^(?:data:|https?:\/\/)/i.test(e)}async function Z(e){if(e.size<2)throw Error(`Файл не является ZIP-архивом .ophx (возможен устаревший формат)`);let t=new Uint8Array(await e.slice(0,4).arrayBuffer());if(t[0]!==80||t[1]!==75)throw Error(`Неподдерживаемый устаревший ophx: ожидается ZIP-архив версии v2`)}function Q(e,t){let n=Object.entries(V).find(([,t])=>t===e)?.[0];if(n)return n;let r=t.match(/\.([a-z0-9]+)(?:[?#]|$)/i)?.[1]?.toLowerCase();return r&&/^[a-z0-9]{1,6}$/.test(r)?r:`bin`}function ne(e){e.querySelectorAll(`script, iframe, object, embed, style, link`).forEach(e=>e.remove()),e.querySelectorAll(`*`).forEach(e=>{for(let t of Array.from(e.attributes))/^on/i.test(t.name)&&e.removeAttribute(t.name),/^(href|src|xlink:href)$/i.test(t.name)&&/^\s*(javascript|vbscript):/i.test(t.value)&&e.removeAttribute(t.name),/^(src|xlink:href)$/i.test(t.name)&&/^\s*data:(?!image\/)/i.test(t.value)&&e.removeAttribute(t.name)})}function $(e){return e.replace(/[&<>"']/g,e=>({"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`})[e])}function re(e,t=`f`){if(!/^[A-Za-z0-9._-]+$/.test(t))throw Error(`Префикс идентификаторов полей содержит недопустимые символы`);let n=new DOMParser().parseFromString(e,`text/html`),r=new Set(Array.from(n.querySelectorAll(`[data-ophx-field]`)).map(e=>e.getAttribute(`data-ophx-field`)??``).filter(Boolean)),i=n.createTreeWalker(n.body,4),a=[];for(;i.nextNode();){let e=i.currentNode,t=e.parentElement;t&&!t.closest(`code, pre, script, style, [contenteditable="false"], [data-ophx-field]`)&&/_{2,}/.test(e.data)&&a.push(e)}let o=[],s=1;for(let e of a){let i=n.createDocumentFragment(),a=0;for(let c of e.data.matchAll(/_{2,}/g)){if(c.index===void 0)continue;c.index>a&&i.append(n.createTextNode(e.data.slice(a,c.index)));let l=`${t}${s++}`;for(;r.has(l);)l=`${t}${s++}`;r.add(l),o.push(l);let u=n.createElement(`span`);u.className=`ophx-field`,u.setAttribute(`contenteditable`,`true`),u.setAttribute(`data-ophx-field`,l),i.append(u),a=c.index+c[0].length}a<e.data.length&&i.append(n.createTextNode(e.data.slice(a))),e.replaceWith(i)}return{html:n.body.innerHTML,count:o.length,ids:o}}exports.CollapsibleHeading=A,exports.Indentation=F,exports.Label=S,exports.OphxBlockField=E,exports.OphxEditability=I,exports.OphxEditor=R,exports.OphxInlineField=T,exports.OphxReadonlyBlock=O,exports.OphxReadonlyInline=D,exports.TextSearch=M,exports.WysiwymRules=P,exports.convertUnderscoresToFields=re,exports.downloadBlob=W,exports.exportOphx=H,exports.importOphx=U,exports.isValidOphxFieldId=L,exports.mountToolbar=te;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));let c=require("@tiptap/core"),l=require("@tiptap/starter-kit");l=s(l,1);let u=require("@tiptap/extension-underline");u=s(u,1);let d=require("@tiptap/extension-link");d=s(d,1);let f=require("@tiptap/extension-placeholder");f=s(f,1);let p=require("@tiptap/extension-table"),m=require("@tiptap/extension-table-row"),h=require("@tiptap/extension-table-header"),g=require("@tiptap/extension-table-cell"),_=require("jszip");_=s(_,1);let v=require("@tiptap/extension-heading");v=s(v,1);let y=require("@tiptap/extension-image");y=s(y,1);let b=require("@tiptap/pm/state"),x=require("@tiptap/pm/view");var ee=[{action:`bold`,label:`Ж`,title:`Жирный (⌘/Ctrl+B)`},{action:`italic`,label:`К`,title:`Курсив (⌘/Ctrl+I)`},{action:`underline`,label:`Ч`,title:`Подчёркнутый (⌘/Ctrl+U)`},{action:`strike`,label:`З`,title:`Зачёркнутый`},{action:`bullet`,label:`<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="7" cy="6" r="1.3"/><circle cx="7" cy="12" r="1.3"/><circle cx="7" cy="18" r="1.3"/><path d="M11 6h8M11 12h8M11 18h8"/></svg>`,title:`Маркированный список`},{action:`ordered`,label:`<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M10 6h10M10 12h10M10 18h10"/><path d="M4 4.8 5.2 4v4.2M3.8 8.2h2.8M3.8 10.8c.2-.5.6-.8 1.2-.8.8 0 1.2.4 1.2 1 0 .4-.3.8-.7 1.2l-1.6 1.5h2.5M3.8 16.2c.2-.5.6-.8 1.2-.8.8 0 1.2.4 1.2.9 0 .5-.4.8-1 .8.7 0 1.1.3 1.1.9 0 .6-.5 1-1.3 1-.6 0-1-.2-1.3-.7"/></svg>`,title:`Нумерованный список`},{action:`outdent`,label:`<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 6h14M5 12h10M5 18h14"/><path d="M9 9l-4 3 4 3"/></svg>`,title:`Уменьшить отступ`},{action:`indent`,label:`<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 6h14M9 12h10M5 18h14"/><path d="M15 9l4 3-4 3"/></svg>`,title:`Увеличить отступ`},{action:`link`,label:`<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M10 13.5a4.5 4.5 0 0 0 6.4 0l3-3a4.5 4.5 0 0 0-6.4-6.4l-1.7 1.7"/><path d="M14 10.5a4.5 4.5 0 0 0-6.4 0l-3 3A4.5 4.5 0 0 0 11 19.9l1.7-1.7"/></svg>`,title:`Добавить ссылку`},{action:`image`,label:`<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><rect x="3" y="4" width="18" height="16" rx="2"/><circle cx="8.5" cy="9" r="1.5"/><path d="m21 15-5-5L5 20"/></svg>`,title:`Вставить изображение`},{action:`table`,label:`<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><rect x="3" y="4" width="18" height="16" rx="1.5"/><path d="M3 10h18M9 4v16M15 4v16"/></svg>`,title:`Вставить таблицу`},{action:`label`,label:`Метка`,title:`Выделить текст меткой`},{action:`toc`,label:`Содержание`,title:`Содержание документа`},{action:`undo`,label:`↶`,title:`Отменить (⌘/Ctrl+Z)`},{action:`redo`,label:`↷`,title:`Повторить (⌘/Ctrl+Shift+Z)`}];function te(e,t,n={}){e.classList.add(`ophx-toolbar`),e.replaceChildren();let r=(e,t)=>{e.style.display=t?``:`none`,e.hidden=!t},i=()=>{f=!1,r(l,!1),o.setAttribute(`aria-expanded`,`false`),r(F,!1),h.get(`toc`)?.setAttribute(`aria-expanded`,`false`)},a=document.createElement(`div`);a.className=`ophx-toolbar__style-wrap`;let o=document.createElement(`button`);o.type=`button`,o.className=`ophx-toolbar__style`,o.setAttribute(`aria-label`,`Стиль текста`),o.setAttribute(`aria-haspopup`,`listbox`),o.setAttribute(`aria-expanded`,`false`);let s=document.createElement(`span`);s.className=`ophx-toolbar__style-label`,o.append(s);let l=document.createElement(`div`);l.className=`ophx-toolbar__style-menu`,r(l,!1);let u=[{value:`p`,label:`Обычный текст`,className:`ophx-toolbar__style-preview--p`},{value:`1`,label:`Заголовок 1`,className:`ophx-toolbar__style-preview--h1`},{value:`2`,label:`Заголовок 2`,className:`ophx-toolbar__style-preview--h2`},{value:`3`,label:`Заголовок 3`,className:`ophx-toolbar__style-preview--h3`}],d=e=>{let n=Number(e),r=t.chain().focus();e===`p`?r.setParagraph().run():r.setHeading({level:n}).run(),m()};for(let e of u){let t=document.createElement(`button`);t.type=`button`,t.className=`ophx-toolbar__style-option`,t.dataset.value=e.value,t.setAttribute(`role`,`option`),t.setAttribute(`aria-selected`,`false`),t.innerHTML=`<span class="ophx-toolbar__style-preview ${e.className}">${e.label}</span>`,t.addEventListener(`mousedown`,e=>{e.preventDefault(),e.stopPropagation()}),t.addEventListener(`click`,()=>d(e.value)),l.append(t)}let f=!1,p=()=>{f=!0,r(l,!0),o.setAttribute(`aria-expanded`,`true`)},m=()=>{f=!1,r(l,!1),o.setAttribute(`aria-expanded`,`false`)};o.addEventListener(`click`,e=>{e.stopPropagation(),f?m():(r(F,!1),p())}),o.addEventListener(`keydown`,e=>{e.key===`Escape`&&m()}),document.addEventListener(`click`,e=>{let t=e.target,n=a.contains(t),r=F.contains(t);!n&&!r&&i()}),a.append(o,l),e.append(a);let h=new Map;for(let n of ee){let r=document.createElement(`button`);r.type=`button`,r.className=`ophx-toolbar__button`,r.dataset.action=n.action,r.innerHTML=n.label,r.title=n.title,r.setAttribute(`aria-label`,n.title),r.addEventListener(`mousedown`,e=>e.preventDefault()),r.addEventListener(`click`,e=>{n.action===`toc`?e.stopPropagation():n.action===`link`?G():n.action===`table`?oe():n.action===`label`?(e.stopPropagation(),Te()):t.isEditable&&ae(n.action,t,_,F)}),h.set(n.action,r),e.append(r)}let g=document.createElement(`input`);g.type=`search`,g.className=`ophx-toolbar__search`,g.placeholder=`Поиск…`,g.setAttribute(`aria-label`,`Поиск по тексту`),g.addEventListener(`input`,()=>t.commands.setSearchQuery(g.value)),g.addEventListener(`keydown`,e=>{e.key===`Escape`&&(g.value=``,t.commands.setSearchQuery(``),t.commands.focus())}),e.append(g);let _=document.createElement(`input`);_.type=`file`,_.accept=`image/*`,_.hidden=!0,_.addEventListener(`change`,()=>{let e=_.files?.[0];if(e){if(n.onInsertImage)n.onInsertImage(e);else{let n=new FileReader;n.addEventListener(`load`,()=>{typeof n.result==`string`&&t.chain().focus().setImage({src:n.result,alt:e.name}).run()}),n.readAsDataURL(e)}}_.value=``}),e.append(_);let v=document.createElement(`form`);v.className=`ophx-table-popover`,v.setAttribute(`aria-label`,`Создать таблицу`),v.hidden=!0,v.innerHTML=`
2
+ <label class="ophx-table-popover__label">Строки<input name="rows" type="number" min="1" max="30" value="3" required></label>
3
+ <label class="ophx-table-popover__label">Столбцы<input name="cols" type="number" min="1" max="20" value="3" required></label>
4
+ <label class="ophx-table-popover__header"><input name="header" type="checkbox" checked> Заголовок таблицы</label>
5
+ <button class="ophx-table-popover__insert" type="submit">Вставить таблицу</button>
6
+ `,document.body.append(v);let y=h.get(`table`),b=v.querySelector(`input[name="rows"]`),x=v.querySelector(`input[name="cols"]`),te=v.querySelector(`input[name="header"]`),S=()=>{if(v.hidden)return;let e=y.getBoundingClientRect(),t=v.offsetWidth,n=Math.max(8,Math.min(e.left,window.innerWidth-t-8));v.style.left=`${n}px`,v.style.top=`${Math.min(e.bottom+8,window.innerHeight-v.offsetHeight-8)}px`};function C(){v.hidden=!0,y.setAttribute(`aria-expanded`,`false`),window.removeEventListener(`resize`,S),document.removeEventListener(`scroll`,S,!0)}function oe(){t.isEditable&&(v.hidden?(v.hidden=!1,y.setAttribute(`aria-expanded`,`true`),S(),window.addEventListener(`resize`,S),document.addEventListener(`scroll`,S,!0),b.focus(),b.select()):C())}y.setAttribute(`aria-haspopup`,`dialog`),y.setAttribute(`aria-expanded`,`false`),v.addEventListener(`mousedown`,e=>e.stopPropagation()),v.addEventListener(`submit`,e=>{e.preventDefault();let n=Math.max(1,Math.min(30,Number(b.value)||1)),r=Math.max(1,Math.min(20,Number(x.value)||1));b.value=String(n),x.value=String(r),t.chain().focus().insertTable({rows:n,cols:r,withHeaderRow:te.checked}).run(),C()}),v.addEventListener(`keydown`,e=>{e.key===`Escape`&&(e.preventDefault(),C(),y.focus())});let w=e=>{let t=e.target;!v.contains(t)&&!y.contains(t)&&C()};document.addEventListener(`click`,w);let T=document.createElement(`div`);T.className=`ophx-table-context`,T.setAttribute(`role`,`toolbar`),T.setAttribute(`aria-label`,`Действия с таблицей`),T.hidden=!0,T.innerHTML=`
7
+ <button type="button" data-command="addRow" aria-label="Добавить строку ниже" title="Добавить строку ниже"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 4h16v12H4zM4 10h16M10 4v12M12 20v-4M10 18h4"/></svg></button>
8
+ <button type="button" data-command="deleteRow" aria-label="Удалить строку" title="Удалить строку"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 4h16v12H4zM4 10h16M10 4v12M10 20h4"/></svg></button>
9
+ <span class="ophx-table-context__divider" aria-hidden="true"></span>
10
+ <button type="button" data-command="addColumn" aria-label="Добавить столбец справа" title="Добавить столбец справа"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 4h12v16H4zM10 4v16M20 12h-4M18 10v4"/></svg></button>
11
+ <button type="button" data-command="deleteColumn" aria-label="Удалить столбец" title="Удалить столбец"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 4h12v16H4zM10 4v16M18 10v4"/></svg></button>
12
+ `,document.body.append(T);let se=()=>{let{$from:e}=t.state.selection;for(let n=e.depth;n>0;--n){if(e.node(n).type.name!==`table`)continue;let r=t.view.nodeDOM(e.before(n));return r instanceof HTMLTableElement?r:r instanceof HTMLElement?r.querySelector(`table`):null}return null},E=()=>{if(T.hidden)return;let e=se();if(!e)return;let t=e.getBoundingClientRect(),n=T.offsetWidth,r=T.offsetHeight,i=Math.max(8,Math.min(t.left,window.innerWidth-n-8)),a=t.top-r-8>=8?t.top-r-8:Math.min(t.bottom+8,window.innerHeight-r-8);T.style.left=`${i}px`,T.style.top=`${Math.max(8,a)}px`},ce=()=>{!t.isEditable||!t.isActive(`table`)?(T.hidden=!0,window.removeEventListener(`resize`,E),document.removeEventListener(`scroll`,E,!0)):(T.hidden=!1,E(),window.addEventListener(`resize`,E),document.addEventListener(`scroll`,E,!0))};T.addEventListener(`mousedown`,e=>e.preventDefault()),T.addEventListener(`click`,e=>{let n=e.target.closest(`[data-command]`);if(!n)return;let r=n.dataset.command,i=t.chain().focus();r===`addRow`?i.addRowAfter().run():r===`deleteRow`?i.deleteRow().run():r===`addColumn`?i.addColumnAfter().run():r===`deleteColumn`&&i.deleteColumn().run()});let D=e=>{if(T.hidden)return;let t=e.target,n=se();!T.contains(t)&&!n?.contains(t)&&(T.hidden=!0)};document.addEventListener(`click`,D);let O=document.createElement(`div`);O.className=`ophx-image-popover`,O.setAttribute(`role`,`dialog`),O.setAttribute(`aria-label`,`Размер и обтекание изображения`),O.hidden=!0,O.innerHTML=`
13
+ <span class="ophx-image-popover__arrow" aria-hidden="true"></span>
14
+ <div class="ophx-image-popover__heading">Обтекание текстом</div>
15
+ <div class="ophx-image-popover__choices" role="group" aria-label="Обтекание текстом">
16
+ <button class="ophx-image-popover__choice" type="button" data-wrap="none" aria-label="Без обтекания" title="Без обтекания"><svg viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="4" width="8" height="7" rx="1"/><path d="M14 5h7M14 8h7M3 14h18M3 18h18"/></svg></button>
17
+ <button class="ophx-image-popover__choice" type="button" data-wrap="left" aria-label="Изображение слева, текст справа" title="Изображение слева, текст справа"><svg viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="4" width="8" height="10" rx="1"/><path d="M14 5h7M14 8h7M14 11h7M3 18h18"/></svg></button>
18
+ <button class="ophx-image-popover__choice" type="button" data-wrap="right" aria-label="Изображение справа, текст слева" title="Изображение справа, текст слева"><svg viewBox="0 0 24 24" aria-hidden="true"><rect x="13" y="4" width="8" height="10" rx="1"/><path d="M3 5h7M3 8h7M3 11h7M3 18h18"/></svg></button>
19
+ </div>
20
+ <div class="ophx-image-popover__heading">Выравнивание</div>
21
+ <div class="ophx-image-popover__choices" role="group" aria-label="Выравнивание изображения">
22
+ <button class="ophx-image-popover__choice" type="button" data-align="left" aria-label="Прижать влево" title="Прижать влево"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 3v18M8 6h12v5H8zM8 15h12"/></svg></button>
23
+ <button class="ophx-image-popover__choice" type="button" data-align="center" aria-label="По центру" title="По центру"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3v18M4 6h16v5H4zM4 15h16"/></svg></button>
24
+ <button class="ophx-image-popover__choice" type="button" data-align="right" aria-label="Прижать вправо" title="Прижать вправо"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20 3v18M4 6h12v5H4zM4 15h12"/></svg></button>
25
+ </div>
26
+ <div class="ophx-image-popover__size" aria-live="polite"></div>
27
+ `,document.body.append(O);let le=O.querySelector(`.ophx-image-popover__size`),k=null,A=()=>{if(!t.isActive(`image`))return null;let e=t.view.nodeDOM(t.state.selection.from);return e instanceof HTMLElement?e.querySelector(`img`):null},j=()=>{let e=A();if(O.hidden||!e)return;let t=e.getBoundingClientRect(),n=t.left+t.width/2,r=O.offsetWidth,i=O.offsetHeight,a=Math.max(8,Math.min(n-r/2,window.innerWidth-r-8)),o=t.bottom+i+12<=window.innerHeight-8;O.style.left=`${a}px`,O.style.top=`${o?t.bottom+10:Math.max(8,t.top-i-10)}px`,O.dataset.placement=o?`bottom`:`top`,O.style.setProperty(`--ophx-image-arrow-left`,`${Math.max(14,Math.min(n-a,r-14))}px`)};function M(){O.hidden=!0,window.removeEventListener(`resize`,j),document.removeEventListener(`scroll`,j,!0)}function ue(){if(!t.isEditable||!O.hidden)return;let e=A();e&&(k=t.state.selection.from,O.hidden=!1,de(),j(),e.complete||e.addEventListener(`load`,()=>{de(),j()},{once:!0}),window.addEventListener(`resize`,j),document.addEventListener(`scroll`,j,!0))}let N=e=>{k!==null&&t.chain().focus().setNodeSelection(k).updateAttributes(`image`,e).run()},de=()=>{if(O.hidden||!t.isActive(`image`))return;let e=t.getAttributes(`image`),n=A();n&&(le.textContent=`${Math.round(n.getBoundingClientRect().width)} px · потяните за боковой маркер, чтобы изменить размер`);for(let t of O.querySelectorAll(`[data-wrap]`)){let n=t.dataset.wrap===(e.textWrap??`none`);t.classList.toggle(`is-selected`,n),t.setAttribute(`aria-pressed`,String(n))}for(let t of O.querySelectorAll(`[data-align]`)){let n=t.dataset.align===(e.alignment??`left`);t.classList.toggle(`is-selected`,n),t.setAttribute(`aria-pressed`,String(n))}};O.addEventListener(`mousedown`,e=>e.stopPropagation()),O.addEventListener(`click`,e=>{let t=e.target.closest(`.ophx-image-popover__choice`);t&&((t.dataset.wrap===`none`||t.dataset.wrap===`left`||t.dataset.wrap===`right`)&&N({textWrap:t.dataset.wrap}),(t.dataset.align===`left`||t.dataset.align===`center`||t.dataset.align===`right`)&&N({alignment:t.dataset.align,textWrap:`none`}))}),O.addEventListener(`keydown`,e=>{e.key===`Escape`&&(e.preventDefault(),M())});let P=e=>{let n=e.target,r=e.target.closest?.(`.ophx-image-node`),i=!!(r&&t.view.dom.contains(r));!O.contains(n)&&!i&&M()};document.addEventListener(`click`,P);let F=document.createElement(`nav`);F.className=`ophx-toc`,F.setAttribute(`aria-label`,`Содержание документа`),r(F,!1),e.append(F);let I=h.get(`toc`);I&&(I.setAttribute(`aria-haspopup`,`true`),I.setAttribute(`aria-expanded`,`false`),I.addEventListener(`click`,()=>{F.hidden||F.style.display===`none`?(m(),r(F,!0),I.setAttribute(`aria-expanded`,`true`)):i()}));let L=document.createElement(`form`);L.className=`ophx-link-popover`,L.setAttribute(`role`,`dialog`),L.setAttribute(`aria-label`,`Добавить ссылку`),L.hidden=!0,L.innerHTML=`
28
+ <span class="ophx-link-popover__arrow" aria-hidden="true"></span>
29
+ <label class="ophx-link-popover__label" for="ophx-link-url">Адрес ссылки</label>
30
+ <div class="ophx-link-popover__row">
31
+ <input class="ophx-link-popover__input" id="ophx-link-url" type="url" placeholder="https://example.com" autocomplete="url">
32
+ </div>
33
+ <div class="ophx-link-popover__actions">
34
+ <button class="ophx-link-popover__go" type="button">Перейти</button>
35
+ <button class="ophx-link-popover__remove" type="button">Удалить ссылку</button>
36
+ <button class="ophx-link-popover__submit" type="submit">ОК</button>
37
+ </div>
38
+ `,document.body.append(L);let R=L.querySelector(`.ophx-link-popover__input`),z=L.querySelector(`.ophx-link-popover__go`),B=L.querySelector(`.ophx-link-popover__remove`),V=h.get(`link`),H=null,U=()=>{if(!L.hidden&&H)try{let e=t.view.coordsAtPos(H.from),n=t.view.coordsAtPos(H.to),r=(e.left+n.right)/2,i=L.offsetWidth,a=L.offsetHeight,o=Math.max(8,Math.min(r-i/2,window.innerWidth-i-8)),s=n.bottom+a+14<=window.innerHeight-8,c=s?n.bottom+12:Math.max(8,e.top-a-12);L.style.left=`${o}px`,L.style.top=`${c}px`,L.dataset.placement=s?`bottom`:`top`,L.style.setProperty(`--ophx-link-arrow-left`,`${Math.max(14,Math.min(r-o,i-14))}px`)}catch{W()}};function W(){L.hidden=!0,V.setAttribute(`aria-expanded`,`false`),window.removeEventListener(`resize`,U),document.removeEventListener(`scroll`,U,!0)}function G(e=!0){if(!t.isEditable)return;if(!L.hidden&&e){W();return}t.state.selection.empty&&t.isActive(`link`)&&t.chain().extendMarkRange(`link`).run();let n=t.state.selection;n.empty||(H={from:n.from,to:n.to},R.value=t.getAttributes(`link`).href??``,B.hidden=!t.isActive(`link`),z.hidden=!R.value,L.hidden=!1,V.setAttribute(`aria-expanded`,`true`),U(),window.addEventListener(`resize`,U),document.addEventListener(`scroll`,U,!0),R.focus(),R.select())}V.setAttribute(`aria-haspopup`,`dialog`),V.setAttribute(`aria-expanded`,`false`);let K=e=>{let n=e.target.closest(`a[href]`);n&&t.view.dom.contains(n)&&(n.title=`⌘/Ctrl+клик — открыть ссылку; клик — выделить для редактирования через кнопку «Ссылка»`)},fe=e=>{let n=e.target.closest(`a[href]`);if(!n||!t.view.dom.contains(n))return;if(e.preventDefault(),e.stopPropagation(),e.metaKey||e.ctrlKey){re(n.href);return}let r=t.view.posAtCoords({left:e.clientX,top:e.clientY});r&&(t.chain().focus().setTextSelection(r.pos).extendMarkRange(`link`).run(),G(!1))};t.view.dom.addEventListener(`pointerover`,K),t.view.dom.addEventListener(`click`,fe),L.addEventListener(`mousedown`,e=>e.stopPropagation()),L.addEventListener(`submit`,e=>{if(e.preventDefault(),!H)return;let n=R.value.trim();n?(t.chain().focus().setTextSelection(H).setLink({href:n}).run(),W()):R.focus()}),z.addEventListener(`click`,()=>re(R.value)),R.addEventListener(`input`,()=>{z.hidden=!R.value.trim()}),B.addEventListener(`click`,()=>{H&&(t.chain().focus().setTextSelection(H).extendMarkRange(`link`).unsetLink().run(),W())}),L.addEventListener(`keydown`,e=>{e.key===`Escape`&&(e.preventDefault(),W(),V.focus())});let pe=e=>{let t=e.target;!L.contains(t)&&!V.contains(t)&&W()};document.addEventListener(`click`,pe);let me=[`важно`,`идея`],q=document.createElement(`form`);q.className=`ophx-link-popover ophx-label-popover`,q.setAttribute(`role`,`dialog`),q.hidden=!0,q.innerHTML=`
39
+ <span class="ophx-link-popover__arrow" aria-hidden="true"></span>
40
+ <div class="ophx-label-popover__view">
41
+ <span class="ophx-link-popover__label">Метка</span>
42
+ <div class="ophx-label-popover__name"><mark class="ophx-label-popover__chip"></mark></div>
43
+ <div class="ophx-link-popover__actions ophx-label-popover__view-actions">
44
+ <button class="ophx-link-popover__remove" type="button" data-label-remove>Удалить метку</button>
45
+ <button class="ophx-link-popover__submit" type="button" data-label-edit>Изменить</button>
46
+ </div>
47
+ </div>
48
+ <div class="ophx-label-popover__edit">
49
+ <label class="ophx-link-popover__label" for="ophx-label-name">Название метки</label>
50
+ <div class="ophx-link-popover__row">
51
+ <input class="ophx-link-popover__input" id="ophx-label-name" type="text" placeholder="Например, важно" autocomplete="off" maxlength="60">
52
+ </div>
53
+ <div class="ophx-label-popover__presets" role="group" aria-label="Быстрый выбор метки"></div>
54
+ <div class="ophx-link-popover__actions">
55
+ <button class="ophx-link-popover__remove" type="button" data-label-remove>Удалить метку</button>
56
+ <button class="ophx-link-popover__submit" type="submit">ОК</button>
57
+ </div>
58
+ </div>
59
+ `,document.body.append(q);let J=q.querySelector(`#ophx-label-name`),he=q.querySelector(`.ophx-label-popover__chip`),ge=q.querySelector(`.ophx-label-popover__presets`),_e=q.querySelector(`[data-label-edit]`),ve=q.querySelectorAll(`[data-label-remove]`),ye=q.querySelector(`.ophx-label-popover__view-actions`),Y=h.get(`label`),X=null,be=`edit`,xe=!1,Z=()=>{!q.hidden&&X&&(ne(t,q,X)||Q())};function Q(){q.hidden=!0,Y.setAttribute(`aria-expanded`,`false`),window.removeEventListener(`resize`,Z),document.removeEventListener(`scroll`,Z,!0)}function Se(){let e=new Set(me);return t.state.doc.descendants(t=>{for(let n of t.marks)n.type.name===`label`&&n.attrs.label&&e.add(String(n.attrs.label))}),[...e]}function Ce(e){ge.replaceChildren();for(let t of Se()){let n=document.createElement(`button`);n.type=`button`,n.className=`ophx-label-popover__preset`,n.classList.toggle(`is-selected`,t===e);let r=document.createElement(`mark`);r.dataset.label=t,r.textContent=t,n.append(r),n.addEventListener(`click`,()=>Ee(t)),ge.append(n)}}function we(e,n,r){X=e,be=r,q.dataset.mode=r,q.setAttribute(`aria-label`,r===`view`?`Метка «${n}»`:`Установить метку`),he.textContent=n,he.dataset.label=n,ye.hidden=!t.isEditable,ve.forEach(e=>{e.hidden=!xe}),J.value=n,Ce(n),q.hidden=!1,Y.setAttribute(`aria-expanded`,String(r===`edit`)),Z(),window.addEventListener(`resize`,Z),document.addEventListener(`scroll`,Z,!0),r===`edit`&&(J.focus(),J.select())}function Te(){if(!t.isEditable)return;if(!q.hidden&&be===`edit`){Q();return}t.state.selection.empty&&t.isActive(`label`)&&t.chain().extendMarkRange(`label`).run();let{from:e,to:n,empty:r}=t.state.selection;if(r)return;xe=t.isActive(`label`);let i=xe?String(t.getAttributes(`label`).label??``):``;we({from:e,to:n},i,`edit`)}function Ee(e){let n=e.trim();X&&(n?(t.chain().focus().setTextSelection(X).setMark(`label`,{label:n}).run(),Q()):J.focus())}Y.setAttribute(`aria-haspopup`,`dialog`),Y.setAttribute(`aria-expanded`,`false`);let De=e=>{let n=e.target,r=n.closest(`mark`);if(!r||!t.view.dom.contains(r)||n.closest(`a[href]`))return null;let i=t.view.posAtCoords({left:e.clientX,top:e.clientY}),a=t.schema.marks.label;if(!i||!a)return null;let o=t.state.doc.resolve(i.pos),s=(0,c.getMarkRange)(o,a)??(i.pos>0?(0,c.getMarkRange)(t.state.doc.resolve(i.pos-1),a):void 0);if(!s)return null;let l=r.dataset.label??``;return t.state.doc.nodesBetween(s.from,s.to,e=>{let t=e.marks.find(e=>e.type===a);t&&(l=String(t.attrs.label??l))}),{range:s,name:l}},Oe=e=>{let n=e.target.closest(`mark[data-label]`);n&&t.view.dom.contains(n)&&(n.title=`Метка: ${n.dataset.label}`)},ke=e=>{if(e.metaKey||e.ctrlKey||e.shiftKey)return;let n=De(e);n&&(t.state.selection.empty||!t.isEditable)&&(e.stopPropagation(),xe=!0,we(n.range,n.name,`view`))};t.view.dom.addEventListener(`pointerover`,Oe),t.view.dom.addEventListener(`click`,ke),q.addEventListener(`mousedown`,e=>e.stopPropagation()),q.addEventListener(`submit`,e=>{e.preventDefault(),Ee(J.value)}),_e.addEventListener(`click`,()=>{X&&t.isEditable&&we(X,he.textContent??``,`edit`)}),ve.forEach(e=>e.addEventListener(`click`,()=>{X&&(t.chain().focus().setTextSelection(X).unsetMark(`label`).run(),Q())})),q.addEventListener(`keydown`,e=>{e.key===`Escape`&&(e.preventDefault(),Q(),t.commands.focus())});let Ae=e=>{let t=e.target;!q.contains(t)&&!Y.contains(t)&&Q()};document.addEventListener(`click`,Ae);let $=()=>{let e=t.isEditable;o.disabled=!e;for(let[t,n]of h)t!==`toc`&&(n.disabled=!e);h.get(`undo`).disabled=!e||!t.can().undo(),h.get(`redo`).disabled=!e||!t.can().redo(),ce(),!e||!t.isActive(`image`)?M():O.hidden?ue():(de(),j()),h.get(`bold`).classList.toggle(`is-active`,t.isActive(`bold`)),h.get(`italic`).classList.toggle(`is-active`,t.isActive(`italic`)),h.get(`underline`).classList.toggle(`is-active`,t.isActive(`underline`)),h.get(`strike`).classList.toggle(`is-active`,t.isActive(`strike`)),h.get(`label`).classList.toggle(`is-active`,t.isActive(`label`)),e||W(),!e&&be===`edit`?Q():q.hidden||Z();let n=t.getAttributes(`heading`).level,r=n?String(n):(t.isActive(`paragraph`),`p`),i=n?`Заголовок ${n}`:`Обычный текст`;s.textContent=i;for(let e of l.querySelectorAll(`.ophx-toolbar__style-option`)){let t=e.dataset.value===r;e.setAttribute(`aria-selected`,String(t)),e.classList.toggle(`is-selected`,t)}F.replaceChildren(),t.state.doc.descendants((e,n)=>{if(e.type.name!==`heading`)return;let r=document.createElement(`button`);r.type=`button`,r.className=`ophx-toc__item`,r.style.paddingInlineStart=`${Math.max(0,Number(e.attrs.level)-1)*12}px`,r.textContent=e.textContent||`Без названия`,r.addEventListener(`mousedown`,e=>e.preventDefault()),r.addEventListener(`click`,()=>{t.commands.setTextSelection(n+1),t.commands.focus(),t.commands.scrollIntoView()}),F.append(r)})},je=({transaction:e})=>{if($(),!e.docChanged)return;let n=ie(e.before,e.doc);n!==null&&t.commands.setNodeSelection(n)},Me=()=>$();return t.on(`transaction`,je),t.on(`selectionUpdate`,Me),t.view.dom.addEventListener(`ophx:editablechange`,$),$(),()=>{t.off(`transaction`,je),t.off(`selectionUpdate`,Me),t.view.dom.removeEventListener(`ophx:editablechange`,$),document.removeEventListener(`click`,w),C(),v.remove(),document.removeEventListener(`click`,D),window.removeEventListener(`resize`,E),document.removeEventListener(`scroll`,E,!0),T.remove(),document.removeEventListener(`click`,P),M(),O.remove(),t.view.dom.removeEventListener(`pointerover`,K),t.view.dom.removeEventListener(`click`,fe),document.removeEventListener(`click`,pe),W(),L.remove(),t.view.dom.removeEventListener(`pointerover`,Oe),t.view.dom.removeEventListener(`click`,ke),document.removeEventListener(`click`,Ae),Q(),q.remove(),e.replaceChildren(),e.classList.remove(`ophx-toolbar`)}}function ne(e,t,n){try{let r=e.view.coordsAtPos(n.from),i=e.view.coordsAtPos(n.to),a=(r.left+i.right)/2,o=t.offsetWidth,s=t.offsetHeight,c=Math.max(8,Math.min(a-o/2,window.innerWidth-o-8)),l=i.bottom+s+14<=window.innerHeight-8,u=l?i.bottom+12:Math.max(8,r.top-s-12);return t.style.left=`${c}px`,t.style.top=`${u}px`,t.dataset.placement=l?`bottom`:`top`,t.style.setProperty(`--ophx-link-arrow-left`,`${Math.max(14,Math.min(a-c,o-14))}px`),!0}catch{return!1}}function re(e){try{let t=new URL(e.trim(),window.location.href);[`http:`,`https:`,`mailto:`].includes(t.protocol)&&window.open(t.href,`_blank`,`noopener,noreferrer`)}catch{}}function ie(e,t){let n=new Map;e.descendants(e=>{if(e.type.name!==`image`)return;let t=String(e.attrs.src??``);n.set(t,(n.get(t)??0)+1)});let r=null;return t.descendants((e,t)=>{if(e.type.name!==`image`||r!==null)return;let i=String(e.attrs.src??``),a=n.get(i)??0;a>0?n.set(i,a-1):r=t}),r}function ae(e,t,n,r){let i=t.chain().focus();switch(e){case`bold`:i.toggleBold().run();break;case`italic`:i.toggleItalic().run();break;case`underline`:i.toggleUnderline().run();break;case`strike`:i.toggleStrike().run();break;case`bullet`:i.toggleBulletList().run();break;case`ordered`:i.toggleOrderedList().run();break;case`indent`:S(t,1);break;case`outdent`:S(t,-1);break;case`image`:n.click();break;case`toc`:r.hidden=!r.hidden;break;case`undo`:i.undo().run();break;case`redo`:i.redo().run()}}function S(e,t){let{$from:n}=e.state.selection;if(n.parent.type.name===`listItem`){let n=e.chain().focus();t>0?n.sinkListItem(`listItem`).run():n.liftListItem(`listItem`).run();return}let r=n.parent.type.name;if(r!==`paragraph`&&r!==`heading`)return;let i=Number(e.getAttributes(r).indent??0);e.chain().focus().updateAttributes(r,{indent:Math.max(0,Math.min(8,i+t))}).run()}var C={avif:`image/avif`,bmp:`image/bmp`,gif:`image/gif`,ico:`image/x-icon`,jpeg:`image/jpeg`,jpg:`image/jpeg`,png:`image/png`,svg:`image/svg+xml`,tif:`image/tiff`,tiff:`image/tiff`,webp:`image/webp`};async function oe(e,t={}){let n=new _.default,r=new DOMParser().parseFromString(e,`text/html`);E(r);let i=ce(t.filename??t.title??`Документ`),a=t.title??r.title??i,o=t.assets??{},s=new Set(Object.keys(o).map(O)),c=0;for(let e of Array.from(r.querySelectorAll(`img[src]`))){let t=e.getAttribute(`src`)?.trim();if(!t||/^https?:\/\//i.test(t)||/^data:(?!image\/)/i.test(t))continue;if(/^data:image\//i.test(t)||/^blob:/i.test(t)){try{let r=await fetch(t);if(!r.ok)throw Error(`Не удалось прочитать изображение: ${t}`);let i=await r.blob();if(!i.type.startsWith(`image/`))throw Error(`Вложение с data/blob URL не является изображением`);let a=`image-${++c}.${A(i.type,t)}`;for(;s.has(a);)a=`image-${++c}.${A(i.type,t)}`;n.file(a,i),s.add(a),e.setAttribute(`src`,encodeURIComponent(a))}catch(e){throw Error(`Не удалось добавить изображение в архив ophx`,{cause:e})}continue}let r=O(t);if(!D(r))throw Error(`Путь изображения должен быть простым именем файла: ${t}`);let i=o[r];if(!i&&!s.has(r))throw Error(`Для локального изображения «${r}» не передан файл media`);i&&n.file(r,i),e.setAttribute(`src`,encodeURIComponent(r))}let l=se(t.styles??{});for(let[e,t]of Object.entries(l))n.file(e,t);let u=Object.keys(l).map(e=>`<link rel="stylesheet" href="${M(encodeURIComponent(e))}">`).join(``),d=r.documentElement.lang||`ru`,f=t.bodyContentEditable?` contenteditable="${t.bodyContentEditable}"`:``,p=`<!doctype html>\n<html lang="${M(d)}"><head><meta charset="utf-8"><title>${M(a)}</title>${u}</head><body${f}>${r.body.innerHTML}</body></html>`;return n.file(`${i}.html`,p),n.generateAsync({type:`blob`,mimeType:`application/zip`,compression:`DEFLATE`,compressionOptions:{level:6}})}async function w(e){await k(e);let t;try{t=await _.default.loadAsync(e)}catch(e){throw Error(`Не удалось прочитать ZIP-архив .ophx (шифрование и неподдерживаемые ZIP-режимы не поддерживаются)`,{cause:e})}if(Object.values(t.files).some(e=>e.dir||/[\\/]/.test(e.name)))throw Error(`В текущей версии .ophx все файлы должны находиться плоским списком в корне архива`);let n=Object.values(t.files).filter(e=>!e.dir),r=n.filter(e=>e.name.toLowerCase().endsWith(`.html`));if(r.length!==1)throw r.length===0&&n.some(e=>e.name.toLowerCase().endsWith(`.xml`))?Error(`Обнаружен устаревший XML-вариант ophx; поддерживается только версия v2 с HTML5 внутри ZIP`):Error(`В архиве должен быть ровно один HTML-файл в корне; найдено: ${r.length}`);let i=r[0],a=i.name.slice(0,-5),o=`name`in e&&typeof e.name==`string`?e.name:``;if(/\.ophx$/i.test(o)&&o.replace(/\.ophx$/i,``)!==a)throw Error(`Имя HTML-файла «${i.name}» должно совпадать с именем архива «${o}»`);let s=await i.async(`string`);if(!/^\s*<!doctype\s+html\b/i.test(s))throw Error(`Основной файл .ophx должен начинаться с <!doctype html>`);let c=new DOMParser().parseFromString(s,`text/html`);if(c.querySelector(`head meta[charset]`)?.getAttribute(`charset`)?.toLowerCase()!==`utf-8`)throw Error(`В <head> документа требуется <meta charset="utf-8">`);let l={};for(let e of Array.from(c.querySelectorAll(`head link[rel~="stylesheet"][href]`))){let n=e.getAttribute(`href`)?.trim();if(!n)continue;if(le(n))throw Error(`CSS должен быть встроенным плоским файлом архива: ${n}`);let r=O(n);if(!D(r)||!r.toLowerCase().endsWith(`.css`))throw Error(`Ссылка на стиль должна указывать на плоский .css-файл: ${n}`);let i=t.file(r);if(!i)throw Error(`Файл стиля «${r}» отсутствует в архиве`);l[r]=await i.async(`string`)}for(let e of Array.from(c.querySelectorAll(`img[src]`))){let n=e.getAttribute(`src`)?.trim();if(!n||le(n))continue;let r=O(n);if(!D(r))throw Error(`Ссылка на изображение должна быть простым именем файла: ${n}`);let i=t.file(r);if(!i)throw Error(`Файл изображения «${r}» отсутствует в архиве`);let a=await i.async(`base64`),o=r.split(`.`).pop()?.toLowerCase()??``,s=C[o]??(o?`image/${o}`:`application/octet-stream`);e.setAttribute(`src`,`data:${s};base64,${a}`)}let u=c.body.getAttribute(`contenteditable`);if(u===`false`)for(let e of Array.from(c.body.children))e.hasAttribute(`contenteditable`)||e.setAttribute(`contenteditable`,`false`);j(c);let d=Object.entries(l);return{html:c.body.innerHTML,title:c.title||a,filename:a,styles:l,css:d[0]?.[1]??``,bodyContentEditable:u===`true`||u===`false`?u:void 0}}function T(e,t){let n=URL.createObjectURL(e),r=window.document.createElement(`a`);r.href=n,r.download=t,r.click(),window.setTimeout(()=>URL.revokeObjectURL(n),0)}function se(e){let t={};for(let[n,r]of Object.entries(e)){let e=O(n);if(!D(e)||!e.toLowerCase().endsWith(`.css`))throw Error(`Имя файла стиля должно быть плоским и оканчиваться на .css: ${n}`);if(Object.hasOwn(t,e))throw Error(`Повторяется имя файла стиля: ${e}`);t[e]=r}return t}function E(e){let t=Array.from(e.querySelectorAll(`[data-ophx-field], .ophx-field`)),n=new Set;for(let e of t){let t=e.getAttribute(`data-ophx-field`)??``,r=e.tagName.toLowerCase();if(!e.classList.contains(`ophx-field`)||e.getAttribute(`contenteditable`)!==`true`)throw Error(`Каждое поле должно иметь класс ophx-field и contenteditable="true"`);if(![`span`,`div`,`p`].includes(r)||!/^[A-Za-z0-9._-]+$/.test(t))throw Error(`Некорректная обёртка или идентификатор поля: ${t||`(пусто)`}`);if(n.has(t))throw Error(`Идентификатор поля должен быть уникальным: ${t}`);if(e.parentElement?.closest(`[data-ophx-field]`))throw Error(`Поля не могут быть вложенными: ${t}`);n.add(t)}}function ce(e){let t=e.trim().replace(/\.(?:ophx|html)$/i,``);if(!t)return`Документ`;if(!D(t)||/[\u0000-\u001f]/.test(t))throw Error(`Имя .ophx должно быть простым именем файла без каталогов`);return t}function D(e){return!!e&&e!==`.`&&e!==`..`&&!/[\\/]/.test(e)}function O(e){try{return decodeURIComponent(e)}catch{throw Error(`Некорректное percent-экранирование в имени ресурса: ${e}`)}}function le(e){return/^(?:data:|https?:\/\/)/i.test(e)}async function k(e){if(e.size<2)throw Error(`Файл не является ZIP-архивом .ophx (возможен устаревший формат)`);let t=new Uint8Array(await e.slice(0,4).arrayBuffer());if(t[0]!==80||t[1]!==75)throw Error(`Неподдерживаемый устаревший ophx: ожидается ZIP-архив версии v2`)}function A(e,t){let n=Object.entries(C).find(([,t])=>t===e)?.[0];if(n)return n;let r=t.match(/\.([a-z0-9]+)(?:[?#]|$)/i)?.[1]?.toLowerCase();return r&&/^[a-z0-9]{1,6}$/.test(r)?r:`bin`}function j(e){e.querySelectorAll(`script, iframe, object, embed, style, link`).forEach(e=>e.remove()),e.querySelectorAll(`*`).forEach(e=>{for(let t of Array.from(e.attributes))/^on/i.test(t.name)&&e.removeAttribute(t.name),/^(href|src|xlink:href)$/i.test(t.name)&&/^\s*(javascript|vbscript):/i.test(t.value)&&e.removeAttribute(t.name),/^(src|xlink:href)$/i.test(t.name)&&/^\s*data:(?!image\/)/i.test(t.value)&&e.removeAttribute(t.name)})}function M(e){return e.replace(/[&<>"']/g,e=>({"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`})[e])}var ue=c.Mark.create({name:`label`,inclusive:!1,addAttributes(){return{label:{default:`highlight`,parseHTML:e=>e.dataset.label??`highlight`,renderHTML:e=>({"data-label":e.label})}}},parseHTML(){return[{tag:`mark[data-label]`},{tag:`mark`}]},renderHTML({HTMLAttributes:e}){return[`mark`,e,0]}});function N(){return{fieldId:{default:``,parseHTML:e=>e.getAttribute(`data-ophx-field`)??``,renderHTML:e=>({"data-ophx-field":e.fieldId??``})},fieldLabel:{default:null,parseHTML:e=>e.getAttribute(`data-ophx-label`),renderHTML:e=>e.fieldLabel?{"data-ophx-label":e.fieldLabel}:{}},required:{default:!1,parseHTML:e=>e.getAttribute(`data-ophx-required`)===`true`,renderHTML:e=>e.required?{"data-ophx-required":`true`}:{}}}}var de=/^[A-Za-z0-9._-]+$/,P=50,F=1200;function I(e){if(!e||!/^\d+$/.test(e))return null;let t=Number(e);return Number.isInteger(t)&&t>=P&&t<=F?t:null}var L=y.default.extend({addAttributes(){return{...this.parent?.(),width:{default:null,parseHTML:e=>I(e.getAttribute(`width`)),renderHTML:e=>{let t=e.width;return Number.isInteger(t)&&Number(t)>=P&&Number(t)<=F?{width:String(t)}:{}}},textWrap:{default:`none`,parseHTML:e=>{let t=e.getAttribute(`data-ophx-wrap`);return t===`left`||t===`right`?t:`none`},renderHTML:e=>({"data-ophx-wrap":e.textWrap===`left`||e.textWrap===`right`?e.textWrap:`none`})},alignment:{default:`left`,parseHTML:e=>{let t=e.getAttribute(`data-ophx-align`);return t===`center`||t===`right`?t:`left`},renderHTML:e=>({"data-ophx-align":e.alignment===`center`||e.alignment===`right`?e.alignment:`left`})}}},addNodeView(){return({node:e,getPos:t,editor:n})=>{let r=e,i=0,a=0,o=0,s=document.createElement(`div`);s.className=`ophx-image-node`,s.contentEditable=`false`;let c=document.createElement(`img`),l=document.createElement(`button`);l.type=`button`,l.className=`ophx-image-node__resize-handle`,l.setAttribute(`role`,`slider`),l.setAttribute(`aria-label`,`Изменить размер изображения перетаскиванием`),l.setAttribute(`aria-valuemin`,String(P)),l.setAttribute(`aria-valuemax`,String(F)),l.title=`Потяните влево или вправо, чтобы изменить размер`,l.innerHTML=`<svg viewBox="0 0 12 28" aria-hidden="true"><path d="M4 3v22M8 3v22"/></svg>`,s.append(c,l);let u=()=>{let e=String(r.attrs.src??``);c.getAttribute(`src`)!==e&&c.setAttribute(`src`,e),c.alt=r.attrs.alt??``,r.attrs.title?c.title=r.attrs.title:c.removeAttribute(`title`),r.attrs.width?c.width=Number(r.attrs.width):c.removeAttribute(`width`);let t=Number(r.attrs.width)||Math.round(c.getBoundingClientRect().width);l.setAttribute(`aria-valuenow`,String(t)),l.setAttribute(`aria-valuetext`,`${t} пикселей`),s.dataset.ophxWrap=r.attrs.textWrap??`none`,s.dataset.ophxAlign=r.attrs.alignment??`left`},d=e=>{if(!n.isEditable)return;let r=typeof t==`function`?t():void 0;if(typeof r!=`number`)return;let i=n.state.doc.nodeAt(r);if(!i||i.type.name!==`image`)return;let a=getComputedStyle(n.view.dom),o=Number.parseFloat(a.paddingLeft)+Number.parseFloat(a.paddingRight),s=Math.max(P,n.view.dom.clientWidth-o),c=Math.min(e,F,Math.floor(s));n.view.dispatch(n.state.tr.setNodeMarkup(r,void 0,{...i.attrs,width:c}))},f=e=>{if(!l.hasPointerCapture(e.pointerId))return;let t=Math.max(50,Math.round((a+e.clientX-i)/5)*5);t!==o&&(o=t,d(t))},p=e=>{l.hasPointerCapture(e.pointerId)&&l.releasePointerCapture(e.pointerId)};return l.addEventListener(`pointerdown`,e=>{n.isEditable&&(e.preventDefault(),e.stopPropagation(),i=e.clientX,a=c.getBoundingClientRect().width,o=Math.round(a),l.setPointerCapture(e.pointerId))}),l.addEventListener(`pointermove`,f),l.addEventListener(`pointerup`,p),l.addEventListener(`pointercancel`,p),l.addEventListener(`keydown`,e=>{if(!n.isEditable||e.key!==`ArrowLeft`&&e.key!==`ArrowRight`)return;e.preventDefault();let t=Number(r.attrs.width)||Math.round(c.getBoundingClientRect().width),i=e.key===`ArrowRight`?10:-10;d(Math.max(P,t+i))}),c.addEventListener(`load`,()=>{if(r.attrs.width)return;let e=Math.round(c.getBoundingClientRect().width);l.setAttribute(`aria-valuenow`,String(e)),l.setAttribute(`aria-valuetext`,`${e} пикселей`)}),u(),{dom:s,update(e){return e.type===r.type&&(r=e,u(),!0)},stopEvent(e){return l.contains(e.target)},ignoreMutation(){return!0}}}}}),R=c.Node.create({name:`ophxInlineField`,priority:1e3,group:`inline`,inline:!0,content:`text*`,defining:!0,addAttributes:N,parseHTML(){return[{tag:`span.ophx-field[contenteditable="true"][data-ophx-field]`,priority:1e3}]},renderHTML({HTMLAttributes:e}){return[`span`,{...e,class:`ophx-field`,contenteditable:`true`},0]}}),z=c.Node.create({name:`ophxBlockField`,priority:1e3,group:`block`,content:`text*`,defining:!0,addAttributes(){return{...N(),tagName:{default:`div`,parseHTML:e=>e.tagName.toLowerCase(),renderHTML:()=>({})}}},parseHTML(){return[{tag:`p.ophx-field[contenteditable="true"][data-ophx-field]`,priority:1e3},{tag:`div.ophx-field[contenteditable="true"][data-ophx-field]`,priority:1e3}]},renderHTML({node:e,HTMLAttributes:t}){return[e.attrs.tagName===`p`?`p`:`div`,{...t,class:`ophx-field`,contenteditable:`true`},0]}}),B=c.Mark.create({name:`ophxReadonlyInline`,inclusive:!1,addAttributes(){return{className:{default:null,parseHTML:e=>e.getAttribute(`class`),renderHTML:e=>e.className?{class:e.className}:{}}}},parseHTML(){return[{tag:`span[contenteditable="false"]`,priority:100}]},renderHTML({HTMLAttributes:e}){return[`span`,{...e,contenteditable:`false`},0]}}),V=c.Node.create({name:`ophxReadonlyBlock`,priority:1e3,group:`block`,content:`block*`,defining:!0,isolating:!0,addAttributes(){return{id:{default:null,parseHTML:e=>e.getAttribute(`id`),renderHTML:e=>e.id?{id:e.id}:{}},className:{default:null,parseHTML:e=>e.getAttribute(`class`),renderHTML:e=>e.className?{class:e.className}:{}},title:{default:null,parseHTML:e=>e.getAttribute(`title`),renderHTML:e=>e.title?{title:e.title}:{}}}},parseHTML(){return[{tag:`div[contenteditable="false"]`,priority:1e3}]},renderHTML({HTMLAttributes:e}){return[`div`,{...e,contenteditable:`false`},0]}}),H=new b.PluginKey(`ophxHeadingCollapse`),U=v.default.extend({addAttributes(){return{...this.parent?.(),collapsed:{default:!1,parseHTML:e=>e.dataset.collapsed===`true`,renderHTML:e=>e.collapsed?{"data-collapsed":`true`}:{}}}},addNodeView(){return({node:e,getPos:t,editor:n})=>{let r=e,i=document.createElement(`h${e.attrs.level}`);i.className=`ophx-heading`;let a=document.createElement(`button`);a.type=`button`,a.className=`ophx-heading__toggle`,a.innerHTML=`<svg viewBox="0 0 16 16" aria-hidden="true"><path d="m5.5 3.5 4.5 4.5-4.5 4.5"/></svg>`;let o=document.createElement(`span`);o.className=`ophx-heading__content`,i.append(o,a);let s=()=>{let e=!!r.attrs.collapsed;a.setAttribute(`aria-expanded`,String(!e)),a.setAttribute(`aria-label`,e?`Развернуть раздел`:`Свернуть раздел`),a.title=e?`Развернуть раздел`:`Свернуть раздел`,i.dataset.collapsed=String(e)};return a.addEventListener(`mousedown`,e=>e.preventDefault()),a.addEventListener(`click`,e=>{if(e.preventDefault(),e.stopPropagation(),!n.isEditable)return;let r=typeof t==`function`?t():void 0;if(typeof r!=`number`)return;let i=n.state.doc.nodeAt(r);i&&i.type.name===`heading`&&n.view.dispatch(n.state.tr.setNodeMarkup(r,void 0,{...i.attrs,collapsed:!i.attrs.collapsed}))}),s(),{dom:i,contentDOM:o,update(e){return e.type!==r.type||e.attrs.level!==r.attrs.level?!1:(r=e,s(),!0)},stopEvent(e){return a.contains(e.target)}}}},addProseMirrorPlugins(){return[new b.Plugin({key:H,props:{decorations(e){let t=[],n=null;return e.doc.forEach((e,r)=>{if(e.type.name===`heading`){let i=Number(e.attrs.level);n!==null&&i<=n&&(n=null),n!==null&&t.push(x.Decoration.node(r,r+e.nodeSize,{class:`ophx-collapsed-content`})),e.attrs.collapsed&&(n=i)}else n!==null&&t.push(x.Decoration.node(r,r+e.nodeSize,{class:`ophx-collapsed-content`}))}),x.DecorationSet.create(e.doc,t)}}})]}}),W=new b.PluginKey(`ophxTextSearch`),G=c.Extension.create({name:`ophxSearch`,addStorage(){return{query:``}},addCommands(){return{setSearchQuery:e=>({tr:t,dispatch:n})=>(this.storage.query=e,n?.(t.setMeta(W,e)),!0)}},addProseMirrorPlugins(){let e=this;return[new b.Plugin({key:W,state:{init:(t,n)=>K(n.doc,e.storage.query),apply:(t,n,r,i)=>{let a=t.getMeta(W);return a!==void 0&&(e.storage.query=a),!t.docChanged&&a===void 0?n:K(i.doc,e.storage.query)}},props:{decorations(e){return W.getState(e)}}})]}});function K(e,t){if(!t.trim())return x.DecorationSet.empty;let n=[],r=t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),i=new RegExp(r,`gi`);return e.descendants((e,t)=>{if(e.isText&&e.text){i.lastIndex=0;for(let r of e.text.matchAll(i))r.index!==void 0&&n.push(x.Decoration.inline(t+r.index,t+r.index+r[0].length,{class:`ophx-search-match`}))}}),x.DecorationSet.create(e,n)}var fe=c.Extension.create({name:`ophxWysiwymRules`,addProseMirrorPlugins(){return[new b.Plugin({props:{handleTextInput(e,t,n,r){return r===` `&&/\s/.test(e.state.doc.textBetween(Math.max(0,t-1),t))},handleKeyDown(e,t){if(t.key!==`Enter`||t.shiftKey)return!1;let{$from:n}=e.state.selection;if(!n.parent.isTextblock||n.parent.content.size!==0||n.depth===0)return!1;let r=n.index(n.depth-1),i=n.node(n.depth-1);return[i.maybeChild(r-1),i.maybeChild(r+1)].some(e=>e?.isTextblock&&e.content.size===0)}}})]}}),pe=c.Extension.create({name:`ophxIndentation`,addGlobalAttributes(){return[{types:[`paragraph`,`heading`],attributes:{indent:{default:0,parseHTML:e=>Number(e.dataset.indent??0),renderHTML:e=>e.indent?{"data-indent":String(e.indent)}:{}}}}]}}),me=c.Extension.create({name:`ophxEditability`,addGlobalAttributes(){return[{types:[`paragraph`,`heading`,`blockquote`,`codeBlock`,`bulletList`,`orderedList`,`listItem`,`horizontalRule`,`image`,`table`,`tableRow`,`tableHeader`,`tableCell`,`bold`,`italic`,`underline`,`strike`,`link`,`label`],attributes:{contenteditable:{default:null,parseHTML:e=>{let t=e.getAttribute(`contenteditable`);return t===`true`||t===`false`?t:null},renderHTML:e=>e.contenteditable?{contenteditable:e.contenteditable}:{}}}}]}});function q(e){return de.test(e)}function J(e,t){if(typeof e!=`string`)return e;let n=document.querySelector(e);if(!n)throw Error(`OphxEditor: элемент для опции "${t}" не найден по селектору "${e}"`);return n}var he=`ophx-editor-editable`,ge=class{editor;archiveDefaults=null;editableStorageKey;unmountToolbar=null;constructor(e){this.editableStorageKey=e.editableStorageKey===void 0?he:e.editableStorageKey,this.editor=new c.Editor({element:J(e.element,`element`),content:e.content??`<p></p>`,editable:this.readStoredEditable()??e.editable??!0,extensions:[l.default.configure({heading:!1,underline:!1,link:!1}),U.configure({levels:[1,2,3,4,5,6]}),u.default,d.default.configure({openOnClick:!1,autolink:!0,linkOnPaste:!0}),L.configure({allowBase64:!0,inline:!1}),p.Table.configure({resizable:!0}),m.TableRow,h.TableHeader,g.TableCell,R,z,V,B,ue,pe,me,G,fe,f.default.configure({placeholder:e.placeholder??`Начните писать…`}),...e.extensions??[]],editorProps:{attributes:{class:`ophx-editor-surface`,spellcheck:`true`,lang:`ru`,"aria-label":`Редактор документа`},handleDOMEvents:{mousedown:(e,t)=>{if(e.editable)return!1;let n=t.target instanceof Element?t.target:null;if(!n)return!1;if(n.closest(`.ophx-image-node, img`))return t.preventDefault(),!0;let r=n.closest(`table`),i=n.closest(`p, span, a, strong, em, code`);return r&&(!i||t.metaKey||t.ctrlKey)?(t.preventDefault(),!0):!1}}},onUpdate:e.onUpdate}),this.syncEditableControls(),e.toolbar&&(this.unmountToolbar=te(J(e.toolbar,`toolbar`),this.editor,e.toolbarOptions))}getHTML(){return this.editor.getHTML()}getJSON(){return this.editor.getJSON()}getText(){return this.editor.getText()}get isEmpty(){return this.editor.isEmpty}get isEditable(){return this.editor.isEditable}setContent(e,t={}){this.archiveDefaults=null,this.editor.commands.setContent(e,{emitUpdate:t.emitUpdate??!1})}clearContent(e={}){this.setContent(`<p></p>`,e)}focus(e){return this.editor.commands.focus(e),this}blur(){return this.editor.commands.blur(),this}setEditable(e){return this.editor.setEditable(e,!1),this.writeStoredEditable(e),this.syncEditableControls(),this}readStoredEditable(){if(!this.editableStorageKey)return null;try{let e=localStorage.getItem(this.editableStorageKey);return e===`true`||e!==`false`&&null}catch{return null}}writeStoredEditable(e){if(this.editableStorageKey)try{localStorage.setItem(this.editableStorageKey,String(e))}catch{}}undo(){return this.editor.commands.undo()}redo(){return this.editor.commands.redo()}canUndo(){return this.editor.can().undo()}canRedo(){return this.editor.can().redo()}syncEditableControls(){let e=this.editor.isEditable;this.editor.view.dom.querySelectorAll(`.ophx-heading__toggle, .ophx-image-node__resize-handle`).forEach(t=>{t.disabled=!e}),this.editor.view.dom.dispatchEvent(new Event(`ophx:editablechange`))}async loadOphx(e){let t=await w(e);return this.editor.commands.setContent(t.html,{emitUpdate:!1}),this.archiveDefaults={filename:t.filename,title:t.title,styles:t.styles,bodyContentEditable:t.bodyContentEditable},t}saveOphx(e={}){return oe(this.getHTML(),{...this.archiveDefaults,...e})}async downloadOphx(e={}){let t=e.filename??this.archiveDefaults?.filename??e.title??this.archiveDefaults?.title??`Документ`;T(await this.saveOphx(e),`${t.replace(/\.ophx$/i,``)}.ophx`)}setSearchQuery(e){this.editor.commands.setSearchQuery(e)}getFields(){let e=Array.from(this.editor.view.dom.querySelectorAll(`[data-ophx-field]`)).filter(e=>{let t=e.getAttribute(`data-ophx-field`)??``;return e.classList.contains(`ophx-field`)&&e.getAttribute(`contenteditable`)===`true`&&q(t)}),t=new Map;for(let n of e){let e=n.getAttribute(`data-ophx-field`);t.set(e,(t.get(e)??0)+1)}return e.filter(e=>t.get(e.getAttribute(`data-ophx-field`))===1).map(e=>({id:e.getAttribute(`data-ophx-field`),label:e.getAttribute(`data-ophx-label`),required:e.getAttribute(`data-ophx-required`)===`true`,value:e.textContent??``}))}getMissingRequiredFields(){return this.getFields().filter(e=>e.required&&!e.value.trim())}destroy(){this.unmountToolbar?.(),this.unmountToolbar=null,this.editor.destroy()}};function _e(e,t=`f`){if(!/^[A-Za-z0-9._-]+$/.test(t))throw Error(`Префикс идентификаторов полей содержит недопустимые символы`);let n=new DOMParser().parseFromString(e,`text/html`),r=new Set(Array.from(n.querySelectorAll(`[data-ophx-field]`)).map(e=>e.getAttribute(`data-ophx-field`)??``).filter(Boolean)),i=n.createTreeWalker(n.body,4),a=[];for(;i.nextNode();){let e=i.currentNode,t=e.parentElement;t&&!t.closest(`code, pre, script, style, [contenteditable="false"], [data-ophx-field]`)&&/_{2,}/.test(e.data)&&a.push(e)}let o=[],s=1;for(let e of a){let i=n.createDocumentFragment(),a=0;for(let c of e.data.matchAll(/_{2,}/g)){if(c.index===void 0)continue;c.index>a&&i.append(n.createTextNode(e.data.slice(a,c.index)));let l=`${t}${s++}`;for(;r.has(l);)l=`${t}${s++}`;r.add(l),o.push(l);let u=n.createElement(`span`);u.className=`ophx-field`,u.setAttribute(`contenteditable`,`true`),u.setAttribute(`data-ophx-field`,l),i.append(u),a=c.index+c[0].length}a<e.data.length&&i.append(n.createTextNode(e.data.slice(a))),e.replaceWith(i)}return{html:n.body.innerHTML,count:o.length,ids:o}}exports.CollapsibleHeading=U,exports.Indentation=pe,exports.Label=ue,exports.OphxBlockField=z,exports.OphxEditability=me,exports.OphxEditor=ge,exports.OphxInlineField=R,exports.OphxReadonlyBlock=V,exports.OphxReadonlyInline=B,exports.TextSearch=G,exports.WysiwymRules=fe,exports.convertUnderscoresToFields=_e,exports.downloadBlob=T,exports.exportOphx=oe,exports.importOphx=w,exports.isValidOphxFieldId=q,exports.mountToolbar=te;
@@ -1,2 +1,2 @@
1
- .ophx-editor-surface{color:#24262d;overflow-wrap:anywhere;background:#fff;outline:0;min-height:480px;padding:clamp(24px,5vw,64px) clamp(22px,8vw,100px);font:16px/1.75 Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.ophx-editor-surface>:first-child{margin-top:0}.ophx-editor-surface p{margin:0 0 .8em}.ophx-editor-surface h1,.ophx-editor-surface h2,.ophx-editor-surface h3,.ophx-editor-surface h4,.ophx-editor-surface h5,.ophx-editor-surface h6{color:#191b23;margin:1.4em 0 .5em;scroll-margin-top:24px;line-height:1.25}.ophx-editor-surface h1{font-size:2.15em}.ophx-editor-surface h2{font-size:1.7em}.ophx-editor-surface h3{font-size:1.35em}.ophx-editor-surface [data-indent="1"]{margin-left:2em}.ophx-editor-surface [data-indent="2"]{margin-left:4em}.ophx-editor-surface [data-indent="3"]{margin-left:6em}.ophx-editor-surface [data-indent="4"]{margin-left:8em}.ophx-editor-surface [data-indent="5"]{margin-left:10em}.ophx-editor-surface [data-indent="6"]{margin-left:12em}.ophx-editor-surface [data-indent="7"]{margin-left:14em}.ophx-editor-surface [data-indent="8"]{margin-left:16em}.ophx-editor-surface ul,.ophx-editor-surface ol{padding-left:1.6em}.ophx-editor-surface a{color:#4359d6;text-underline-offset:3px;text-decoration:underline}.ophx-editor-surface img{border-radius:6px;max-width:100%;height:auto;display:block}.ophx-editor-surface table{border-collapse:collapse;table-layout:fixed;width:100%;margin:1em 0}.ophx-editor-surface th,.ophx-editor-surface td{vertical-align:top;border:1px solid #dfe1e8;padding:8px 10px}.ophx-editor-surface th{background:#f5f6fa;font-weight:650}.ophx-editor-surface mark{background:#fff1a8;border-radius:3px;padding:0 2px}.ophx-editor-surface mark[data-label=важно]{background:#ffd9d9}.ophx-editor-surface mark[data-label=идея]{background:#d9f4e3}.ophx-editor-surface .ophx-field{border-bottom:1px dotted #888;outline:none;min-width:4em}.ophx-editor-surface .ophx-field:focus{border-bottom-style:solid}.ophx-editor-surface .ophx-field:empty:before{content:attr(data-ophx-label);color:#aaa}.ophx-editor-surface [data-collapsed=true]:after{content:" ▸";color:#8b91a2;font-size:.7em}.ophx-editor-surface .ophx-collapsed-content{display:none}.ophx-editor-surface .ophx-search-match{background:#ffe580;border-radius:2px}.ophx-editor-surface .is-empty:before{content:attr(data-placeholder);color:#a4a8b3;float:left;pointer-events:none;height:0}.ophx-toolbar{background:#fff;border-bottom:1px solid #e6e8ed;flex-wrap:wrap;align-items:center;gap:5px;padding:10px 12px;font:13px/1.4 Inter,ui-sans-serif,system-ui,sans-serif;display:flex;position:relative}.ophx-toolbar__style,.ophx-toolbar__button{color:#3a3d48;min-height:34px;font:inherit;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px;padding:6px 9px}.ophx-toolbar__style{border-color:#e6e8ed;margin-right:4px}.ophx-toolbar__button:hover,.ophx-toolbar__button.is-active{background:#f1f3fa;border-color:#e1e4ee}.ophx-toolbar__button:disabled{opacity:.38;cursor:default}.ophx-toolbar__button:focus-visible,.ophx-toolbar__style:focus-visible{outline-offset:1px;outline:2px solid #5868db}.ophx-toc{z-index:3;background:#fff;border:1px solid #e4e6ed;border-radius:9px;min-width:220px;max-width:min(360px,90vw);max-height:320px;padding:8px;display:grid;position:absolute;top:calc(100% + 4px);right:12px;overflow:auto;box-shadow:0 12px 30px #1820441f}.ophx-toc[hidden]{display:none}.ophx-toc__item{text-align:left;color:#373a46;cursor:pointer;background:0 0;border:0;border-radius:5px;padding:7px 8px}.ophx-toc__item:hover{background:#f2f4fa}
1
+ .ophx-editor-surface{color:#24262d;overflow-wrap:anywhere;background:#fff;outline:0;min-height:480px;padding:clamp(24px,5vw,64px) clamp(22px,8vw,100px);font:16px/1.75 Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;display:flow-root}.ophx-editor-surface>:first-child{margin-top:0}.ophx-editor-surface p{margin:0 0 .8em}.ophx-editor-surface h1,.ophx-editor-surface h2,.ophx-editor-surface h3,.ophx-editor-surface h4,.ophx-editor-surface h5,.ophx-editor-surface h6{color:#191b23;letter-spacing:-.02em;margin:1.2em 0 .45em;scroll-margin-top:24px;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;font-weight:700;line-height:1.2}.ophx-editor-surface h1{margin-top:.2em;font-size:2.3em}.ophx-editor-surface h2{font-size:1.8em}.ophx-editor-surface h3{font-size:1.45em}.ophx-editor-surface h4{font-size:1.2em}.ophx-editor-surface h5{font-size:1.08em}.ophx-editor-surface h6{font-size:1em}.ophx-editor-surface .ophx-heading{align-items:center;gap:7px;display:flex}.ophx-heading__toggle{color:#b6bdc8;cursor:pointer;background:0 0;border:0;border-radius:5px;flex:0 0 24px;order:2;place-items:center;width:24px;height:24px;margin-left:auto;padding:0;transition:background-color .14s,color .14s;display:inline-grid}.ophx-heading__toggle:hover,.ophx-heading__toggle:focus-visible{color:#1e88c4;background:#eaf3f8;outline:none}.ophx-heading__toggle:disabled{color:#d0d5dc;cursor:default;background:0 0}.ophx-heading__toggle svg{fill:none;stroke:currentColor;stroke-width:1.8px;stroke-linecap:round;stroke-linejoin:round;width:14px;height:14px;transition:transform .14s}.ophx-heading[data-collapsed=true] .ophx-heading__toggle svg{transform:rotate(0)}.ophx-heading:not([data-collapsed=true]) .ophx-heading__toggle svg{transform:rotate(90deg)}.ophx-heading__content{order:1;min-width:0}.ophx-editor-surface [data-indent="1"]{margin-left:2em}.ophx-editor-surface [data-indent="2"]{margin-left:4em}.ophx-editor-surface [data-indent="3"]{margin-left:6em}.ophx-editor-surface [data-indent="4"]{margin-left:8em}.ophx-editor-surface [data-indent="5"]{margin-left:10em}.ophx-editor-surface [data-indent="6"]{margin-left:12em}.ophx-editor-surface [data-indent="7"]{margin-left:14em}.ophx-editor-surface [data-indent="8"]{margin-left:16em}.ophx-editor-surface ul,.ophx-editor-surface ol{padding-left:1.6em}.ophx-editor-surface a{color:#4359d6;cursor:pointer;text-underline-offset:3px;border-radius:2px;text-decoration:underline;transition:background-color .12s,color .12s,box-shadow .12s}.ophx-editor-surface a:hover{color:#3346bd;background:#edf0ff;text-decoration-thickness:2px;box-shadow:0 0 0 2px #edf0ff}.ophx-editor-surface a:focus-visible{outline-offset:2px;border-radius:2px;outline:2px solid #5868d9}.ophx-editor-surface img{border-radius:6px;max-width:100%;height:auto;display:block}.ophx-editor-surface .ophx-image-node{box-sizing:border-box;width:fit-content;max-width:100%;margin:0 0 .8em;display:table;position:relative}.ophx-editor-surface .ophx-image-node[data-ophx-wrap=left]{float:left;margin:.25em 1em .75em 0}.ophx-editor-surface .ophx-image-node[data-ophx-wrap=right]{float:right;margin:.25em 0 .75em 1em}.ophx-editor-surface .ophx-image-node[data-ophx-wrap=none][data-ophx-align=center]{margin-inline:auto}.ophx-editor-surface .ophx-image-node[data-ophx-wrap=none][data-ophx-align=right]{margin-left:auto}.ophx-editor-surface .ophx-image-node img{border-radius:6px;max-width:100%;height:auto;display:block}.ophx-editor-surface .ophx-image-node.ProseMirror-selectednode{outline-offset:3px;outline:2px solid #5868d9}.ophx-editor-surface[contenteditable=false] .ophx-image-node.ProseMirror-selectednode{outline:0}.ophx-editor-surface[contenteditable=false] .ophx-image-node__resize-handle{display:none!important}.ophx-image-node__resize-handle{z-index:4;color:#fff;cursor:ew-resize;touch-action:none;background:#1e88c4;border:1px solid #fff;border-radius:9px;width:18px;height:34px;padding:3px;display:none;position:absolute;top:50%;right:-9px;transform:translateY(-50%);box-shadow:0 1px 5px #1820304d}.ophx-image-node__resize-handle:hover{background:#082d42}.ophx-image-node.ProseMirror-selectednode .ophx-image-node__resize-handle{place-items:center;display:grid}.ophx-image-node__resize-handle svg{fill:none;stroke:currentColor;stroke-width:1.5px;width:8px;height:22px}.ophx-editor-surface table{border-collapse:collapse;table-layout:fixed;width:100%;margin:1em 0}.ophx-editor-surface th,.ophx-editor-surface td{vertical-align:top;border:1px solid #dfe1e8;padding:8px 10px}.ophx-editor-surface th{background:#f5f6fa;font-weight:650}.ophx-editor-surface mark{background:#fff1a8;border-radius:3px;padding:0 2px}.ophx-editor-surface mark[data-label=важно]{background:#ffd9d9}.ophx-editor-surface mark[data-label=идея]{background:#d9f4e3}.ophx-editor-surface .ophx-field{border-bottom:1px dotted #888;outline:none;min-width:4em}.ophx-editor-surface .ophx-field:focus{border-bottom-style:solid}.ophx-editor-surface .ophx-field:empty:before{content:attr(data-ophx-label);color:#aaa}.ophx-editor-surface .ophx-collapsed-content{display:none}.ophx-editor-surface .ophx-search-match{background:#ffe580;border-radius:2px}.ophx-editor-surface .is-empty:before{content:attr(data-placeholder);color:#a4a8b3;float:left;pointer-events:none;height:0}.ophx-toolbar{z-index:15;isolation:isolate;background:#f8f9fb;border:1px solid #e0e3eb;border-bottom-color:#dfe3ec;border-radius:0;flex-wrap:wrap;align-items:center;gap:6px;padding:10px 12px;font:13px/1.4 Segoe UI,Tahoma,Geneva,Verdana,sans-serif;display:flex;position:sticky;top:0;box-shadow:inset 0 1px #ffffffe6}.ophx-toolbar__style-wrap{display:inline-flex;position:relative}.ophx-toolbar__style,.ophx-toolbar__button{color:#2d313b;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px;min-height:32px;padding:6px 10px;font:500 13px/1.3 Segoe UI,Tahoma,Geneva,Verdana,sans-serif;transition:background-color .12s,border-color .12s,box-shadow .12s}.ophx-toolbar__style{color:#1f2430;text-align:left;background:#fff;border:1px solid #d8dce6;border-radius:7px;justify-content:space-between;align-items:center;min-width:170px;margin-right:4px;padding:7px 30px 7px 12px;display:inline-flex;position:relative;box-shadow:inset 0 1px #ffffffe6}.ophx-toolbar__style:after{content:"";pointer-events:none;border-bottom:1.5px solid #5d6475;border-right:1.5px solid #5d6475;width:7px;height:7px;position:absolute;top:50%;right:11px;transform:translateY(-60%)rotate(45deg)}.ophx-toolbar__style:focus,.ophx-toolbar__style-option:focus-visible{border-color:#a9b4ff;outline:none;box-shadow:0 0 0 3px #596adc1f}.ophx-toolbar__style-label{color:#1f2430;min-width:0;display:inline-block}.ophx-toolbar__style-menu{z-index:20;background:#fff;border:1px solid #dfe3ee;border-radius:10px;min-width:220px;padding:8px;display:grid;position:absolute;top:calc(100% + 6px);left:0;box-shadow:0 8px 24px #1820301a}.ophx-toolbar__style-option{color:#1f2430;text-align:left;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:8px;align-items:center;width:100%;padding:9px 10px;display:flex}.ophx-toolbar__style-option:hover,.ophx-toolbar__style-option.is-selected{background:#f3f6fb;border-color:#e6eaf3}.ophx-toolbar__style-preview{color:#1d2431;width:100%;line-height:1.2;display:block}.ophx-toolbar__style-preview--p{font-size:13px;font-weight:500}.ophx-toolbar__style-preview--h1{letter-spacing:-.03em;font-size:1.9em;font-weight:700}.ophx-toolbar__style-preview--h2{letter-spacing:-.025em;font-size:1.5em;font-weight:700}.ophx-toolbar__style-preview--h3{letter-spacing:-.02em;font-size:1.2em;font-weight:700}.ophx-toolbar__button{color:#2d313b;text-align:center;background:#ffffff59;border-color:#cbd0dccc;min-width:34px;padding:6px 9px;font-weight:500;line-height:1}.ophx-toolbar__button[data-action=bold]{font-weight:700}.ophx-toolbar__button[data-action=italic]{font-style:italic;font-weight:500}.ophx-toolbar__button[data-action=underline]{text-underline-offset:3px;text-decoration:underline}.ophx-toolbar__button[data-action=strike]{text-decoration:line-through}.ophx-toolbar__button[data-action=bullet],.ophx-toolbar__button[data-action=ordered],.ophx-toolbar__button[data-action=outdent],.ophx-toolbar__button[data-action=indent],.ophx-toolbar__button[data-action=image],.ophx-toolbar__button[data-action=undo],.ophx-toolbar__button[data-action=redo]{letter-spacing:0;min-width:38px;font-size:17px;font-weight:500;line-height:1.1}.ophx-toolbar__button svg{stroke:currentColor;fill:none;stroke-width:1.8px;stroke-linecap:round;stroke-linejoin:round;width:16px;height:16px;display:block}.ophx-toolbar__button[data-action=ordered] svg{stroke-width:1.7px}.ophx-toolbar__button[data-action=bullet] svg{width:15px;height:15px}.ophx-toolbar__button[data-action=image]{place-items:center;display:inline-grid}.ophx-toolbar__button[data-action=image] svg{width:17px;height:17px}.ophx-toolbar__button[data-action=link],.ophx-toolbar__button[data-action=table]{place-items:center;min-width:38px;padding-inline:8px;display:inline-grid}.ophx-toolbar__button[data-action=link] svg,.ophx-toolbar__button[data-action=table] svg{width:17px;height:17px}.ophx-toolbar__button[data-action=label],.ophx-toolbar__button[data-action=toc]{letter-spacing:.02em;font-size:12px;font-weight:500}.ophx-toolbar__button:hover,.ophx-toolbar__button.is-active{background:#eef2fb;border-color:#d7dff4}.ophx-toolbar__button:disabled,.ophx-toolbar__style:disabled{opacity:.38;cursor:default}.ophx-toolbar__button:focus-visible,.ophx-toolbar__style:focus-visible{outline-offset:2px;outline:2px solid #1e88c4}.ophx-link-popover{z-index:1000;color:#242733;background:#fff;border:1px solid #dfe3ed;border-radius:10px;width:min(340px,100vw - 24px);padding:14px;font:13px/1.4 Segoe UI,Tahoma,Geneva,Verdana,sans-serif;position:fixed;box-shadow:0 10px 28px #1820302e}.ophx-link-popover[hidden]{display:none}.ophx-link-popover__arrow{left:var(--ophx-link-arrow-left,50%);background:#fff;border:1px solid #dfe3ed;width:10px;height:10px;position:absolute;transform:translate(-50%)rotate(45deg)}.ophx-link-popover[data-placement=bottom] .ophx-link-popover__arrow{border-bottom:0;border-right:0;top:-6px}.ophx-link-popover[data-placement=top] .ophx-link-popover__arrow{border-top:0;border-left:0;bottom:-6px}.ophx-link-popover__label{color:#555b69;margin-bottom:7px;font-size:12px;font-weight:600;display:block}.ophx-link-popover__row{gap:8px;display:flex}.ophx-link-popover__input{color:#242733;min-width:0;height:34px;font:inherit;border:1px solid #d8dce6;border-radius:6px;flex:1;padding:0 9px}.ophx-link-popover__actions{align-items:center;gap:8px;margin-top:10px;display:flex}.ophx-link-popover__go,.ophx-link-popover__submit{color:#fff;cursor:pointer;background:#1e88c4;border:1px solid #1e88c4;border-radius:6px;min-height:32px;padding:0 11px;font:600 12px/1 Segoe UI,Tahoma,Geneva,Verdana,sans-serif}.ophx-link-popover__go:hover,.ophx-link-popover__submit:hover{color:#fff;background:#082d42;border-color:#082d42}.ophx-link-popover__go[hidden]{display:none}.ophx-link-popover__input:focus{border-color:#7d89df;outline:2px solid #5868d929}.ophx-link-popover__remove{color:#707688;cursor:pointer;background:0 0;border:0;margin-right:auto;padding:2px 0;font:12px/1.4 Segoe UI,Tahoma,Geneva,Verdana,sans-serif}.ophx-link-popover__remove:hover{color:#b13d4a}.ophx-link-popover__remove[hidden]{display:none}.ophx-label-popover{width:min(300px,100vw - 24px)}.ophx-label-popover[data-mode=view] .ophx-label-popover__edit,.ophx-label-popover[data-mode=edit] .ophx-label-popover__view,.ophx-label-popover__view-actions[hidden]{display:none}.ophx-label-popover mark,.ophx-label-popover__chip{color:#242733;background:#fff1a8;border-radius:4px;padding:2px 8px}.ophx-label-popover mark[data-label=важно]{background:#ffd9d9}.ophx-label-popover mark[data-label=идея]{background:#d9f4e3}.ophx-label-popover__name{overflow-wrap:anywhere;font-size:15px;font-weight:600}.ophx-label-popover__presets{flex-wrap:wrap;gap:6px;margin-top:10px;display:flex}.ophx-label-popover__presets:empty{display:none}.ophx-label-popover__preset{cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px;padding:2px;font:12px/1.4 Segoe UI,Tahoma,Geneva,Verdana,sans-serif}.ophx-label-popover__preset:hover{border-color:#d8dce6}.ophx-label-popover__preset.is-selected{border-color:#1e88c4}.ophx-editor-surface mark[data-label]{cursor:pointer}.ophx-image-popover{z-index:1000;color:#242733;background:#fff;border:1px solid #dfe3ed;border-radius:10px;width:min(330px,100vw - 24px);padding:14px;font:13px/1.4 Segoe UI,Tahoma,Geneva,Verdana,sans-serif;position:fixed;box-shadow:0 10px 28px #1820302e}.ophx-image-popover[hidden]{display:none}.ophx-image-popover__arrow{left:var(--ophx-image-arrow-left,50%);background:#fff;border:1px solid #dfe3ed;width:10px;height:10px;position:absolute;transform:translate(-50%)rotate(45deg)}.ophx-image-popover[data-placement=bottom] .ophx-image-popover__arrow{border-bottom:0;border-right:0;top:-6px}.ophx-image-popover[data-placement=top] .ophx-image-popover__arrow{border-top:0;border-left:0;bottom:-6px}.ophx-image-popover__heading{color:#252834;margin:0 0 7px;font-size:12px;font-weight:650}.ophx-image-popover__heading:not(:first-of-type){margin-top:12px}.ophx-image-popover__choices{gap:5px;display:flex}.ophx-image-popover__choice{color:#4a5060;cursor:pointer;background:#fff;border:1px solid #dfe3ed;border-radius:6px;place-items:center;width:38px;height:34px;padding:5px;display:grid}.ophx-image-popover__choice:hover{color:#fff;background:#082d42;border-color:#082d42}.ophx-image-popover__choice.is-selected{color:#fff;background:#1e88c4;border-color:#1e88c4}.ophx-image-popover__choice.is-selected:hover{background:#082d42;border-color:#082d42}.ophx-image-popover__choice:focus-visible{outline-offset:2px;outline:2px solid #1e88c4}.ophx-image-popover__choice svg{fill:none;stroke:currentColor;stroke-width:1.5px;stroke-linecap:round;stroke-linejoin:round;width:25px;height:22px}.ophx-image-popover__size{color:#858b99;margin-top:10px;font-size:11px}.ophx-table-popover{z-index:1000;color:#242733;background:#fff;border:1px solid #dfe3ed;border-radius:10px;grid-template-columns:1fr 1fr;gap:10px;width:min(280px,100vw - 24px);padding:14px;font:13px/1.4 Segoe UI,Tahoma,Geneva,Verdana,sans-serif;display:grid;position:fixed;box-shadow:0 10px 28px #1820302e}.ophx-table-popover[hidden]{display:none}.ophx-table-popover__label{color:#555b69;gap:5px;font-size:12px;font-weight:600;display:grid}.ophx-table-popover__label input{color:#242733;width:100%;height:34px;font:inherit;border:1px solid #d8dce6;border-radius:6px;padding:0 8px}.ophx-table-popover__label input:focus{border-color:#7d89df;outline:2px solid #5868d929}.ophx-table-popover__header{color:#555b69;grid-column:1/-1;align-items:center;gap:7px;font-size:12px;display:flex}.ophx-table-popover__header input{accent-color:#1e88c4}.ophx-table-popover__insert{color:#fff;cursor:pointer;background:#1e88c4;border:1px solid #1e88c4;border-radius:6px;grid-column:1/-1;min-height:34px;font:600 12px/1 Segoe UI,Tahoma,Geneva,Verdana,sans-serif}.ophx-table-popover__insert:hover{color:#fff;background:#082d42;border-color:#082d42}.ophx-table-context{z-index:1000;background:#fff;border:1px solid #dfe3ed;border-radius:9px;align-items:center;gap:4px;padding:5px;display:flex;position:fixed;box-shadow:0 8px 24px #18203029}.ophx-table-context[hidden]{display:none}.ophx-table-context button{color:#454b59;cursor:pointer;background:#fff;border:1px solid #0000;border-radius:6px;place-items:center;width:32px;height:30px;padding:5px;display:grid}.ophx-table-context button:hover{color:#fff;background:#082d42;border-color:#082d42}.ophx-table-context button:focus-visible{outline-offset:2px;outline:2px solid #1e88c4}.ophx-table-context button svg{fill:none;stroke:currentColor;stroke-width:1.7px;stroke-linecap:round;stroke-linejoin:round;width:18px;height:18px}.ophx-table-context__divider{background:#e3e6ee;width:1px;height:22px}.ophx-toc{z-index:3;background:#fff;border:1px solid #e1e5ee;border-radius:10px;min-width:220px;max-width:min(360px,90vw);max-height:320px;padding:8px;display:grid;position:absolute;top:calc(100% + 4px);right:12px;overflow:auto;box-shadow:0 10px 24px #16213914}.ophx-toc[hidden]{display:none}.ophx-toc__item{text-align:left;color:#373d4b;cursor:pointer;background:0 0;border:0;border-radius:6px;padding:7px 8px;font:500 13px/1.35 Segoe UI,Tahoma,Geneva,Verdana,sans-serif}.ophx-toc__item:hover{background:#f3f5fa}
2
2
  /*$vite$:1*/