@getdraft/plugin 1.17.0 → 1.19.0-alpha.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.
Binary file
@@ -1,6 +1,5 @@
1
-
2
- 
3
- > @getdraft/plugin@1.17.0 dev-tsc /Users/nipanasovich/Documents/Work/draft.worktrees/feat-root-paddings/packages/plugin
4
- > tsc-check --pretty
5
-
6
- ✓ No errors found
1
+
2
+ > @getdraft/plugin@1.18.0 dev-tsc /Users/gerus/Documents/sendsay/draft/packages/plugin
3
+ > tsc-check --pretty
4
+
5
+ ✓ No errors found
@@ -1,24 +1,9 @@
1
-
2
- 
3
- > @getdraft/plugin@1.17.0 eslint /Users/nipanasovich/Documents/Work/draft.worktrees/feat-root-paddings/packages/plugin
4
- > npx eslint src --quiet --fix
5
-
6
- npm warn Unknown env config "npm-globalconfig". This will stop working in the next major version of npm.
7
- npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
8
- npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
9
- npm warn Unknown project config "supportedArchitectures.os". This will stop working in the next major version of npm.
10
- npm warn Unknown project config "supportedArchitectures.cpu". This will stop working in the next major version of npm.
11
- ⠙=============
12
-
13
- WARNING: You are currently running a version of TypeScript which is not officially supported by @typescript-eslint/typescript-estree.
14
-
15
- You may find that it works just fine, or you may not.
16
-
17
- SUPPORTED TYPESCRIPT VERSIONS: >=4.3.5 <5.4.0
18
-
19
- YOUR TYPESCRIPT VERSION: 5.9.3
20
-
21
- Please only submit bug reports when using the officially supported version.
22
-
23
- =============
24
- ⠙
1
+
2
+ > @getdraft/plugin@1.18.0 eslint /Users/gerus/Documents/sendsay/draft/packages/plugin
3
+ > npx eslint src --quiet
4
+
5
+ npm warn Unknown env config "npm-globalconfig". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options.
6
+ npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options.
7
+ npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options.
8
+ npm warn Unknown project config "supportedArchitectures.os". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options.
9
+ npm warn Unknown project config "supportedArchitectures.cpu". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options.
@@ -0,0 +1,11 @@
1
+
2
+ > @getdraft/plugin@1.18.0 prettify /Users/gerus/Documents/sendsay/draft/packages/plugin
3
+ > npx prettier --check src
4
+
5
+ npm warn Unknown env config "npm-globalconfig". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options.
6
+ npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options.
7
+ npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options.
8
+ npm warn Unknown project config "supportedArchitectures.os". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options.
9
+ npm warn Unknown project config "supportedArchitectures.cpu". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options.
10
+ Checking formatting...
11
+ All matched files use Prettier code style!
package/README.md CHANGED
@@ -130,7 +130,14 @@ Endpoint URL: Ваш endpoint из ЛК
130
130
  pluginId: "ID созданного плагина из ЛК",
131
131
  locale: "en" либо "ru",
132
132
  apiUrl: 'https://api.kvilla.ru',
133
- on: {} // Обработчики событий от редактора
133
+ sectionPersonalization: {
134
+ enabled: true,
135
+ aboutUrl: 'https://example.com/personalization-guide',
136
+ },
137
+ on: {
138
+ loadSectionPersonalizationCatalog: async () => catalog,
139
+ renderSectionPersonalizationGroup: async (group) => renderGroup(group),
140
+ },
134
141
  });
135
142
  ```
136
143
 
@@ -157,22 +164,50 @@ draft.start({
157
164
 
158
165
  Объект содержащий обработчики событий редактора.
159
166
 
160
- | Событие | Описание | Возвращаемые параметры |
161
- | --------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
162
- | `ready` | Редактор загрузился и готов к работе | <code>{<br>&nbsp;json: TemplateJSON;<br>&nbsp;html: string;<br>&nbsp;lastSavedTemplate: TemplateJSON;<br>&nbsp;}</code> |
163
- | `error` | Произошла ошибка | <code>{<br>&nbsp;message: string;<br>&nbsp;details: object\|string;<br>&nbsp;}</code> |
164
- | `notification` | Уведомление от редактора | <code>{<br>&nbsp;intent: 'error' \| 'info' \| 'success' \| 'warning';<br>&nbsp;errorDetails?: object;<br>&nbsp;message: string;<br>&nbsp;}</code> |
165
- | `autosave` | Произошло автосохранение | <code>{<br>&nbsp;json: TemplateJSON;<br>&nbsp;}</code> |
166
- | `save` | Произошло сохранение<br>_(Вызывается, в случае если используется внутренняя шапка редактора)_ | <code>{<br>&nbsp;json: TemplateJSON;<br>&nbsp;}</code> |
167
- | `exit` | Попытка выхода из редактора<br>_(Вызывается, в случае если используется внутренняя шапка редактора)_ | <code>{<br>&nbsp;json: TemplateJSON;<br>&nbsp;}</code> |
168
- | `toggleGrid` | Включена подсветка сетки | <code>{<br>&nbsp;state: boolean;<br>&nbsp;}</code> |
169
- | `toggleInvisibleCharacters` | Включено отображение служебных символов | <code>{<br>&nbsp;state: boolean;<br>&nbsp;}</code> |
170
- | `togglePreview` | Включен предпросмотр | <code>{<br>&nbsp;state: boolean;<br>&nbsp;json: TemplateJSON;<br>&nbsp;html: string;<br>&nbsp;darkHTML: string;<br>&nbsp;}</code> |
171
- | `toggleMenu` | Включено меню | <code>{<br>&nbsp;menu: [EditorMenu](#EditorMenu) \| null;<br>&nbsp;}</code> |
172
- | `history` | Добавлено изменение/Произошло перемещение по истории | <code>{<br>&nbsp;hasUndos: boolean;<br>&nbsp;hasRedos: boolean;<br>&nbsp;type: 'change'\|'undo'\|'redo'<br>&nbsp;}</code> |
173
- | `uploadImage` | В редактор пришло изображение для загрузки | |
174
- | `openGallery` | Открыта галерея | |
175
- | `loadPersonalization` | Редактор запрашивает данные персонализации. Асинхронный обработчик — должен вернуть словарь персонализации | Обработчик должен вернуть: <code>Promise<{<br>&nbsp;items: Array&lt;<br>&nbsp;&nbsp;{ name: string; value: string }<br>&nbsp;&nbsp;\| { groupName: string; items: Array&lt;{ name: string; value: string }&gt; }<br>&nbsp;&gt;<br>}></code> |
167
+ | Событие | Описание | Возвращаемые параметры |
168
+ | ----------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
169
+ | `ready` | Редактор загрузился и готов к работе | <code>{<br>&nbsp;json: TemplateJSON;<br>&nbsp;html: string;<br>&nbsp;lastSavedTemplate: TemplateJSON;<br>&nbsp;}</code> |
170
+ | `error` | Произошла ошибка | <code>{<br>&nbsp;message: string;<br>&nbsp;details: object\|string;<br>&nbsp;}</code> |
171
+ | `notification` | Уведомление от редактора | <code>{<br>&nbsp;intent: 'error' \| 'info' \| 'success' \| 'warning';<br>&nbsp;errorDetails?: object;<br>&nbsp;message: string;<br>&nbsp;}</code> |
172
+ | `autosave` | Произошло автосохранение | <code>{<br>&nbsp;json: TemplateJSON;<br>&nbsp;}</code> |
173
+ | `save` | Произошло сохранение<br>_(Вызывается, в случае если используется внутренняя шапка редактора)_ | <code>{<br>&nbsp;json: TemplateJSON;<br>&nbsp;}</code> |
174
+ | `exit` | Попытка выхода из редактора<br>_(Вызывается, в случае если используется внутренняя шапка редактора)_ | <code>{<br>&nbsp;json: TemplateJSON;<br>&nbsp;}</code> |
175
+ | `toggleGrid` | Включена подсветка сетки | <code>{<br>&nbsp;state: boolean;<br>&nbsp;}</code> |
176
+ | `toggleInvisibleCharacters` | Включено отображение служебных символов | <code>{<br>&nbsp;state: boolean;<br>&nbsp;}</code> |
177
+ | `togglePreview` | Включен предпросмотр | <code>{<br>&nbsp;state: boolean;<br>&nbsp;json: TemplateJSON;<br>&nbsp;html: string;<br>&nbsp;darkHTML: string;<br>&nbsp;}</code> |
178
+ | `toggleMenu` | Включено меню | <code>{<br>&nbsp;menu: [EditorMenu](#EditorMenu) \| null;<br>&nbsp;}</code> |
179
+ | `history` | Добавлено изменение/Произошло перемещение по истории | <code>{<br>&nbsp;hasUndos: boolean;<br>&nbsp;hasRedos: boolean;<br>&nbsp;type: 'change'\|'undo'\|'redo'<br>&nbsp;}</code> |
180
+ | `uploadImage` | В редактор пришло изображение для загрузки | |
181
+ | `openGallery` | Открыта галерея | |
182
+ | `loadPersonalization` | Редактор запрашивает данные персонализации. Асинхронный обработчик — должен вернуть словарь персонализации | Обработчик должен вернуть: <code>Promise<{<br>&nbsp;items: Array&lt;<br>&nbsp;&nbsp;{ name: string; value: string }<br>&nbsp;&nbsp;\| { groupName: string; items: Array&lt;{ name: string; value: string }&gt; }<br>&nbsp;&gt;<br>}></code> |
183
+ | `loadSectionPersonalizationCatalog` | Редактор запрашивает древовидный каталог полей для персонализации секций | Асинхронный обработчик должен вернуть `SectionPersonalizationCatalogNode[]` |
184
+ | `renderSectionPersonalizationGroup` | Редактор передаёт условия и отдельно скомпилированный HTML вариантов одной группы | Асинхронный обработчик должен вернуть HTML группы с конструкциями шаблонизатора интеграции |
185
+
186
+ ### **sectionPersonalization — опциональный**
187
+
188
+ Включает персонализацию наборов секций. Draft хранит группы и условия в JSON, но не знает синтаксис шаблонизатора интеграции. Для включённой функции необходимо передать оба async-обработчика выше.
189
+
190
+ ```typescript
191
+ sectionPersonalization: {
192
+ enabled: true;
193
+ aboutUrl?: string;
194
+ }
195
+ ```
196
+
197
+ Renderer получает поля группы, упорядоченные условные варианты и отдельный fallback:
198
+
199
+ ```typescript
200
+ {
201
+ groupId: string;
202
+ fields: Array<{ id: string; operatorId: 'equals' }>;
203
+ variants: Array<{
204
+ id: string;
205
+ values: Record<string, string | number | boolean | null>;
206
+ html: string;
207
+ }>;
208
+ fallback?: { id: string; html: string };
209
+ }
210
+ ```
176
211
 
177
212
  ### **container - опциональный**
178
213
 
@@ -235,6 +270,14 @@ Id элемента в котором будет развернут iframe с р
235
270
  ) => void
236
271
  ```
237
272
 
273
+ ### `isInvisibleCharactersVisible` - проверить отображение служебных символов
274
+
275
+ Возвращает текущее состояние отображения служебных символов.
276
+
277
+ ```typescript
278
+ () => Promise<boolean>;
279
+ ```
280
+
238
281
  ### `togglePreview` - Переключить отображение предпросмотра
239
282
 
240
283
  Вызывает ивент `togglePreview`
