@getdraft/plugin 1.13.0-beta.0 → 1.14.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.
package/README.md CHANGED
@@ -11,18 +11,20 @@
11
11
  #### npm
12
12
 
13
13
  ```
14
- npm i @letty-email/plugin -E
14
+ npm i @draft-email/plugin -E
15
15
  ```
16
16
 
17
17
  #### yarn
18
18
 
19
19
  ```
20
- yarn add @letty-email/plugin --exact
20
+ yarn add @draft-email/plugin --exact
21
21
  ```
22
22
 
23
23
  ### HTML-script
24
24
 
25
- _**Coming soon**_
25
+ ```
26
+ <script src="https://eimage.sendsay.ru/app/se/draft-plugin-v1.12.1.js"></script>
27
+ ```
26
28
 
27
29
  ## Инициализация
28
30
 
@@ -31,7 +33,7 @@ _**Coming soon**_
31
33
  Если используете npm-пакет
32
34
 
33
35
  ```javascript
34
- import DraftPlugin from '@letty-email/plugin';
36
+ import DraftPlugin from '@draft-email/plugin';
35
37
  ```
36
38
 
37
39
  в случае встраивания плагина напрямую в html используйте объект `window`
@@ -42,21 +44,21 @@ const DraftPlugin = window.DraftPlugin;
42
44
 
43
45
  ### **Шаг 2. Создание контейнера**
44
46
 
45
- Чтобы редактор отобразился на вашей странице необходимо создать div-элемент с id `letty-plugin-container`
47
+ Чтобы редактор отобразился на вашей странице необходимо создать div-элемент с id `draft-plugin-container`
46
48
 
47
49
  ```html
48
- <div id="letty-plugin-container"></div>
50
+ <div id="draft-plugin-container"></div>
49
51
  ```
50
52
 
51
53
  ### **Шаг 3. Аутентификация**
52
54
 
53
- Endpoint URL: `https://api.kvilla.ru`
55
+ Endpoint URL: Ваш endpoint из ЛК
54
56
 
55
57
  - **Основной пользователь**
56
58
 
57
59
  - **Первый вход**
58
60
 
59
- 1. Зарегистрируйте пользователя через `POST` `v1/register`
61
+ 1. Авторизуйтесь через `POST` `v1/login` используя админ-логин и пароль
60
62
 
61
63
  ```JSON
62
64
  {
@@ -65,7 +67,11 @@ Endpoint URL: `https://api.kvilla.ru`
65
67
  }
66
68
  ```
67
69
 
68
- 2. Авторизуйтесь через `POST` `v1/login`
70
+ и получите сессионный токен.
71
+
72
+ Для последующих запросов в Headers нужно выставить Authorization = полученный токен в этом шаге.
73
+
74
+ 2. Зарегистрируйте пользователя через `POST` `v1/users`
69
75
 
70
76
  ```JSON
71
77
  {
@@ -74,8 +80,6 @@ Endpoint URL: `https://api.kvilla.ru`
74
80
  }
75
81
  ```
76
82
 
77
- и получите сессионную куку.
78
-
79
83
  3. Создайте организацию через `POST` `v1/organizations` с параметрами:
80
84
 
81
85
  ```JSON
@@ -86,40 +90,26 @@ Endpoint URL: `https://api.kvilla.ru`
86
90
  }
87
91
  ```
88
92
 
89
- в Headers нужно выставить Cookie = полученная сессия из прошлого шага.
90
-
91
- 4. Создайте постоянный токен (API key) для организации: `POST` `/v1/organizations/{organizationID}/tokens`.
93
+ 4. Добавьте в эту организацию пользователя `POST` `/v1/organizations/{organizationID}/users`:
92
94
 
93
95
  ```JSON
94
- {
95
- "name": "string",
96
- "expires_at": "2025-08-26T00:16:54.409Z"
97
- }
96
+ {
97
+ "user_id": "ID созданного юзера",
98
+ "role_id": 1,
99
+ }
98
100
  ```
99
101
 
100
- 5. Сохраните API key у себя на бэкенде.
101
- 6. Передайте ключ в редактор.
102
-
103
- - **Саблогин**
102
+ 5. Создайте постоянный токен (API key) для организации: `POST` `/v1/organizations/{organizationID}/users/{userID}/tokens`.
104
103
 
105
- - **Первый вход**
106
- 1. Если основной логин ещё не создан или не заходил — выполните шаги 1–5 для основного пользователя.
107
- 2. Зарегистрируйте саблогин проделав шаги 1-2 для саблогина.
108
- 3. Под авторизацией основного пользователя добавьте саблогин в организацию основного пользователя аккаунта: `POST` `/v1/organizations/{organizationID}/users`.
109
- ```JSON
110
- {
111
- "user_id": "ID саблогина",
112
- "role_id": 1
113
- }
114
- ```
115
- 4. Создайте токен для пользователя: `POST` `/v1/organizations/{organizationID}/users/{userID}/tokens`.
116
104
  ```JSON
117
105
  {
118
106
  "name": "string",
119
107
  "expires_at": "2025-08-26T00:16:54.409Z"
120
108
  }
121
109
  ```
122
- 5. Сохраните токен у себя бэкенде и передавайте его в редактор.
110
+
111
+ 6. Сохраните API key у себя на бэкенде.
112
+ 7. Передайте ключ в редактор.
123
113
 
124
114
  - **Повторный вход**
125
115
 
@@ -131,22 +121,23 @@ Endpoint URL: `https://api.kvilla.ru`
131
121
  Инициализируйте редактор в JavaScript-коде:
132
122
 
133
123
  ```javascript
134
- import DraftPlugin from '@letty-email/plugin'
124
+ import DraftPlugin from '@draft-email/plugin'
135
125
 
136
- const letty = DraftPlugin.create({
126
+ const draft = DraftPlugin.create({
137
127
  token: "полученный токен авторизации",
138
128
  pluginId: "ID созданного плагина из ЛК",
139
129
  locale: "en" либо "ru",
130
+ apiUrl: 'https://api.kvilla.ru',
131
+ on: {} // Обработчики событий от редактора
140
132
  });
141
133
  ```
142
134
 
143
135
  ### **Шаг 5. Запуск редактора**
144
136
 
145
137
  ```javascript
146
- letty.start({
138
+ draft.start({
147
139
  template: {}, // JSON-письма
148
140
  uid: 'Уникальный ID письма в вашей системе',
149
- templateName?: 'Название письма(если используете встроенную шапку редактора)'
150
141
  });
151
142
  ```
152
143
 