package/dist/index.cjs.js CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var e=`http://localhost:5174`,t=`https://seplugin.sendsay.ru`,n=function(e){return e.Audit=`audit`,e.Guide=`guide`,e.Style=`style`,e.Blocks=`blocks`,e}({}),r=function(e){return e.Desktop=`desktop`,e.Mobile=`mobile`,e}({}),i=class extends Error{code;constructor(e,t){super(t),this.name=`DraftError`,this.code=e}},a=async e=>{try{let t=await fetch(e,{method:`HEAD`});if(!t.ok)return null;let n=t.headers.get(`Content-Length`);return n?parseInt(n,10):null}catch{return null}},o=e=>new Promise((t,n)=>{let r=new Image;r.onload=async()=>{let n=await a(e)??0;t({originalWidth:r.width,originalHeight:r.height,ratio:r.width/r.height,fileSize:n})},r.onerror=e=>{n(e)},r.src=e}),s=(e,t)=>{if(e.length!==1)return e;if(e.charCodeAt(0)>=880){if(t.indexOf(`Key`)===0&&t.length===4)return t.charAt(3);if(t.indexOf(`Digit`)===0&&t.length===6)return t.charAt(5)}return e},c=e=>{let t=`${s(e.key,e.code)}`.toLowerCase()||e.key,n=navigator.userAgent.includes(`Mac OS`);t===`backspace`&&n&&(t=`delete`);let r=[];return(n&&e.metaKey||!n&&e.ctrlKey)&&r.push(`mod`),e.shiftKey&&r.push(`shift`),r.length>0&&(t=`${r.join(`-`)}-${s(t,e.code)}`),t},l=new Set([`escape`,`mod-c`,`mod-d`,`mod-z`,`mod-y`,`mod-shift-z`,`mod-v`,`delete`,`mod-g`,`mod-p`,`mod-s`]),u=`@getdraft/plugin`,d=`1.17.0`,f={name:u,version:d,main:`dist/index.cjs.js`,module:`dist/index.es.js`,types:`dist/types/index.d.ts`,exports:{".":{types:`./dist/types/index.d.ts`,import:`./dist/index.es.js`,require:`./dist/index.cjs.js`}},scripts:{prebuild:`rm -rf dist`,build:`vite build`,"dev-tsc":`tsc-check`,eslint:`npx eslint src`,"eslint:fix":`pnpm eslint --fix`,prettify:`npx prettier --check src`,"prettify:fix":`npx prettier -w src`,prepublish:`pnpm build`,watch:`NODE_ENV=development vite build --watch`,start:`NODE_ENV=development npx vite`},dependencies:{},devDependencies:{"@getdraft/types":`workspace:^`,"@getdraft/eslint-config-ts":`workspace:^`,"@getdraft/prettier":`workspace:^`,"vite-plugin-dts":`4.5.4`},license:`MIT`},p=()=>{let n=RegExp(`(^| )seplugin-dev=([^;]+)`),r=document.cookie.match(n)?.[2].toLowerCase?.();if(r===`true`)return e;if(r?.startsWith(`https://`))return r;let[i,a]=f.version.split(`.`);return`${t}/v${i}.${a}`},m=({token:e,pluginId:t,apiUrl:n})=>{if(!e)throw Error(`No [token] was provided`);if(!t)throw Error(`No [pluginId] was provided`);if(!n)throw Error(`No [apiUrl] was provided`)},h=e=>{let t=document.createElement(`iframe`),n=new URL(p());return n.searchParams.set(`parentOrigin`,e),t.src=n.toString(),t.setAttribute(`style`,`height:100%;width:100%;min-width:960px;border:0px;`),t.setAttribute(`allow`,`clipboard-read; clipboard-write`),t.setAttribute(`sandbox`,`allow-scripts allow-same-origin allow-forms allow-popups allow-downloads`),t},g=class e{iframe=null;hotkeysAttached=!1;iframeOrigin=null;constructor(e){this.config=e}captureHotkeysEnabled(){return this.config.disableHotkeysPassing!==!0}onHostHotkey=e=>{if(!this.captureHotkeysEnabled()||!this.iframe?.contentWindow)return;let t=c(e);if(!l.has(t))return;let n=e.target;if(n&&(n.isContentEditable||[`INPUT`,`TEXTAREA`,`SELECT`].includes(n.tagName)))return;e.preventDefault();let{key:r,ctrlKey:i,metaKey:a,shiftKey:o,altKey:s}=e;this.postEvent(`hostHotkey`,{key:r,code:e.code,metaKey:a,ctrlKey:i,shiftKey:o,altKey:s,keyCode:t})};static HEARTBEAT_TIMEOUT=4e3;promisedIframeMethod(t){let n=null,r=null,a=()=>{n&&=(clearTimeout(n),null),r&&=(window.removeEventListener(`message`,r,!0),null)},o=new Promise((o,s)=>{let c=()=>{n&&clearTimeout(n),n=setTimeout(()=>{a(),s(new i(`timeout_error`,`Action "${t}" timed out`))},e.HEARTBEAT_TIMEOUT)};r=e=>{if(e.source!==this.iframe?.contentWindow)return;let{data:n}=e;if(n.source===`DraftPlugin`){if(n.event===`actionPing`&&n.action===t){e.stopPropagation(),c();return}if(n.event===t){e.stopPropagation(),a();let{source:t,event:r,ok:c,code:l,message:u,...d}=n;c===!1?s(new i(l||`unknown_error`,u||`Unknown error`)):o(d)}}},window.addEventListener(`message`,r,!0),c()});return this.postEvent(t),o}postEvent(e,t={}){if(this.iframe&&this.iframe.contentWindow&&this.iframeOrigin)this.iframe.contentWindow.postMessage({...t,event:e,source:`DraftPlugin`},this.iframeOrigin);else if(!this.iframeOrigin)throw Error(`Iframe origin is not initialized`)}onImageUpload=async({id:e,...t})=>{try{let n=await this.config.on.uploadImage?.(t),r={};n&&(r=await o(n)),this.postEvent(`imageUploaded`,{id:e,img:{...r,url:n}})}catch{this.postEvent(`imageUploaded`,{id:e})}};onLoadPersonalization=async()=>{try{if(!this.config.on.loadPersonalization)throw Error(`No personalization loader provided`);let e=await this.config.on.loadPersonalization();this.postEvent(`loadPersonalization`,{items:e})}catch{this.postEvent(`loadPersonalization`,{})}};onGalleryOpen=async({id:e})=>{this.config.on.openGallery?.(async t=>{let n={url:t};if(t){let e=await o(t);Object.assign(n,e)}this.postEvent(`imageUploaded`,{id:e,img:n})})};triggerEvent(e,t){if(e)return e(t)}onMessage=e=>{if(e.source!==this.iframe?.contentWindow)return;let{data:{source:t,event:n,...r}}=e;t===`DraftPlugin`&&(n===`openGallery`?this.onGalleryOpen(r):n===`uploadImage`?this.onImageUpload(r):n===`loadPersonalization`?this.onLoadPersonalization():this.triggerEvent(this.config.on[n],r))};start({template:e,templateName:t,uid:n}){let r=document.querySelector(this.config.container);if(r){let i=r=>{let{data:{source:a,event:o}}=r;if(a===`DraftPlugin`&&o===`loaded`){if(r.source!==this.iframe?.contentWindow)return;this.iframeOrigin=r.origin;let{on:a,container:o,locale:s,autosave:c,token:l,apiUrl:u,pluginId:d,authData:f,__config:p}=this.config;m(this.config),this.iframe&&this.iframe.contentWindow&&this.postEvent(`init`,{container:o,locale:s,uid:n,autosave:c,token:l,pluginId:d,authData:f,apiUrl:u,__config:p,enabledListeners:Object.keys(a),template:e,templateName:t}),window.addEventListener(`message`,this.onMessage),window.removeEventListener(`message`,i)}};this.iframe=h(window.location.origin),window.addEventListener(`message`,i),r.appendChild(this.iframe),this.captureHotkeysEnabled()&&!this.hotkeysAttached&&(window.addEventListener(`keydown`,this.onHostHotkey),this.hotkeysAttached=!0)}else throw Error(`Specified container not found`)}destroy=()=>{this.iframe?.remove(),this.iframe=null,window.removeEventListener(`message`,this.onMessage),this.hotkeysAttached&&=(window.removeEventListener(`keydown`,this.onHostHotkey),!1)};changeTemplate(e,t={}){this.postEvent(`changeTemplate`,{...t,template:e})}toggleGrid(e){this.postEvent(`toggleGrid`,{state:e})}toggleInvisibleCharacters(e){this.postEvent(`toggleInvisibleCharacters`,{state:e})}togglePreview(e){this.postEvent(`togglePreview`,{state:e})}toggleMenu(e=null){this.postEvent(`toggleMenu`,{menu:e})}toggleViewMode(e){this.postEvent(`toggleViewMode`,{viewMode:e})}undo(){this.postEvent(`undo`)}undoToStep(e){this.postEvent(`undoToStep`,{targetStep:e})}redo(){this.postEvent(`redo`)}save(){return this.promisedIframeMethod(`saveAction`)}exit(){return this.promisedIframeMethod(`exitAction`)}exportContent(){return this.promisedIframeMethod(`exportContent`)}exportAsFile(){return this.promisedIframeMethod(`exportAsFile`)}},_={container:`#draft-plugin-container`,disableHotkeysPassing:!1,locale:`ru`,on:{}},v=new class{version=d;create(e){return new g({..._,...e})}};window.DraftPlugin=v,exports.DraftError=i,exports.EditorMenu=n,exports.ViewMode=r,exports.default=v;
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var e=`http://localhost:5174`,t=`https://seplugin.sendsay.ru`,n=function(e){return e.Audit=`audit`,e.Guide=`guide`,e.Style=`style`,e.Blocks=`blocks`,e}({}),r=function(e){return e.Desktop=`desktop`,e.Mobile=`mobile`,e}({}),i=class extends Error{code;constructor(e,t){super(t),this.name=`DraftError`,this.code=e}},a=async e=>{try{let t=await fetch(e,{method:`HEAD`});if(!t.ok)return null;let n=t.headers.get(`Content-Length`);return n?parseInt(n,10):null}catch{return null}},o=e=>new Promise((t,n)=>{let r=new Image;r.onload=async()=>{let n=await a(e)??0;t({originalWidth:r.width,originalHeight:r.height,ratio:r.width/r.height,fileSize:n})},r.onerror=e=>{n(e)},r.src=e}),s=(e,t)=>{if(e.length!==1)return e;if(e.charCodeAt(0)>=880){if(t.indexOf(`Key`)===0&&t.length===4)return t.charAt(3);if(t.indexOf(`Digit`)===0&&t.length===6)return t.charAt(5)}return e},c=e=>{let t=`${s(e.key,e.code)}`.toLowerCase()||e.key,n=navigator.userAgent.includes(`Mac OS`);t===`backspace`&&n&&(t=`delete`);let r=[];return(n&&e.metaKey||!n&&e.ctrlKey)&&r.push(`mod`),e.shiftKey&&r.push(`shift`),r.length>0&&(t=`${r.join(`-`)}-${s(t,e.code)}`),t},l=new Set([`escape`,`mod-c`,`mod-d`,`mod-z`,`mod-y`,`mod-shift-z`,`mod-v`,`delete`,`mod-g`,`mod-p`,`mod-s`]),u=`@getdraft/plugin`,d=`1.19.0-alpha.0`,f={name:u,version:d,main:`dist/index.cjs.js`,module:`dist/index.es.js`,types:`dist/types/index.d.ts`,exports:{".":{types:`./dist/types/index.d.ts`,import:`./dist/index.es.js`,require:`./dist/index.cjs.js`}},scripts:{prebuild:`rm -rf dist`,build:`vite build`,"dev-tsc":`tsc-check`,eslint:`npx eslint src`,"eslint:fix":`pnpm eslint --fix`,prettify:`npx prettier --check src`,"prettify:fix":`npx prettier -w src`,prepublish:`pnpm build`,watch:`NODE_ENV=development vite build --watch`,start:`NODE_ENV=development npx vite`},dependencies:{},devDependencies:{"@getdraft/types":`workspace:^`,"@getdraft/eslint-config-ts":`workspace:^`,"@getdraft/prettier":`workspace:^`,"vite-plugin-dts":`4.5.4`},license:`MIT`},p=`Unknown error`,m=()=>{let n=RegExp(`(^| )seplugin-dev=([^;]+)`),r=document.cookie.match(n)?.[2].toLowerCase?.();if(r===`true`)return e;if(r?.startsWith(`https://`))return r;let[i,a]=f.version.split(`.`);return`${t}/v${i}.${a}`},h=({token:e,pluginId:t,apiUrl:n})=>{if(!e)throw Error(`No [token] was provided`);if(!t)throw Error(`No [pluginId] was provided`);if(!n)throw Error(`No [apiUrl] was provided`)},g=e=>{let t=document.createElement(`iframe`),n=new URL(m());return n.searchParams.set(`parentOrigin`,e),t.src=n.toString(),t.setAttribute(`style`,`height:100%;width:100%;min-width:960px;border:0px;`),t.setAttribute(`allow`,`clipboard-read; clipboard-write`),t.setAttribute(`sandbox`,`allow-scripts allow-same-origin allow-forms allow-popups allow-downloads`),t},_=class e{iframe=null;hotkeysAttached=!1;iframeOrigin=null;constructor(e){this.config=e}captureHotkeysEnabled(){return this.config.disableHotkeysPassing!==!0}onHostHotkey=e=>{if(!this.captureHotkeysEnabled()||!this.iframe?.contentWindow)return;let t=c(e);if(!l.has(t))return;let n=e.target;if(n&&(n.isContentEditable||[`INPUT`,`TEXTAREA`,`SELECT`].includes(n.tagName)))return;e.preventDefault();let{key:r,ctrlKey:i,metaKey:a,shiftKey:o,altKey:s}=e;this.postEvent(`hostHotkey`,{key:r,code:e.code,metaKey:a,ctrlKey:i,shiftKey:o,altKey:s,keyCode:t})};static HEARTBEAT_TIMEOUT=4e3;promisedIframeMethod(t){let n=null,r=null,a=()=>{n&&=(clearTimeout(n),null),r&&=(window.removeEventListener(`message`,r,!0),null)},o=new Promise((o,s)=>{let c=()=>{n&&clearTimeout(n),n=setTimeout(()=>{a(),s(new i(`timeout_error`,`Action "${t}" timed out`))},e.HEARTBEAT_TIMEOUT)};r=e=>{if(e.source!==this.iframe?.contentWindow)return;let{data:n}=e;if(n.source===`DraftPlugin`){if(n.event===`actionPing`&&n.action===t){e.stopPropagation(),c();return}if(n.event===t){e.stopPropagation(),a();let{source:t,event:r,ok:c,code:l,message:u,...d}=n;c===!1?s(new i(l||`unknown_error`,u||p)):o(d)}}},window.addEventListener(`message`,r,!0),c()});return this.postEvent(t),o}postEvent(e,t={}){if(this.iframe&&this.iframe.contentWindow&&this.iframeOrigin)this.iframe.contentWindow.postMessage({...t,event:e,source:`DraftPlugin`},this.iframeOrigin);else if(!this.iframeOrigin)throw Error(`Iframe origin is not initialized`)}onImageUpload=async({id:e,...t})=>{try{let n=await this.config.on.uploadImage?.(t),r={};n&&(r=await o(n)),this.postEvent(`imageUploaded`,{id:e,img:{...r,url:n}})}catch{this.postEvent(`imageUploaded`,{id:e})}};onLoadPersonalization=async e=>{try{if(!this.config.on.loadPersonalization)throw Error(`No personalization loader provided`);let t=await this.config.on.loadPersonalization();this.postEvent(`loadPersonalization`,{items:t,requestId:e})}catch{this.postEvent(`loadPersonalization`,{requestId:e})}};onLoadSectionPersonalizationCatalog=async e=>{try{let t=this.config.on.loadSectionPersonalizationCatalog;if(!t)throw Error(`No section personalization catalog loader provided`);let n=await t();this.postEvent(`loadSectionPersonalizationCatalog`,{ok:!0,requestId:e,catalog:n})}catch(t){this.postEvent(`loadSectionPersonalizationCatalog`,{ok:!1,requestId:e,message:t instanceof Error?t.message:p})}};onRenderSectionPersonalizationGroup=async e=>{let{requestId:t,...n}=e;try{let e=this.config.on.renderSectionPersonalizationGroup;if(!e)throw Error(`No section personalization renderer provided`);let r=await e(n);this.postEvent(`renderSectionPersonalizationGroup`,{ok:!0,requestId:t,html:r})}catch(e){this.postEvent(`renderSectionPersonalizationGroup`,{ok:!1,requestId:t,message:e instanceof Error?e.message:p})}};onGalleryOpen=async({id:e})=>{this.config.on.openGallery?.(async t=>{let n={url:t};if(t){let e=await o(t);Object.assign(n,e)}this.postEvent(`imageUploaded`,{id:e,img:n})})};triggerEvent(e,t){if(e)return e(t)}onMessage=e=>{if(e.source!==this.iframe?.contentWindow)return;let{data:{source:t,event:n,...r}}=e;t===`DraftPlugin`&&(n===`openGallery`?this.onGalleryOpen(r):n===`uploadImage`?this.onImageUpload(r):n===`loadPersonalization`?this.onLoadPersonalization(r.requestId):n===`loadSectionPersonalizationCatalog`?this.onLoadSectionPersonalizationCatalog(r.requestId):n===`renderSectionPersonalizationGroup`?this.onRenderSectionPersonalizationGroup(r):this.triggerEvent(this.config.on[n],r))};start({template:e,templateName:t,uid:n}){let r=document.querySelector(this.config.container);if(r){let i=r=>{let{data:{source:a,event:o}}=r;if(a===`DraftPlugin`&&o===`loaded`){if(r.source!==this.iframe?.contentWindow)return;this.iframeOrigin=r.origin;let{on:a,container:o,locale:s,autosave:c,token:l,apiUrl:u,pluginId:d,authData:f,sectionPersonalization:p,__config:m}=this.config;if(h(this.config),this.iframe&&this.iframe.contentWindow){let r={...p,enabled:p?.enabled===!0&&!!a.loadSectionPersonalizationCatalog&&!!a.renderSectionPersonalizationGroup};this.postEvent(`init`,{container:o,locale:s,uid:n,autosave:c,token:l,pluginId:d,authData:f,sectionPersonalization:r,apiUrl:u,__config:m,enabledListeners:Object.keys(a),template:e,templateName:t})}window.addEventListener(`message`,this.onMessage),window.removeEventListener(`message`,i)}};this.iframe=g(window.location.origin),window.addEventListener(`message`,i),r.appendChild(this.iframe),this.captureHotkeysEnabled()&&!this.hotkeysAttached&&(window.addEventListener(`keydown`,this.onHostHotkey),this.hotkeysAttached=!0)}else throw Error(`Specified container not found`)}destroy=()=>{this.iframe?.remove(),this.iframe=null,window.removeEventListener(`message`,this.onMessage),this.hotkeysAttached&&=(window.removeEventListener(`keydown`,this.onHostHotkey),!1)};changeTemplate(e,t={}){this.postEvent(`changeTemplate`,{...t,template:e})}toggleGrid(e){this.postEvent(`toggleGrid`,{state:e})}toggleInvisibleCharacters(e){this.postEvent(`toggleInvisibleCharacters`,{state:e})}async isInvisibleCharactersVisible(){let{state:e}=await this.promisedIframeMethod(`getInvisibleCharactersVisibility`);return e}togglePreview(e){this.postEvent(`togglePreview`,{state:e})}toggleMenu(e=null){this.postEvent(`toggleMenu`,{menu:e})}toggleViewMode(e){this.postEvent(`toggleViewMode`,{viewMode:e})}undo(){this.postEvent(`undo`)}undoToStep(e){this.postEvent(`undoToStep`,{targetStep:e})}redo(){this.postEvent(`redo`)}save(){return this.promisedIframeMethod(`saveAction`)}exit(){return this.promisedIframeMethod(`exitAction`)}exportContent(){return this.promisedIframeMethod(`exportContent`)}exportAsFile(){return this.promisedIframeMethod(`exportAsFile`)}},v={container:`#draft-plugin-container`,disableHotkeysPassing:!1,locale:`ru`,on:{}},y=new class{version=d;create(e){return new _({...v,...e})}};window.DraftPlugin=y,exports.DraftError=i,exports.EditorMenu=n,exports.ViewMode=r,exports.default=y;
2
2
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","names":[],"sources":["../src/routes.ts","../src/types.ts","../src/utils.ts","../package.json","../src/plugin.ts","../src/index.ts"],"sourcesContent":["export const LOCAL_ENDPOINT = 'http://localhost:5174';\nexport const PROD_ENDPOINT = 'https://seplugin.sendsay.ru';\n","export enum EditorMenu {\n Audit = 'audit',\n Guide = 'guide',\n Style = 'style',\n Blocks = 'blocks',\n}\n\nexport enum ViewMode {\n Desktop = 'desktop',\n Mobile = 'mobile',\n}\n\nexport interface Notification {\n intent: 'error' | 'info' | 'success' | 'warning';\n errorDetails?: object;\n message?: string;\n title: string;\n}\n\ntype PersonalizationDictionaryEntry =\n | { name: string; value: string }\n | { groupName: string; items: Array<{ name: string; value: string }> };\n\nexport type PersonalizationDictionaryItems = PersonalizationDictionaryEntry[];\n\nexport interface SerializedTemplate {\n [key: string]: unknown;\n parentId: string | null;\n id: string;\n parameters: object;\n layer: string;\n type: string;\n children?: SerializedTemplate[];\n meta?: { [key: string]: unknown; version: string };\n}\n\nexport type EventHandler<T> = (data: T) => void;\n\nexport type AsyncEventHandler<P, R> = (params: P) => Promise<R>;\n\nexport class DraftError extends Error {\n public readonly code: string;\n\n constructor(code: string, message: string) {\n super(message);\n this.name = 'DraftError';\n this.code = code;\n }\n}\n\nexport type MessageData = {\n source: string;\n event: string;\n ok?: boolean;\n code?: string;\n message?: string;\n action?: string;\n};\n\nexport interface ExportAsFileParams {\n blob: Blob;\n fileName: string;\n}\n\nexport interface SaveParams {\n json: TemplateJSON;\n html: string;\n}\n\nexport type OnInitParams = MessageEvent<{\n source: string;\n event: 'loaded' | unknown;\n}>;\n\nexport interface ReadyParams extends SaveParams {\n lastSavedTemplate?: {\n template: TemplateJSON;\n date: Date;\n };\n}\n\nexport interface ErrorParams {\n message: string;\n code?: string;\n details?: unknown;\n}\n\nexport interface ExitParams extends SaveParams {}\n\nexport type NotificationParams = Notification;\n\nexport interface OpenGalleryParams {\n id: string;\n}\n\nexport interface UploadImageParams {\n file: string;\n name: string;\n}\n\nexport interface ImageParams {\n url: string;\n originalWidth: number;\n originalHeight: number;\n ratio: number;\n fileSize: number;\n}\n\nexport interface AutosaveParams {\n json: TemplateJSON;\n}\n\ninterface ToggleParams {\n state: boolean;\n}\n\nexport interface ToggleGridParams extends ToggleParams {}\n\nexport interface ToggleInvisibleCharactersParams extends ToggleParams {}\n\nexport interface TogglePreviewParams extends ToggleParams {\n json: TemplateJSON;\n html: string;\n darkHTML: string;\n}\n\nexport interface ToggleViewModeParams {\n mode: ViewMode;\n}\n\nexport interface ToggleMenuParams {\n menu: EditorMenu | null;\n}\n\nexport interface HistoryParams {\n hasUndos: boolean;\n hasRedos: boolean;\n currentStep: number;\n}\n\nexport type TemplateJSON = SerializedTemplate;\n\nexport type PersonalizationDictionary = PersonalizationDictionaryItems;\n\nexport type ToolbarActionName =\n | 'duplicate'\n | 'destroy'\n | 'edit'\n | 'up'\n | 'down';\nexport type HotkeyContext = 'hotkey';\nexport type OverlayContext = 'overlay-click' | 'overlay-double-click';\nexport type ToolbarContext = 'toolbar';\nexport type UnitSettingsContext = 'unit-settings';\nexport type BlockType = 'system' | 'user';\nexport type DndDragContext = 'canvas' | 'list' | 'palette';\nexport type DndDropContext = 'dropline' | 'placeholder' | 'empty-placeholder';\nexport type DndDropTarget = 'root' | 'section' | 'column' | 'element';\n\nexport interface DuplicateEvent {\n name: 'duplicate';\n context: HotkeyContext | ToolbarContext | UnitSettingsContext;\n unitType: string;\n}\n\nexport interface DestroyEvent {\n name: 'destroy';\n context: HotkeyContext | ToolbarContext | UnitSettingsContext;\n unitType: string;\n}\n\nexport interface EditEvent {\n name: 'edit';\n context: OverlayContext | ToolbarContext;\n unitType: string;\n}\n\nexport interface HistoryEvent {\n name: 'history';\n type: 'undo' | 'redo';\n context: HotkeyContext;\n}\n\nexport interface PreviewEvent {\n name: 'preview';\n context: HotkeyContext;\n}\n\nexport interface ToolbarMoveEvent {\n name: 'up' | 'down';\n context: ToolbarContext;\n unitType: string;\n}\n\nexport interface BlockInsertEvent {\n name: 'block-insert';\n context: 'double-click';\n blockType: BlockType;\n blockName: string;\n blockCategory: string | number;\n blockId: string | number;\n}\n\nexport interface BlockSaveEvent {\n name: 'block-save';\n blockType: 'user';\n blockName: string;\n blockCategory: string | number;\n blockId: string | number;\n elements: Record<string, number> & { sum: number };\n}\n\nexport interface BlockDestroyEvent {\n name: 'block-destroy';\n}\n\nexport interface DropEventDragMeta {\n context?: DndDragContext;\n layer?: 'element' | 'section' | 'column' | 'root';\n type?: string | string[];\n blockCategory?: string | number;\n blockId?: string | number;\n blockName?: string;\n blockType?: BlockType;\n alt?: boolean;\n dropKind?: 'create' | 'move';\n}\n\nexport interface DropEventDropzoneMeta {\n context?: DndDropContext;\n dropTarget?: DndDropTarget;\n}\n\nexport interface DropEvent {\n name: 'drop';\n drag?: DropEventDragMeta;\n dropzone?: DropEventDropzoneMeta;\n}\n\nexport type AnalyticsParams =\n | DuplicateEvent\n | DestroyEvent\n | EditEvent\n | HistoryEvent\n | PreviewEvent\n | ToolbarMoveEvent\n | BlockInsertEvent\n | BlockSaveEvent\n | BlockDestroyEvent\n | DropEvent;\n\nexport interface Handlers {\n ready: EventHandler<ReadyParams>;\n error: EventHandler<ErrorParams>;\n save: EventHandler<SaveParams>;\n exit: EventHandler<ExitParams>;\n notification: EventHandler<NotificationParams>;\n autosave: EventHandler<AutosaveParams>;\n toggleGrid: EventHandler<ToggleGridParams>;\n toggleInvisibleCharacters: EventHandler<ToggleInvisibleCharactersParams>;\n togglePreview: EventHandler<TogglePreviewParams>;\n toggleViewMode: EventHandler<ToggleViewModeParams>;\n toggleMenu: EventHandler<ToggleMenuParams>;\n history: EventHandler<HistoryParams>;\n analytics: EventHandler<AnalyticsParams>;\n openGallery: EventHandler<(url?: string) => Promise<void>>;\n uploadImage: AsyncEventHandler<UploadImageParams, string>;\n loadPersonalization: AsyncEventHandler<void, PersonalizationDictionary>;\n}\n\nexport type HandlerParams<H> = H extends\n | EventHandler<infer P>\n | AsyncEventHandler<infer P, unknown>\n ? P\n : never;\n\nexport interface PluginConfig {\n container: string;\n locale?: string;\n autosave?:\n | boolean\n | {\n interval: number;\n };\n token: string;\n authData?: {\n orgId: number;\n projectId?: number;\n };\n pluginId: string;\n apiUrl: string;\n disableHotkeysPassing?: boolean;\n __config?: object;\n on: Partial<Handlers>;\n}\n","import { ImageParams } from './types';\n\nconst getImageFileSize = async (imageUrl: string) => {\n try {\n const response = await fetch(imageUrl, { method: 'HEAD' });\n\n if (!response.ok) {\n return null;\n }\n\n const contentLength = response.headers.get('Content-Length');\n\n if (contentLength) {\n return parseInt(contentLength, 10);\n } else {\n return null;\n }\n } catch (error) {\n return null;\n }\n};\n\nexport const getImageParamsFromFileUrl = (imgSrc: string) =>\n new Promise<Omit<ImageParams, 'url'>>((resolve, reject) => {\n const img = new Image();\n\n img.onload = async () => {\n const fileSize = (await getImageFileSize(imgSrc)) ?? 0;\n\n resolve({\n originalWidth: img.width,\n originalHeight: img.height,\n ratio: img.width / img.height,\n fileSize,\n });\n };\n\n img.onerror = (error) => {\n reject(error);\n };\n\n img.src = imgSrc;\n });\n\nconst getLatinKey = (key: string, code: string) => {\n if (key.length !== 1) {\n return key;\n }\n\n const capitalHetaCode = 880;\n const isNonLatin = key.charCodeAt(0) >= capitalHetaCode;\n\n if (isNonLatin) {\n if (code.indexOf('Key') === 0 && code.length === 4) {\n return code.charAt(3);\n }\n\n if (code.indexOf('Digit') === 0 && code.length === 6) {\n return code.charAt(5);\n }\n }\n\n return key;\n};\n\nexport const constructKeyCode = (event: KeyboardEvent) => {\n let keyCode =\n `${getLatinKey(event.key, event.code)}`.toLowerCase() || event.key;\n const macOs = navigator.userAgent.includes('Mac OS');\n\n if (keyCode === 'backspace' && macOs) {\n keyCode = 'delete';\n }\n\n const prefix = [];\n\n if ((macOs && event.metaKey) || (!macOs && event.ctrlKey)) {\n prefix.push('mod');\n }\n\n if (event.shiftKey) {\n prefix.push('shift');\n }\n\n if (prefix.length > 0) {\n keyCode = `${prefix.join('-')}-${getLatinKey(keyCode, event.code)}`;\n }\n\n return keyCode;\n};\n\nexport const CORE_HOTKEYS = new Set([\n 'escape',\n 'mod-c',\n 'mod-d',\n 'mod-z',\n 'mod-y',\n 'mod-shift-z',\n 'mod-v',\n 'delete',\n 'mod-g',\n 'mod-p',\n 'mod-s',\n]);\n","{\n \"name\": \"@getdraft/plugin\",\n \"version\": \"1.17.0\",\n \"main\": \"dist/index.cjs.js\",\n \"module\": \"dist/index.es.js\",\n \"types\": \"dist/types/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/types/index.d.ts\",\n \"import\": \"./dist/index.es.js\",\n \"require\": \"./dist/index.cjs.js\"\n }\n },\n \"scripts\": {\n \"prebuild\": \"rm -rf dist\",\n \"build\": \"vite build\",\n \"dev-tsc\": \"tsc-check\",\n \"eslint\": \"npx eslint src\",\n \"eslint:fix\": \"pnpm eslint --fix\",\n \"prettify\": \"npx prettier --check src\",\n \"prettify:fix\": \"npx prettier -w src\",\n \"prepublish\": \"pnpm build\",\n \"watch\": \"NODE_ENV=development vite build --watch\",\n \"start\": \"NODE_ENV=development npx vite\"\n },\n \"dependencies\": {},\n \"devDependencies\": {\n \"@getdraft/types\": \"workspace:^\",\n \"@getdraft/eslint-config-ts\": \"workspace:^\",\n \"@getdraft/prettier\": \"workspace:^\",\n \"vite-plugin-dts\": \"4.5.4\"\n },\n \"license\": \"MIT\"\n}\n","import { LOCAL_ENDPOINT, PROD_ENDPOINT } from './routes';\nimport {\n DraftError,\n EditorMenu,\n ExitParams,\n OnInitParams,\n OpenGalleryParams,\n Handlers,\n PluginConfig,\n SaveParams,\n TemplateJSON,\n UploadImageParams,\n ViewMode,\n HandlerParams,\n MessageData,\n ExportAsFileParams,\n} from './types';\nimport {\n getImageParamsFromFileUrl,\n constructKeyCode,\n CORE_HOTKEYS,\n} from './utils';\nimport pkg from '../package.json';\n\nconst getDeployLink = () => {\n const regex = new RegExp(`(^| )seplugin-dev=([^;]+)`);\n const match = document.cookie.match(regex);\n const value = match?.[2].toLowerCase?.();\n\n if (value === 'true') {\n return LOCAL_ENDPOINT;\n }\n\n if (value?.startsWith('https://')) {\n return value;\n }\n\n const [major, mid] = pkg.version.split('.');\n\n return `${PROD_ENDPOINT}/v${major}.${mid}`;\n};\n\nconst verifyConfig = ({ token, pluginId, apiUrl }: PluginConfig) => {\n if (!token) {\n throw new Error('No [token] was provided');\n }\n\n if (!pluginId) {\n throw new Error('No [pluginId] was provided');\n }\n\n if (!apiUrl) {\n throw new Error('No [apiUrl] was provided');\n }\n};\n\nconst createIframe = (parentOrigin: string) => {\n const iframe = document.createElement('iframe');\n const url = new URL(getDeployLink());\n url.searchParams.set('parentOrigin', parentOrigin);\n iframe.src = url.toString();\n iframe.setAttribute(\n 'style',\n 'height:100%;width:100%;min-width:960px;border:0px;',\n );\n iframe.setAttribute('allow', 'clipboard-read; clipboard-write');\n iframe.setAttribute(\n 'sandbox',\n 'allow-scripts allow-same-origin allow-forms allow-popups allow-downloads',\n );\n\n return iframe;\n};\n\nexport class PluginInstance {\n public iframe: HTMLIFrameElement | null = null;\n private hotkeysAttached = false;\n private iframeOrigin: string | null = null;\n constructor(public config: PluginConfig) {}\n\n private captureHotkeysEnabled() {\n return this.config.disableHotkeysPassing !== true;\n }\n\n private onHostHotkey = (event: KeyboardEvent) => {\n if (!this.captureHotkeysEnabled() || !this.iframe?.contentWindow) {\n return;\n }\n\n const keyCode = constructKeyCode(event);\n\n if (!CORE_HOTKEYS.has(keyCode)) {\n return;\n }\n\n const target = event.target as HTMLElement | null;\n\n if (\n target &&\n (target.isContentEditable ||\n ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName))\n ) {\n return;\n }\n\n event.preventDefault();\n\n const { key, ctrlKey, metaKey, shiftKey, altKey } = event;\n\n this.postEvent('hostHotkey', {\n key,\n code: event.code,\n metaKey,\n ctrlKey,\n shiftKey,\n altKey,\n keyCode,\n });\n };\n\n private static HEARTBEAT_TIMEOUT = 4000;\n\n private promisedIframeMethod<T>(eventName: string) {\n let timer: Timeout | null = null;\n let listener: ((e: MessageEvent<MessageData>) => void) | null = null;\n\n const cleanup = () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n\n if (listener) {\n window.removeEventListener('message', listener, true);\n listener = null;\n }\n };\n\n const res = new Promise<T>((resolve, reject) => {\n const resetTimer = () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n cleanup();\n reject(\n new DraftError('timeout_error', `Action \"${eventName}\" timed out`),\n );\n }, PluginInstance.HEARTBEAT_TIMEOUT);\n };\n\n listener = (e: MessageEvent<MessageData>) => {\n if (e.source !== this.iframe?.contentWindow) return;\n\n const { data } = e;\n if (data.source !== 'DraftPlugin') return;\n\n if (data.event === 'actionPing' && data.action === eventName) {\n e.stopPropagation();\n resetTimer();\n\n return;\n }\n\n if (data.event === eventName) {\n e.stopPropagation();\n cleanup();\n\n const { source: _1, event: _2, ok, code, message, ...rest } = data;\n\n if (ok === false) {\n reject(\n new DraftError(\n code || 'unknown_error',\n message || 'Unknown error',\n ),\n );\n } else {\n resolve(rest as T);\n }\n }\n };\n\n window.addEventListener('message', listener, true);\n resetTimer();\n });\n\n this.postEvent(eventName);\n\n return res;\n }\n\n private postEvent(event: string, data: object = {}) {\n if (this.iframe && this.iframe.contentWindow && this.iframeOrigin) {\n this.iframe.contentWindow.postMessage(\n {\n ...data,\n event,\n source: 'DraftPlugin',\n },\n this.iframeOrigin,\n );\n } else if (!this.iframeOrigin) {\n throw new Error('Iframe origin is not initialized');\n }\n }\n\n private onImageUpload = async ({\n id,\n ...data\n }: UploadImageParams & { id: string }) => {\n try {\n const url = await this.config.on.uploadImage?.(data);\n let params = {};\n\n if (url) {\n params = await getImageParamsFromFileUrl(url);\n }\n\n this.postEvent('imageUploaded', { id, img: { ...params, url } });\n } catch (e) {\n this.postEvent('imageUploaded', { id });\n }\n };\n\n private onLoadPersonalization = async () => {\n try {\n if (!this.config.on.loadPersonalization) {\n throw new Error('No personalization loader provided');\n }\n\n const personalizationDictionary =\n await this.config.on.loadPersonalization();\n\n this.postEvent('loadPersonalization', {\n items: personalizationDictionary,\n });\n } catch (e) {\n this.postEvent('loadPersonalization', {});\n }\n };\n\n private onGalleryOpen = async ({ id }: { id: string }) => {\n const applyImage = async (url?: string) => {\n const imgParams = { url };\n\n if (url) {\n const params = await getImageParamsFromFileUrl(url);\n Object.assign(imgParams, params);\n }\n\n this.postEvent('imageUploaded', {\n id,\n img: imgParams,\n });\n };\n\n this.config.on.openGallery?.(applyImage);\n };\n\n private triggerEvent<H extends CallableFunction | undefined>(\n handler: H,\n params: HandlerParams<H>,\n ) {\n if (!handler) {\n return;\n }\n\n return handler(params);\n }\n\n private onMessage = (\n ev: MessageEvent<{ source: string; event: keyof Handlers }>,\n ) => {\n if (ev.source !== this.iframe?.contentWindow) {\n return;\n }\n\n const {\n data: { source, event, ...data },\n } = ev;\n\n if (source === 'DraftPlugin') {\n if (event === 'openGallery') {\n this.onGalleryOpen(data as OpenGalleryParams);\n } else if (event === 'uploadImage') {\n this.onImageUpload(data as UploadImageParams & { id: string });\n } else if (event === 'loadPersonalization') {\n this.onLoadPersonalization();\n } else {\n this.triggerEvent(\n this.config.on[event],\n data as HandlerParams<Handlers[typeof event]>,\n );\n }\n }\n };\n\n start({\n template,\n templateName,\n uid,\n }: {\n template: string | TemplateJSON;\n uid: string | number;\n templateName?: string;\n }) {\n const containerEl = document.querySelector(this.config.container);\n\n if (!containerEl) {\n throw new Error('Specified container not found');\n } else {\n const onInit = (msg: OnInitParams) => {\n const {\n data: { source, event },\n } = msg;\n if (source === 'DraftPlugin' && event === 'loaded') {\n if (msg.source !== this.iframe?.contentWindow) return;\n\n this.iframeOrigin = msg.origin;\n\n const {\n on,\n container,\n locale,\n autosave,\n token,\n apiUrl,\n pluginId,\n authData,\n __config,\n } = this.config;\n\n verifyConfig(this.config);\n\n if (this.iframe && this.iframe.contentWindow) {\n this.postEvent('init', {\n container,\n locale,\n uid,\n autosave,\n token,\n pluginId,\n authData,\n apiUrl,\n __config,\n enabledListeners: Object.keys(on),\n template,\n templateName,\n });\n }\n\n window.addEventListener('message', this.onMessage);\n window.removeEventListener('message', onInit);\n }\n };\n\n this.iframe = createIframe(window.location.origin);\n window.addEventListener('message', onInit);\n containerEl.appendChild(this.iframe);\n\n if (this.captureHotkeysEnabled() && !this.hotkeysAttached) {\n window.addEventListener('keydown', this.onHostHotkey);\n this.hotkeysAttached = true;\n }\n }\n }\n\n destroy = () => {\n this.iframe?.remove();\n this.iframe = null;\n window.removeEventListener('message', this.onMessage);\n\n if (this.hotkeysAttached) {\n window.removeEventListener('keydown', this.onHostHotkey);\n this.hotkeysAttached = false;\n }\n };\n\n changeTemplate(\n template: string | TemplateJSON,\n options: {\n templateName?: string;\n uid?: string;\n } = {},\n ) {\n this.postEvent('changeTemplate', { ...options, template });\n }\n\n toggleGrid(state?: boolean) {\n this.postEvent('toggleGrid', { state });\n }\n\n toggleInvisibleCharacters(state?: boolean) {\n this.postEvent('toggleInvisibleCharacters', { state });\n }\n\n togglePreview(state?: boolean) {\n this.postEvent('togglePreview', { state });\n }\n\n toggleMenu(menu: EditorMenu | null = null) {\n this.postEvent('toggleMenu', { menu });\n }\n\n toggleViewMode(viewMode: ViewMode) {\n this.postEvent('toggleViewMode', { viewMode });\n }\n\n undo() {\n this.postEvent('undo');\n }\n\n undoToStep(targetStep: number) {\n this.postEvent('undoToStep', { targetStep });\n }\n\n redo() {\n this.postEvent('redo');\n }\n\n save() {\n return this.promisedIframeMethod<SaveParams>('saveAction');\n }\n\n exit() {\n return this.promisedIframeMethod<ExitParams>('exitAction');\n }\n\n exportContent() {\n return this.promisedIframeMethod<SaveParams>('exportContent');\n }\n\n exportAsFile() {\n return this.promisedIframeMethod<ExportAsFileParams>('exportAsFile');\n }\n}\n","import { PluginInstance } from './plugin';\nimport { PluginConfig } from './types';\nimport { version } from '../package.json';\n\nconst DEFAULT_CONFIG: Partial<PluginConfig> = {\n container: '#draft-plugin-container',\n disableHotkeysPassing: false,\n locale: 'ru',\n on: {},\n};\n\nclass PluginWrapper {\n public version = version;\n\n create(config: PluginConfig) {\n return new PluginInstance({\n ...DEFAULT_CONFIG,\n ...config,\n });\n }\n}\n\nconst DraftPlugin = new PluginWrapper();\n\ndeclare global {\n interface Window {\n DraftPlugin: PluginWrapper;\n }\n}\n\nwindow.DraftPlugin = DraftPlugin;\n\nexport default DraftPlugin;\nexport type { PluginInstance } from './plugin';\nexport * from './types';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","names":[],"sources":["../src/routes.ts","../src/types.ts","../src/utils.ts","../package.json","../src/plugin.ts","../src/index.ts"],"sourcesContent":["export const LOCAL_ENDPOINT = 'http://localhost:5174';\nexport const PROD_ENDPOINT = 'https://seplugin.sendsay.ru';\n","export enum EditorMenu {\n Audit = 'audit',\n Guide = 'guide',\n Style = 'style',\n Blocks = 'blocks',\n}\n\nexport enum ViewMode {\n Desktop = 'desktop',\n Mobile = 'mobile',\n}\n\nexport interface Notification {\n intent: 'error' | 'info' | 'success' | 'warning';\n errorDetails?: object;\n message?: string;\n title: string;\n}\n\ntype PersonalizationDictionaryEntry =\n | { name: string; value: string }\n | { groupName: string; items: Array<{ name: string; value: string }> };\n\nexport type PersonalizationDictionaryItems = PersonalizationDictionaryEntry[];\n\nexport type SectionPersonalizationValue = string | number | boolean | null;\n\nexport interface SectionPersonalizationField {\n id: string;\n operatorId: 'equals';\n}\n\nexport interface SectionPersonalizationCatalogOption {\n label: string;\n value: Exclude<SectionPersonalizationValue, null>;\n}\n\nexport interface SectionPersonalizationCatalogGroup {\n type: 'group';\n id: string;\n label: string;\n children: SectionPersonalizationCatalogNode[];\n}\n\nexport interface SectionPersonalizationCatalogField {\n type: 'field';\n id: string;\n label: string;\n valueType?: 'string' | 'number' | 'boolean' | 'date';\n options?: SectionPersonalizationCatalogOption[];\n}\n\nexport type SectionPersonalizationCatalogNode =\n | SectionPersonalizationCatalogGroup\n | SectionPersonalizationCatalogField;\n\nexport interface SectionPersonalizationConfig {\n enabled: boolean;\n aboutUrl?: string;\n}\n\nexport interface RenderSectionPersonalizationGroupInput {\n groupId: string;\n fields: SectionPersonalizationField[];\n variants: Array<{\n id: string;\n values: Record<string, SectionPersonalizationValue>;\n html: string;\n }>;\n fallback?: {\n id: string;\n html: string;\n };\n}\n\nexport interface SerializedTemplate {\n [key: string]: unknown;\n parentId: string | null;\n id: string;\n parameters: object;\n layer: string;\n type: string;\n children?: SerializedTemplate[];\n meta?: { [key: string]: unknown; version: string };\n}\n\nexport type EventHandler<T> = (data: T) => void;\n\nexport type AsyncEventHandler<P, R> = (params: P) => Promise<R>;\n\nexport class DraftError extends Error {\n public readonly code: string;\n\n constructor(code: string, message: string) {\n super(message);\n this.name = 'DraftError';\n this.code = code;\n }\n}\n\nexport type MessageData = {\n source: string;\n event: string;\n ok?: boolean;\n code?: string;\n message?: string;\n action?: string;\n requestId?: string;\n};\n\nexport interface ExportAsFileParams {\n blob: Blob;\n fileName: string;\n}\n\nexport interface SaveParams {\n json: TemplateJSON;\n html: string;\n}\n\nexport type OnInitParams = MessageEvent<{\n source: string;\n event: 'loaded' | unknown;\n}>;\n\nexport interface ReadyParams extends SaveParams {\n lastSavedTemplate?: {\n template: TemplateJSON;\n date: Date;\n };\n}\n\nexport interface ErrorParams {\n message: string;\n code?: string;\n details?: unknown;\n}\n\nexport interface ExitParams extends SaveParams {}\n\nexport type NotificationParams = Notification;\n\nexport interface OpenGalleryParams {\n id: string;\n}\n\nexport interface UploadImageParams {\n file: string;\n name: string;\n}\n\nexport interface ImageParams {\n url: string;\n originalWidth: number;\n originalHeight: number;\n ratio: number;\n fileSize: number;\n}\n\nexport interface AutosaveParams {\n json: TemplateJSON;\n}\n\ninterface ToggleParams {\n state: boolean;\n}\n\nexport interface ToggleGridParams extends ToggleParams {}\n\nexport interface ToggleInvisibleCharactersParams extends ToggleParams {}\n\nexport interface TogglePreviewParams extends ToggleParams {\n json: TemplateJSON;\n html: string;\n darkHTML: string;\n}\n\nexport interface ToggleViewModeParams {\n mode: ViewMode;\n}\n\nexport interface ToggleMenuParams {\n menu: EditorMenu | null;\n}\n\nexport interface HistoryParams {\n hasUndos: boolean;\n hasRedos: boolean;\n currentStep: number;\n}\n\nexport type TemplateJSON = SerializedTemplate;\n\nexport type PersonalizationDictionary = PersonalizationDictionaryItems;\n\nexport type ToolbarActionName =\n | 'duplicate'\n | 'destroy'\n | 'edit'\n | 'up'\n | 'down';\nexport type HotkeyContext = 'hotkey';\nexport type OverlayContext = 'overlay-click' | 'overlay-double-click';\nexport type ToolbarContext = 'toolbar';\nexport type UnitSettingsContext = 'unit-settings';\nexport type BlockType = 'system' | 'user';\nexport type DndDragContext = 'canvas' | 'list' | 'palette';\nexport type DndDropContext = 'dropline' | 'placeholder' | 'empty-placeholder';\nexport type DndDropTarget = 'root' | 'section' | 'column' | 'element';\n\nexport interface DuplicateEvent {\n name: 'duplicate';\n context: HotkeyContext | ToolbarContext | UnitSettingsContext;\n unitType: string;\n}\n\nexport interface DestroyEvent {\n name: 'destroy';\n context: HotkeyContext | ToolbarContext | UnitSettingsContext;\n unitType: string;\n}\n\nexport interface EditEvent {\n name: 'edit';\n context: OverlayContext | ToolbarContext;\n unitType: string;\n}\n\nexport interface HistoryEvent {\n name: 'history';\n type: 'undo' | 'redo';\n context: HotkeyContext;\n}\n\nexport interface PreviewEvent {\n name: 'preview';\n context: HotkeyContext;\n}\n\nexport interface ToolbarMoveEvent {\n name: 'up' | 'down';\n context: ToolbarContext;\n unitType: string;\n}\n\nexport interface BlockInsertEvent {\n name: 'block-insert';\n context: 'double-click';\n blockType: BlockType;\n blockName: string;\n blockCategory: string | number;\n blockId: string | number;\n}\n\nexport interface BlockSaveEvent {\n name: 'block-save';\n blockType: 'user';\n blockName: string;\n blockCategory: string | number;\n blockId: string | number;\n elements: Record<string, number> & { sum: number };\n}\n\nexport interface BlockDestroyEvent {\n name: 'block-destroy';\n}\n\nexport interface DropEventDragMeta {\n context?: DndDragContext;\n layer?: 'element' | 'section' | 'column' | 'root';\n type?: string | string[];\n blockCategory?: string | number;\n blockId?: string | number;\n blockName?: string;\n blockType?: BlockType;\n alt?: boolean;\n dropKind?: 'create' | 'move';\n}\n\nexport interface DropEventDropzoneMeta {\n context?: DndDropContext;\n dropTarget?: DndDropTarget;\n}\n\nexport interface DropEvent {\n name: 'drop';\n drag?: DropEventDragMeta;\n dropzone?: DropEventDropzoneMeta;\n}\n\nexport type AnalyticsParams =\n | DuplicateEvent\n | DestroyEvent\n | EditEvent\n | HistoryEvent\n | PreviewEvent\n | ToolbarMoveEvent\n | BlockInsertEvent\n | BlockSaveEvent\n | BlockDestroyEvent\n | DropEvent;\n\nexport interface Handlers {\n ready: EventHandler<ReadyParams>;\n error: EventHandler<ErrorParams>;\n save: EventHandler<SaveParams>;\n exit: EventHandler<ExitParams>;\n notification: EventHandler<NotificationParams>;\n autosave: EventHandler<AutosaveParams>;\n toggleGrid: EventHandler<ToggleGridParams>;\n toggleInvisibleCharacters: EventHandler<ToggleInvisibleCharactersParams>;\n togglePreview: EventHandler<TogglePreviewParams>;\n toggleViewMode: EventHandler<ToggleViewModeParams>;\n toggleMenu: EventHandler<ToggleMenuParams>;\n history: EventHandler<HistoryParams>;\n analytics: EventHandler<AnalyticsParams>;\n openGallery: EventHandler<(url?: string) => Promise<void>>;\n uploadImage: AsyncEventHandler<UploadImageParams, string>;\n loadPersonalization: AsyncEventHandler<void, PersonalizationDictionary>;\n loadSectionPersonalizationCatalog: AsyncEventHandler<\n void,\n SectionPersonalizationCatalogNode[]\n >;\n renderSectionPersonalizationGroup: AsyncEventHandler<\n RenderSectionPersonalizationGroupInput,\n string\n >;\n}\n\nexport type HandlerParams<H> = H extends\n | EventHandler<infer P>\n | AsyncEventHandler<infer P, unknown>\n ? P\n : never;\n\nexport interface PluginConfig {\n container: string;\n locale?: string;\n autosave?:\n | boolean\n | {\n interval: number;\n };\n token: string;\n authData?: {\n orgId: number;\n projectId?: number;\n };\n pluginId: string;\n apiUrl: string;\n disableHotkeysPassing?: boolean;\n sectionPersonalization?: SectionPersonalizationConfig;\n __config?: object;\n on: Partial<Handlers>;\n}\n","import { ImageParams } from './types';\n\nconst getImageFileSize = async (imageUrl: string) => {\n try {\n const response = await fetch(imageUrl, { method: 'HEAD' });\n\n if (!response.ok) {\n return null;\n }\n\n const contentLength = response.headers.get('Content-Length');\n\n if (contentLength) {\n return parseInt(contentLength, 10);\n } else {\n return null;\n }\n } catch (error) {\n return null;\n }\n};\n\nexport const getImageParamsFromFileUrl = (imgSrc: string) =>\n new Promise<Omit<ImageParams, 'url'>>((resolve, reject) => {\n const img = new Image();\n\n img.onload = async () => {\n const fileSize = (await getImageFileSize(imgSrc)) ?? 0;\n\n resolve({\n originalWidth: img.width,\n originalHeight: img.height,\n ratio: img.width / img.height,\n fileSize,\n });\n };\n\n img.onerror = (error) => {\n reject(error);\n };\n\n img.src = imgSrc;\n });\n\nconst getLatinKey = (key: string, code: string) => {\n if (key.length !== 1) {\n return key;\n }\n\n const capitalHetaCode = 880;\n const isNonLatin = key.charCodeAt(0) >= capitalHetaCode;\n\n if (isNonLatin) {\n if (code.indexOf('Key') === 0 && code.length === 4) {\n return code.charAt(3);\n }\n\n if (code.indexOf('Digit') === 0 && code.length === 6) {\n return code.charAt(5);\n }\n }\n\n return key;\n};\n\nexport const constructKeyCode = (event: KeyboardEvent) => {\n let keyCode =\n `${getLatinKey(event.key, event.code)}`.toLowerCase() || event.key;\n const macOs = navigator.userAgent.includes('Mac OS');\n\n if (keyCode === 'backspace' && macOs) {\n keyCode = 'delete';\n }\n\n const prefix = [];\n\n if ((macOs && event.metaKey) || (!macOs && event.ctrlKey)) {\n prefix.push('mod');\n }\n\n if (event.shiftKey) {\n prefix.push('shift');\n }\n\n if (prefix.length > 0) {\n keyCode = `${prefix.join('-')}-${getLatinKey(keyCode, event.code)}`;\n }\n\n return keyCode;\n};\n\nexport const CORE_HOTKEYS = new Set([\n 'escape',\n 'mod-c',\n 'mod-d',\n 'mod-z',\n 'mod-y',\n 'mod-shift-z',\n 'mod-v',\n 'delete',\n 'mod-g',\n 'mod-p',\n 'mod-s',\n]);\n","{\n \"name\": \"@getdraft/plugin\",\n \"version\": \"1.19.0-alpha.0\",\n \"main\": \"dist/index.cjs.js\",\n \"module\": \"dist/index.es.js\",\n \"types\": \"dist/types/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/types/index.d.ts\",\n \"import\": \"./dist/index.es.js\",\n \"require\": \"./dist/index.cjs.js\"\n }\n },\n \"scripts\": {\n \"prebuild\": \"rm -rf dist\",\n \"build\": \"vite build\",\n \"dev-tsc\": \"tsc-check\",\n \"eslint\": \"npx eslint src\",\n \"eslint:fix\": \"pnpm eslint --fix\",\n \"prettify\": \"npx prettier --check src\",\n \"prettify:fix\": \"npx prettier -w src\",\n \"prepublish\": \"pnpm build\",\n \"watch\": \"NODE_ENV=development vite build --watch\",\n \"start\": \"NODE_ENV=development npx vite\"\n },\n \"dependencies\": {},\n \"devDependencies\": {\n \"@getdraft/types\": \"workspace:^\",\n \"@getdraft/eslint-config-ts\": \"workspace:^\",\n \"@getdraft/prettier\": \"workspace:^\",\n \"vite-plugin-dts\": \"4.5.4\"\n },\n \"license\": \"MIT\"\n}\n","import { LOCAL_ENDPOINT, PROD_ENDPOINT } from './routes';\nimport {\n DraftError,\n EditorMenu,\n ExitParams,\n OnInitParams,\n OpenGalleryParams,\n Handlers,\n PluginConfig,\n SaveParams,\n TemplateJSON,\n UploadImageParams,\n ViewMode,\n HandlerParams,\n MessageData,\n ExportAsFileParams,\n RenderSectionPersonalizationGroupInput,\n} from './types';\nimport {\n getImageParamsFromFileUrl,\n constructKeyCode,\n CORE_HOTKEYS,\n} from './utils';\nimport pkg from '../package.json';\n\nconst UNKNOWN_ERROR_MESSAGE = 'Unknown error';\n\nconst getDeployLink = () => {\n const regex = new RegExp(`(^| )seplugin-dev=([^;]+)`);\n const match = document.cookie.match(regex);\n const value = match?.[2].toLowerCase?.();\n\n if (value === 'true') {\n return LOCAL_ENDPOINT;\n }\n\n if (value?.startsWith('https://')) {\n return value;\n }\n\n const [major, mid] = pkg.version.split('.');\n\n return `${PROD_ENDPOINT}/v${major}.${mid}`;\n};\n\nconst verifyConfig = ({ token, pluginId, apiUrl }: PluginConfig) => {\n if (!token) {\n throw new Error('No [token] was provided');\n }\n\n if (!pluginId) {\n throw new Error('No [pluginId] was provided');\n }\n\n if (!apiUrl) {\n throw new Error('No [apiUrl] was provided');\n }\n};\n\nconst createIframe = (parentOrigin: string) => {\n const iframe = document.createElement('iframe');\n const url = new URL(getDeployLink());\n url.searchParams.set('parentOrigin', parentOrigin);\n iframe.src = url.toString();\n iframe.setAttribute(\n 'style',\n 'height:100%;width:100%;min-width:960px;border:0px;',\n );\n iframe.setAttribute('allow', 'clipboard-read; clipboard-write');\n iframe.setAttribute(\n 'sandbox',\n 'allow-scripts allow-same-origin allow-forms allow-popups allow-downloads',\n );\n\n return iframe;\n};\n\nexport class PluginInstance {\n public iframe: HTMLIFrameElement | null = null;\n private hotkeysAttached = false;\n private iframeOrigin: string | null = null;\n constructor(public config: PluginConfig) {}\n\n private captureHotkeysEnabled() {\n return this.config.disableHotkeysPassing !== true;\n }\n\n private onHostHotkey = (event: KeyboardEvent) => {\n if (!this.captureHotkeysEnabled() || !this.iframe?.contentWindow) {\n return;\n }\n\n const keyCode = constructKeyCode(event);\n\n if (!CORE_HOTKEYS.has(keyCode)) {\n return;\n }\n\n const target = event.target as HTMLElement | null;\n\n if (\n target &&\n (target.isContentEditable ||\n ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName))\n ) {\n return;\n }\n\n event.preventDefault();\n\n const { key, ctrlKey, metaKey, shiftKey, altKey } = event;\n\n this.postEvent('hostHotkey', {\n key,\n code: event.code,\n metaKey,\n ctrlKey,\n shiftKey,\n altKey,\n keyCode,\n });\n };\n\n private static HEARTBEAT_TIMEOUT = 4000;\n\n private promisedIframeMethod<T>(eventName: string) {\n let timer: Timeout | null = null;\n let listener: ((e: MessageEvent<MessageData>) => void) | null = null;\n\n const cleanup = () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n\n if (listener) {\n window.removeEventListener('message', listener, true);\n listener = null;\n }\n };\n\n const res = new Promise<T>((resolve, reject) => {\n const resetTimer = () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n cleanup();\n reject(\n new DraftError('timeout_error', `Action \"${eventName}\" timed out`),\n );\n }, PluginInstance.HEARTBEAT_TIMEOUT);\n };\n\n listener = (e: MessageEvent<MessageData>) => {\n if (e.source !== this.iframe?.contentWindow) return;\n\n const { data } = e;\n if (data.source !== 'DraftPlugin') return;\n\n if (data.event === 'actionPing' && data.action === eventName) {\n e.stopPropagation();\n resetTimer();\n\n return;\n }\n\n if (data.event === eventName) {\n e.stopPropagation();\n cleanup();\n\n const { source: _1, event: _2, ok, code, message, ...rest } = data;\n\n if (ok === false) {\n reject(\n new DraftError(\n code || 'unknown_error',\n message || UNKNOWN_ERROR_MESSAGE,\n ),\n );\n } else {\n resolve(rest as T);\n }\n }\n };\n\n window.addEventListener('message', listener, true);\n resetTimer();\n });\n\n this.postEvent(eventName);\n\n return res;\n }\n\n private postEvent(event: string, data: object = {}) {\n if (this.iframe && this.iframe.contentWindow && this.iframeOrigin) {\n this.iframe.contentWindow.postMessage(\n {\n ...data,\n event,\n source: 'DraftPlugin',\n },\n this.iframeOrigin,\n );\n } else if (!this.iframeOrigin) {\n throw new Error('Iframe origin is not initialized');\n }\n }\n\n private onImageUpload = async ({\n id,\n ...data\n }: UploadImageParams & { id: string }) => {\n try {\n const url = await this.config.on.uploadImage?.(data);\n let params = {};\n\n if (url) {\n params = await getImageParamsFromFileUrl(url);\n }\n\n this.postEvent('imageUploaded', { id, img: { ...params, url } });\n } catch (e) {\n this.postEvent('imageUploaded', { id });\n }\n };\n\n private onLoadPersonalization = async (requestId?: string) => {\n try {\n if (!this.config.on.loadPersonalization) {\n throw new Error('No personalization loader provided');\n }\n\n const personalizationDictionary =\n await this.config.on.loadPersonalization();\n\n this.postEvent('loadPersonalization', {\n items: personalizationDictionary,\n requestId,\n });\n } catch (e) {\n this.postEvent('loadPersonalization', { requestId });\n }\n };\n\n private onLoadSectionPersonalizationCatalog = async (requestId?: string) => {\n try {\n const handler = this.config.on.loadSectionPersonalizationCatalog;\n\n if (!handler) {\n throw new Error('No section personalization catalog loader provided');\n }\n\n const catalog = await handler();\n\n this.postEvent('loadSectionPersonalizationCatalog', {\n ok: true,\n requestId,\n catalog,\n });\n } catch (error) {\n this.postEvent('loadSectionPersonalizationCatalog', {\n ok: false,\n requestId,\n message: error instanceof Error ? error.message : UNKNOWN_ERROR_MESSAGE,\n });\n }\n };\n\n private onRenderSectionPersonalizationGroup = async (\n data: RenderSectionPersonalizationGroupInput & { requestId?: string },\n ) => {\n const { requestId, ...input } = data;\n\n try {\n const handler = this.config.on.renderSectionPersonalizationGroup;\n\n if (!handler) {\n throw new Error('No section personalization renderer provided');\n }\n\n const renderedHtml = await handler(input);\n\n this.postEvent('renderSectionPersonalizationGroup', {\n ok: true,\n requestId,\n html: renderedHtml,\n });\n } catch (error) {\n this.postEvent('renderSectionPersonalizationGroup', {\n ok: false,\n requestId,\n message: error instanceof Error ? error.message : UNKNOWN_ERROR_MESSAGE,\n });\n }\n };\n\n private onGalleryOpen = async ({ id }: { id: string }) => {\n const applyImage = async (url?: string) => {\n const imgParams = { url };\n\n if (url) {\n const params = await getImageParamsFromFileUrl(url);\n Object.assign(imgParams, params);\n }\n\n this.postEvent('imageUploaded', {\n id,\n img: imgParams,\n });\n };\n\n this.config.on.openGallery?.(applyImage);\n };\n\n private triggerEvent<H extends CallableFunction | undefined>(\n handler: H,\n params: HandlerParams<H>,\n ) {\n if (!handler) {\n return;\n }\n\n return handler(params);\n }\n\n private onMessage = (\n ev: MessageEvent<{ source: string; event: keyof Handlers }>,\n ) => {\n if (ev.source !== this.iframe?.contentWindow) {\n return;\n }\n\n const {\n data: { source, event, ...data },\n } = ev;\n\n if (source === 'DraftPlugin') {\n if (event === 'openGallery') {\n this.onGalleryOpen(data as OpenGalleryParams);\n } else if (event === 'uploadImage') {\n this.onImageUpload(data as UploadImageParams & { id: string });\n } else if (event === 'loadPersonalization') {\n this.onLoadPersonalization((data as { requestId?: string }).requestId);\n } else if (event === 'loadSectionPersonalizationCatalog') {\n this.onLoadSectionPersonalizationCatalog(\n (data as { requestId?: string }).requestId,\n );\n } else if (event === 'renderSectionPersonalizationGroup') {\n this.onRenderSectionPersonalizationGroup(\n data as RenderSectionPersonalizationGroupInput & {\n requestId?: string;\n },\n );\n } else {\n this.triggerEvent(\n this.config.on[event],\n data as HandlerParams<Handlers[typeof event]>,\n );\n }\n }\n };\n\n start({\n template,\n templateName,\n uid,\n }: {\n template: string | TemplateJSON;\n uid: string | number;\n templateName?: string;\n }) {\n const containerEl = document.querySelector(this.config.container);\n\n if (!containerEl) {\n throw new Error('Specified container not found');\n } else {\n const onInit = (msg: OnInitParams) => {\n const {\n data: { source, event },\n } = msg;\n if (source === 'DraftPlugin' && event === 'loaded') {\n if (msg.source !== this.iframe?.contentWindow) return;\n\n this.iframeOrigin = msg.origin;\n\n const {\n on,\n container,\n locale,\n autosave,\n token,\n apiUrl,\n pluginId,\n authData,\n sectionPersonalization,\n __config,\n } = this.config;\n\n verifyConfig(this.config);\n\n if (this.iframe && this.iframe.contentWindow) {\n const resolvedSectionPersonalization = {\n ...sectionPersonalization,\n enabled:\n sectionPersonalization?.enabled === true &&\n !!on.loadSectionPersonalizationCatalog &&\n !!on.renderSectionPersonalizationGroup,\n };\n\n this.postEvent('init', {\n container,\n locale,\n uid,\n autosave,\n token,\n pluginId,\n authData,\n sectionPersonalization: resolvedSectionPersonalization,\n apiUrl,\n __config,\n enabledListeners: Object.keys(on),\n template,\n templateName,\n });\n }\n\n window.addEventListener('message', this.onMessage);\n window.removeEventListener('message', onInit);\n }\n };\n\n this.iframe = createIframe(window.location.origin);\n window.addEventListener('message', onInit);\n containerEl.appendChild(this.iframe);\n\n if (this.captureHotkeysEnabled() && !this.hotkeysAttached) {\n window.addEventListener('keydown', this.onHostHotkey);\n this.hotkeysAttached = true;\n }\n }\n }\n\n destroy = () => {\n this.iframe?.remove();\n this.iframe = null;\n window.removeEventListener('message', this.onMessage);\n\n if (this.hotkeysAttached) {\n window.removeEventListener('keydown', this.onHostHotkey);\n this.hotkeysAttached = false;\n }\n };\n\n changeTemplate(\n template: string | TemplateJSON,\n options: {\n templateName?: string;\n uid?: string;\n } = {},\n ) {\n this.postEvent('changeTemplate', { ...options, template });\n }\n\n toggleGrid(state?: boolean) {\n this.postEvent('toggleGrid', { state });\n }\n\n toggleInvisibleCharacters(state?: boolean) {\n this.postEvent('toggleInvisibleCharacters', { state });\n }\n\n async isInvisibleCharactersVisible() {\n const { state } = await this.promisedIframeMethod<{ state: boolean }>(\n 'getInvisibleCharactersVisibility',\n );\n\n return state;\n }\n\n togglePreview(state?: boolean) {\n this.postEvent('togglePreview', { state });\n }\n\n toggleMenu(menu: EditorMenu | null = null) {\n this.postEvent('toggleMenu', { menu });\n }\n\n toggleViewMode(viewMode: ViewMode) {\n this.postEvent('toggleViewMode', { viewMode });\n }\n\n undo() {\n this.postEvent('undo');\n }\n\n undoToStep(targetStep: number) {\n this.postEvent('undoToStep', { targetStep });\n }\n\n redo() {\n this.postEvent('redo');\n }\n\n save() {\n return this.promisedIframeMethod<SaveParams>('saveAction');\n }\n\n exit() {\n return this.promisedIframeMethod<ExitParams>('exitAction');\n }\n\n exportContent() {\n return this.promisedIframeMethod<SaveParams>('exportContent');\n }\n\n exportAsFile() {\n return this.promisedIframeMethod<ExportAsFileParams>('exportAsFile');\n }\n}\n","import { PluginInstance } from './plugin';\nimport { PluginConfig } from './types';\nimport { version } from '../package.json';\n\nconst DEFAULT_CONFIG: Partial<PluginConfig> = {\n container: '#draft-plugin-container',\n disableHotkeysPassing: false,\n locale: 'ru',\n on: {},\n};\n\nclass PluginWrapper {\n public version = version;\n\n create(config: PluginConfig) {\n return new PluginInstance({\n ...DEFAULT_CONFIG,\n ...config,\n });\n }\n}\n\nconst DraftPlugin = new PluginWrapper();\n\ndeclare global {\n interface Window {\n DraftPlugin: PluginWrapper;\n }\n}\n\nwindow.DraftPlugin = DraftPlugin;\n\nexport default DraftPlugin;\nexport type { PluginInstance } from './plugin';\nexport * from './types';\n"],"mappings":"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"}
package/dist/index.es.js CHANGED
@@ -54,7 +54,7 @@ var e = "http://localhost:5174", t = "https://seplugin.sendsay.ru", n = /* @__PU
54
54
  "mod-g",
55
55
  "mod-p",
56
56
  "mod-s"
57
- ]), u = "@getdraft/plugin", d = "1.17.0", f = {
57
+ ]), u = "@getdraft/plugin", d = "1.19.0-alpha.0", f = {
58
58
  name: u,
59
59
  version: d,
60
60
  main: "dist/index.cjs.js",
@@ -85,20 +85,20 @@ var e = "http://localhost:5174", t = "https://seplugin.sendsay.ru", n = /* @__PU
85
85
  "vite-plugin-dts": "4.5.4"
86
86
  },
87
87
  license: "MIT"
88
- }, p = () => {
88
+ }, p = "Unknown error", m = () => {
89
89
  let n = RegExp("(^| )seplugin-dev=([^;]+)"), r = document.cookie.match(n)?.[2].toLowerCase?.();
90
90
  if (r === "true") return e;
91
91
  if (r?.startsWith("https://")) return r;
92
92
  let [i, a] = f.version.split(".");
93
93
  return `${t}/v${i}.${a}`;
94
- }, m = ({ token: e, pluginId: t, apiUrl: n }) => {
94
+ }, h = ({ token: e, pluginId: t, apiUrl: n }) => {
95
95
  if (!e) throw Error("No [token] was provided");
96
96
  if (!t) throw Error("No [pluginId] was provided");
97
97
  if (!n) throw Error("No [apiUrl] was provided");
98
- }, h = (e) => {
99
- let t = document.createElement("iframe"), n = new URL(p());
98
+ }, g = (e) => {
99
+ let t = document.createElement("iframe"), n = new URL(m());
100
100
  return n.searchParams.set("parentOrigin", e), t.src = n.toString(), t.setAttribute("style", "height:100%;width:100%;min-width:960px;border:0px;"), t.setAttribute("allow", "clipboard-read; clipboard-write"), t.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms allow-popups allow-downloads"), t;
101
- }, g = class e {
101
+ }, _ = class e {
102
102
  iframe = null;
103
103
  hotkeysAttached = !1;
104
104
  iframeOrigin = null;
@@ -151,7 +151,7 @@ var e = "http://localhost:5174", t = "https://seplugin.sendsay.ru", n = /* @__PU
151
151
  if (n.event === t) {
152
152
  e.stopPropagation(), a();
153
153
  let { source: t, event: r, ok: c, code: l, message: u, ...d } = n;
154
- c === !1 ? s(new i(l || "unknown_error", u || "Unknown error")) : o(d);
154
+ c === !1 ? s(new i(l || "unknown_error", u || p)) : o(d);
155
155
  }
156
156
  }
157
157
  }, window.addEventListener("message", r, !0), c();
@@ -180,13 +180,53 @@ var e = "http://localhost:5174", t = "https://seplugin.sendsay.ru", n = /* @__PU
180
180
  this.postEvent("imageUploaded", { id: e });
181
181
  }
182
182
  };
183
- onLoadPersonalization = async () => {
183
+ onLoadPersonalization = async (e) => {
184
184
  try {
185
185
  if (!this.config.on.loadPersonalization) throw Error("No personalization loader provided");
186
- let e = await this.config.on.loadPersonalization();
187
- this.postEvent("loadPersonalization", { items: e });
186
+ let t = await this.config.on.loadPersonalization();
187
+ this.postEvent("loadPersonalization", {
188
+ items: t,
189
+ requestId: e
190
+ });
188
191
  } catch {
189
- this.postEvent("loadPersonalization", {});
192
+ this.postEvent("loadPersonalization", { requestId: e });
193
+ }
194
+ };
195
+ onLoadSectionPersonalizationCatalog = async (e) => {
196
+ try {
197
+ let t = this.config.on.loadSectionPersonalizationCatalog;
198
+ if (!t) throw Error("No section personalization catalog loader provided");
199
+ let n = await t();
200
+ this.postEvent("loadSectionPersonalizationCatalog", {
201
+ ok: !0,
202
+ requestId: e,
203
+ catalog: n
204
+ });
205
+ } catch (t) {
206
+ this.postEvent("loadSectionPersonalizationCatalog", {
207
+ ok: !1,
208
+ requestId: e,
209
+ message: t instanceof Error ? t.message : p
210
+ });
211
+ }
212
+ };
213
+ onRenderSectionPersonalizationGroup = async (e) => {
214
+ let { requestId: t, ...n } = e;
215
+ try {
216
+ let e = this.config.on.renderSectionPersonalizationGroup;
217
+ if (!e) throw Error("No section personalization renderer provided");
218
+ let r = await e(n);
219
+ this.postEvent("renderSectionPersonalizationGroup", {
220
+ ok: !0,
221
+ requestId: t,
222
+ html: r
223
+ });
224
+ } catch (e) {
225
+ this.postEvent("renderSectionPersonalizationGroup", {
226
+ ok: !1,
227
+ requestId: t,
228
+ message: e instanceof Error ? e.message : p
229
+ });
190
230
  }
191
231
  };
192
232
  onGalleryOpen = async ({ id: e }) => {
@@ -208,7 +248,7 @@ var e = "http://localhost:5174", t = "https://seplugin.sendsay.ru", n = /* @__PU
208
248
  onMessage = (e) => {
209
249
  if (e.source !== this.iframe?.contentWindow) return;
210
250
  let { data: { source: t, event: n, ...r } } = e;
211
- t === "DraftPlugin" && (n === "openGallery" ? this.onGalleryOpen(r) : n === "uploadImage" ? this.onImageUpload(r) : n === "loadPersonalization" ? this.onLoadPersonalization() : this.triggerEvent(this.config.on[n], r));
251
+ t === "DraftPlugin" && (n === "openGallery" ? this.onGalleryOpen(r) : n === "uploadImage" ? this.onImageUpload(r) : n === "loadPersonalization" ? this.onLoadPersonalization(r.requestId) : n === "loadSectionPersonalizationCatalog" ? this.onLoadSectionPersonalizationCatalog(r.requestId) : n === "renderSectionPersonalizationGroup" ? this.onRenderSectionPersonalizationGroup(r) : this.triggerEvent(this.config.on[n], r));
212
252
  };
213
253
  start({ template: e, templateName: t, uid: n }) {
214
254
  let r = document.querySelector(this.config.container);
@@ -218,24 +258,32 @@ var e = "http://localhost:5174", t = "https://seplugin.sendsay.ru", n = /* @__PU
218
258
  if (a === "DraftPlugin" && o === "loaded") {
219
259
  if (r.source !== this.iframe?.contentWindow) return;
220
260
  this.iframeOrigin = r.origin;
221
- let { on: a, container: o, locale: s, autosave: c, token: l, apiUrl: u, pluginId: d, authData: f, __config: p } = this.config;
222
- m(this.config), this.iframe && this.iframe.contentWindow && this.postEvent("init", {
223
- container: o,
224
- locale: s,
225
- uid: n,
226
- autosave: c,
227
- token: l,
228
- pluginId: d,
229
- authData: f,
230
- apiUrl: u,
231
- __config: p,
232
- enabledListeners: Object.keys(a),
233
- template: e,
234
- templateName: t
235
- }), window.addEventListener("message", this.onMessage), window.removeEventListener("message", i);
261
+ let { on: a, container: o, locale: s, autosave: c, token: l, apiUrl: u, pluginId: d, authData: f, sectionPersonalization: p, __config: m } = this.config;
262
+ if (h(this.config), this.iframe && this.iframe.contentWindow) {
263
+ let r = {
264
+ ...p,
265
+ enabled: p?.enabled === !0 && !!a.loadSectionPersonalizationCatalog && !!a.renderSectionPersonalizationGroup
266
+ };
267
+ this.postEvent("init", {
268
+ container: o,
269
+ locale: s,
270
+ uid: n,
271
+ autosave: c,
272
+ token: l,
273
+ pluginId: d,
274
+ authData: f,
275
+ sectionPersonalization: r,
276
+ apiUrl: u,
277
+ __config: m,
278
+ enabledListeners: Object.keys(a),
279
+ template: e,
280
+ templateName: t
281
+ });
282
+ }
283
+ window.addEventListener("message", this.onMessage), window.removeEventListener("message", i);
236
284
  }
237
285
  };
238
- this.iframe = h(window.location.origin), window.addEventListener("message", i), r.appendChild(this.iframe), this.captureHotkeysEnabled() && !this.hotkeysAttached && (window.addEventListener("keydown", this.onHostHotkey), this.hotkeysAttached = !0);
286
+ this.iframe = g(window.location.origin), window.addEventListener("message", i), r.appendChild(this.iframe), this.captureHotkeysEnabled() && !this.hotkeysAttached && (window.addEventListener("keydown", this.onHostHotkey), this.hotkeysAttached = !0);
239
287
  } else throw Error("Specified container not found");
240
288
  }
241
289
  destroy = () => {
@@ -253,6 +301,10 @@ var e = "http://localhost:5174", t = "https://seplugin.sendsay.ru", n = /* @__PU
253
301
  toggleInvisibleCharacters(e) {
254
302
  this.postEvent("toggleInvisibleCharacters", { state: e });
255
303
  }
304
+ async isInvisibleCharactersVisible() {
305
+ let { state: e } = await this.promisedIframeMethod("getInvisibleCharactersVisibility");
306
+ return e;
307
+ }
256
308
  togglePreview(e) {
257
309
  this.postEvent("togglePreview", { state: e });
258
310
  }
@@ -283,22 +335,22 @@ var e = "http://localhost:5174", t = "https://seplugin.sendsay.ru", n = /* @__PU
283
335
  exportAsFile() {
284
336
  return this.promisedIframeMethod("exportAsFile");
285
337
  }
286
- }, _ = {
338
+ }, v = {
287
339
  container: "#draft-plugin-container",
288
340
  disableHotkeysPassing: !1,
289
341
  locale: "ru",
290
342
  on: {}
291
- }, v = new class {
343
+ }, y = new class {
292
344
  version = d;
293
345
  create(e) {
294
- return new g({
295
- ..._,
346
+ return new _({
347
+ ...v,
296
348
  ...e
297
349
  });
298
350
  }
299
351
  }();
300
- window.DraftPlugin = v;
352
+ window.DraftPlugin = y;
301
353
  //#endregion
302
- export { i as DraftError, n as EditorMenu, r as ViewMode, v as default };
354
+ export { i as DraftError, n as EditorMenu, r as ViewMode, y as default };
303
355
 
304
356
  //# sourceMappingURL=index.es.js.map