@@ -182,7 +173,7 @@ letty.start({
182
173
  ### **container - опциональный**
183
174
 
184
175
  Id элемента в котором будет развернут iframe с редактором
185
- По умолчанию `letty-plugin-container`
176
+ По умолчанию `draft-plugin-container`
186
177
 
187
178
  ### **locale - опциональный**
188
179
 
package/dist/index.cjs.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var P=Object.defineProperty;var L=(n,e,t)=>e in n?P(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var a=(n,e,t)=>L(n,typeof e!="symbol"?e+"":e,t);Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const I="http://localhost:5174",h="https://seplugin.sendsay.ru",x=async n=>{try{const e=await fetch(n,{method:"HEAD"});if(!e.ok)return null;const t=e.headers.get("Content-Length");return t?parseInt(t,10):null}catch{return null}},g=n=>new Promise((e,t)=>{const o=new Image;o.onload=async()=>{const i=await x(n)??0;e({originalWidth:o.width,originalHeight:o.height,ratio:o.width/o.height,fileSize:i})},o.onerror=i=>{t(i)},o.src=n}),A="@getdraft/plugin",D="1.13.1-beta.0",C="dist/index.cjs.js",O="dist/index.es.js",H="src",N={prebuild:"rm -rf dist",build:"vite build","dev-tsc":"npx tsc --noEmit",eslint:"npx eslint src","eslint:fix":"pnpm eslint --fix",prettify:"npx prettier -w ./",prepublish:"pnpm build",watch:"NODE_ENV=development vite build --watch",start:"NODE_ENV=development npx vite"},M={},T={"@types/letty":"workspace:^","@vitejs/plugin-legacy":"5.4.1",rollup:"4.22.4",terser:"5.31.3","rollup-plugin-dts":"6.1.1","@letty/eslint-config-ts":"workspace:^","@letty/prettier":"workspace:^"},z="MIT",K={name:A,version:D,main:C,module:O,types:H,scripts:N,dependencies:M,devDependencies:T,license:z},u=(n,e)=>{if(n.length!==1)return n;if(n.charCodeAt(0)>=880){if(e.indexOf("Key")===0&&e.length===4)return e.charAt(3);if(e.indexOf("Digit")===0&&e.length===6)return e.charAt(5)}return n},S=n=>{let e=`${u(n.key,n.code)}`.toLowerCase()||n.key;const t=navigator.userAgent.includes("Mac OS");e==="backspace"&&t&&(e="delete");const o=[];return(t&&n.metaKey||!t&&n.ctrlKey)&&o.push("mod"),n.shiftKey&&o.push("shift"),o.length>0&&(e=`${o.join("-")}-${u(e,n.code)}`),e},U=new Set(["escape","mod-c","mod-d","mod-z","mod-y","mod-shift-z","mod-v","delete","mod-g","mod-p","mod-s"]),_=()=>{var s,r;const n=new RegExp("(^| )seplugin-dev=([^;]+)"),e=document.cookie.match(n),t=(r=e==null?void 0:(s=e[2]).toLowerCase)==null?void 0:r.call(s);if(t==="true")return I;if(t==="stage"||t!=null&&t.includes("https://")||window.location.pathname.includes("netlify"))return t!=null&&t.includes("https://")?t:`${h}/stage`;const[o,i]=K.version.split(".");return`${h}/v${o}.${i}`},j=({token:n,pluginId:e,apiUrl:t})=>{if(!n)throw new Error("No [token] was provided");if(!e)throw new Error("No [pluginId] was provided");if(!t)throw new Error("No [apiUrl] was provided")},G=()=>{const n=document.createElement("iframe");return n.src=_(),n.setAttribute("style","height:100%;width:100%;min-width:960px;border:0px"),n.setAttribute("allow","clipboard-read; clipboard-write"),n.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms allow-popups"),n};class ${constructor(e){a(this,"iframe",null);a(this,"hotkeysAttached",!1);a(this,"onHostHotkey",e=>{var c;if(!this.captureHotkeysEnabled()||!((c=this.iframe)!=null&&c.contentWindow))return;const t=S(e);if(!U.has(t))return;const o=e.target;if(o&&(o.isContentEditable||["INPUT","TEXTAREA","SELECT"].includes(o.tagName)))return;e.preventDefault();const{key:i,ctrlKey:s,metaKey:r,shiftKey:l,altKey:d}=e;this.postEvent("hostHotkey",{key:i,code:e.code,metaKey:r,ctrlKey:s,shiftKey:l,altKey:d,keyCode:t})});a(this,"onImageUpload",async({id:e,...t})=>{var o,i;try{const s=await((i=(o=this.config.on).uploadImage)==null?void 0:i.call(o,t));let r={};s&&(r=await g(s)),this.postEvent("imageUploaded",{id:e,img:{...r,url:s}})}catch{this.postEvent("imageUploaded",{id:e})}});a(this,"onLoadPersonalization",async()=>{try{if(!this.config.on.loadPersonalization)throw new Error("No personalization loader provided");const e=await this.config.on.loadPersonalization();this.postEvent("loadPersonalization",{items:e})}catch{this.postEvent("loadPersonalization",{})}});a(this,"onGalleryOpen",async({id:e})=>{var o,i;const t=async s=>{const r={url:s};if(s){const l=await g(s);Object.assign(r,l)}this.postEvent("imageUploaded",{id:e,img:r})};(i=(o=this.config.on).openGallery)==null||i.call(o,t)});a(this,"onMessage",e=>{const{data:{source:t,event:o,...i}}=e;t==="DraftPlugin"&&(o==="openGallery"?this.onGalleryOpen(i):o==="uploadImage"?this.onImageUpload(i):o==="loadPersonalization"?this.onLoadPersonalization():this.triggerEvent(this.config.on[o],i))});a(this,"destroy",()=>{var e;(e=this.iframe)==null||e.remove(),this.iframe=null,window.removeEventListener("message",this.onMessage),this.hotkeysAttached&&(window.removeEventListener("keydown",this.onHostHotkey),this.hotkeysAttached=!1)});this.config=e}captureHotkeysEnabled(){return this.config.disableHotkeysPassing!==!0}promisedIframeMethod(e){let t=null;const o=new Promise((i,s)=>{const r=l=>{const{data:{source:d,event:c,...p}}=l;d==="DraftPlugin"&&c===e&&(l.stopPropagation(),t&&(clearTimeout(t),t=null),i(p),window.removeEventListener("message",r,!0))};window.addEventListener("message",r,!0),t=setTimeout(()=>{window.removeEventListener("message",r,!0),s("Request timed out"),t=null},2e3)});return this.postEvent(e),o}postEvent(e,t={}){this.iframe&&this.iframe.contentWindow&&this.iframe.contentWindow.postMessage({...t,event:e,source:"DraftPlugin"},"*")}triggerEvent(e,t){if(e)return e(t)}start({template:e,templateName:t,uid:o}){const i=document.querySelector(this.config.container);if(i){const s=({data:{source:r,event:l}})=>{if(r==="DraftPlugin"&&l==="loaded"){const{on:d,container:c,locale:p,autosave:y,token:v,apiUrl:E,pluginId:k,__config:b}=this.config;j(this.config),this.iframe&&this.iframe.contentWindow&&this.postEvent("init",{container:c,locale:p,uid:o,autosave:y,token:v,pluginId:k,apiUrl:E,__config:b,enabledListeners:Object.keys(d),template:e,templateName:t}),window.addEventListener("message",this.onMessage),window.removeEventListener("message",s)}};this.iframe=G(),window.addEventListener("message",s),i.appendChild(this.iframe),this.captureHotkeysEnabled()&&!this.hotkeysAttached&&(window.addEventListener("keydown",this.onHostHotkey),this.hotkeysAttached=!0)}else throw new Error("Specified container not found")}changeTemplate(e,t={}){this.postEvent("changeTemplate",{...t,template:e})}toggleGrid(e){this.postEvent("toggleGrid",{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")}redo(){this.postEvent("redo")}save(){return this.promisedIframeMethod("saveAction")}exit(){return this.promisedIframeMethod("exitAction")}exportContent(){return this.promisedIframeMethod("exportContent")}}var m=(n=>(n.Audit="audit",n.Guide="guide",n.Style="style",n.Blocks="blocks",n))(m||{}),f=(n=>(n.Desktop="desktop",n.Mobile="mobile",n))(f||{});const W={container:"#draft-plugin-container",disableHotkeysPassing:!1,locale:"ru",on:{}};class F{create(e){return new $({...W,...e})}}const w=new F;window.DraftPlugin=w;exports.EditorMenu=m;exports.ViewMode=f;exports.default=w;
1
+ "use strict";var P=Object.defineProperty;var L=(t,e,o)=>e in t?P(t,e,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[e]=o;var a=(t,e,o)=>L(t,typeof e!="symbol"?e+"":e,o);Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const b="http://localhost:5174",I="https://seplugin.sendsay.ru",A=async t=>{try{const e=await fetch(t,{method:"HEAD"});if(!e.ok)return null;const o=e.headers.get("Content-Length");return o?parseInt(o,10):null}catch{return null}},g=t=>new Promise((e,o)=>{const n=new Image;n.onload=async()=>{const i=await A(t)??0;e({originalWidth:n.width,originalHeight:n.height,ratio:n.width/n.height,fileSize:i})},n.onerror=i=>{o(i)},n.src=t}),u=(t,e)=>{if(t.length!==1)return t;if(t.charCodeAt(0)>=880){if(e.indexOf("Key")===0&&e.length===4)return e.charAt(3);if(e.indexOf("Digit")===0&&e.length===6)return e.charAt(5)}return t},C=t=>{let e=`${u(t.key,t.code)}`.toLowerCase()||t.key;const o=navigator.userAgent.includes("Mac OS");e==="backspace"&&o&&(e="delete");const n=[];return(o&&t.metaKey||!o&&t.ctrlKey)&&n.push("mod"),t.shiftKey&&n.push("shift"),n.length>0&&(e=`${n.join("-")}-${u(e,t.code)}`),e},H=new Set(["escape","mod-c","mod-d","mod-z","mod-y","mod-shift-z","mod-v","delete","mod-g","mod-p","mod-s"]),D="1.14.0",O={version:D},M=()=>{var s,r;const t=new RegExp("(^| )seplugin-dev=([^;]+)"),e=document.cookie.match(t),o=(r=e==null?void 0:(s=e[2]).toLowerCase)==null?void 0:r.call(s);if(o==="true")return b;if(o!=null&&o.startsWith("https://"))return o;const[n,i]=O.version.split(".");return`${I}/v${n}.${i}`},z=({token:t,pluginId:e,apiUrl:o})=>{if(!t)throw new Error("No [token] was provided");if(!e)throw new Error("No [pluginId] was provided");if(!o)throw new Error("No [apiUrl] was provided")},T=()=>{const t=document.createElement("iframe");return t.src=M(),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"),t};class x{constructor(e){a(this,"iframe",null);a(this,"hotkeysAttached",!1);a(this,"onHostHotkey",e=>{var d;if(!this.captureHotkeysEnabled()||!((d=this.iframe)!=null&&d.contentWindow))return;const o=C(e);if(!H.has(o))return;const n=e.target;if(n&&(n.isContentEditable||["INPUT","TEXTAREA","SELECT"].includes(n.tagName)))return;e.preventDefault();const{key:i,ctrlKey:s,metaKey:r,shiftKey:l,altKey:c}=e;this.postEvent("hostHotkey",{key:i,code:e.code,metaKey:r,ctrlKey:s,shiftKey:l,altKey:c,keyCode:o})});a(this,"onImageUpload",async({id:e,...o})=>{var n,i;try{const s=await((i=(n=this.config.on).uploadImage)==null?void 0:i.call(n,o));let r={};s&&(r=await g(s)),this.postEvent("imageUploaded",{id:e,img:{...r,url:s}})}catch{this.postEvent("imageUploaded",{id:e})}});a(this,"onLoadPersonalization",async()=>{try{if(!this.config.on.loadPersonalization)throw new Error("No personalization loader provided");const e=await this.config.on.loadPersonalization();this.postEvent("loadPersonalization",{items:e})}catch{this.postEvent("loadPersonalization",{})}});a(this,"onGalleryOpen",async({id:e})=>{var n,i;const o=async s=>{const r={url:s};if(s){const l=await g(s);Object.assign(r,l)}this.postEvent("imageUploaded",{id:e,img:r})};(i=(n=this.config.on).openGallery)==null||i.call(n,o)});a(this,"onMessage",e=>{const{data:{source:o,event:n,...i}}=e;o==="DraftPlugin"&&(n==="openGallery"?this.onGalleryOpen(i):n==="uploadImage"?this.onImageUpload(i):n==="loadPersonalization"?this.onLoadPersonalization():this.triggerEvent(this.config.on[n],i))});a(this,"destroy",()=>{var e;(e=this.iframe)==null||e.remove(),this.iframe=null,window.removeEventListener("message",this.onMessage),this.hotkeysAttached&&(window.removeEventListener("keydown",this.onHostHotkey),this.hotkeysAttached=!1)});this.config=e}captureHotkeysEnabled(){return this.config.disableHotkeysPassing!==!0}promisedIframeMethod(e){let o=null;const n=new Promise((i,s)=>{const r=l=>{const{data:{source:c,event:d,...h}}=l;c==="DraftPlugin"&&d===e&&(l.stopPropagation(),o&&(clearTimeout(o),o=null),i(h),window.removeEventListener("message",r,!0))};window.addEventListener("message",r,!0),o=setTimeout(()=>{window.removeEventListener("message",r,!0),s("Request timed out"),o=null},2e3)});return this.postEvent(e),n}postEvent(e,o={}){this.iframe&&this.iframe.contentWindow&&this.iframe.contentWindow.postMessage({...o,event:e,source:"DraftPlugin"},"*")}triggerEvent(e,o){if(e)return e(o)}start({template:e,templateName:o,uid:n}){const i=document.querySelector(this.config.container);if(i){const s=({data:{source:r,event:l}})=>{if(r==="DraftPlugin"&&l==="loaded"){const{on:c,container:d,locale:h,autosave:w,token:y,apiUrl:E,pluginId:v,__config:k}=this.config;z(this.config),this.iframe&&this.iframe.contentWindow&&this.postEvent("init",{container:d,locale:h,uid:n,autosave:w,token:y,pluginId:v,apiUrl:E,__config:k,enabledListeners:Object.keys(c),template:e,templateName:o}),window.addEventListener("message",this.onMessage),window.removeEventListener("message",s)}};this.iframe=T(),window.addEventListener("message",s),i.appendChild(this.iframe),this.captureHotkeysEnabled()&&!this.hotkeysAttached&&(window.addEventListener("keydown",this.onHostHotkey),this.hotkeysAttached=!0)}else throw new Error("Specified container not found")}changeTemplate(e,o={}){this.postEvent("changeTemplate",{...o,template:e})}toggleGrid(e){this.postEvent("toggleGrid",{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")}redo(){this.postEvent("redo")}save(){return this.promisedIframeMethod("saveAction")}exit(){return this.promisedIframeMethod("exitAction")}exportContent(){return this.promisedIframeMethod("exportContent")}}var p=(t=>(t.Audit="audit",t.Guide="guide",t.Style="style",t.Blocks="blocks",t))(p||{}),f=(t=>(t.Desktop="desktop",t.Mobile="mobile",t))(f||{});const N={container:"#draft-plugin-container",disableHotkeysPassing:!1,locale:"ru",on:{}};class K{create(e){return new x({...N,...e})}}const m=new K;window.DraftPlugin=m;exports.EditorMenu=p;exports.ViewMode=f;exports.default=m;
2
2
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/routes.ts","../src/utils.ts","../src/plugin.ts","../src/types.ts","../src/index.ts"],"sourcesContent":["export const LOCAL_ENDPOINT = 'http://localhost:5174';\nexport const PROD_ENDPOINT = 'https://seplugin.sendsay.ru';\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","import { LOCAL_ENDPOINT, PROD_ENDPOINT } from './routes';\nimport {\n EditorMenu,\n ExitParams,\n OnInitParams,\n OpenGalleryParams,\n Handlers,\n PluginConfig,\n SaveParams,\n TemplateJSON,\n UploadImageParams,\n ViewMode,\n HandlerParams,\n} from './types';\nimport { getImageParamsFromFileUrl } from './utils';\nimport pkg from '../package.json';\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\nconst 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\nconst 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\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 (\n value === 'stage' ||\n value?.includes('https://') ||\n window.location.pathname.includes('netlify')\n ) {\n return value?.includes('https://') ? value : `${PROD_ENDPOINT}/stage`;\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 = () => {\n const iframe = document.createElement('iframe');\n iframe.src = getDeployLink();\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',\n );\n\n return iframe;\n};\n\nexport class PluginInstance {\n public iframe: HTMLIFrameElement | null = null;\n private hotkeysAttached = false;\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 promisedIframeMethod<T>(eventName: string) {\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const res = new Promise<T>((resolve, reject) => {\n const onEvent = (\n e: MessageEvent<{ source: string; event: keyof PluginConfig['on'] }>,\n ) => {\n const {\n data: { source, event, ...data },\n } = e;\n if (source === 'DraftPlugin' && event === eventName) {\n e.stopPropagation();\n\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n resolve(data as T);\n window.removeEventListener('message', onEvent, true);\n }\n };\n\n window.addEventListener('message', onEvent, true);\n\n timer = setTimeout(() => {\n window.removeEventListener('message', onEvent, true);\n reject('Request timed out');\n timer = null;\n }, 2000);\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) {\n this.iframe.contentWindow.postMessage(\n {\n ...data,\n event,\n source: 'DraftPlugin',\n },\n '*',\n );\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 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;\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 = ({ data: { source, event } }: OnInitParams) => {\n if (source === 'DraftPlugin' && event === 'loaded') {\n const {\n on,\n container,\n locale,\n autosave,\n token,\n apiUrl,\n pluginId,\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 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();\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 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 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","export type EventHandler<T> = (data: T) => void;\n\nexport type AsyncEventHandler<P, R> = (params: P) => Promise<R>;\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 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 ReadyParams extends SaveParams {\n lastSavedTemplate?: {\n template: TemplateJSON;\n date: Date;\n };\n}\n\nexport interface ErrorParams {\n message: string;\n code?: string;\n}\n\nexport interface ExitParams extends SaveParams {}\n\nexport interface NotificationParams {\n intent: 'error' | 'info' | 'success' | 'warning';\n errorDetails?: object;\n message?: string;\n title: string;\n}\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 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 = Record<string, any>;\n\nexport type PersonalizationDictionary = Array<\n | { name: string; value: string }\n | { groupName: string; items: Array<{ name: string; value: string }> }\n>;\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 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 pluginId: string;\n apiUrl: string;\n disableHotkeysPassing?: boolean;\n __config?: object;\n on: Partial<Handlers>;\n}\n","import { PluginInstance } from './plugin';\nimport { PluginConfig } from './types';\n\nconst DEFAULT_CONFIG: Partial<PluginConfig> = {\n container: '#draft-plugin-container',\n disableHotkeysPassing: false,\n locale: 'ru',\n on: {},\n};\n\nclass PluginWrapper {\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 * from './types';\n"],"names":["LOCAL_ENDPOINT","PROD_ENDPOINT","getImageFileSize","imageUrl","response","contentLength","getImageParamsFromFileUrl","imgSrc","resolve","reject","img","fileSize","error","getLatinKey","key","code","constructKeyCode","event","keyCode","macOs","prefix","CORE_HOTKEYS","getDeployLink","regex","match","value","_b","_a","major","mid","pkg","verifyConfig","token","pluginId","apiUrl","createIframe","iframe","PluginInstance","config","__publicField","target","ctrlKey","metaKey","shiftKey","altKey","id","data","url","params","personalizationDictionary","applyImage","imgParams","ev","source","eventName","timer","res","onEvent","e","handler","template","templateName","uid","containerEl","onInit","on","container","locale","autosave","__config","options","state","menu","viewMode","EditorMenu","ViewMode","DEFAULT_CONFIG","PluginWrapper","DraftPlugin"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/routes.ts","../src/utils.ts","../src/plugin.ts","../src/types.ts","../src/index.ts"],"sourcesContent":["export const LOCAL_ENDPOINT = 'http://localhost:5174';\nexport const PROD_ENDPOINT = 'https://seplugin.sendsay.ru';\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","import { LOCAL_ENDPOINT, PROD_ENDPOINT } from './routes';\nimport {\n EditorMenu,\n ExitParams,\n OnInitParams,\n OpenGalleryParams,\n Handlers,\n PluginConfig,\n SaveParams,\n TemplateJSON,\n UploadImageParams,\n ViewMode,\n HandlerParams,\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 = () => {\n const iframe = document.createElement('iframe');\n iframe.src = getDeployLink();\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',\n );\n\n return iframe;\n};\n\nexport class PluginInstance {\n public iframe: HTMLIFrameElement | null = null;\n private hotkeysAttached = false;\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 promisedIframeMethod<T>(eventName: string) {\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const res = new Promise<T>((resolve, reject) => {\n const onEvent = (\n e: MessageEvent<{ source: string; event: keyof PluginConfig['on'] }>,\n ) => {\n const {\n data: { source, event, ...data },\n } = e;\n if (source === 'DraftPlugin' && event === eventName) {\n e.stopPropagation();\n\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n resolve(data as T);\n window.removeEventListener('message', onEvent, true);\n }\n };\n\n window.addEventListener('message', onEvent, true);\n\n timer = setTimeout(() => {\n window.removeEventListener('message', onEvent, true);\n reject('Request timed out');\n timer = null;\n }, 2000);\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) {\n this.iframe.contentWindow.postMessage(\n {\n ...data,\n event,\n source: 'DraftPlugin',\n },\n '*',\n );\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 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;\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 = ({ data: { source, event } }: OnInitParams) => {\n if (source === 'DraftPlugin' && event === 'loaded') {\n const {\n on,\n container,\n locale,\n autosave,\n token,\n apiUrl,\n pluginId,\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 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();\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 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 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","export type EventHandler<T> = (data: T) => void;\n\nexport type AsyncEventHandler<P, R> = (params: P) => Promise<R>;\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 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 ReadyParams extends SaveParams {\n lastSavedTemplate?: {\n template: TemplateJSON;\n date: Date;\n };\n}\n\nexport interface ErrorParams {\n message: string;\n code?: string;\n}\n\nexport interface ExitParams extends SaveParams {}\n\nexport interface NotificationParams {\n intent: 'error' | 'info' | 'success' | 'warning';\n errorDetails?: object;\n message?: string;\n title: string;\n}\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 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 = Record<string, any>;\n\nexport type PersonalizationDictionary = Array<\n | { name: string; value: string }\n | { groupName: string; items: Array<{ name: string; value: string }> }\n>;\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 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 pluginId: string;\n apiUrl: string;\n disableHotkeysPassing?: boolean;\n __config?: object;\n on: Partial<Handlers>;\n}\n","import { PluginInstance } from './plugin';\nimport { PluginConfig } from './types';\n\nconst DEFAULT_CONFIG: Partial<PluginConfig> = {\n container: '#draft-plugin-container',\n disableHotkeysPassing: false,\n locale: 'ru',\n on: {},\n};\n\nclass PluginWrapper {\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 * from './types';\n"],"names":["LOCAL_ENDPOINT","PROD_ENDPOINT","getImageFileSize","imageUrl","response","contentLength","getImageParamsFromFileUrl","imgSrc","resolve","reject","img","fileSize","error","getLatinKey","key","code","constructKeyCode","event","keyCode","macOs","prefix","CORE_HOTKEYS","getDeployLink","regex","match","value","_b","_a","major","mid","pkg","verifyConfig","token","pluginId","apiUrl","createIframe","iframe","PluginInstance","config","__publicField","target","ctrlKey","metaKey","shiftKey","altKey","id","data","url","params","personalizationDictionary","applyImage","imgParams","ev","source","eventName","timer","res","onEvent","e","handler","template","templateName","uid","containerEl","onInit","on","container","locale","autosave","__config","options","state","menu","viewMode","EditorMenu","ViewMode","DEFAULT_CONFIG","PluginWrapper","DraftPlugin"],"mappings":"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"}
package/dist/index.es.js CHANGED
@@ -1,74 +1,46 @@
1
- var v = Object.defineProperty;
2
- var k = (n, e, t) => e in n ? v(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
3
- var a = (n, e, t) => k(n, typeof e != "symbol" ? e + "" : e, t);
4
- const P = "http://localhost:5174", h = "https://seplugin.sendsay.ru", b = async (n) => {
1
+ var E = Object.defineProperty;
2
+ var v = (t, e, o) => e in t ? E(t, e, { enumerable: !0, configurable: !0, writable: !0, value: o }) : t[e] = o;
3
+ var a = (t, e, o) => v(t, typeof e != "symbol" ? e + "" : e, o);
4
+ const k = "http://localhost:5174", P = "https://seplugin.sendsay.ru", L = async (t) => {
5
5
  try {
6
- const e = await fetch(n, { method: "HEAD" });
6
+ const e = await fetch(t, { method: "HEAD" });
7
7
  if (!e.ok)
8
8
  return null;
9
- const t = e.headers.get("Content-Length");
10
- return t ? parseInt(t, 10) : null;
9
+ const o = e.headers.get("Content-Length");
10
+ return o ? parseInt(o, 10) : null;
11
11
  } catch {
12
12
  return null;
13
13
  }
14
- }, g = (n) => new Promise((e, t) => {
15
- const o = new Image();
16
- o.onload = async () => {
17
- const i = await b(n) ?? 0;
14
+ }, g = (t) => new Promise((e, o) => {
15
+ const n = new Image();
16
+ n.onload = async () => {
17
+ const i = await L(t) ?? 0;
18
18
  e({
19
- originalWidth: o.width,
20
- originalHeight: o.height,
21
- ratio: o.width / o.height,
19
+ originalWidth: n.width,
20
+ originalHeight: n.height,
21
+ ratio: n.width / n.height,
22
22
  fileSize: i
23
23
  });
24
- }, o.onerror = (i) => {
25
- t(i);
26
- }, o.src = n;
27
- }), L = "@getdraft/plugin", I = "1.13.1-beta.0", x = "dist/index.cjs.js", A = "dist/index.es.js", D = "src", C = {
28
- prebuild: "rm -rf dist",
29
- build: "vite build",
30
- "dev-tsc": "npx tsc --noEmit",
31
- eslint: "npx eslint src",
32
- "eslint:fix": "pnpm eslint --fix",
33
- prettify: "npx prettier -w ./",
34
- prepublish: "pnpm build",
35
- watch: "NODE_ENV=development vite build --watch",
36
- start: "NODE_ENV=development npx vite"
37
- }, H = {}, O = {
38
- "@types/letty": "workspace:^",
39
- "@vitejs/plugin-legacy": "5.4.1",
40
- rollup: "4.22.4",
41
- terser: "5.31.3",
42
- "rollup-plugin-dts": "6.1.1",
43
- "@letty/eslint-config-ts": "workspace:^",
44
- "@letty/prettier": "workspace:^"
45
- }, N = "MIT", z = {
46
- name: L,
47
- version: I,
48
- main: x,
49
- module: A,
50
- types: D,
51
- scripts: C,
52
- dependencies: H,
53
- devDependencies: O,
54
- license: N
55
- }, u = (n, e) => {
56
- if (n.length !== 1)
57
- return n;
58
- if (n.charCodeAt(0) >= 880) {
24
+ }, n.onerror = (i) => {
25
+ o(i);
26
+ }, n.src = t;
27
+ }), p = (t, e) => {
28
+ if (t.length !== 1)
29
+ return t;
30
+ if (t.charCodeAt(0) >= 880) {
59
31
  if (e.indexOf("Key") === 0 && e.length === 4)
60
32
  return e.charAt(3);
61
33
  if (e.indexOf("Digit") === 0 && e.length === 6)
62
34
  return e.charAt(5);
63
35
  }
64
- return n;
65
- }, T = (n) => {
66
- let e = `${u(n.key, n.code)}`.toLowerCase() || n.key;
67
- const t = navigator.userAgent.includes("Mac OS");
68
- e === "backspace" && t && (e = "delete");
69
- const o = [];
70
- return (t && n.metaKey || !t && n.ctrlKey) && o.push("mod"), n.shiftKey && o.push("shift"), o.length > 0 && (e = `${o.join("-")}-${u(e, n.code)}`), e;
71
- }, K = /* @__PURE__ */ new Set([
36
+ return t;
37
+ }, I = (t) => {
38
+ let e = `${p(t.key, t.code)}`.toLowerCase() || t.key;
39
+ const o = navigator.userAgent.includes("Mac OS");
40
+ e === "backspace" && o && (e = "delete");
41
+ const n = [];
42
+ return (o && t.metaKey || !o && t.ctrlKey) && n.push("mod"), t.shiftKey && n.push("shift"), n.length > 0 && (e = `${n.join("-")}-${p(e, t.code)}`), e;
43
+ }, b = /* @__PURE__ */ new Set([
72
44
  "escape",
73
45
  "mod-c",
74
46
  "mod-d",
@@ -80,33 +52,35 @@ const P = "http://localhost:5174", h = "https://seplugin.sendsay.ru", b = async
80
52
  "mod-g",
81
53
  "mod-p",
82
54
  "mod-s"
83
- ]), M = () => {
55
+ ]), A = "1.14.0", C = {
56
+ version: A
57
+ }, H = () => {
84
58
  var s, r;
85
- const n = new RegExp("(^| )seplugin-dev=([^;]+)"), e = document.cookie.match(n), t = (r = e == null ? void 0 : (s = e[2]).toLowerCase) == null ? void 0 : r.call(s);
86
- if (t === "true")
87
- return P;
88
- if (t === "stage" || t != null && t.includes("https://") || window.location.pathname.includes("netlify"))
89
- return t != null && t.includes("https://") ? t : `${h}/stage`;
90
- const [o, i] = z.version.split(".");
91
- return `${h}/v${o}.${i}`;
92
- }, U = ({ token: n, pluginId: e, apiUrl: t }) => {
93
- if (!n)
59
+ const t = new RegExp("(^| )seplugin-dev=([^;]+)"), e = document.cookie.match(t), o = (r = e == null ? void 0 : (s = e[2]).toLowerCase) == null ? void 0 : r.call(s);
60
+ if (o === "true")
61
+ return k;
62
+ if (o != null && o.startsWith("https://"))
63
+ return o;
64
+ const [n, i] = C.version.split(".");
65
+ return `${P}/v${n}.${i}`;
66
+ }, D = ({ token: t, pluginId: e, apiUrl: o }) => {
67
+ if (!t)
94
68
  throw new Error("No [token] was provided");
95
69
  if (!e)
96
70
  throw new Error("No [pluginId] was provided");
97
- if (!t)
71
+ if (!o)
98
72
  throw new Error("No [apiUrl] was provided");
99
- }, j = () => {
100
- const n = document.createElement("iframe");
101
- return n.src = M(), n.setAttribute(
73
+ }, O = () => {
74
+ const t = document.createElement("iframe");
75
+ return t.src = H(), t.setAttribute(
102
76
  "style",
103
77
  "height:100%;width:100%;min-width:960px;border:0px"
104
- ), n.setAttribute("allow", "clipboard-read; clipboard-write"), n.setAttribute(
78
+ ), t.setAttribute("allow", "clipboard-read; clipboard-write"), t.setAttribute(
105
79
  "sandbox",
106
80
  "allow-scripts allow-same-origin allow-forms allow-popups"
107
- ), n;
81
+ ), t;
108
82
  };
109
- class G {
83
+ class x {
110
84
  constructor(e) {
111
85
  a(this, "iframe", null);
112
86
  a(this, "hotkeysAttached", !1);
@@ -114,11 +88,11 @@ class G {
114
88
  var c;
115
89
  if (!this.captureHotkeysEnabled() || !((c = this.iframe) != null && c.contentWindow))
116
90
  return;
117
- const t = T(e);
118
- if (!K.has(t))
91
+ const o = I(e);
92
+ if (!b.has(o))
119
93
  return;
120
- const o = e.target;
121
- if (o && (o.isContentEditable || ["INPUT", "TEXTAREA", "SELECT"].includes(o.tagName)))
94
+ const n = e.target;
95
+ if (n && (n.isContentEditable || ["INPUT", "TEXTAREA", "SELECT"].includes(n.tagName)))
122
96
  return;
123
97
  e.preventDefault();
124
98
  const { key: i, ctrlKey: s, metaKey: r, shiftKey: l, altKey: d } = e;
@@ -129,16 +103,16 @@ class G {
129
103
  ctrlKey: s,
130
104
  shiftKey: l,
131
105
  altKey: d,
132
- keyCode: t
106
+ keyCode: o
133
107
  });
134
108
  });
135
109
  a(this, "onImageUpload", async ({
136
110
  id: e,
137
- ...t
111
+ ...o
138
112
  }) => {
139
- var o, i;
113
+ var n, i;
140
114
  try {
141
- const s = await ((i = (o = this.config.on).uploadImage) == null ? void 0 : i.call(o, t));
115
+ const s = await ((i = (n = this.config.on).uploadImage) == null ? void 0 : i.call(n, o));
142
116
  let r = {};
143
117
  s && (r = await g(s)), this.postEvent("imageUploaded", { id: e, img: { ...r, url: s } });
144
118
  } catch {
@@ -158,8 +132,8 @@ class G {
158
132
  }
159
133
  });
160
134
  a(this, "onGalleryOpen", async ({ id: e }) => {
161
- var o, i;
162
- const t = async (s) => {
135
+ var n, i;
136
+ const o = async (s) => {
163
137
  const r = { url: s };
164
138
  if (s) {
165
139
  const l = await g(s);
@@ -170,14 +144,14 @@ class G {
170
144
  img: r
171
145
  });
172
146
  };
173
- (i = (o = this.config.on).openGallery) == null || i.call(o, t);
147
+ (i = (n = this.config.on).openGallery) == null || i.call(n, o);
174
148
  });
175
149
  a(this, "onMessage", (e) => {
176
150
  const {
177
- data: { source: t, event: o, ...i }
151
+ data: { source: o, event: n, ...i }
178
152
  } = e;
179
- t === "DraftPlugin" && (o === "openGallery" ? this.onGalleryOpen(i) : o === "uploadImage" ? this.onImageUpload(i) : o === "loadPersonalization" ? this.onLoadPersonalization() : this.triggerEvent(
180
- this.config.on[o],
153
+ o === "DraftPlugin" && (n === "openGallery" ? this.onGalleryOpen(i) : n === "uploadImage" ? this.onImageUpload(i) : n === "loadPersonalization" ? this.onLoadPersonalization() : this.triggerEvent(
154
+ this.config.on[n],
181
155
  i
182
156
  ));
183
157
  });
@@ -191,38 +165,38 @@ class G {
191
165
  return this.config.disableHotkeysPassing !== !0;
192
166
  }
193
167
  promisedIframeMethod(e) {
194
- let t = null;
195
- const o = new Promise((i, s) => {
168
+ let o = null;
169
+ const n = new Promise((i, s) => {
196
170
  const r = (l) => {
197
171
  const {
198
- data: { source: d, event: c, ...p }
172
+ data: { source: d, event: c, ...h }
199
173
  } = l;
200
- d === "DraftPlugin" && c === e && (l.stopPropagation(), t && (clearTimeout(t), t = null), i(p), window.removeEventListener("message", r, !0));
174
+ d === "DraftPlugin" && c === e && (l.stopPropagation(), o && (clearTimeout(o), o = null), i(h), window.removeEventListener("message", r, !0));
201
175
  };
202
- window.addEventListener("message", r, !0), t = setTimeout(() => {
203
- window.removeEventListener("message", r, !0), s("Request timed out"), t = null;
176
+ window.addEventListener("message", r, !0), o = setTimeout(() => {
177
+ window.removeEventListener("message", r, !0), s("Request timed out"), o = null;
204
178
  }, 2e3);
205
179
  });
206
- return this.postEvent(e), o;
180
+ return this.postEvent(e), n;
207
181
  }
208
- postEvent(e, t = {}) {
182
+ postEvent(e, o = {}) {
209
183
  this.iframe && this.iframe.contentWindow && this.iframe.contentWindow.postMessage(
210
184
  {
211
- ...t,
185
+ ...o,
212
186
  event: e,
213
187
  source: "DraftPlugin"
214
188
  },
215
189
  "*"
216
190
  );
217
191
  }
218
- triggerEvent(e, t) {
192
+ triggerEvent(e, o) {
219
193
  if (e)
220
- return e(t);
194
+ return e(o);
221
195
  }
222
196
  start({
223
197
  template: e,
224
- templateName: t,
225
- uid: o
198
+ templateName: o,
199
+ uid: n
226
200
  }) {
227
201
  const i = document.querySelector(this.config.container);
228
202
  if (i) {
@@ -231,34 +205,34 @@ class G {
231
205
  const {
232
206
  on: d,
233
207
  container: c,
234
- locale: p,
235
- autosave: m,
208
+ locale: h,
209
+ autosave: u,
236
210
  token: f,
237
- apiUrl: w,
238
- pluginId: y,
239
- __config: E
211
+ apiUrl: m,
212
+ pluginId: w,
213
+ __config: y
240
214
  } = this.config;
241
- U(this.config), this.iframe && this.iframe.contentWindow && this.postEvent("init", {
215
+ D(this.config), this.iframe && this.iframe.contentWindow && this.postEvent("init", {
242
216
  container: c,
243
- locale: p,
244
- uid: o,
245
- autosave: m,
217
+ locale: h,
218
+ uid: n,
219
+ autosave: u,
246
220
  token: f,
247
- pluginId: y,
248
- apiUrl: w,
249
- __config: E,
221
+ pluginId: w,
222
+ apiUrl: m,
223
+ __config: y,
250
224
  enabledListeners: Object.keys(d),
251
225
  template: e,
252
- templateName: t
226
+ templateName: o
253
227
  }), window.addEventListener("message", this.onMessage), window.removeEventListener("message", s);
254
228
  }
255
229
  };
256
- this.iframe = j(), window.addEventListener("message", s), i.appendChild(this.iframe), this.captureHotkeysEnabled() && !this.hotkeysAttached && (window.addEventListener("keydown", this.onHostHotkey), this.hotkeysAttached = !0);
230
+ this.iframe = O(), window.addEventListener("message", s), i.appendChild(this.iframe), this.captureHotkeysEnabled() && !this.hotkeysAttached && (window.addEventListener("keydown", this.onHostHotkey), this.hotkeysAttached = !0);
257
231
  } else
258
232
  throw new Error("Specified container not found");
259
233
  }
260
- changeTemplate(e, t = {}) {
261
- this.postEvent("changeTemplate", { ...t, template: e });
234
+ changeTemplate(e, o = {}) {
235
+ this.postEvent("changeTemplate", { ...o, template: e });
262
236
  }
263
237
  toggleGrid(e) {
264
238
  this.postEvent("toggleGrid", { state: e });
@@ -288,26 +262,26 @@ class G {
288
262
  return this.promisedIframeMethod("exportContent");
289
263
  }
290
264
  }
291
- var S = /* @__PURE__ */ ((n) => (n.Audit = "audit", n.Guide = "guide", n.Style = "style", n.Blocks = "blocks", n))(S || {}), _ = /* @__PURE__ */ ((n) => (n.Desktop = "desktop", n.Mobile = "mobile", n))(_ || {});
292
- const $ = {
265
+ var z = /* @__PURE__ */ ((t) => (t.Audit = "audit", t.Guide = "guide", t.Style = "style", t.Blocks = "blocks", t))(z || {}), N = /* @__PURE__ */ ((t) => (t.Desktop = "desktop", t.Mobile = "mobile", t))(N || {});
266
+ const T = {
293
267
  container: "#draft-plugin-container",
294
268
  disableHotkeysPassing: !1,
295
269
  locale: "ru",
296
270
  on: {}
297
271
  };
298
- class W {
272
+ class K {
299
273
  create(e) {
300
- return new G({
301
- ...$,
274
+ return new x({
275
+ ...T,
302
276
  ...e
303
277
  });
304
278
  }
305
279
  }
306
- const F = new W();
307
- window.DraftPlugin = F;
280
+ const M = new K();
281
+ window.DraftPlugin = M;
308
282
  export {
309
- S as EditorMenu,
310
- _ as ViewMode,
311
- F as default
283
+ z as EditorMenu,
284
+ N as ViewMode,
285
+ M as default
312
286
  };
313
287
  //# sourceMappingURL=index.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/routes.ts","../src/utils.ts","../src/plugin.ts","../src/types.ts","../src/index.ts"],"sourcesContent":["export const LOCAL_ENDPOINT = 'http://localhost:5174';\nexport const PROD_ENDPOINT = 'https://seplugin.sendsay.ru';\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","import { LOCAL_ENDPOINT, PROD_ENDPOINT } from './routes';\nimport {\n EditorMenu,\n ExitParams,\n OnInitParams,\n OpenGalleryParams,\n Handlers,\n PluginConfig,\n SaveParams,\n TemplateJSON,\n UploadImageParams,\n ViewMode,\n HandlerParams,\n} from './types';\nimport { getImageParamsFromFileUrl } from './utils';\nimport pkg from '../package.json';\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\nconst 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\nconst 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\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 (\n value === 'stage' ||\n value?.includes('https://') ||\n window.location.pathname.includes('netlify')\n ) {\n return value?.includes('https://') ? value : `${PROD_ENDPOINT}/stage`;\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 = () => {\n const iframe = document.createElement('iframe');\n iframe.src = getDeployLink();\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',\n );\n\n return iframe;\n};\n\nexport class PluginInstance {\n public iframe: HTMLIFrameElement | null = null;\n private hotkeysAttached = false;\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 promisedIframeMethod<T>(eventName: string) {\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const res = new Promise<T>((resolve, reject) => {\n const onEvent = (\n e: MessageEvent<{ source: string; event: keyof PluginConfig['on'] }>,\n ) => {\n const {\n data: { source, event, ...data },\n } = e;\n if (source === 'DraftPlugin' && event === eventName) {\n e.stopPropagation();\n\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n resolve(data as T);\n window.removeEventListener('message', onEvent, true);\n }\n };\n\n window.addEventListener('message', onEvent, true);\n\n timer = setTimeout(() => {\n window.removeEventListener('message', onEvent, true);\n reject('Request timed out');\n timer = null;\n }, 2000);\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) {\n this.iframe.contentWindow.postMessage(\n {\n ...data,\n event,\n source: 'DraftPlugin',\n },\n '*',\n );\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 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;\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 = ({ data: { source, event } }: OnInitParams) => {\n if (source === 'DraftPlugin' && event === 'loaded') {\n const {\n on,\n container,\n locale,\n autosave,\n token,\n apiUrl,\n pluginId,\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 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();\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 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 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","export type EventHandler<T> = (data: T) => void;\n\nexport type AsyncEventHandler<P, R> = (params: P) => Promise<R>;\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 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 ReadyParams extends SaveParams {\n lastSavedTemplate?: {\n template: TemplateJSON;\n date: Date;\n };\n}\n\nexport interface ErrorParams {\n message: string;\n code?: string;\n}\n\nexport interface ExitParams extends SaveParams {}\n\nexport interface NotificationParams {\n intent: 'error' | 'info' | 'success' | 'warning';\n errorDetails?: object;\n message?: string;\n title: string;\n}\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 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 = Record<string, any>;\n\nexport type PersonalizationDictionary = Array<\n | { name: string; value: string }\n | { groupName: string; items: Array<{ name: string; value: string }> }\n>;\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 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 pluginId: string;\n apiUrl: string;\n disableHotkeysPassing?: boolean;\n __config?: object;\n on: Partial<Handlers>;\n}\n","import { PluginInstance } from './plugin';\nimport { PluginConfig } from './types';\n\nconst DEFAULT_CONFIG: Partial<PluginConfig> = {\n container: '#draft-plugin-container',\n disableHotkeysPassing: false,\n locale: 'ru',\n on: {},\n};\n\nclass PluginWrapper {\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 * from './types';\n"],"names":["LOCAL_ENDPOINT","PROD_ENDPOINT","getImageFileSize","imageUrl","response","contentLength","getImageParamsFromFileUrl","imgSrc","resolve","reject","img","fileSize","error","getLatinKey","key","code","constructKeyCode","event","keyCode","macOs","prefix","CORE_HOTKEYS","getDeployLink","_a","_b","regex","match","value","major","mid","pkg","verifyConfig","token","pluginId","apiUrl","createIframe","iframe","PluginInstance","config","__publicField","target","ctrlKey","metaKey","shiftKey","altKey","id","data","url","params","personalizationDictionary","applyImage","imgParams","ev","source","eventName","timer","res","onEvent","e","handler","template","templateName","uid","containerEl","onInit","on","container","locale","autosave","__config","options","state","menu","viewMode","EditorMenu","ViewMode","DEFAULT_CONFIG","PluginWrapper","DraftPlugin"],"mappings":"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"}
1
+ {"version":3,"file":"index.es.js","sources":["../src/routes.ts","../src/utils.ts","../src/plugin.ts","../src/types.ts","../src/index.ts"],"sourcesContent":["export const LOCAL_ENDPOINT = 'http://localhost:5174';\nexport const PROD_ENDPOINT = 'https://seplugin.sendsay.ru';\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","import { LOCAL_ENDPOINT, PROD_ENDPOINT } from './routes';\nimport {\n EditorMenu,\n ExitParams,\n OnInitParams,\n OpenGalleryParams,\n Handlers,\n PluginConfig,\n SaveParams,\n TemplateJSON,\n UploadImageParams,\n ViewMode,\n HandlerParams,\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 = () => {\n const iframe = document.createElement('iframe');\n iframe.src = getDeployLink();\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',\n );\n\n return iframe;\n};\n\nexport class PluginInstance {\n public iframe: HTMLIFrameElement | null = null;\n private hotkeysAttached = false;\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 promisedIframeMethod<T>(eventName: string) {\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const res = new Promise<T>((resolve, reject) => {\n const onEvent = (\n e: MessageEvent<{ source: string; event: keyof PluginConfig['on'] }>,\n ) => {\n const {\n data: { source, event, ...data },\n } = e;\n if (source === 'DraftPlugin' && event === eventName) {\n e.stopPropagation();\n\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n resolve(data as T);\n window.removeEventListener('message', onEvent, true);\n }\n };\n\n window.addEventListener('message', onEvent, true);\n\n timer = setTimeout(() => {\n window.removeEventListener('message', onEvent, true);\n reject('Request timed out');\n timer = null;\n }, 2000);\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) {\n this.iframe.contentWindow.postMessage(\n {\n ...data,\n event,\n source: 'DraftPlugin',\n },\n '*',\n );\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 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;\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 = ({ data: { source, event } }: OnInitParams) => {\n if (source === 'DraftPlugin' && event === 'loaded') {\n const {\n on,\n container,\n locale,\n autosave,\n token,\n apiUrl,\n pluginId,\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 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();\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 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 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","export type EventHandler<T> = (data: T) => void;\n\nexport type AsyncEventHandler<P, R> = (params: P) => Promise<R>;\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 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 ReadyParams extends SaveParams {\n lastSavedTemplate?: {\n template: TemplateJSON;\n date: Date;\n };\n}\n\nexport interface ErrorParams {\n message: string;\n code?: string;\n}\n\nexport interface ExitParams extends SaveParams {}\n\nexport interface NotificationParams {\n intent: 'error' | 'info' | 'success' | 'warning';\n errorDetails?: object;\n message?: string;\n title: string;\n}\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 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 = Record<string, any>;\n\nexport type PersonalizationDictionary = Array<\n | { name: string; value: string }\n | { groupName: string; items: Array<{ name: string; value: string }> }\n>;\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 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 pluginId: string;\n apiUrl: string;\n disableHotkeysPassing?: boolean;\n __config?: object;\n on: Partial<Handlers>;\n}\n","import { PluginInstance } from './plugin';\nimport { PluginConfig } from './types';\n\nconst DEFAULT_CONFIG: Partial<PluginConfig> = {\n container: '#draft-plugin-container',\n disableHotkeysPassing: false,\n locale: 'ru',\n on: {},\n};\n\nclass PluginWrapper {\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 * from './types';\n"],"names":["LOCAL_ENDPOINT","PROD_ENDPOINT","getImageFileSize","imageUrl","response","contentLength","getImageParamsFromFileUrl","imgSrc","resolve","reject","img","fileSize","error","getLatinKey","key","code","constructKeyCode","event","keyCode","macOs","prefix","CORE_HOTKEYS","getDeployLink","_a","_b","regex","match","value","major","mid","pkg","verifyConfig","token","pluginId","apiUrl","createIframe","iframe","PluginInstance","config","__publicField","target","ctrlKey","metaKey","shiftKey","altKey","id","data","url","params","personalizationDictionary","applyImage","imgParams","ev","source","eventName","timer","res","onEvent","e","handler","template","templateName","uid","containerEl","onInit","on","container","locale","autosave","__config","options","state","menu","viewMode","EditorMenu","ViewMode","DEFAULT_CONFIG","PluginWrapper","DraftPlugin"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,UAAU,EAIV,YAAY,EACZ,UAAU,EACV,YAAY,EAEZ,QAAQ,EAET,MAAM,SAAS,CAAC;AAqHjB,qBAAa,cAAc;IAGN,MAAM,EAAE,YAAY;IAFhC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAQ;IAC/C,OAAO,CAAC,eAAe,CAAS;gBACb,MAAM,EAAE,YAAY;IAEvC,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,YAAY,CAkClB;IAEF,OAAO,CAAC,oBAAoB;IAoC5B,OAAO,CAAC,SAAS;IAajB,OAAO,CAAC,aAAa,CAgBnB;IAEF,OAAO,CAAC,qBAAqB,CAe3B;IAEF,OAAO,CAAC,aAAa,CAgBnB;IAEF,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,SAAS,CAqBf;IAEF,KAAK,CAAC,EACJ,QAAQ,EACR,YAAY,EACZ,GAAG,GACJ,EAAE;QACD,QAAQ,EAAE,MAAM,GAAG,YAAY,CAAC;QAChC,GAAG,EAAE,MAAM,CAAC;QACZ,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB;IAqDD,OAAO,aASL;IAEF,cAAc,CACZ,QAAQ,EAAE,MAAM,GAAG,YAAY,EAC/B,OAAO,GAAE;QACP,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,GAAG,CAAC,EAAE,MAAM,CAAC;KACT;IAKR,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO;IAI1B,aAAa,CAAC,KAAK,CAAC,EAAE,OAAO;IAI7B,UAAU,CAAC,IAAI,GAAE,UAAU,GAAG,IAAW;IAIzC,cAAc,CAAC,QAAQ,EAAE,QAAQ;IAIjC,IAAI;IAIJ,IAAI;IAIJ,IAAI;IAIJ,IAAI;IAIJ,aAAa;CAGd"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,UAAU,EAIV,YAAY,EACZ,UAAU,EACV,YAAY,EAEZ,QAAQ,EAET,MAAM,SAAS,CAAC;AAwDjB,qBAAa,cAAc;IAGN,MAAM,EAAE,YAAY;IAFhC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAQ;IAC/C,OAAO,CAAC,eAAe,CAAS;gBACb,MAAM,EAAE,YAAY;IAEvC,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,YAAY,CAkClB;IAEF,OAAO,CAAC,oBAAoB;IAoC5B,OAAO,CAAC,SAAS;IAajB,OAAO,CAAC,aAAa,CAgBnB;IAEF,OAAO,CAAC,qBAAqB,CAe3B;IAEF,OAAO,CAAC,aAAa,CAgBnB;IAEF,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,SAAS,CAqBf;IAEF,KAAK,CAAC,EACJ,QAAQ,EACR,YAAY,EACZ,GAAG,GACJ,EAAE;QACD,QAAQ,EAAE,MAAM,GAAG,YAAY,CAAC;QAChC,GAAG,EAAE,MAAM,CAAC;QACZ,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB;IAqDD,OAAO,aASL;IAEF,cAAc,CACZ,QAAQ,EAAE,MAAM,GAAG,YAAY,EAC/B,OAAO,GAAE;QACP,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,GAAG,CAAC,EAAE,MAAM,CAAC;KACT;IAKR,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO;IAI1B,aAAa,CAAC,KAAK,CAAC,EAAE,OAAO;IAI7B,UAAU,CAAC,IAAI,GAAE,UAAU,GAAG,IAAW;IAIzC,cAAc,CAAC,QAAQ,EAAE,QAAQ;IAIjC,IAAI;IAIJ,IAAI;IAIJ,IAAI;IAIJ,IAAI;IAIJ,aAAa;CAGd"}
@@ -1,3 +1,5 @@
1
1
  import { ImageParams } from './types';
2
2
  export declare const getImageParamsFromFileUrl: (imgSrc: string) => Promise<Omit<ImageParams, "url">>;
3
+ export declare const constructKeyCode: (event: KeyboardEvent) => string;
4
+ export declare const CORE_HOTKEYS: Set<string>;
3
5
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAsBtC,eAAO,MAAM,yBAAyB,WAAY,MAAM,sCAoBpD,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAsBtC,eAAO,MAAM,yBAAyB,WAAY,MAAM,sCAoBpD,CAAC;AAuBL,eAAO,MAAM,gBAAgB,UAAW,aAAa,WAwBpD,CAAC;AAEF,eAAO,MAAM,YAAY,aAYvB,CAAC"}
package/package.json CHANGED
@@ -1,29 +1,29 @@
1
1
  {
2
2
  "name": "@getdraft/plugin",
3
- "version": "1.13.0-beta.0",
3
+ "version": "1.14.0",
4
4
  "main": "dist/index.cjs.js",
5
5
  "module": "dist/index.es.js",
6
6
  "types": "src",
7
+ "dependencies": {},
8
+ "devDependencies": {
9
+ "@vitejs/plugin-legacy": "5.4.1",
10
+ "rollup": "4.22.4",
11
+ "terser": "5.31.3",
12
+ "rollup-plugin-dts": "6.1.1",
13
+ "@types/letty": "^1.0.0",
14
+ "@letty/eslint-config-ts": "^1.0.0",
15
+ "@letty/prettier": "^1.0.0"
16
+ },
17
+ "license": "MIT",
7
18
  "scripts": {
8
19
  "prebuild": "rm -rf dist",
9
20
  "build": "vite build",
10
- "dev-tsc": "npx tsc --noEmit",
21
+ "dev-tsc": "tsc-check",
11
22
  "eslint": "npx eslint src",
12
23
  "eslint:fix": "pnpm eslint --fix",
13
24
  "prettify": "npx prettier -w ./",
14
25
  "prepublish": "pnpm build",
15
26
  "watch": "NODE_ENV=development vite build --watch",
16
27
  "start": "NODE_ENV=development npx vite"
17
- },
18
- "dependencies": {},
19
- "devDependencies": {
20
- "@types/letty": "workspace:^",
21
- "@vitejs/plugin-legacy": "5.4.1",
22
- "rollup": "4.22.4",
23
- "terser": "5.31.3",
24
- "rollup-plugin-dts": "6.1.1",
25
- "@letty/eslint-config-ts": "workspace:^",
26
- "@letty/prettier": "workspace:^"
27
- },
28
- "license": "MIT"
29
- }
28
+ }
29
+ }
package/src/plugin.ts CHANGED
@@ -12,70 +12,13 @@ import {
12
12
  ViewMode,
13
13
  HandlerParams,
14
14
  } from './types';
15
- import { getImageParamsFromFileUrl } from './utils';
15
+ import {
16
+ getImageParamsFromFileUrl,
17
+ constructKeyCode,
18
+ CORE_HOTKEYS,
19
+ } from './utils';
16
20
  import pkg from '../package.json';
17
21
 
18
- const getLatinKey = (key: string, code: string) => {
19
- if (key.length !== 1) {
20
- return key;
21
- }
22
-
23
- const capitalHetaCode = 880;
24
- const isNonLatin = key.charCodeAt(0) >= capitalHetaCode;
25
-
26
- if (isNonLatin) {
27
- if (code.indexOf('Key') === 0 && code.length === 4) {
28
- return code.charAt(3);
29
- }
30
-
31
- if (code.indexOf('Digit') === 0 && code.length === 6) {
32
- return code.charAt(5);
33
- }
34
- }
35
-
36
- return key;
37
- };
38
-
39
- const constructKeyCode = (event: KeyboardEvent) => {
40
- let keyCode =
41
- `${getLatinKey(event.key, event.code)}`.toLowerCase() || event.key;
42
- const macOs = navigator.userAgent.includes('Mac OS');
43
-
44
- if (keyCode === 'backspace' && macOs) {
45
- keyCode = 'delete';
46
- }
47
-
48
- const prefix = [];
49
-
50
- if ((macOs && event.metaKey) || (!macOs && event.ctrlKey)) {
51
- prefix.push('mod');
52
- }
53
-
54
- if (event.shiftKey) {
55
- prefix.push('shift');
56
- }
57
-
58
- if (prefix.length > 0) {
59
- keyCode = `${prefix.join('-')}-${getLatinKey(keyCode, event.code)}`;
60
- }
61
-
62
- return keyCode;
63
- };
64
-
65
- const CORE_HOTKEYS = new Set([
66
- 'escape',
67
- 'mod-c',
68
- 'mod-d',
69
- 'mod-z',
70
- 'mod-y',
71
- 'mod-shift-z',
72
- 'mod-v',
73
- 'delete',
74
- 'mod-g',
75
- 'mod-p',
76
- 'mod-s',
77
- ]);
78
-
79
22
  const getDeployLink = () => {
80
23
  const regex = new RegExp(`(^| )seplugin-dev=([^;]+)`);
81
24
  const match = document.cookie.match(regex);
@@ -85,12 +28,8 @@ const getDeployLink = () => {
85
28
  return LOCAL_ENDPOINT;
86
29
  }
87
30
 
88
- if (
89
- value === 'stage' ||
90
- value?.includes('https://') ||
91
- window.location.pathname.includes('netlify')
92
- ) {
93
- return value?.includes('https://') ? value : `${PROD_ENDPOINT}/stage`;
31
+ if (value?.startsWith('https://')) {
32
+ return value;
94
33
  }
95
34
 
96
35
  const [major, mid] = pkg.version.split('.');
package/src/utils.ts CHANGED
@@ -41,3 +41,64 @@ export const getImageParamsFromFileUrl = (imgSrc: string) =>
41
41
 
42
42
  img.src = imgSrc;
43
43
  });
44
+
45
+ const getLatinKey = (key: string, code: string) => {
46
+ if (key.length !== 1) {
47
+ return key;
48
+ }
49
+
50
+ const capitalHetaCode = 880;
51
+ const isNonLatin = key.charCodeAt(0) >= capitalHetaCode;
52
+
53
+ if (isNonLatin) {
54
+ if (code.indexOf('Key') === 0 && code.length === 4) {
55
+ return code.charAt(3);
56
+ }
57
+
58
+ if (code.indexOf('Digit') === 0 && code.length === 6) {
59
+ return code.charAt(5);
60
+ }
61
+ }
62
+
63
+ return key;
64
+ };
65
+
66
+ export const constructKeyCode = (event: KeyboardEvent) => {
67
+ let keyCode =
68
+ `${getLatinKey(event.key, event.code)}`.toLowerCase() || event.key;
69
+ const macOs = navigator.userAgent.includes('Mac OS');
70
+
71
+ if (keyCode === 'backspace' && macOs) {
72
+ keyCode = 'delete';
73
+ }
74
+
75
+ const prefix = [];
76
+
77
+ if ((macOs && event.metaKey) || (!macOs && event.ctrlKey)) {
78
+ prefix.push('mod');
79
+ }
80
+
81
+ if (event.shiftKey) {
82
+ prefix.push('shift');
83
+ }
84
+
85
+ if (prefix.length > 0) {
86
+ keyCode = `${prefix.join('-')}-${getLatinKey(keyCode, event.code)}`;
87
+ }
88
+
89
+ return keyCode;
90
+ };
91
+
92
+ export const CORE_HOTKEYS = new Set([
93
+ 'escape',
94
+ 'mod-c',
95
+ 'mod-d',
96
+ 'mod-z',
97
+ 'mod-y',
98
+ 'mod-shift-z',
99
+ 'mod-v',
100
+ 'delete',
101
+ 'mod-g',
102
+ 'mod-p',
103
+ 'mod-s',
104
+ ]);