@getdraft/plugin 1.17.0 → 1.19.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +0 -0
- package/.turbo/turbo-dev-tsc.log +5 -6
- package/.turbo/turbo-eslint.log +9 -24
- package/.turbo/turbo-prettify.log +11 -0
- package/README.md +60 -17
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +86 -34
- package/dist/index.es.js.map +1 -1
- package/dist/index.iife.js +1 -1
- package/dist/index.iife.js.map +1 -1
- package/dist/types/index.d.ts +55 -0
- package/package.json +3 -3
- package/src/plugin.ts +88 -4
- package/src/types.ts +60 -0
- package/tsconfig.tsbuildinfo +1 -1
package/dist/index.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","names":[],"sources":["../src/routes.ts","../src/types.ts","../src/utils.ts","../package.json","../src/plugin.ts","../src/index.ts"],"sourcesContent":["export const LOCAL_ENDPOINT = 'http://localhost:5174';\nexport const PROD_ENDPOINT = 'https://seplugin.sendsay.ru';\n","export enum EditorMenu {\n Audit = 'audit',\n Guide = 'guide',\n Style = 'style',\n Blocks = 'blocks',\n}\n\nexport enum ViewMode {\n Desktop = 'desktop',\n Mobile = 'mobile',\n}\n\nexport interface Notification {\n intent: 'error' | 'info' | 'success' | 'warning';\n errorDetails?: object;\n message?: string;\n title: string;\n}\n\ntype PersonalizationDictionaryEntry =\n | { name: string; value: string }\n | { groupName: string; items: Array<{ name: string; value: string }> };\n\nexport type PersonalizationDictionaryItems = PersonalizationDictionaryEntry[];\n\nexport interface SerializedTemplate {\n [key: string]: unknown;\n parentId: string | null;\n id: string;\n parameters: object;\n layer: string;\n type: string;\n children?: SerializedTemplate[];\n meta?: { [key: string]: unknown; version: string };\n}\n\nexport type EventHandler<T> = (data: T) => void;\n\nexport type AsyncEventHandler<P, R> = (params: P) => Promise<R>;\n\nexport class DraftError extends Error {\n public readonly code: string;\n\n constructor(code: string, message: string) {\n super(message);\n this.name = 'DraftError';\n this.code = code;\n }\n}\n\nexport type MessageData = {\n source: string;\n event: string;\n ok?: boolean;\n code?: string;\n message?: string;\n action?: string;\n};\n\nexport interface ExportAsFileParams {\n blob: Blob;\n fileName: string;\n}\n\nexport interface SaveParams {\n json: TemplateJSON;\n html: string;\n}\n\nexport type OnInitParams = MessageEvent<{\n source: string;\n event: 'loaded' | unknown;\n}>;\n\nexport interface ReadyParams extends SaveParams {\n lastSavedTemplate?: {\n template: TemplateJSON;\n date: Date;\n };\n}\n\nexport interface ErrorParams {\n message: string;\n code?: string;\n details?: unknown;\n}\n\nexport interface ExitParams extends SaveParams {}\n\nexport type NotificationParams = Notification;\n\nexport interface OpenGalleryParams {\n id: string;\n}\n\nexport interface UploadImageParams {\n file: string;\n name: string;\n}\n\nexport interface ImageParams {\n url: string;\n originalWidth: number;\n originalHeight: number;\n ratio: number;\n fileSize: number;\n}\n\nexport interface AutosaveParams {\n json: TemplateJSON;\n}\n\ninterface ToggleParams {\n state: boolean;\n}\n\nexport interface ToggleGridParams extends ToggleParams {}\n\nexport interface ToggleInvisibleCharactersParams extends ToggleParams {}\n\nexport interface TogglePreviewParams extends ToggleParams {\n json: TemplateJSON;\n html: string;\n darkHTML: string;\n}\n\nexport interface ToggleViewModeParams {\n mode: ViewMode;\n}\n\nexport interface ToggleMenuParams {\n menu: EditorMenu | null;\n}\n\nexport interface HistoryParams {\n hasUndos: boolean;\n hasRedos: boolean;\n currentStep: number;\n}\n\nexport type TemplateJSON = SerializedTemplate;\n\nexport type PersonalizationDictionary = PersonalizationDictionaryItems;\n\nexport type ToolbarActionName =\n | 'duplicate'\n | 'destroy'\n | 'edit'\n | 'up'\n | 'down';\nexport type HotkeyContext = 'hotkey';\nexport type OverlayContext = 'overlay-click' | 'overlay-double-click';\nexport type ToolbarContext = 'toolbar';\nexport type UnitSettingsContext = 'unit-settings';\nexport type BlockType = 'system' | 'user';\nexport type DndDragContext = 'canvas' | 'list' | 'palette';\nexport type DndDropContext = 'dropline' | 'placeholder' | 'empty-placeholder';\nexport type DndDropTarget = 'root' | 'section' | 'column' | 'element';\n\nexport interface DuplicateEvent {\n name: 'duplicate';\n context: HotkeyContext | ToolbarContext | UnitSettingsContext;\n unitType: string;\n}\n\nexport interface DestroyEvent {\n name: 'destroy';\n context: HotkeyContext | ToolbarContext | UnitSettingsContext;\n unitType: string;\n}\n\nexport interface EditEvent {\n name: 'edit';\n context: OverlayContext | ToolbarContext;\n unitType: string;\n}\n\nexport interface HistoryEvent {\n name: 'history';\n type: 'undo' | 'redo';\n context: HotkeyContext;\n}\n\nexport interface PreviewEvent {\n name: 'preview';\n context: HotkeyContext;\n}\n\nexport interface ToolbarMoveEvent {\n name: 'up' | 'down';\n context: ToolbarContext;\n unitType: string;\n}\n\nexport interface BlockInsertEvent {\n name: 'block-insert';\n context: 'double-click';\n blockType: BlockType;\n blockName: string;\n blockCategory: string | number;\n blockId: string | number;\n}\n\nexport interface BlockSaveEvent {\n name: 'block-save';\n blockType: 'user';\n blockName: string;\n blockCategory: string | number;\n blockId: string | number;\n elements: Record<string, number> & { sum: number };\n}\n\nexport interface BlockDestroyEvent {\n name: 'block-destroy';\n}\n\nexport interface DropEventDragMeta {\n context?: DndDragContext;\n layer?: 'element' | 'section' | 'column' | 'root';\n type?: string | string[];\n blockCategory?: string | number;\n blockId?: string | number;\n blockName?: string;\n blockType?: BlockType;\n alt?: boolean;\n dropKind?: 'create' | 'move';\n}\n\nexport interface DropEventDropzoneMeta {\n context?: DndDropContext;\n dropTarget?: DndDropTarget;\n}\n\nexport interface DropEvent {\n name: 'drop';\n drag?: DropEventDragMeta;\n dropzone?: DropEventDropzoneMeta;\n}\n\nexport type AnalyticsParams =\n | DuplicateEvent\n | DestroyEvent\n | EditEvent\n | HistoryEvent\n | PreviewEvent\n | ToolbarMoveEvent\n | BlockInsertEvent\n | BlockSaveEvent\n | BlockDestroyEvent\n | DropEvent;\n\nexport interface Handlers {\n ready: EventHandler<ReadyParams>;\n error: EventHandler<ErrorParams>;\n save: EventHandler<SaveParams>;\n exit: EventHandler<ExitParams>;\n notification: EventHandler<NotificationParams>;\n autosave: EventHandler<AutosaveParams>;\n toggleGrid: EventHandler<ToggleGridParams>;\n toggleInvisibleCharacters: EventHandler<ToggleInvisibleCharactersParams>;\n togglePreview: EventHandler<TogglePreviewParams>;\n toggleViewMode: EventHandler<ToggleViewModeParams>;\n toggleMenu: EventHandler<ToggleMenuParams>;\n history: EventHandler<HistoryParams>;\n analytics: EventHandler<AnalyticsParams>;\n openGallery: EventHandler<(url?: string) => Promise<void>>;\n uploadImage: AsyncEventHandler<UploadImageParams, string>;\n loadPersonalization: AsyncEventHandler<void, PersonalizationDictionary>;\n}\n\nexport type HandlerParams<H> = H extends\n | EventHandler<infer P>\n | AsyncEventHandler<infer P, unknown>\n ? P\n : never;\n\nexport interface PluginConfig {\n container: string;\n locale?: string;\n autosave?:\n | boolean\n | {\n interval: number;\n };\n token: string;\n authData?: {\n orgId: number;\n projectId?: number;\n };\n pluginId: string;\n apiUrl: string;\n disableHotkeysPassing?: boolean;\n __config?: object;\n on: Partial<Handlers>;\n}\n","import { ImageParams } from './types';\n\nconst getImageFileSize = async (imageUrl: string) => {\n try {\n const response = await fetch(imageUrl, { method: 'HEAD' });\n\n if (!response.ok) {\n return null;\n }\n\n const contentLength = response.headers.get('Content-Length');\n\n if (contentLength) {\n return parseInt(contentLength, 10);\n } else {\n return null;\n }\n } catch (error) {\n return null;\n }\n};\n\nexport const getImageParamsFromFileUrl = (imgSrc: string) =>\n new Promise<Omit<ImageParams, 'url'>>((resolve, reject) => {\n const img = new Image();\n\n img.onload = async () => {\n const fileSize = (await getImageFileSize(imgSrc)) ?? 0;\n\n resolve({\n originalWidth: img.width,\n originalHeight: img.height,\n ratio: img.width / img.height,\n fileSize,\n });\n };\n\n img.onerror = (error) => {\n reject(error);\n };\n\n img.src = imgSrc;\n });\n\nconst getLatinKey = (key: string, code: string) => {\n if (key.length !== 1) {\n return key;\n }\n\n const capitalHetaCode = 880;\n const isNonLatin = key.charCodeAt(0) >= capitalHetaCode;\n\n if (isNonLatin) {\n if (code.indexOf('Key') === 0 && code.length === 4) {\n return code.charAt(3);\n }\n\n if (code.indexOf('Digit') === 0 && code.length === 6) {\n return code.charAt(5);\n }\n }\n\n return key;\n};\n\nexport const constructKeyCode = (event: KeyboardEvent) => {\n let keyCode =\n `${getLatinKey(event.key, event.code)}`.toLowerCase() || event.key;\n const macOs = navigator.userAgent.includes('Mac OS');\n\n if (keyCode === 'backspace' && macOs) {\n keyCode = 'delete';\n }\n\n const prefix = [];\n\n if ((macOs && event.metaKey) || (!macOs && event.ctrlKey)) {\n prefix.push('mod');\n }\n\n if (event.shiftKey) {\n prefix.push('shift');\n }\n\n if (prefix.length > 0) {\n keyCode = `${prefix.join('-')}-${getLatinKey(keyCode, event.code)}`;\n }\n\n return keyCode;\n};\n\nexport const CORE_HOTKEYS = new Set([\n 'escape',\n 'mod-c',\n 'mod-d',\n 'mod-z',\n 'mod-y',\n 'mod-shift-z',\n 'mod-v',\n 'delete',\n 'mod-g',\n 'mod-p',\n 'mod-s',\n]);\n","{\n \"name\": \"@getdraft/plugin\",\n \"version\": \"1.17.0\",\n \"main\": \"dist/index.cjs.js\",\n \"module\": \"dist/index.es.js\",\n \"types\": \"dist/types/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/types/index.d.ts\",\n \"import\": \"./dist/index.es.js\",\n \"require\": \"./dist/index.cjs.js\"\n }\n },\n \"scripts\": {\n \"prebuild\": \"rm -rf dist\",\n \"build\": \"vite build\",\n \"dev-tsc\": \"tsc-check\",\n \"eslint\": \"npx eslint src\",\n \"eslint:fix\": \"pnpm eslint --fix\",\n \"prettify\": \"npx prettier --check src\",\n \"prettify:fix\": \"npx prettier -w src\",\n \"prepublish\": \"pnpm build\",\n \"watch\": \"NODE_ENV=development vite build --watch\",\n \"start\": \"NODE_ENV=development npx vite\"\n },\n \"dependencies\": {},\n \"devDependencies\": {\n \"@getdraft/types\": \"workspace:^\",\n \"@getdraft/eslint-config-ts\": \"workspace:^\",\n \"@getdraft/prettier\": \"workspace:^\",\n \"vite-plugin-dts\": \"4.5.4\"\n },\n \"license\": \"MIT\"\n}\n","import { LOCAL_ENDPOINT, PROD_ENDPOINT } from './routes';\nimport {\n DraftError,\n EditorMenu,\n ExitParams,\n OnInitParams,\n OpenGalleryParams,\n Handlers,\n PluginConfig,\n SaveParams,\n TemplateJSON,\n UploadImageParams,\n ViewMode,\n HandlerParams,\n MessageData,\n ExportAsFileParams,\n} from './types';\nimport {\n getImageParamsFromFileUrl,\n constructKeyCode,\n CORE_HOTKEYS,\n} from './utils';\nimport pkg from '../package.json';\n\nconst getDeployLink = () => {\n const regex = new RegExp(`(^| )seplugin-dev=([^;]+)`);\n const match = document.cookie.match(regex);\n const value = match?.[2].toLowerCase?.();\n\n if (value === 'true') {\n return LOCAL_ENDPOINT;\n }\n\n if (value?.startsWith('https://')) {\n return value;\n }\n\n const [major, mid] = pkg.version.split('.');\n\n return `${PROD_ENDPOINT}/v${major}.${mid}`;\n};\n\nconst verifyConfig = ({ token, pluginId, apiUrl }: PluginConfig) => {\n if (!token) {\n throw new Error('No [token] was provided');\n }\n\n if (!pluginId) {\n throw new Error('No [pluginId] was provided');\n }\n\n if (!apiUrl) {\n throw new Error('No [apiUrl] was provided');\n }\n};\n\nconst createIframe = (parentOrigin: string) => {\n const iframe = document.createElement('iframe');\n const url = new URL(getDeployLink());\n url.searchParams.set('parentOrigin', parentOrigin);\n iframe.src = url.toString();\n iframe.setAttribute(\n 'style',\n 'height:100%;width:100%;min-width:960px;border:0px;',\n );\n iframe.setAttribute('allow', 'clipboard-read; clipboard-write');\n iframe.setAttribute(\n 'sandbox',\n 'allow-scripts allow-same-origin allow-forms allow-popups allow-downloads',\n );\n\n return iframe;\n};\n\nexport class PluginInstance {\n public iframe: HTMLIFrameElement | null = null;\n private hotkeysAttached = false;\n private iframeOrigin: string | null = null;\n constructor(public config: PluginConfig) {}\n\n private captureHotkeysEnabled() {\n return this.config.disableHotkeysPassing !== true;\n }\n\n private onHostHotkey = (event: KeyboardEvent) => {\n if (!this.captureHotkeysEnabled() || !this.iframe?.contentWindow) {\n return;\n }\n\n const keyCode = constructKeyCode(event);\n\n if (!CORE_HOTKEYS.has(keyCode)) {\n return;\n }\n\n const target = event.target as HTMLElement | null;\n\n if (\n target &&\n (target.isContentEditable ||\n ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName))\n ) {\n return;\n }\n\n event.preventDefault();\n\n const { key, ctrlKey, metaKey, shiftKey, altKey } = event;\n\n this.postEvent('hostHotkey', {\n key,\n code: event.code,\n metaKey,\n ctrlKey,\n shiftKey,\n altKey,\n keyCode,\n });\n };\n\n private static HEARTBEAT_TIMEOUT = 4000;\n\n private promisedIframeMethod<T>(eventName: string) {\n let timer: Timeout | null = null;\n let listener: ((e: MessageEvent<MessageData>) => void) | null = null;\n\n const cleanup = () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n\n if (listener) {\n window.removeEventListener('message', listener, true);\n listener = null;\n }\n };\n\n const res = new Promise<T>((resolve, reject) => {\n const resetTimer = () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n cleanup();\n reject(\n new DraftError('timeout_error', `Action \"${eventName}\" timed out`),\n );\n }, PluginInstance.HEARTBEAT_TIMEOUT);\n };\n\n listener = (e: MessageEvent<MessageData>) => {\n if (e.source !== this.iframe?.contentWindow) return;\n\n const { data } = e;\n if (data.source !== 'DraftPlugin') return;\n\n if (data.event === 'actionPing' && data.action === eventName) {\n e.stopPropagation();\n resetTimer();\n\n return;\n }\n\n if (data.event === eventName) {\n e.stopPropagation();\n cleanup();\n\n const { source: _1, event: _2, ok, code, message, ...rest } = data;\n\n if (ok === false) {\n reject(\n new DraftError(\n code || 'unknown_error',\n message || 'Unknown error',\n ),\n );\n } else {\n resolve(rest as T);\n }\n }\n };\n\n window.addEventListener('message', listener, true);\n resetTimer();\n });\n\n this.postEvent(eventName);\n\n return res;\n }\n\n private postEvent(event: string, data: object = {}) {\n if (this.iframe && this.iframe.contentWindow && this.iframeOrigin) {\n this.iframe.contentWindow.postMessage(\n {\n ...data,\n event,\n source: 'DraftPlugin',\n },\n this.iframeOrigin,\n );\n } else if (!this.iframeOrigin) {\n throw new Error('Iframe origin is not initialized');\n }\n }\n\n private onImageUpload = async ({\n id,\n ...data\n }: UploadImageParams & { id: string }) => {\n try {\n const url = await this.config.on.uploadImage?.(data);\n let params = {};\n\n if (url) {\n params = await getImageParamsFromFileUrl(url);\n }\n\n this.postEvent('imageUploaded', { id, img: { ...params, url } });\n } catch (e) {\n this.postEvent('imageUploaded', { id });\n }\n };\n\n private onLoadPersonalization = async () => {\n try {\n if (!this.config.on.loadPersonalization) {\n throw new Error('No personalization loader provided');\n }\n\n const personalizationDictionary =\n await this.config.on.loadPersonalization();\n\n this.postEvent('loadPersonalization', {\n items: personalizationDictionary,\n });\n } catch (e) {\n this.postEvent('loadPersonalization', {});\n }\n };\n\n private onGalleryOpen = async ({ id }: { id: string }) => {\n const applyImage = async (url?: string) => {\n const imgParams = { url };\n\n if (url) {\n const params = await getImageParamsFromFileUrl(url);\n Object.assign(imgParams, params);\n }\n\n this.postEvent('imageUploaded', {\n id,\n img: imgParams,\n });\n };\n\n this.config.on.openGallery?.(applyImage);\n };\n\n private triggerEvent<H extends CallableFunction | undefined>(\n handler: H,\n params: HandlerParams<H>,\n ) {\n if (!handler) {\n return;\n }\n\n return handler(params);\n }\n\n private onMessage = (\n ev: MessageEvent<{ source: string; event: keyof Handlers }>,\n ) => {\n if (ev.source !== this.iframe?.contentWindow) {\n return;\n }\n\n const {\n data: { source, event, ...data },\n } = ev;\n\n if (source === 'DraftPlugin') {\n if (event === 'openGallery') {\n this.onGalleryOpen(data as OpenGalleryParams);\n } else if (event === 'uploadImage') {\n this.onImageUpload(data as UploadImageParams & { id: string });\n } else if (event === 'loadPersonalization') {\n this.onLoadPersonalization();\n } else {\n this.triggerEvent(\n this.config.on[event],\n data as HandlerParams<Handlers[typeof event]>,\n );\n }\n }\n };\n\n start({\n template,\n templateName,\n uid,\n }: {\n template: string | TemplateJSON;\n uid: string | number;\n templateName?: string;\n }) {\n const containerEl = document.querySelector(this.config.container);\n\n if (!containerEl) {\n throw new Error('Specified container not found');\n } else {\n const onInit = (msg: OnInitParams) => {\n const {\n data: { source, event },\n } = msg;\n if (source === 'DraftPlugin' && event === 'loaded') {\n if (msg.source !== this.iframe?.contentWindow) return;\n\n this.iframeOrigin = msg.origin;\n\n const {\n on,\n container,\n locale,\n autosave,\n token,\n apiUrl,\n pluginId,\n authData,\n __config,\n } = this.config;\n\n verifyConfig(this.config);\n\n if (this.iframe && this.iframe.contentWindow) {\n this.postEvent('init', {\n container,\n locale,\n uid,\n autosave,\n token,\n pluginId,\n authData,\n apiUrl,\n __config,\n enabledListeners: Object.keys(on),\n template,\n templateName,\n });\n }\n\n window.addEventListener('message', this.onMessage);\n window.removeEventListener('message', onInit);\n }\n };\n\n this.iframe = createIframe(window.location.origin);\n window.addEventListener('message', onInit);\n containerEl.appendChild(this.iframe);\n\n if (this.captureHotkeysEnabled() && !this.hotkeysAttached) {\n window.addEventListener('keydown', this.onHostHotkey);\n this.hotkeysAttached = true;\n }\n }\n }\n\n destroy = () => {\n this.iframe?.remove();\n this.iframe = null;\n window.removeEventListener('message', this.onMessage);\n\n if (this.hotkeysAttached) {\n window.removeEventListener('keydown', this.onHostHotkey);\n this.hotkeysAttached = false;\n }\n };\n\n changeTemplate(\n template: string | TemplateJSON,\n options: {\n templateName?: string;\n uid?: string;\n } = {},\n ) {\n this.postEvent('changeTemplate', { ...options, template });\n }\n\n toggleGrid(state?: boolean) {\n this.postEvent('toggleGrid', { state });\n }\n\n toggleInvisibleCharacters(state?: boolean) {\n this.postEvent('toggleInvisibleCharacters', { state });\n }\n\n togglePreview(state?: boolean) {\n this.postEvent('togglePreview', { state });\n }\n\n toggleMenu(menu: EditorMenu | null = null) {\n this.postEvent('toggleMenu', { menu });\n }\n\n toggleViewMode(viewMode: ViewMode) {\n this.postEvent('toggleViewMode', { viewMode });\n }\n\n undo() {\n this.postEvent('undo');\n }\n\n undoToStep(targetStep: number) {\n this.postEvent('undoToStep', { targetStep });\n }\n\n redo() {\n this.postEvent('redo');\n }\n\n save() {\n return this.promisedIframeMethod<SaveParams>('saveAction');\n }\n\n exit() {\n return this.promisedIframeMethod<ExitParams>('exitAction');\n }\n\n exportContent() {\n return this.promisedIframeMethod<SaveParams>('exportContent');\n }\n\n exportAsFile() {\n return this.promisedIframeMethod<ExportAsFileParams>('exportAsFile');\n }\n}\n","import { PluginInstance } from './plugin';\nimport { PluginConfig } from './types';\nimport { version } from '../package.json';\n\nconst DEFAULT_CONFIG: Partial<PluginConfig> = {\n container: '#draft-plugin-container',\n disableHotkeysPassing: false,\n locale: 'ru',\n on: {},\n};\n\nclass PluginWrapper {\n public version = version;\n\n create(config: PluginConfig) {\n return new PluginInstance({\n ...DEFAULT_CONFIG,\n ...config,\n });\n }\n}\n\nconst DraftPlugin = new PluginWrapper();\n\ndeclare global {\n interface Window {\n DraftPlugin: PluginWrapper;\n }\n}\n\nwindow.DraftPlugin = DraftPlugin;\n\nexport default DraftPlugin;\nexport type { PluginInstance } from './plugin';\nexport * from './types';\n"],"mappings":";AAAA,IAAa,IAAiB,yBACjB,IAAgB,+BCDjB,IAAL,yBAAA,GAAA;QACL,EAAA,QAAA,SACA,EAAA,QAAA,SACA,EAAA,QAAA,SACA,EAAA,SAAA;KACD,EAEW,IAAL,yBAAA,GAAA;QACL,EAAA,UAAA,WACA,EAAA,SAAA;KACD,EA8BY,IAAb,cAAgC,MAAM;CACpC;CAEA,YAAY,GAAc,GAAiB;AAGzC,EAFA,MAAM,EAAQ,EACd,KAAK,OAAO,cACZ,KAAK,OAAO;;GC5CV,IAAmB,OAAO,MAAqB;AACnD,KAAI;EACF,IAAM,IAAW,MAAM,MAAM,GAAU,EAAE,QAAQ,QAAQ,CAAC;AAE1D,MAAI,CAAC,EAAS,GACZ,QAAO;EAGT,IAAM,IAAgB,EAAS,QAAQ,IAAI,iBAAiB;AAK1D,SAHE,IACK,SAAS,GAAe,GAAG,GAE3B;SAEK;AACd,SAAO;;GAIE,KAA6B,MACxC,IAAI,SAAmC,GAAS,MAAW;CACzD,IAAM,IAAM,IAAI,OAAO;AAiBvB,CAfA,EAAI,SAAS,YAAY;EACvB,IAAM,IAAY,MAAM,EAAiB,EAAO,IAAK;AAErD,IAAQ;GACN,eAAe,EAAI;GACnB,gBAAgB,EAAI;GACpB,OAAO,EAAI,QAAQ,EAAI;GACvB;GACD,CAAC;IAGJ,EAAI,WAAW,MAAU;AACvB,IAAO,EAAM;IAGf,EAAI,MAAM;EACV,EAEE,KAAe,GAAa,MAAiB;AACjD,KAAI,EAAI,WAAW,EACjB,QAAO;AAMT,KAFmB,EAAI,WAAW,EAAE,IADZ,KAGR;AACd,MAAI,EAAK,QAAQ,MAAM,KAAK,KAAK,EAAK,WAAW,EAC/C,QAAO,EAAK,OAAO,EAAE;AAGvB,MAAI,EAAK,QAAQ,QAAQ,KAAK,KAAK,EAAK,WAAW,EACjD,QAAO,EAAK,OAAO,EAAE;;AAIzB,QAAO;GAGI,KAAoB,MAAyB;CACxD,IAAI,IACF,GAAG,EAAY,EAAM,KAAK,EAAM,KAAK,GAAG,aAAa,IAAI,EAAM,KAC3D,IAAQ,UAAU,UAAU,SAAS,SAAS;AAEpD,CAAI,MAAY,eAAe,MAC7B,IAAU;CAGZ,IAAM,IAAS,EAAE;AAcjB,SAZK,KAAS,EAAM,WAAa,CAAC,KAAS,EAAM,YAC/C,EAAO,KAAK,MAAM,EAGhB,EAAM,YACR,EAAO,KAAK,QAAQ,EAGlB,EAAO,SAAS,MAClB,IAAU,GAAG,EAAO,KAAK,IAAI,CAAC,GAAG,EAAY,GAAS,EAAM,KAAK,KAG5D;GAGI,IAAe,IAAI,IAAI;CAClC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GE/EI,UAAsB;CAC1B,IAAM,IAAY,OAAO,4BAA4B,EAE/C,IADQ,SAAS,OAAO,MAAM,EAAM,GACpB,GAAG,eAAe;AAExC,KAAI,MAAU,OACZ,QAAO;AAGT,KAAI,GAAO,WAAW,WAAW,CAC/B,QAAO;CAGT,IAAM,CAAC,GAAO,KAAO,EAAI,QAAQ,MAAM,IAAI;AAE3C,QAAO,GAAG,EAAc,IAAI,EAAM,GAAG;GAGjC,KAAgB,EAAE,UAAO,aAAU,gBAA2B;AAClE,KAAI,CAAC,EACH,OAAU,MAAM,0BAA0B;AAG5C,KAAI,CAAC,EACH,OAAU,MAAM,6BAA6B;AAG/C,KAAI,CAAC,EACH,OAAU,MAAM,2BAA2B;GAIzC,KAAgB,MAAyB;CAC7C,IAAM,IAAS,SAAS,cAAc,SAAS,EACzC,IAAM,IAAI,IAAI,GAAe,CAAC;AAapC,QAZA,EAAI,aAAa,IAAI,gBAAgB,EAAa,EAClD,EAAO,MAAM,EAAI,UAAU,EAC3B,EAAO,aACL,SACA,qDACD,EACD,EAAO,aAAa,SAAS,kCAAkC,EAC/D,EAAO,aACL,WACA,2EACD,EAEM;GAGI,IAAb,MAAa,EAAe;CAC1B,SAA0C;CAC1C,kBAA0B;CAC1B,eAAsC;CACtC,YAAY,GAA6B;AAAtB,OAAA,SAAA;;CAEnB,wBAAgC;AAC9B,SAAO,KAAK,OAAO,0BAA0B;;CAG/C,gBAAwB,MAAyB;AAC/C,MAAI,CAAC,KAAK,uBAAuB,IAAI,CAAC,KAAK,QAAQ,cACjD;EAGF,IAAM,IAAU,EAAiB,EAAM;AAEvC,MAAI,CAAC,EAAa,IAAI,EAAQ,CAC5B;EAGF,IAAM,IAAS,EAAM;AAErB,MACE,MACC,EAAO,qBACN;GAAC;GAAS;GAAY;GAAS,CAAC,SAAS,EAAO,QAAQ,EAE1D;AAGF,IAAM,gBAAgB;EAEtB,IAAM,EAAE,QAAK,YAAS,YAAS,aAAU,cAAW;AAEpD,OAAK,UAAU,cAAc;GAC3B;GACA,MAAM,EAAM;GACZ;GACA;GACA;GACA;GACA;GACD,CAAC;;CAGJ,OAAe,oBAAoB;CAEnC,qBAAgC,GAAmB;EACjD,IAAI,IAAwB,MACxB,IAA4D,MAE1D,UAAgB;AAMpB,GALA,AAEE,OADA,aAAa,EAAM,EACX,OAGV,AAEE,OADA,OAAO,oBAAoB,WAAW,GAAU,GAAK,EAC1C;KAIT,IAAM,IAAI,SAAY,GAAS,MAAW;GAC9C,IAAM,UAAmB;AAEvB,IADI,KAAO,aAAa,EAAM,EAC9B,IAAQ,iBAAiB;AAEvB,KADA,GAAS,EACT,EACE,IAAI,EAAW,iBAAiB,WAAW,EAAU,aAAa,CACnE;OACA,EAAe,kBAAkB;;AAoCtC,GAjCA,KAAY,MAAiC;AAC3C,QAAI,EAAE,WAAW,KAAK,QAAQ,cAAe;IAE7C,IAAM,EAAE,YAAS;AACb,UAAK,WAAW,eAEpB;SAAI,EAAK,UAAU,gBAAgB,EAAK,WAAW,GAAW;AAE5D,MADA,EAAE,iBAAiB,EACnB,GAAY;AAEZ;;AAGF,SAAI,EAAK,UAAU,GAAW;AAE5B,MADA,EAAE,iBAAiB,EACnB,GAAS;MAET,IAAM,EAAE,QAAQ,GAAI,OAAO,GAAI,OAAI,SAAM,YAAS,GAAG,MAAS;AAE9D,MAAI,MAAO,KACT,EACE,IAAI,EACF,KAAQ,iBACR,KAAW,gBACZ,CACF,GAED,EAAQ,EAAU;;;MAKxB,OAAO,iBAAiB,WAAW,GAAU,GAAK,EAClD,GAAY;IACZ;AAIF,SAFA,KAAK,UAAU,EAAU,EAElB;;CAGT,UAAkB,GAAe,IAAe,EAAE,EAAE;AAClD,MAAI,KAAK,UAAU,KAAK,OAAO,iBAAiB,KAAK,aACnD,MAAK,OAAO,cAAc,YACxB;GACE,GAAG;GACH;GACA,QAAQ;GACT,EACD,KAAK,aACN;WACQ,CAAC,KAAK,aACf,OAAU,MAAM,mCAAmC;;CAIvD,gBAAwB,OAAO,EAC7B,OACA,GAAG,QACqC;AACxC,MAAI;GACF,IAAM,IAAM,MAAM,KAAK,OAAO,GAAG,cAAc,EAAK,EAChD,IAAS,EAAE;AAMf,GAJI,MACF,IAAS,MAAM,EAA0B,EAAI,GAG/C,KAAK,UAAU,iBAAiB;IAAE;IAAI,KAAK;KAAE,GAAG;KAAQ;KAAK;IAAE,CAAC;UACtD;AACV,QAAK,UAAU,iBAAiB,EAAE,OAAI,CAAC;;;CAI3C,wBAAgC,YAAY;AAC1C,MAAI;AACF,OAAI,CAAC,KAAK,OAAO,GAAG,oBAClB,OAAU,MAAM,qCAAqC;GAGvD,IAAM,IACJ,MAAM,KAAK,OAAO,GAAG,qBAAqB;AAE5C,QAAK,UAAU,uBAAuB,EACpC,OAAO,GACR,CAAC;UACQ;AACV,QAAK,UAAU,uBAAuB,EAAE,CAAC;;;CAI7C,gBAAwB,OAAO,EAAE,YAAyB;AAexD,OAAK,OAAO,GAAG,cAdI,OAAO,MAAiB;GACzC,IAAM,IAAY,EAAE,QAAK;AAEzB,OAAI,GAAK;IACP,IAAM,IAAS,MAAM,EAA0B,EAAI;AACnD,WAAO,OAAO,GAAW,EAAO;;AAGlC,QAAK,UAAU,iBAAiB;IAC9B;IACA,KAAK;IACN,CAAC;IAGoC;;CAG1C,aACE,GACA,GACA;AACK,QAIL,QAAO,EAAQ,EAAO;;CAGxB,aACE,MACG;AACH,MAAI,EAAG,WAAW,KAAK,QAAQ,cAC7B;EAGF,IAAM,EACJ,MAAM,EAAE,WAAQ,UAAO,GAAG,QACxB;AAEJ,EAAI,MAAW,kBACT,MAAU,gBACZ,KAAK,cAAc,EAA0B,GACpC,MAAU,gBACnB,KAAK,cAAc,EAA2C,GACrD,MAAU,wBACnB,KAAK,uBAAuB,GAE5B,KAAK,aACH,KAAK,OAAO,GAAG,IACf,EACD;;CAKP,MAAM,EACJ,aACA,iBACA,UAKC;EACD,IAAM,IAAc,SAAS,cAAc,KAAK,OAAO,UAAU;AAEjE,MAAK,GAEE;GACL,IAAM,KAAU,MAAsB;IACpC,IAAM,EACJ,MAAM,EAAE,WAAQ,eACd;AACJ,QAAI,MAAW,iBAAiB,MAAU,UAAU;AAClD,SAAI,EAAI,WAAW,KAAK,QAAQ,cAAe;AAE/C,UAAK,eAAe,EAAI;KAExB,IAAM,EACJ,OACA,cACA,WACA,aACA,UACA,WACA,aACA,aACA,gBACE,KAAK;AAsBT,KApBA,EAAa,KAAK,OAAO,EAErB,KAAK,UAAU,KAAK,OAAO,iBAC7B,KAAK,UAAU,QAAQ;MACrB;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA,kBAAkB,OAAO,KAAK,EAAG;MACjC;MACA;MACD,CAAC,EAGJ,OAAO,iBAAiB,WAAW,KAAK,UAAU,EAClD,OAAO,oBAAoB,WAAW,EAAO;;;AAQjD,GAJA,KAAK,SAAS,EAAa,OAAO,SAAS,OAAO,EAClD,OAAO,iBAAiB,WAAW,EAAO,EAC1C,EAAY,YAAY,KAAK,OAAO,EAEhC,KAAK,uBAAuB,IAAI,CAAC,KAAK,oBACxC,OAAO,iBAAiB,WAAW,KAAK,aAAa,EACrD,KAAK,kBAAkB;QArDzB,OAAU,MAAM,gCAAgC;;CA0DpD,gBAAgB;AAKd,EAJA,KAAK,QAAQ,QAAQ,EACrB,KAAK,SAAS,MACd,OAAO,oBAAoB,WAAW,KAAK,UAAU,EAErD,AAEE,KAAK,qBADL,OAAO,oBAAoB,WAAW,KAAK,aAAa,EACjC;;CAI3B,eACE,GACA,IAGI,EAAE,EACN;AACA,OAAK,UAAU,kBAAkB;GAAE,GAAG;GAAS;GAAU,CAAC;;CAG5D,WAAW,GAAiB;AAC1B,OAAK,UAAU,cAAc,EAAE,UAAO,CAAC;;CAGzC,0BAA0B,GAAiB;AACzC,OAAK,UAAU,6BAA6B,EAAE,UAAO,CAAC;;CAGxD,cAAc,GAAiB;AAC7B,OAAK,UAAU,iBAAiB,EAAE,UAAO,CAAC;;CAG5C,WAAW,IAA0B,MAAM;AACzC,OAAK,UAAU,cAAc,EAAE,SAAM,CAAC;;CAGxC,eAAe,GAAoB;AACjC,OAAK,UAAU,kBAAkB,EAAE,aAAU,CAAC;;CAGhD,OAAO;AACL,OAAK,UAAU,OAAO;;CAGxB,WAAW,GAAoB;AAC7B,OAAK,UAAU,cAAc,EAAE,eAAY,CAAC;;CAG9C,OAAO;AACL,OAAK,UAAU,OAAO;;CAGxB,OAAO;AACL,SAAO,KAAK,qBAAiC,aAAa;;CAG5D,OAAO;AACL,SAAO,KAAK,qBAAiC,aAAa;;CAG5D,gBAAgB;AACd,SAAO,KAAK,qBAAiC,gBAAgB;;CAG/D,eAAe;AACb,SAAO,KAAK,qBAAyC,eAAe;;GC5alE,IAAwC;CAC5C,WAAW;CACX,uBAAuB;CACvB,QAAQ;CACR,IAAI,EAAE;CACP,EAaK,IAAc,IAXpB,MAAoB;CAClB,UAAiB;CAEjB,OAAO,GAAsB;AAC3B,SAAO,IAAI,EAAe;GACxB,GAAG;GACH,GAAG;GACJ,CAAC;;GAIiC;AAQvC,OAAO,cAAc"}
|
|
1
|
+
{"version":3,"file":"index.es.js","names":[],"sources":["../src/routes.ts","../src/types.ts","../src/utils.ts","../package.json","../src/plugin.ts","../src/index.ts"],"sourcesContent":["export const LOCAL_ENDPOINT = 'http://localhost:5174';\nexport const PROD_ENDPOINT = 'https://seplugin.sendsay.ru';\n","export enum EditorMenu {\n Audit = 'audit',\n Guide = 'guide',\n Style = 'style',\n Blocks = 'blocks',\n}\n\nexport enum ViewMode {\n Desktop = 'desktop',\n Mobile = 'mobile',\n}\n\nexport interface Notification {\n intent: 'error' | 'info' | 'success' | 'warning';\n errorDetails?: object;\n message?: string;\n title: string;\n}\n\ntype PersonalizationDictionaryEntry =\n | { name: string; value: string }\n | { groupName: string; items: Array<{ name: string; value: string }> };\n\nexport type PersonalizationDictionaryItems = PersonalizationDictionaryEntry[];\n\nexport type SectionPersonalizationValue = string | number | boolean | null;\n\nexport interface SectionPersonalizationField {\n id: string;\n operatorId: 'equals';\n}\n\nexport interface SectionPersonalizationCatalogOption {\n label: string;\n value: Exclude<SectionPersonalizationValue, null>;\n}\n\nexport interface SectionPersonalizationCatalogGroup {\n type: 'group';\n id: string;\n label: string;\n children: SectionPersonalizationCatalogNode[];\n}\n\nexport interface SectionPersonalizationCatalogField {\n type: 'field';\n id: string;\n label: string;\n valueType?: 'string' | 'number' | 'boolean' | 'date';\n options?: SectionPersonalizationCatalogOption[];\n}\n\nexport type SectionPersonalizationCatalogNode =\n | SectionPersonalizationCatalogGroup\n | SectionPersonalizationCatalogField;\n\nexport interface SectionPersonalizationConfig {\n enabled: boolean;\n aboutUrl?: string;\n}\n\nexport interface RenderSectionPersonalizationGroupInput {\n groupId: string;\n fields: SectionPersonalizationField[];\n variants: Array<{\n id: string;\n values: Record<string, SectionPersonalizationValue>;\n html: string;\n }>;\n fallback?: {\n id: string;\n html: string;\n };\n}\n\nexport interface SerializedTemplate {\n [key: string]: unknown;\n parentId: string | null;\n id: string;\n parameters: object;\n layer: string;\n type: string;\n children?: SerializedTemplate[];\n meta?: { [key: string]: unknown; version: string };\n}\n\nexport type EventHandler<T> = (data: T) => void;\n\nexport type AsyncEventHandler<P, R> = (params: P) => Promise<R>;\n\nexport class DraftError extends Error {\n public readonly code: string;\n\n constructor(code: string, message: string) {\n super(message);\n this.name = 'DraftError';\n this.code = code;\n }\n}\n\nexport type MessageData = {\n source: string;\n event: string;\n ok?: boolean;\n code?: string;\n message?: string;\n action?: string;\n requestId?: string;\n};\n\nexport interface ExportAsFileParams {\n blob: Blob;\n fileName: string;\n}\n\nexport interface SaveParams {\n json: TemplateJSON;\n html: string;\n}\n\nexport type OnInitParams = MessageEvent<{\n source: string;\n event: 'loaded' | unknown;\n}>;\n\nexport interface ReadyParams extends SaveParams {\n lastSavedTemplate?: {\n template: TemplateJSON;\n date: Date;\n };\n}\n\nexport interface ErrorParams {\n message: string;\n code?: string;\n details?: unknown;\n}\n\nexport interface ExitParams extends SaveParams {}\n\nexport type NotificationParams = Notification;\n\nexport interface OpenGalleryParams {\n id: string;\n}\n\nexport interface UploadImageParams {\n file: string;\n name: string;\n}\n\nexport interface ImageParams {\n url: string;\n originalWidth: number;\n originalHeight: number;\n ratio: number;\n fileSize: number;\n}\n\nexport interface AutosaveParams {\n json: TemplateJSON;\n}\n\ninterface ToggleParams {\n state: boolean;\n}\n\nexport interface ToggleGridParams extends ToggleParams {}\n\nexport interface ToggleInvisibleCharactersParams extends ToggleParams {}\n\nexport interface TogglePreviewParams extends ToggleParams {\n json: TemplateJSON;\n html: string;\n darkHTML: string;\n}\n\nexport interface ToggleViewModeParams {\n mode: ViewMode;\n}\n\nexport interface ToggleMenuParams {\n menu: EditorMenu | null;\n}\n\nexport interface HistoryParams {\n hasUndos: boolean;\n hasRedos: boolean;\n currentStep: number;\n}\n\nexport type TemplateJSON = SerializedTemplate;\n\nexport type PersonalizationDictionary = PersonalizationDictionaryItems;\n\nexport type ToolbarActionName =\n | 'duplicate'\n | 'destroy'\n | 'edit'\n | 'up'\n | 'down';\nexport type HotkeyContext = 'hotkey';\nexport type OverlayContext = 'overlay-click' | 'overlay-double-click';\nexport type ToolbarContext = 'toolbar';\nexport type UnitSettingsContext = 'unit-settings';\nexport type BlockType = 'system' | 'user';\nexport type DndDragContext = 'canvas' | 'list' | 'palette';\nexport type DndDropContext = 'dropline' | 'placeholder' | 'empty-placeholder';\nexport type DndDropTarget = 'root' | 'section' | 'column' | 'element';\n\nexport interface DuplicateEvent {\n name: 'duplicate';\n context: HotkeyContext | ToolbarContext | UnitSettingsContext;\n unitType: string;\n}\n\nexport interface DestroyEvent {\n name: 'destroy';\n context: HotkeyContext | ToolbarContext | UnitSettingsContext;\n unitType: string;\n}\n\nexport interface EditEvent {\n name: 'edit';\n context: OverlayContext | ToolbarContext;\n unitType: string;\n}\n\nexport interface HistoryEvent {\n name: 'history';\n type: 'undo' | 'redo';\n context: HotkeyContext;\n}\n\nexport interface PreviewEvent {\n name: 'preview';\n context: HotkeyContext;\n}\n\nexport interface ToolbarMoveEvent {\n name: 'up' | 'down';\n context: ToolbarContext;\n unitType: string;\n}\n\nexport interface BlockInsertEvent {\n name: 'block-insert';\n context: 'double-click';\n blockType: BlockType;\n blockName: string;\n blockCategory: string | number;\n blockId: string | number;\n}\n\nexport interface BlockSaveEvent {\n name: 'block-save';\n blockType: 'user';\n blockName: string;\n blockCategory: string | number;\n blockId: string | number;\n elements: Record<string, number> & { sum: number };\n}\n\nexport interface BlockDestroyEvent {\n name: 'block-destroy';\n}\n\nexport interface DropEventDragMeta {\n context?: DndDragContext;\n layer?: 'element' | 'section' | 'column' | 'root';\n type?: string | string[];\n blockCategory?: string | number;\n blockId?: string | number;\n blockName?: string;\n blockType?: BlockType;\n alt?: boolean;\n dropKind?: 'create' | 'move';\n}\n\nexport interface DropEventDropzoneMeta {\n context?: DndDropContext;\n dropTarget?: DndDropTarget;\n}\n\nexport interface DropEvent {\n name: 'drop';\n drag?: DropEventDragMeta;\n dropzone?: DropEventDropzoneMeta;\n}\n\nexport type AnalyticsParams =\n | DuplicateEvent\n | DestroyEvent\n | EditEvent\n | HistoryEvent\n | PreviewEvent\n | ToolbarMoveEvent\n | BlockInsertEvent\n | BlockSaveEvent\n | BlockDestroyEvent\n | DropEvent;\n\nexport interface Handlers {\n ready: EventHandler<ReadyParams>;\n error: EventHandler<ErrorParams>;\n save: EventHandler<SaveParams>;\n exit: EventHandler<ExitParams>;\n notification: EventHandler<NotificationParams>;\n autosave: EventHandler<AutosaveParams>;\n toggleGrid: EventHandler<ToggleGridParams>;\n toggleInvisibleCharacters: EventHandler<ToggleInvisibleCharactersParams>;\n togglePreview: EventHandler<TogglePreviewParams>;\n toggleViewMode: EventHandler<ToggleViewModeParams>;\n toggleMenu: EventHandler<ToggleMenuParams>;\n history: EventHandler<HistoryParams>;\n analytics: EventHandler<AnalyticsParams>;\n openGallery: EventHandler<(url?: string) => Promise<void>>;\n uploadImage: AsyncEventHandler<UploadImageParams, string>;\n loadPersonalization: AsyncEventHandler<void, PersonalizationDictionary>;\n loadSectionPersonalizationCatalog: AsyncEventHandler<\n void,\n SectionPersonalizationCatalogNode[]\n >;\n renderSectionPersonalizationGroup: AsyncEventHandler<\n RenderSectionPersonalizationGroupInput,\n string\n >;\n}\n\nexport type HandlerParams<H> = H extends\n | EventHandler<infer P>\n | AsyncEventHandler<infer P, unknown>\n ? P\n : never;\n\nexport interface PluginConfig {\n container: string;\n locale?: string;\n autosave?:\n | boolean\n | {\n interval: number;\n };\n token: string;\n authData?: {\n orgId: number;\n projectId?: number;\n };\n pluginId: string;\n apiUrl: string;\n disableHotkeysPassing?: boolean;\n sectionPersonalization?: SectionPersonalizationConfig;\n __config?: object;\n on: Partial<Handlers>;\n}\n","import { ImageParams } from './types';\n\nconst getImageFileSize = async (imageUrl: string) => {\n try {\n const response = await fetch(imageUrl, { method: 'HEAD' });\n\n if (!response.ok) {\n return null;\n }\n\n const contentLength = response.headers.get('Content-Length');\n\n if (contentLength) {\n return parseInt(contentLength, 10);\n } else {\n return null;\n }\n } catch (error) {\n return null;\n }\n};\n\nexport const getImageParamsFromFileUrl = (imgSrc: string) =>\n new Promise<Omit<ImageParams, 'url'>>((resolve, reject) => {\n const img = new Image();\n\n img.onload = async () => {\n const fileSize = (await getImageFileSize(imgSrc)) ?? 0;\n\n resolve({\n originalWidth: img.width,\n originalHeight: img.height,\n ratio: img.width / img.height,\n fileSize,\n });\n };\n\n img.onerror = (error) => {\n reject(error);\n };\n\n img.src = imgSrc;\n });\n\nconst getLatinKey = (key: string, code: string) => {\n if (key.length !== 1) {\n return key;\n }\n\n const capitalHetaCode = 880;\n const isNonLatin = key.charCodeAt(0) >= capitalHetaCode;\n\n if (isNonLatin) {\n if (code.indexOf('Key') === 0 && code.length === 4) {\n return code.charAt(3);\n }\n\n if (code.indexOf('Digit') === 0 && code.length === 6) {\n return code.charAt(5);\n }\n }\n\n return key;\n};\n\nexport const constructKeyCode = (event: KeyboardEvent) => {\n let keyCode =\n `${getLatinKey(event.key, event.code)}`.toLowerCase() || event.key;\n const macOs = navigator.userAgent.includes('Mac OS');\n\n if (keyCode === 'backspace' && macOs) {\n keyCode = 'delete';\n }\n\n const prefix = [];\n\n if ((macOs && event.metaKey) || (!macOs && event.ctrlKey)) {\n prefix.push('mod');\n }\n\n if (event.shiftKey) {\n prefix.push('shift');\n }\n\n if (prefix.length > 0) {\n keyCode = `${prefix.join('-')}-${getLatinKey(keyCode, event.code)}`;\n }\n\n return keyCode;\n};\n\nexport const CORE_HOTKEYS = new Set([\n 'escape',\n 'mod-c',\n 'mod-d',\n 'mod-z',\n 'mod-y',\n 'mod-shift-z',\n 'mod-v',\n 'delete',\n 'mod-g',\n 'mod-p',\n 'mod-s',\n]);\n","{\n \"name\": \"@getdraft/plugin\",\n \"version\": \"1.19.0-alpha.0\",\n \"main\": \"dist/index.cjs.js\",\n \"module\": \"dist/index.es.js\",\n \"types\": \"dist/types/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/types/index.d.ts\",\n \"import\": \"./dist/index.es.js\",\n \"require\": \"./dist/index.cjs.js\"\n }\n },\n \"scripts\": {\n \"prebuild\": \"rm -rf dist\",\n \"build\": \"vite build\",\n \"dev-tsc\": \"tsc-check\",\n \"eslint\": \"npx eslint src\",\n \"eslint:fix\": \"pnpm eslint --fix\",\n \"prettify\": \"npx prettier --check src\",\n \"prettify:fix\": \"npx prettier -w src\",\n \"prepublish\": \"pnpm build\",\n \"watch\": \"NODE_ENV=development vite build --watch\",\n \"start\": \"NODE_ENV=development npx vite\"\n },\n \"dependencies\": {},\n \"devDependencies\": {\n \"@getdraft/types\": \"workspace:^\",\n \"@getdraft/eslint-config-ts\": \"workspace:^\",\n \"@getdraft/prettier\": \"workspace:^\",\n \"vite-plugin-dts\": \"4.5.4\"\n },\n \"license\": \"MIT\"\n}\n","import { LOCAL_ENDPOINT, PROD_ENDPOINT } from './routes';\nimport {\n DraftError,\n EditorMenu,\n ExitParams,\n OnInitParams,\n OpenGalleryParams,\n Handlers,\n PluginConfig,\n SaveParams,\n TemplateJSON,\n UploadImageParams,\n ViewMode,\n HandlerParams,\n MessageData,\n ExportAsFileParams,\n RenderSectionPersonalizationGroupInput,\n} from './types';\nimport {\n getImageParamsFromFileUrl,\n constructKeyCode,\n CORE_HOTKEYS,\n} from './utils';\nimport pkg from '../package.json';\n\nconst UNKNOWN_ERROR_MESSAGE = 'Unknown error';\n\nconst getDeployLink = () => {\n const regex = new RegExp(`(^| )seplugin-dev=([^;]+)`);\n const match = document.cookie.match(regex);\n const value = match?.[2].toLowerCase?.();\n\n if (value === 'true') {\n return LOCAL_ENDPOINT;\n }\n\n if (value?.startsWith('https://')) {\n return value;\n }\n\n const [major, mid] = pkg.version.split('.');\n\n return `${PROD_ENDPOINT}/v${major}.${mid}`;\n};\n\nconst verifyConfig = ({ token, pluginId, apiUrl }: PluginConfig) => {\n if (!token) {\n throw new Error('No [token] was provided');\n }\n\n if (!pluginId) {\n throw new Error('No [pluginId] was provided');\n }\n\n if (!apiUrl) {\n throw new Error('No [apiUrl] was provided');\n }\n};\n\nconst createIframe = (parentOrigin: string) => {\n const iframe = document.createElement('iframe');\n const url = new URL(getDeployLink());\n url.searchParams.set('parentOrigin', parentOrigin);\n iframe.src = url.toString();\n iframe.setAttribute(\n 'style',\n 'height:100%;width:100%;min-width:960px;border:0px;',\n );\n iframe.setAttribute('allow', 'clipboard-read; clipboard-write');\n iframe.setAttribute(\n 'sandbox',\n 'allow-scripts allow-same-origin allow-forms allow-popups allow-downloads',\n );\n\n return iframe;\n};\n\nexport class PluginInstance {\n public iframe: HTMLIFrameElement | null = null;\n private hotkeysAttached = false;\n private iframeOrigin: string | null = null;\n constructor(public config: PluginConfig) {}\n\n private captureHotkeysEnabled() {\n return this.config.disableHotkeysPassing !== true;\n }\n\n private onHostHotkey = (event: KeyboardEvent) => {\n if (!this.captureHotkeysEnabled() || !this.iframe?.contentWindow) {\n return;\n }\n\n const keyCode = constructKeyCode(event);\n\n if (!CORE_HOTKEYS.has(keyCode)) {\n return;\n }\n\n const target = event.target as HTMLElement | null;\n\n if (\n target &&\n (target.isContentEditable ||\n ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName))\n ) {\n return;\n }\n\n event.preventDefault();\n\n const { key, ctrlKey, metaKey, shiftKey, altKey } = event;\n\n this.postEvent('hostHotkey', {\n key,\n code: event.code,\n metaKey,\n ctrlKey,\n shiftKey,\n altKey,\n keyCode,\n });\n };\n\n private static HEARTBEAT_TIMEOUT = 4000;\n\n private promisedIframeMethod<T>(eventName: string) {\n let timer: Timeout | null = null;\n let listener: ((e: MessageEvent<MessageData>) => void) | null = null;\n\n const cleanup = () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n\n if (listener) {\n window.removeEventListener('message', listener, true);\n listener = null;\n }\n };\n\n const res = new Promise<T>((resolve, reject) => {\n const resetTimer = () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n cleanup();\n reject(\n new DraftError('timeout_error', `Action \"${eventName}\" timed out`),\n );\n }, PluginInstance.HEARTBEAT_TIMEOUT);\n };\n\n listener = (e: MessageEvent<MessageData>) => {\n if (e.source !== this.iframe?.contentWindow) return;\n\n const { data } = e;\n if (data.source !== 'DraftPlugin') return;\n\n if (data.event === 'actionPing' && data.action === eventName) {\n e.stopPropagation();\n resetTimer();\n\n return;\n }\n\n if (data.event === eventName) {\n e.stopPropagation();\n cleanup();\n\n const { source: _1, event: _2, ok, code, message, ...rest } = data;\n\n if (ok === false) {\n reject(\n new DraftError(\n code || 'unknown_error',\n message || UNKNOWN_ERROR_MESSAGE,\n ),\n );\n } else {\n resolve(rest as T);\n }\n }\n };\n\n window.addEventListener('message', listener, true);\n resetTimer();\n });\n\n this.postEvent(eventName);\n\n return res;\n }\n\n private postEvent(event: string, data: object = {}) {\n if (this.iframe && this.iframe.contentWindow && this.iframeOrigin) {\n this.iframe.contentWindow.postMessage(\n {\n ...data,\n event,\n source: 'DraftPlugin',\n },\n this.iframeOrigin,\n );\n } else if (!this.iframeOrigin) {\n throw new Error('Iframe origin is not initialized');\n }\n }\n\n private onImageUpload = async ({\n id,\n ...data\n }: UploadImageParams & { id: string }) => {\n try {\n const url = await this.config.on.uploadImage?.(data);\n let params = {};\n\n if (url) {\n params = await getImageParamsFromFileUrl(url);\n }\n\n this.postEvent('imageUploaded', { id, img: { ...params, url } });\n } catch (e) {\n this.postEvent('imageUploaded', { id });\n }\n };\n\n private onLoadPersonalization = async (requestId?: string) => {\n try {\n if (!this.config.on.loadPersonalization) {\n throw new Error('No personalization loader provided');\n }\n\n const personalizationDictionary =\n await this.config.on.loadPersonalization();\n\n this.postEvent('loadPersonalization', {\n items: personalizationDictionary,\n requestId,\n });\n } catch (e) {\n this.postEvent('loadPersonalization', { requestId });\n }\n };\n\n private onLoadSectionPersonalizationCatalog = async (requestId?: string) => {\n try {\n const handler = this.config.on.loadSectionPersonalizationCatalog;\n\n if (!handler) {\n throw new Error('No section personalization catalog loader provided');\n }\n\n const catalog = await handler();\n\n this.postEvent('loadSectionPersonalizationCatalog', {\n ok: true,\n requestId,\n catalog,\n });\n } catch (error) {\n this.postEvent('loadSectionPersonalizationCatalog', {\n ok: false,\n requestId,\n message: error instanceof Error ? error.message : UNKNOWN_ERROR_MESSAGE,\n });\n }\n };\n\n private onRenderSectionPersonalizationGroup = async (\n data: RenderSectionPersonalizationGroupInput & { requestId?: string },\n ) => {\n const { requestId, ...input } = data;\n\n try {\n const handler = this.config.on.renderSectionPersonalizationGroup;\n\n if (!handler) {\n throw new Error('No section personalization renderer provided');\n }\n\n const renderedHtml = await handler(input);\n\n this.postEvent('renderSectionPersonalizationGroup', {\n ok: true,\n requestId,\n html: renderedHtml,\n });\n } catch (error) {\n this.postEvent('renderSectionPersonalizationGroup', {\n ok: false,\n requestId,\n message: error instanceof Error ? error.message : UNKNOWN_ERROR_MESSAGE,\n });\n }\n };\n\n private onGalleryOpen = async ({ id }: { id: string }) => {\n const applyImage = async (url?: string) => {\n const imgParams = { url };\n\n if (url) {\n const params = await getImageParamsFromFileUrl(url);\n Object.assign(imgParams, params);\n }\n\n this.postEvent('imageUploaded', {\n id,\n img: imgParams,\n });\n };\n\n this.config.on.openGallery?.(applyImage);\n };\n\n private triggerEvent<H extends CallableFunction | undefined>(\n handler: H,\n params: HandlerParams<H>,\n ) {\n if (!handler) {\n return;\n }\n\n return handler(params);\n }\n\n private onMessage = (\n ev: MessageEvent<{ source: string; event: keyof Handlers }>,\n ) => {\n if (ev.source !== this.iframe?.contentWindow) {\n return;\n }\n\n const {\n data: { source, event, ...data },\n } = ev;\n\n if (source === 'DraftPlugin') {\n if (event === 'openGallery') {\n this.onGalleryOpen(data as OpenGalleryParams);\n } else if (event === 'uploadImage') {\n this.onImageUpload(data as UploadImageParams & { id: string });\n } else if (event === 'loadPersonalization') {\n this.onLoadPersonalization((data as { requestId?: string }).requestId);\n } else if (event === 'loadSectionPersonalizationCatalog') {\n this.onLoadSectionPersonalizationCatalog(\n (data as { requestId?: string }).requestId,\n );\n } else if (event === 'renderSectionPersonalizationGroup') {\n this.onRenderSectionPersonalizationGroup(\n data as RenderSectionPersonalizationGroupInput & {\n requestId?: string;\n },\n );\n } else {\n this.triggerEvent(\n this.config.on[event],\n data as HandlerParams<Handlers[typeof event]>,\n );\n }\n }\n };\n\n start({\n template,\n templateName,\n uid,\n }: {\n template: string | TemplateJSON;\n uid: string | number;\n templateName?: string;\n }) {\n const containerEl = document.querySelector(this.config.container);\n\n if (!containerEl) {\n throw new Error('Specified container not found');\n } else {\n const onInit = (msg: OnInitParams) => {\n const {\n data: { source, event },\n } = msg;\n if (source === 'DraftPlugin' && event === 'loaded') {\n if (msg.source !== this.iframe?.contentWindow) return;\n\n this.iframeOrigin = msg.origin;\n\n const {\n on,\n container,\n locale,\n autosave,\n token,\n apiUrl,\n pluginId,\n authData,\n sectionPersonalization,\n __config,\n } = this.config;\n\n verifyConfig(this.config);\n\n if (this.iframe && this.iframe.contentWindow) {\n const resolvedSectionPersonalization = {\n ...sectionPersonalization,\n enabled:\n sectionPersonalization?.enabled === true &&\n !!on.loadSectionPersonalizationCatalog &&\n !!on.renderSectionPersonalizationGroup,\n };\n\n this.postEvent('init', {\n container,\n locale,\n uid,\n autosave,\n token,\n pluginId,\n authData,\n sectionPersonalization: resolvedSectionPersonalization,\n apiUrl,\n __config,\n enabledListeners: Object.keys(on),\n template,\n templateName,\n });\n }\n\n window.addEventListener('message', this.onMessage);\n window.removeEventListener('message', onInit);\n }\n };\n\n this.iframe = createIframe(window.location.origin);\n window.addEventListener('message', onInit);\n containerEl.appendChild(this.iframe);\n\n if (this.captureHotkeysEnabled() && !this.hotkeysAttached) {\n window.addEventListener('keydown', this.onHostHotkey);\n this.hotkeysAttached = true;\n }\n }\n }\n\n destroy = () => {\n this.iframe?.remove();\n this.iframe = null;\n window.removeEventListener('message', this.onMessage);\n\n if (this.hotkeysAttached) {\n window.removeEventListener('keydown', this.onHostHotkey);\n this.hotkeysAttached = false;\n }\n };\n\n changeTemplate(\n template: string | TemplateJSON,\n options: {\n templateName?: string;\n uid?: string;\n } = {},\n ) {\n this.postEvent('changeTemplate', { ...options, template });\n }\n\n toggleGrid(state?: boolean) {\n this.postEvent('toggleGrid', { state });\n }\n\n toggleInvisibleCharacters(state?: boolean) {\n this.postEvent('toggleInvisibleCharacters', { state });\n }\n\n async isInvisibleCharactersVisible() {\n const { state } = await this.promisedIframeMethod<{ state: boolean }>(\n 'getInvisibleCharactersVisibility',\n );\n\n return state;\n }\n\n togglePreview(state?: boolean) {\n this.postEvent('togglePreview', { state });\n }\n\n toggleMenu(menu: EditorMenu | null = null) {\n this.postEvent('toggleMenu', { menu });\n }\n\n toggleViewMode(viewMode: ViewMode) {\n this.postEvent('toggleViewMode', { viewMode });\n }\n\n undo() {\n this.postEvent('undo');\n }\n\n undoToStep(targetStep: number) {\n this.postEvent('undoToStep', { targetStep });\n }\n\n redo() {\n this.postEvent('redo');\n }\n\n save() {\n return this.promisedIframeMethod<SaveParams>('saveAction');\n }\n\n exit() {\n return this.promisedIframeMethod<ExitParams>('exitAction');\n }\n\n exportContent() {\n return this.promisedIframeMethod<SaveParams>('exportContent');\n }\n\n exportAsFile() {\n return this.promisedIframeMethod<ExportAsFileParams>('exportAsFile');\n }\n}\n","import { PluginInstance } from './plugin';\nimport { PluginConfig } from './types';\nimport { version } from '../package.json';\n\nconst DEFAULT_CONFIG: Partial<PluginConfig> = {\n container: '#draft-plugin-container',\n disableHotkeysPassing: false,\n locale: 'ru',\n on: {},\n};\n\nclass PluginWrapper {\n public version = version;\n\n create(config: PluginConfig) {\n return new PluginInstance({\n ...DEFAULT_CONFIG,\n ...config,\n });\n }\n}\n\nconst DraftPlugin = new PluginWrapper();\n\ndeclare global {\n interface Window {\n DraftPlugin: PluginWrapper;\n }\n}\n\nwindow.DraftPlugin = DraftPlugin;\n\nexport default DraftPlugin;\nexport type { PluginInstance } from './plugin';\nexport * from './types';\n"],"mappings":"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"}
|
package/dist/index.iife.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var DraftPlugin=(function(e){Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var t=`http://localhost:5174`,n=`https://seplugin.sendsay.ru`,r=function(e){return e.Audit=`audit`,e.Guide=`guide`,e.Style=`style`,e.Blocks=`blocks`,e}({}),i=function(e){return e.Desktop=`desktop`,e.Mobile=`mobile`,e}({}),a=class extends Error{code;constructor(e,t){super(t),this.name=`DraftError`,this.code=e}},o=async e=>{try{let t=await fetch(e,{method:`HEAD`});if(!t.ok)return null;let n=t.headers.get(`Content-Length`);return n?parseInt(n,10):null}catch{return null}},s=e=>new Promise((t,n)=>{let r=new Image;r.onload=async()=>{let n=await o(e)??0;t({originalWidth:r.width,originalHeight:r.height,ratio:r.width/r.height,fileSize:n})},r.onerror=e=>{n(e)},r.src=e}),c=(e,t)=>{if(e.length!==1)return e;if(e.charCodeAt(0)>=880){if(t.indexOf(`Key`)===0&&t.length===4)return t.charAt(3);if(t.indexOf(`Digit`)===0&&t.length===6)return t.charAt(5)}return e},l=e=>{let t=`${c(e.key,e.code)}`.toLowerCase()||e.key,n=navigator.userAgent.includes(`Mac OS`);t===`backspace`&&n&&(t=`delete`);let r=[];return(n&&e.metaKey||!n&&e.ctrlKey)&&r.push(`mod`),e.shiftKey&&r.push(`shift`),r.length>0&&(t=`${r.join(`-`)}-${c(t,e.code)}`),t},u=new Set([`escape`,`mod-c`,`mod-d`,`mod-z`,`mod-y`,`mod-shift-z`,`mod-v`,`delete`,`mod-g`,`mod-p`,`mod-s`]),d=`@getdraft/plugin`,f=`1.
|
|
1
|
+
var DraftPlugin=(function(e){Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var t=`http://localhost:5174`,n=`https://seplugin.sendsay.ru`,r=function(e){return e.Audit=`audit`,e.Guide=`guide`,e.Style=`style`,e.Blocks=`blocks`,e}({}),i=function(e){return e.Desktop=`desktop`,e.Mobile=`mobile`,e}({}),a=class extends Error{code;constructor(e,t){super(t),this.name=`DraftError`,this.code=e}},o=async e=>{try{let t=await fetch(e,{method:`HEAD`});if(!t.ok)return null;let n=t.headers.get(`Content-Length`);return n?parseInt(n,10):null}catch{return null}},s=e=>new Promise((t,n)=>{let r=new Image;r.onload=async()=>{let n=await o(e)??0;t({originalWidth:r.width,originalHeight:r.height,ratio:r.width/r.height,fileSize:n})},r.onerror=e=>{n(e)},r.src=e}),c=(e,t)=>{if(e.length!==1)return e;if(e.charCodeAt(0)>=880){if(t.indexOf(`Key`)===0&&t.length===4)return t.charAt(3);if(t.indexOf(`Digit`)===0&&t.length===6)return t.charAt(5)}return e},l=e=>{let t=`${c(e.key,e.code)}`.toLowerCase()||e.key,n=navigator.userAgent.includes(`Mac OS`);t===`backspace`&&n&&(t=`delete`);let r=[];return(n&&e.metaKey||!n&&e.ctrlKey)&&r.push(`mod`),e.shiftKey&&r.push(`shift`),r.length>0&&(t=`${r.join(`-`)}-${c(t,e.code)}`),t},u=new Set([`escape`,`mod-c`,`mod-d`,`mod-z`,`mod-y`,`mod-shift-z`,`mod-v`,`delete`,`mod-g`,`mod-p`,`mod-s`]),d=`@getdraft/plugin`,f=`1.19.0-alpha.0`,p={name:d,version:f,main:`dist/index.cjs.js`,module:`dist/index.es.js`,types:`dist/types/index.d.ts`,exports:{".":{types:`./dist/types/index.d.ts`,import:`./dist/index.es.js`,require:`./dist/index.cjs.js`}},scripts:{prebuild:`rm -rf dist`,build:`vite build`,"dev-tsc":`tsc-check`,eslint:`npx eslint src`,"eslint:fix":`pnpm eslint --fix`,prettify:`npx prettier --check src`,"prettify:fix":`npx prettier -w src`,prepublish:`pnpm build`,watch:`NODE_ENV=development vite build --watch`,start:`NODE_ENV=development npx vite`},dependencies:{},devDependencies:{"@getdraft/types":`workspace:^`,"@getdraft/eslint-config-ts":`workspace:^`,"@getdraft/prettier":`workspace:^`,"vite-plugin-dts":`4.5.4`},license:`MIT`},m=`Unknown error`,h=()=>{let e=RegExp(`(^| )seplugin-dev=([^;]+)`),r=document.cookie.match(e)?.[2].toLowerCase?.();if(r===`true`)return t;if(r?.startsWith(`https://`))return r;let[i,a]=p.version.split(`.`);return`${n}/v${i}.${a}`},g=({token:e,pluginId:t,apiUrl:n})=>{if(!e)throw Error(`No [token] was provided`);if(!t)throw Error(`No [pluginId] was provided`);if(!n)throw Error(`No [apiUrl] was provided`)},_=e=>{let t=document.createElement(`iframe`),n=new URL(h());return n.searchParams.set(`parentOrigin`,e),t.src=n.toString(),t.setAttribute(`style`,`height:100%;width:100%;min-width:960px;border:0px;`),t.setAttribute(`allow`,`clipboard-read; clipboard-write`),t.setAttribute(`sandbox`,`allow-scripts allow-same-origin allow-forms allow-popups allow-downloads`),t},v=class e{iframe=null;hotkeysAttached=!1;iframeOrigin=null;constructor(e){this.config=e}captureHotkeysEnabled(){return this.config.disableHotkeysPassing!==!0}onHostHotkey=e=>{if(!this.captureHotkeysEnabled()||!this.iframe?.contentWindow)return;let t=l(e);if(!u.has(t))return;let n=e.target;if(n&&(n.isContentEditable||[`INPUT`,`TEXTAREA`,`SELECT`].includes(n.tagName)))return;e.preventDefault();let{key:r,ctrlKey:i,metaKey:a,shiftKey:o,altKey:s}=e;this.postEvent(`hostHotkey`,{key:r,code:e.code,metaKey:a,ctrlKey:i,shiftKey:o,altKey:s,keyCode:t})};static HEARTBEAT_TIMEOUT=4e3;promisedIframeMethod(t){let n=null,r=null,i=()=>{n&&=(clearTimeout(n),null),r&&=(window.removeEventListener(`message`,r,!0),null)},o=new Promise((o,s)=>{let c=()=>{n&&clearTimeout(n),n=setTimeout(()=>{i(),s(new a(`timeout_error`,`Action "${t}" timed out`))},e.HEARTBEAT_TIMEOUT)};r=e=>{if(e.source!==this.iframe?.contentWindow)return;let{data:n}=e;if(n.source===`DraftPlugin`){if(n.event===`actionPing`&&n.action===t){e.stopPropagation(),c();return}if(n.event===t){e.stopPropagation(),i();let{source:t,event:r,ok:c,code:l,message:u,...d}=n;c===!1?s(new a(l||`unknown_error`,u||m)):o(d)}}},window.addEventListener(`message`,r,!0),c()});return this.postEvent(t),o}postEvent(e,t={}){if(this.iframe&&this.iframe.contentWindow&&this.iframeOrigin)this.iframe.contentWindow.postMessage({...t,event:e,source:`DraftPlugin`},this.iframeOrigin);else if(!this.iframeOrigin)throw Error(`Iframe origin is not initialized`)}onImageUpload=async({id:e,...t})=>{try{let n=await this.config.on.uploadImage?.(t),r={};n&&(r=await s(n)),this.postEvent(`imageUploaded`,{id:e,img:{...r,url:n}})}catch{this.postEvent(`imageUploaded`,{id:e})}};onLoadPersonalization=async e=>{try{if(!this.config.on.loadPersonalization)throw Error(`No personalization loader provided`);let t=await this.config.on.loadPersonalization();this.postEvent(`loadPersonalization`,{items:t,requestId:e})}catch{this.postEvent(`loadPersonalization`,{requestId:e})}};onLoadSectionPersonalizationCatalog=async e=>{try{let t=this.config.on.loadSectionPersonalizationCatalog;if(!t)throw Error(`No section personalization catalog loader provided`);let n=await t();this.postEvent(`loadSectionPersonalizationCatalog`,{ok:!0,requestId:e,catalog:n})}catch(t){this.postEvent(`loadSectionPersonalizationCatalog`,{ok:!1,requestId:e,message:t instanceof Error?t.message:m})}};onRenderSectionPersonalizationGroup=async e=>{let{requestId:t,...n}=e;try{let e=this.config.on.renderSectionPersonalizationGroup;if(!e)throw Error(`No section personalization renderer provided`);let r=await e(n);this.postEvent(`renderSectionPersonalizationGroup`,{ok:!0,requestId:t,html:r})}catch(e){this.postEvent(`renderSectionPersonalizationGroup`,{ok:!1,requestId:t,message:e instanceof Error?e.message:m})}};onGalleryOpen=async({id:e})=>{this.config.on.openGallery?.(async t=>{let n={url:t};if(t){let e=await s(t);Object.assign(n,e)}this.postEvent(`imageUploaded`,{id:e,img:n})})};triggerEvent(e,t){if(e)return e(t)}onMessage=e=>{if(e.source!==this.iframe?.contentWindow)return;let{data:{source:t,event:n,...r}}=e;t===`DraftPlugin`&&(n===`openGallery`?this.onGalleryOpen(r):n===`uploadImage`?this.onImageUpload(r):n===`loadPersonalization`?this.onLoadPersonalization(r.requestId):n===`loadSectionPersonalizationCatalog`?this.onLoadSectionPersonalizationCatalog(r.requestId):n===`renderSectionPersonalizationGroup`?this.onRenderSectionPersonalizationGroup(r):this.triggerEvent(this.config.on[n],r))};start({template:e,templateName:t,uid:n}){let r=document.querySelector(this.config.container);if(r){let i=r=>{let{data:{source:a,event:o}}=r;if(a===`DraftPlugin`&&o===`loaded`){if(r.source!==this.iframe?.contentWindow)return;this.iframeOrigin=r.origin;let{on:a,container:o,locale:s,autosave:c,token:l,apiUrl:u,pluginId:d,authData:f,sectionPersonalization:p,__config:m}=this.config;if(g(this.config),this.iframe&&this.iframe.contentWindow){let r={...p,enabled:p?.enabled===!0&&!!a.loadSectionPersonalizationCatalog&&!!a.renderSectionPersonalizationGroup};this.postEvent(`init`,{container:o,locale:s,uid:n,autosave:c,token:l,pluginId:d,authData:f,sectionPersonalization:r,apiUrl:u,__config:m,enabledListeners:Object.keys(a),template:e,templateName:t})}window.addEventListener(`message`,this.onMessage),window.removeEventListener(`message`,i)}};this.iframe=_(window.location.origin),window.addEventListener(`message`,i),r.appendChild(this.iframe),this.captureHotkeysEnabled()&&!this.hotkeysAttached&&(window.addEventListener(`keydown`,this.onHostHotkey),this.hotkeysAttached=!0)}else throw Error(`Specified container not found`)}destroy=()=>{this.iframe?.remove(),this.iframe=null,window.removeEventListener(`message`,this.onMessage),this.hotkeysAttached&&=(window.removeEventListener(`keydown`,this.onHostHotkey),!1)};changeTemplate(e,t={}){this.postEvent(`changeTemplate`,{...t,template:e})}toggleGrid(e){this.postEvent(`toggleGrid`,{state:e})}toggleInvisibleCharacters(e){this.postEvent(`toggleInvisibleCharacters`,{state:e})}async isInvisibleCharactersVisible(){let{state:e}=await this.promisedIframeMethod(`getInvisibleCharactersVisibility`);return e}togglePreview(e){this.postEvent(`togglePreview`,{state:e})}toggleMenu(e=null){this.postEvent(`toggleMenu`,{menu:e})}toggleViewMode(e){this.postEvent(`toggleViewMode`,{viewMode:e})}undo(){this.postEvent(`undo`)}undoToStep(e){this.postEvent(`undoToStep`,{targetStep:e})}redo(){this.postEvent(`redo`)}save(){return this.promisedIframeMethod(`saveAction`)}exit(){return this.promisedIframeMethod(`exitAction`)}exportContent(){return this.promisedIframeMethod(`exportContent`)}exportAsFile(){return this.promisedIframeMethod(`exportAsFile`)}},y={container:`#draft-plugin-container`,disableHotkeysPassing:!1,locale:`ru`,on:{}},b=new class{version=f;create(e){return new v({...y,...e})}};return window.DraftPlugin=b,e.DraftError=a,e.EditorMenu=r,e.ViewMode=i,e.default=b,e})({});
|
|
2
2
|
//# sourceMappingURL=index.iife.js.map
|
package/dist/index.iife.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.iife.js","names":[],"sources":["../src/routes.ts","../src/types.ts","../src/utils.ts","../package.json","../src/plugin.ts","../src/index.ts"],"sourcesContent":["export const LOCAL_ENDPOINT = 'http://localhost:5174';\nexport const PROD_ENDPOINT = 'https://seplugin.sendsay.ru';\n","export enum EditorMenu {\n Audit = 'audit',\n Guide = 'guide',\n Style = 'style',\n Blocks = 'blocks',\n}\n\nexport enum ViewMode {\n Desktop = 'desktop',\n Mobile = 'mobile',\n}\n\nexport interface Notification {\n intent: 'error' | 'info' | 'success' | 'warning';\n errorDetails?: object;\n message?: string;\n title: string;\n}\n\ntype PersonalizationDictionaryEntry =\n | { name: string; value: string }\n | { groupName: string; items: Array<{ name: string; value: string }> };\n\nexport type PersonalizationDictionaryItems = PersonalizationDictionaryEntry[];\n\nexport interface SerializedTemplate {\n [key: string]: unknown;\n parentId: string | null;\n id: string;\n parameters: object;\n layer: string;\n type: string;\n children?: SerializedTemplate[];\n meta?: { [key: string]: unknown; version: string };\n}\n\nexport type EventHandler<T> = (data: T) => void;\n\nexport type AsyncEventHandler<P, R> = (params: P) => Promise<R>;\n\nexport class DraftError extends Error {\n public readonly code: string;\n\n constructor(code: string, message: string) {\n super(message);\n this.name = 'DraftError';\n this.code = code;\n }\n}\n\nexport type MessageData = {\n source: string;\n event: string;\n ok?: boolean;\n code?: string;\n message?: string;\n action?: string;\n};\n\nexport interface ExportAsFileParams {\n blob: Blob;\n fileName: string;\n}\n\nexport interface SaveParams {\n json: TemplateJSON;\n html: string;\n}\n\nexport type OnInitParams = MessageEvent<{\n source: string;\n event: 'loaded' | unknown;\n}>;\n\nexport interface ReadyParams extends SaveParams {\n lastSavedTemplate?: {\n template: TemplateJSON;\n date: Date;\n };\n}\n\nexport interface ErrorParams {\n message: string;\n code?: string;\n details?: unknown;\n}\n\nexport interface ExitParams extends SaveParams {}\n\nexport type NotificationParams = Notification;\n\nexport interface OpenGalleryParams {\n id: string;\n}\n\nexport interface UploadImageParams {\n file: string;\n name: string;\n}\n\nexport interface ImageParams {\n url: string;\n originalWidth: number;\n originalHeight: number;\n ratio: number;\n fileSize: number;\n}\n\nexport interface AutosaveParams {\n json: TemplateJSON;\n}\n\ninterface ToggleParams {\n state: boolean;\n}\n\nexport interface ToggleGridParams extends ToggleParams {}\n\nexport interface ToggleInvisibleCharactersParams extends ToggleParams {}\n\nexport interface TogglePreviewParams extends ToggleParams {\n json: TemplateJSON;\n html: string;\n darkHTML: string;\n}\n\nexport interface ToggleViewModeParams {\n mode: ViewMode;\n}\n\nexport interface ToggleMenuParams {\n menu: EditorMenu | null;\n}\n\nexport interface HistoryParams {\n hasUndos: boolean;\n hasRedos: boolean;\n currentStep: number;\n}\n\nexport type TemplateJSON = SerializedTemplate;\n\nexport type PersonalizationDictionary = PersonalizationDictionaryItems;\n\nexport type ToolbarActionName =\n | 'duplicate'\n | 'destroy'\n | 'edit'\n | 'up'\n | 'down';\nexport type HotkeyContext = 'hotkey';\nexport type OverlayContext = 'overlay-click' | 'overlay-double-click';\nexport type ToolbarContext = 'toolbar';\nexport type UnitSettingsContext = 'unit-settings';\nexport type BlockType = 'system' | 'user';\nexport type DndDragContext = 'canvas' | 'list' | 'palette';\nexport type DndDropContext = 'dropline' | 'placeholder' | 'empty-placeholder';\nexport type DndDropTarget = 'root' | 'section' | 'column' | 'element';\n\nexport interface DuplicateEvent {\n name: 'duplicate';\n context: HotkeyContext | ToolbarContext | UnitSettingsContext;\n unitType: string;\n}\n\nexport interface DestroyEvent {\n name: 'destroy';\n context: HotkeyContext | ToolbarContext | UnitSettingsContext;\n unitType: string;\n}\n\nexport interface EditEvent {\n name: 'edit';\n context: OverlayContext | ToolbarContext;\n unitType: string;\n}\n\nexport interface HistoryEvent {\n name: 'history';\n type: 'undo' | 'redo';\n context: HotkeyContext;\n}\n\nexport interface PreviewEvent {\n name: 'preview';\n context: HotkeyContext;\n}\n\nexport interface ToolbarMoveEvent {\n name: 'up' | 'down';\n context: ToolbarContext;\n unitType: string;\n}\n\nexport interface BlockInsertEvent {\n name: 'block-insert';\n context: 'double-click';\n blockType: BlockType;\n blockName: string;\n blockCategory: string | number;\n blockId: string | number;\n}\n\nexport interface BlockSaveEvent {\n name: 'block-save';\n blockType: 'user';\n blockName: string;\n blockCategory: string | number;\n blockId: string | number;\n elements: Record<string, number> & { sum: number };\n}\n\nexport interface BlockDestroyEvent {\n name: 'block-destroy';\n}\n\nexport interface DropEventDragMeta {\n context?: DndDragContext;\n layer?: 'element' | 'section' | 'column' | 'root';\n type?: string | string[];\n blockCategory?: string | number;\n blockId?: string | number;\n blockName?: string;\n blockType?: BlockType;\n alt?: boolean;\n dropKind?: 'create' | 'move';\n}\n\nexport interface DropEventDropzoneMeta {\n context?: DndDropContext;\n dropTarget?: DndDropTarget;\n}\n\nexport interface DropEvent {\n name: 'drop';\n drag?: DropEventDragMeta;\n dropzone?: DropEventDropzoneMeta;\n}\n\nexport type AnalyticsParams =\n | DuplicateEvent\n | DestroyEvent\n | EditEvent\n | HistoryEvent\n | PreviewEvent\n | ToolbarMoveEvent\n | BlockInsertEvent\n | BlockSaveEvent\n | BlockDestroyEvent\n | DropEvent;\n\nexport interface Handlers {\n ready: EventHandler<ReadyParams>;\n error: EventHandler<ErrorParams>;\n save: EventHandler<SaveParams>;\n exit: EventHandler<ExitParams>;\n notification: EventHandler<NotificationParams>;\n autosave: EventHandler<AutosaveParams>;\n toggleGrid: EventHandler<ToggleGridParams>;\n toggleInvisibleCharacters: EventHandler<ToggleInvisibleCharactersParams>;\n togglePreview: EventHandler<TogglePreviewParams>;\n toggleViewMode: EventHandler<ToggleViewModeParams>;\n toggleMenu: EventHandler<ToggleMenuParams>;\n history: EventHandler<HistoryParams>;\n analytics: EventHandler<AnalyticsParams>;\n openGallery: EventHandler<(url?: string) => Promise<void>>;\n uploadImage: AsyncEventHandler<UploadImageParams, string>;\n loadPersonalization: AsyncEventHandler<void, PersonalizationDictionary>;\n}\n\nexport type HandlerParams<H> = H extends\n | EventHandler<infer P>\n | AsyncEventHandler<infer P, unknown>\n ? P\n : never;\n\nexport interface PluginConfig {\n container: string;\n locale?: string;\n autosave?:\n | boolean\n | {\n interval: number;\n };\n token: string;\n authData?: {\n orgId: number;\n projectId?: number;\n };\n pluginId: string;\n apiUrl: string;\n disableHotkeysPassing?: boolean;\n __config?: object;\n on: Partial<Handlers>;\n}\n","import { ImageParams } from './types';\n\nconst getImageFileSize = async (imageUrl: string) => {\n try {\n const response = await fetch(imageUrl, { method: 'HEAD' });\n\n if (!response.ok) {\n return null;\n }\n\n const contentLength = response.headers.get('Content-Length');\n\n if (contentLength) {\n return parseInt(contentLength, 10);\n } else {\n return null;\n }\n } catch (error) {\n return null;\n }\n};\n\nexport const getImageParamsFromFileUrl = (imgSrc: string) =>\n new Promise<Omit<ImageParams, 'url'>>((resolve, reject) => {\n const img = new Image();\n\n img.onload = async () => {\n const fileSize = (await getImageFileSize(imgSrc)) ?? 0;\n\n resolve({\n originalWidth: img.width,\n originalHeight: img.height,\n ratio: img.width / img.height,\n fileSize,\n });\n };\n\n img.onerror = (error) => {\n reject(error);\n };\n\n img.src = imgSrc;\n });\n\nconst getLatinKey = (key: string, code: string) => {\n if (key.length !== 1) {\n return key;\n }\n\n const capitalHetaCode = 880;\n const isNonLatin = key.charCodeAt(0) >= capitalHetaCode;\n\n if (isNonLatin) {\n if (code.indexOf('Key') === 0 && code.length === 4) {\n return code.charAt(3);\n }\n\n if (code.indexOf('Digit') === 0 && code.length === 6) {\n return code.charAt(5);\n }\n }\n\n return key;\n};\n\nexport const constructKeyCode = (event: KeyboardEvent) => {\n let keyCode =\n `${getLatinKey(event.key, event.code)}`.toLowerCase() || event.key;\n const macOs = navigator.userAgent.includes('Mac OS');\n\n if (keyCode === 'backspace' && macOs) {\n keyCode = 'delete';\n }\n\n const prefix = [];\n\n if ((macOs && event.metaKey) || (!macOs && event.ctrlKey)) {\n prefix.push('mod');\n }\n\n if (event.shiftKey) {\n prefix.push('shift');\n }\n\n if (prefix.length > 0) {\n keyCode = `${prefix.join('-')}-${getLatinKey(keyCode, event.code)}`;\n }\n\n return keyCode;\n};\n\nexport const CORE_HOTKEYS = new Set([\n 'escape',\n 'mod-c',\n 'mod-d',\n 'mod-z',\n 'mod-y',\n 'mod-shift-z',\n 'mod-v',\n 'delete',\n 'mod-g',\n 'mod-p',\n 'mod-s',\n]);\n","{\n \"name\": \"@getdraft/plugin\",\n \"version\": \"1.17.0\",\n \"main\": \"dist/index.cjs.js\",\n \"module\": \"dist/index.es.js\",\n \"types\": \"dist/types/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/types/index.d.ts\",\n \"import\": \"./dist/index.es.js\",\n \"require\": \"./dist/index.cjs.js\"\n }\n },\n \"scripts\": {\n \"prebuild\": \"rm -rf dist\",\n \"build\": \"vite build\",\n \"dev-tsc\": \"tsc-check\",\n \"eslint\": \"npx eslint src\",\n \"eslint:fix\": \"pnpm eslint --fix\",\n \"prettify\": \"npx prettier --check src\",\n \"prettify:fix\": \"npx prettier -w src\",\n \"prepublish\": \"pnpm build\",\n \"watch\": \"NODE_ENV=development vite build --watch\",\n \"start\": \"NODE_ENV=development npx vite\"\n },\n \"dependencies\": {},\n \"devDependencies\": {\n \"@getdraft/types\": \"workspace:^\",\n \"@getdraft/eslint-config-ts\": \"workspace:^\",\n \"@getdraft/prettier\": \"workspace:^\",\n \"vite-plugin-dts\": \"4.5.4\"\n },\n \"license\": \"MIT\"\n}\n","import { LOCAL_ENDPOINT, PROD_ENDPOINT } from './routes';\nimport {\n DraftError,\n EditorMenu,\n ExitParams,\n OnInitParams,\n OpenGalleryParams,\n Handlers,\n PluginConfig,\n SaveParams,\n TemplateJSON,\n UploadImageParams,\n ViewMode,\n HandlerParams,\n MessageData,\n ExportAsFileParams,\n} from './types';\nimport {\n getImageParamsFromFileUrl,\n constructKeyCode,\n CORE_HOTKEYS,\n} from './utils';\nimport pkg from '../package.json';\n\nconst getDeployLink = () => {\n const regex = new RegExp(`(^| )seplugin-dev=([^;]+)`);\n const match = document.cookie.match(regex);\n const value = match?.[2].toLowerCase?.();\n\n if (value === 'true') {\n return LOCAL_ENDPOINT;\n }\n\n if (value?.startsWith('https://')) {\n return value;\n }\n\n const [major, mid] = pkg.version.split('.');\n\n return `${PROD_ENDPOINT}/v${major}.${mid}`;\n};\n\nconst verifyConfig = ({ token, pluginId, apiUrl }: PluginConfig) => {\n if (!token) {\n throw new Error('No [token] was provided');\n }\n\n if (!pluginId) {\n throw new Error('No [pluginId] was provided');\n }\n\n if (!apiUrl) {\n throw new Error('No [apiUrl] was provided');\n }\n};\n\nconst createIframe = (parentOrigin: string) => {\n const iframe = document.createElement('iframe');\n const url = new URL(getDeployLink());\n url.searchParams.set('parentOrigin', parentOrigin);\n iframe.src = url.toString();\n iframe.setAttribute(\n 'style',\n 'height:100%;width:100%;min-width:960px;border:0px;',\n );\n iframe.setAttribute('allow', 'clipboard-read; clipboard-write');\n iframe.setAttribute(\n 'sandbox',\n 'allow-scripts allow-same-origin allow-forms allow-popups allow-downloads',\n );\n\n return iframe;\n};\n\nexport class PluginInstance {\n public iframe: HTMLIFrameElement | null = null;\n private hotkeysAttached = false;\n private iframeOrigin: string | null = null;\n constructor(public config: PluginConfig) {}\n\n private captureHotkeysEnabled() {\n return this.config.disableHotkeysPassing !== true;\n }\n\n private onHostHotkey = (event: KeyboardEvent) => {\n if (!this.captureHotkeysEnabled() || !this.iframe?.contentWindow) {\n return;\n }\n\n const keyCode = constructKeyCode(event);\n\n if (!CORE_HOTKEYS.has(keyCode)) {\n return;\n }\n\n const target = event.target as HTMLElement | null;\n\n if (\n target &&\n (target.isContentEditable ||\n ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName))\n ) {\n return;\n }\n\n event.preventDefault();\n\n const { key, ctrlKey, metaKey, shiftKey, altKey } = event;\n\n this.postEvent('hostHotkey', {\n key,\n code: event.code,\n metaKey,\n ctrlKey,\n shiftKey,\n altKey,\n keyCode,\n });\n };\n\n private static HEARTBEAT_TIMEOUT = 4000;\n\n private promisedIframeMethod<T>(eventName: string) {\n let timer: Timeout | null = null;\n let listener: ((e: MessageEvent<MessageData>) => void) | null = null;\n\n const cleanup = () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n\n if (listener) {\n window.removeEventListener('message', listener, true);\n listener = null;\n }\n };\n\n const res = new Promise<T>((resolve, reject) => {\n const resetTimer = () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n cleanup();\n reject(\n new DraftError('timeout_error', `Action \"${eventName}\" timed out`),\n );\n }, PluginInstance.HEARTBEAT_TIMEOUT);\n };\n\n listener = (e: MessageEvent<MessageData>) => {\n if (e.source !== this.iframe?.contentWindow) return;\n\n const { data } = e;\n if (data.source !== 'DraftPlugin') return;\n\n if (data.event === 'actionPing' && data.action === eventName) {\n e.stopPropagation();\n resetTimer();\n\n return;\n }\n\n if (data.event === eventName) {\n e.stopPropagation();\n cleanup();\n\n const { source: _1, event: _2, ok, code, message, ...rest } = data;\n\n if (ok === false) {\n reject(\n new DraftError(\n code || 'unknown_error',\n message || 'Unknown error',\n ),\n );\n } else {\n resolve(rest as T);\n }\n }\n };\n\n window.addEventListener('message', listener, true);\n resetTimer();\n });\n\n this.postEvent(eventName);\n\n return res;\n }\n\n private postEvent(event: string, data: object = {}) {\n if (this.iframe && this.iframe.contentWindow && this.iframeOrigin) {\n this.iframe.contentWindow.postMessage(\n {\n ...data,\n event,\n source: 'DraftPlugin',\n },\n this.iframeOrigin,\n );\n } else if (!this.iframeOrigin) {\n throw new Error('Iframe origin is not initialized');\n }\n }\n\n private onImageUpload = async ({\n id,\n ...data\n }: UploadImageParams & { id: string }) => {\n try {\n const url = await this.config.on.uploadImage?.(data);\n let params = {};\n\n if (url) {\n params = await getImageParamsFromFileUrl(url);\n }\n\n this.postEvent('imageUploaded', { id, img: { ...params, url } });\n } catch (e) {\n this.postEvent('imageUploaded', { id });\n }\n };\n\n private onLoadPersonalization = async () => {\n try {\n if (!this.config.on.loadPersonalization) {\n throw new Error('No personalization loader provided');\n }\n\n const personalizationDictionary =\n await this.config.on.loadPersonalization();\n\n this.postEvent('loadPersonalization', {\n items: personalizationDictionary,\n });\n } catch (e) {\n this.postEvent('loadPersonalization', {});\n }\n };\n\n private onGalleryOpen = async ({ id }: { id: string }) => {\n const applyImage = async (url?: string) => {\n const imgParams = { url };\n\n if (url) {\n const params = await getImageParamsFromFileUrl(url);\n Object.assign(imgParams, params);\n }\n\n this.postEvent('imageUploaded', {\n id,\n img: imgParams,\n });\n };\n\n this.config.on.openGallery?.(applyImage);\n };\n\n private triggerEvent<H extends CallableFunction | undefined>(\n handler: H,\n params: HandlerParams<H>,\n ) {\n if (!handler) {\n return;\n }\n\n return handler(params);\n }\n\n private onMessage = (\n ev: MessageEvent<{ source: string; event: keyof Handlers }>,\n ) => {\n if (ev.source !== this.iframe?.contentWindow) {\n return;\n }\n\n const {\n data: { source, event, ...data },\n } = ev;\n\n if (source === 'DraftPlugin') {\n if (event === 'openGallery') {\n this.onGalleryOpen(data as OpenGalleryParams);\n } else if (event === 'uploadImage') {\n this.onImageUpload(data as UploadImageParams & { id: string });\n } else if (event === 'loadPersonalization') {\n this.onLoadPersonalization();\n } else {\n this.triggerEvent(\n this.config.on[event],\n data as HandlerParams<Handlers[typeof event]>,\n );\n }\n }\n };\n\n start({\n template,\n templateName,\n uid,\n }: {\n template: string | TemplateJSON;\n uid: string | number;\n templateName?: string;\n }) {\n const containerEl = document.querySelector(this.config.container);\n\n if (!containerEl) {\n throw new Error('Specified container not found');\n } else {\n const onInit = (msg: OnInitParams) => {\n const {\n data: { source, event },\n } = msg;\n if (source === 'DraftPlugin' && event === 'loaded') {\n if (msg.source !== this.iframe?.contentWindow) return;\n\n this.iframeOrigin = msg.origin;\n\n const {\n on,\n container,\n locale,\n autosave,\n token,\n apiUrl,\n pluginId,\n authData,\n __config,\n } = this.config;\n\n verifyConfig(this.config);\n\n if (this.iframe && this.iframe.contentWindow) {\n this.postEvent('init', {\n container,\n locale,\n uid,\n autosave,\n token,\n pluginId,\n authData,\n apiUrl,\n __config,\n enabledListeners: Object.keys(on),\n template,\n templateName,\n });\n }\n\n window.addEventListener('message', this.onMessage);\n window.removeEventListener('message', onInit);\n }\n };\n\n this.iframe = createIframe(window.location.origin);\n window.addEventListener('message', onInit);\n containerEl.appendChild(this.iframe);\n\n if (this.captureHotkeysEnabled() && !this.hotkeysAttached) {\n window.addEventListener('keydown', this.onHostHotkey);\n this.hotkeysAttached = true;\n }\n }\n }\n\n destroy = () => {\n this.iframe?.remove();\n this.iframe = null;\n window.removeEventListener('message', this.onMessage);\n\n if (this.hotkeysAttached) {\n window.removeEventListener('keydown', this.onHostHotkey);\n this.hotkeysAttached = false;\n }\n };\n\n changeTemplate(\n template: string | TemplateJSON,\n options: {\n templateName?: string;\n uid?: string;\n } = {},\n ) {\n this.postEvent('changeTemplate', { ...options, template });\n }\n\n toggleGrid(state?: boolean) {\n this.postEvent('toggleGrid', { state });\n }\n\n toggleInvisibleCharacters(state?: boolean) {\n this.postEvent('toggleInvisibleCharacters', { state });\n }\n\n togglePreview(state?: boolean) {\n this.postEvent('togglePreview', { state });\n }\n\n toggleMenu(menu: EditorMenu | null = null) {\n this.postEvent('toggleMenu', { menu });\n }\n\n toggleViewMode(viewMode: ViewMode) {\n this.postEvent('toggleViewMode', { viewMode });\n }\n\n undo() {\n this.postEvent('undo');\n }\n\n undoToStep(targetStep: number) {\n this.postEvent('undoToStep', { targetStep });\n }\n\n redo() {\n this.postEvent('redo');\n }\n\n save() {\n return this.promisedIframeMethod<SaveParams>('saveAction');\n }\n\n exit() {\n return this.promisedIframeMethod<ExitParams>('exitAction');\n }\n\n exportContent() {\n return this.promisedIframeMethod<SaveParams>('exportContent');\n }\n\n exportAsFile() {\n return this.promisedIframeMethod<ExportAsFileParams>('exportAsFile');\n }\n}\n","import { PluginInstance } from './plugin';\nimport { PluginConfig } from './types';\nimport { version } from '../package.json';\n\nconst DEFAULT_CONFIG: Partial<PluginConfig> = {\n container: '#draft-plugin-container',\n disableHotkeysPassing: false,\n locale: 'ru',\n on: {},\n};\n\nclass PluginWrapper {\n public version = version;\n\n create(config: PluginConfig) {\n return new PluginInstance({\n ...DEFAULT_CONFIG,\n ...config,\n });\n }\n}\n\nconst DraftPlugin = new PluginWrapper();\n\ndeclare global {\n interface Window {\n DraftPlugin: PluginWrapper;\n }\n}\n\nwindow.DraftPlugin = DraftPlugin;\n\nexport default DraftPlugin;\nexport type { PluginInstance } from './plugin';\nexport * from './types';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.iife.js","names":[],"sources":["../src/routes.ts","../src/types.ts","../src/utils.ts","../package.json","../src/plugin.ts","../src/index.ts"],"sourcesContent":["export const LOCAL_ENDPOINT = 'http://localhost:5174';\nexport const PROD_ENDPOINT = 'https://seplugin.sendsay.ru';\n","export enum EditorMenu {\n Audit = 'audit',\n Guide = 'guide',\n Style = 'style',\n Blocks = 'blocks',\n}\n\nexport enum ViewMode {\n Desktop = 'desktop',\n Mobile = 'mobile',\n}\n\nexport interface Notification {\n intent: 'error' | 'info' | 'success' | 'warning';\n errorDetails?: object;\n message?: string;\n title: string;\n}\n\ntype PersonalizationDictionaryEntry =\n | { name: string; value: string }\n | { groupName: string; items: Array<{ name: string; value: string }> };\n\nexport type PersonalizationDictionaryItems = PersonalizationDictionaryEntry[];\n\nexport type SectionPersonalizationValue = string | number | boolean | null;\n\nexport interface SectionPersonalizationField {\n id: string;\n operatorId: 'equals';\n}\n\nexport interface SectionPersonalizationCatalogOption {\n label: string;\n value: Exclude<SectionPersonalizationValue, null>;\n}\n\nexport interface SectionPersonalizationCatalogGroup {\n type: 'group';\n id: string;\n label: string;\n children: SectionPersonalizationCatalogNode[];\n}\n\nexport interface SectionPersonalizationCatalogField {\n type: 'field';\n id: string;\n label: string;\n valueType?: 'string' | 'number' | 'boolean' | 'date';\n options?: SectionPersonalizationCatalogOption[];\n}\n\nexport type SectionPersonalizationCatalogNode =\n | SectionPersonalizationCatalogGroup\n | SectionPersonalizationCatalogField;\n\nexport interface SectionPersonalizationConfig {\n enabled: boolean;\n aboutUrl?: string;\n}\n\nexport interface RenderSectionPersonalizationGroupInput {\n groupId: string;\n fields: SectionPersonalizationField[];\n variants: Array<{\n id: string;\n values: Record<string, SectionPersonalizationValue>;\n html: string;\n }>;\n fallback?: {\n id: string;\n html: string;\n };\n}\n\nexport interface SerializedTemplate {\n [key: string]: unknown;\n parentId: string | null;\n id: string;\n parameters: object;\n layer: string;\n type: string;\n children?: SerializedTemplate[];\n meta?: { [key: string]: unknown; version: string };\n}\n\nexport type EventHandler<T> = (data: T) => void;\n\nexport type AsyncEventHandler<P, R> = (params: P) => Promise<R>;\n\nexport class DraftError extends Error {\n public readonly code: string;\n\n constructor(code: string, message: string) {\n super(message);\n this.name = 'DraftError';\n this.code = code;\n }\n}\n\nexport type MessageData = {\n source: string;\n event: string;\n ok?: boolean;\n code?: string;\n message?: string;\n action?: string;\n requestId?: string;\n};\n\nexport interface ExportAsFileParams {\n blob: Blob;\n fileName: string;\n}\n\nexport interface SaveParams {\n json: TemplateJSON;\n html: string;\n}\n\nexport type OnInitParams = MessageEvent<{\n source: string;\n event: 'loaded' | unknown;\n}>;\n\nexport interface ReadyParams extends SaveParams {\n lastSavedTemplate?: {\n template: TemplateJSON;\n date: Date;\n };\n}\n\nexport interface ErrorParams {\n message: string;\n code?: string;\n details?: unknown;\n}\n\nexport interface ExitParams extends SaveParams {}\n\nexport type NotificationParams = Notification;\n\nexport interface OpenGalleryParams {\n id: string;\n}\n\nexport interface UploadImageParams {\n file: string;\n name: string;\n}\n\nexport interface ImageParams {\n url: string;\n originalWidth: number;\n originalHeight: number;\n ratio: number;\n fileSize: number;\n}\n\nexport interface AutosaveParams {\n json: TemplateJSON;\n}\n\ninterface ToggleParams {\n state: boolean;\n}\n\nexport interface ToggleGridParams extends ToggleParams {}\n\nexport interface ToggleInvisibleCharactersParams extends ToggleParams {}\n\nexport interface TogglePreviewParams extends ToggleParams {\n json: TemplateJSON;\n html: string;\n darkHTML: string;\n}\n\nexport interface ToggleViewModeParams {\n mode: ViewMode;\n}\n\nexport interface ToggleMenuParams {\n menu: EditorMenu | null;\n}\n\nexport interface HistoryParams {\n hasUndos: boolean;\n hasRedos: boolean;\n currentStep: number;\n}\n\nexport type TemplateJSON = SerializedTemplate;\n\nexport type PersonalizationDictionary = PersonalizationDictionaryItems;\n\nexport type ToolbarActionName =\n | 'duplicate'\n | 'destroy'\n | 'edit'\n | 'up'\n | 'down';\nexport type HotkeyContext = 'hotkey';\nexport type OverlayContext = 'overlay-click' | 'overlay-double-click';\nexport type ToolbarContext = 'toolbar';\nexport type UnitSettingsContext = 'unit-settings';\nexport type BlockType = 'system' | 'user';\nexport type DndDragContext = 'canvas' | 'list' | 'palette';\nexport type DndDropContext = 'dropline' | 'placeholder' | 'empty-placeholder';\nexport type DndDropTarget = 'root' | 'section' | 'column' | 'element';\n\nexport interface DuplicateEvent {\n name: 'duplicate';\n context: HotkeyContext | ToolbarContext | UnitSettingsContext;\n unitType: string;\n}\n\nexport interface DestroyEvent {\n name: 'destroy';\n context: HotkeyContext | ToolbarContext | UnitSettingsContext;\n unitType: string;\n}\n\nexport interface EditEvent {\n name: 'edit';\n context: OverlayContext | ToolbarContext;\n unitType: string;\n}\n\nexport interface HistoryEvent {\n name: 'history';\n type: 'undo' | 'redo';\n context: HotkeyContext;\n}\n\nexport interface PreviewEvent {\n name: 'preview';\n context: HotkeyContext;\n}\n\nexport interface ToolbarMoveEvent {\n name: 'up' | 'down';\n context: ToolbarContext;\n unitType: string;\n}\n\nexport interface BlockInsertEvent {\n name: 'block-insert';\n context: 'double-click';\n blockType: BlockType;\n blockName: string;\n blockCategory: string | number;\n blockId: string | number;\n}\n\nexport interface BlockSaveEvent {\n name: 'block-save';\n blockType: 'user';\n blockName: string;\n blockCategory: string | number;\n blockId: string | number;\n elements: Record<string, number> & { sum: number };\n}\n\nexport interface BlockDestroyEvent {\n name: 'block-destroy';\n}\n\nexport interface DropEventDragMeta {\n context?: DndDragContext;\n layer?: 'element' | 'section' | 'column' | 'root';\n type?: string | string[];\n blockCategory?: string | number;\n blockId?: string | number;\n blockName?: string;\n blockType?: BlockType;\n alt?: boolean;\n dropKind?: 'create' | 'move';\n}\n\nexport interface DropEventDropzoneMeta {\n context?: DndDropContext;\n dropTarget?: DndDropTarget;\n}\n\nexport interface DropEvent {\n name: 'drop';\n drag?: DropEventDragMeta;\n dropzone?: DropEventDropzoneMeta;\n}\n\nexport type AnalyticsParams =\n | DuplicateEvent\n | DestroyEvent\n | EditEvent\n | HistoryEvent\n | PreviewEvent\n | ToolbarMoveEvent\n | BlockInsertEvent\n | BlockSaveEvent\n | BlockDestroyEvent\n | DropEvent;\n\nexport interface Handlers {\n ready: EventHandler<ReadyParams>;\n error: EventHandler<ErrorParams>;\n save: EventHandler<SaveParams>;\n exit: EventHandler<ExitParams>;\n notification: EventHandler<NotificationParams>;\n autosave: EventHandler<AutosaveParams>;\n toggleGrid: EventHandler<ToggleGridParams>;\n toggleInvisibleCharacters: EventHandler<ToggleInvisibleCharactersParams>;\n togglePreview: EventHandler<TogglePreviewParams>;\n toggleViewMode: EventHandler<ToggleViewModeParams>;\n toggleMenu: EventHandler<ToggleMenuParams>;\n history: EventHandler<HistoryParams>;\n analytics: EventHandler<AnalyticsParams>;\n openGallery: EventHandler<(url?: string) => Promise<void>>;\n uploadImage: AsyncEventHandler<UploadImageParams, string>;\n loadPersonalization: AsyncEventHandler<void, PersonalizationDictionary>;\n loadSectionPersonalizationCatalog: AsyncEventHandler<\n void,\n SectionPersonalizationCatalogNode[]\n >;\n renderSectionPersonalizationGroup: AsyncEventHandler<\n RenderSectionPersonalizationGroupInput,\n string\n >;\n}\n\nexport type HandlerParams<H> = H extends\n | EventHandler<infer P>\n | AsyncEventHandler<infer P, unknown>\n ? P\n : never;\n\nexport interface PluginConfig {\n container: string;\n locale?: string;\n autosave?:\n | boolean\n | {\n interval: number;\n };\n token: string;\n authData?: {\n orgId: number;\n projectId?: number;\n };\n pluginId: string;\n apiUrl: string;\n disableHotkeysPassing?: boolean;\n sectionPersonalization?: SectionPersonalizationConfig;\n __config?: object;\n on: Partial<Handlers>;\n}\n","import { ImageParams } from './types';\n\nconst getImageFileSize = async (imageUrl: string) => {\n try {\n const response = await fetch(imageUrl, { method: 'HEAD' });\n\n if (!response.ok) {\n return null;\n }\n\n const contentLength = response.headers.get('Content-Length');\n\n if (contentLength) {\n return parseInt(contentLength, 10);\n } else {\n return null;\n }\n } catch (error) {\n return null;\n }\n};\n\nexport const getImageParamsFromFileUrl = (imgSrc: string) =>\n new Promise<Omit<ImageParams, 'url'>>((resolve, reject) => {\n const img = new Image();\n\n img.onload = async () => {\n const fileSize = (await getImageFileSize(imgSrc)) ?? 0;\n\n resolve({\n originalWidth: img.width,\n originalHeight: img.height,\n ratio: img.width / img.height,\n fileSize,\n });\n };\n\n img.onerror = (error) => {\n reject(error);\n };\n\n img.src = imgSrc;\n });\n\nconst getLatinKey = (key: string, code: string) => {\n if (key.length !== 1) {\n return key;\n }\n\n const capitalHetaCode = 880;\n const isNonLatin = key.charCodeAt(0) >= capitalHetaCode;\n\n if (isNonLatin) {\n if (code.indexOf('Key') === 0 && code.length === 4) {\n return code.charAt(3);\n }\n\n if (code.indexOf('Digit') === 0 && code.length === 6) {\n return code.charAt(5);\n }\n }\n\n return key;\n};\n\nexport const constructKeyCode = (event: KeyboardEvent) => {\n let keyCode =\n `${getLatinKey(event.key, event.code)}`.toLowerCase() || event.key;\n const macOs = navigator.userAgent.includes('Mac OS');\n\n if (keyCode === 'backspace' && macOs) {\n keyCode = 'delete';\n }\n\n const prefix = [];\n\n if ((macOs && event.metaKey) || (!macOs && event.ctrlKey)) {\n prefix.push('mod');\n }\n\n if (event.shiftKey) {\n prefix.push('shift');\n }\n\n if (prefix.length > 0) {\n keyCode = `${prefix.join('-')}-${getLatinKey(keyCode, event.code)}`;\n }\n\n return keyCode;\n};\n\nexport const CORE_HOTKEYS = new Set([\n 'escape',\n 'mod-c',\n 'mod-d',\n 'mod-z',\n 'mod-y',\n 'mod-shift-z',\n 'mod-v',\n 'delete',\n 'mod-g',\n 'mod-p',\n 'mod-s',\n]);\n","{\n \"name\": \"@getdraft/plugin\",\n \"version\": \"1.19.0-alpha.0\",\n \"main\": \"dist/index.cjs.js\",\n \"module\": \"dist/index.es.js\",\n \"types\": \"dist/types/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/types/index.d.ts\",\n \"import\": \"./dist/index.es.js\",\n \"require\": \"./dist/index.cjs.js\"\n }\n },\n \"scripts\": {\n \"prebuild\": \"rm -rf dist\",\n \"build\": \"vite build\",\n \"dev-tsc\": \"tsc-check\",\n \"eslint\": \"npx eslint src\",\n \"eslint:fix\": \"pnpm eslint --fix\",\n \"prettify\": \"npx prettier --check src\",\n \"prettify:fix\": \"npx prettier -w src\",\n \"prepublish\": \"pnpm build\",\n \"watch\": \"NODE_ENV=development vite build --watch\",\n \"start\": \"NODE_ENV=development npx vite\"\n },\n \"dependencies\": {},\n \"devDependencies\": {\n \"@getdraft/types\": \"workspace:^\",\n \"@getdraft/eslint-config-ts\": \"workspace:^\",\n \"@getdraft/prettier\": \"workspace:^\",\n \"vite-plugin-dts\": \"4.5.4\"\n },\n \"license\": \"MIT\"\n}\n","import { LOCAL_ENDPOINT, PROD_ENDPOINT } from './routes';\nimport {\n DraftError,\n EditorMenu,\n ExitParams,\n OnInitParams,\n OpenGalleryParams,\n Handlers,\n PluginConfig,\n SaveParams,\n TemplateJSON,\n UploadImageParams,\n ViewMode,\n HandlerParams,\n MessageData,\n ExportAsFileParams,\n RenderSectionPersonalizationGroupInput,\n} from './types';\nimport {\n getImageParamsFromFileUrl,\n constructKeyCode,\n CORE_HOTKEYS,\n} from './utils';\nimport pkg from '../package.json';\n\nconst UNKNOWN_ERROR_MESSAGE = 'Unknown error';\n\nconst getDeployLink = () => {\n const regex = new RegExp(`(^| )seplugin-dev=([^;]+)`);\n const match = document.cookie.match(regex);\n const value = match?.[2].toLowerCase?.();\n\n if (value === 'true') {\n return LOCAL_ENDPOINT;\n }\n\n if (value?.startsWith('https://')) {\n return value;\n }\n\n const [major, mid] = pkg.version.split('.');\n\n return `${PROD_ENDPOINT}/v${major}.${mid}`;\n};\n\nconst verifyConfig = ({ token, pluginId, apiUrl }: PluginConfig) => {\n if (!token) {\n throw new Error('No [token] was provided');\n }\n\n if (!pluginId) {\n throw new Error('No [pluginId] was provided');\n }\n\n if (!apiUrl) {\n throw new Error('No [apiUrl] was provided');\n }\n};\n\nconst createIframe = (parentOrigin: string) => {\n const iframe = document.createElement('iframe');\n const url = new URL(getDeployLink());\n url.searchParams.set('parentOrigin', parentOrigin);\n iframe.src = url.toString();\n iframe.setAttribute(\n 'style',\n 'height:100%;width:100%;min-width:960px;border:0px;',\n );\n iframe.setAttribute('allow', 'clipboard-read; clipboard-write');\n iframe.setAttribute(\n 'sandbox',\n 'allow-scripts allow-same-origin allow-forms allow-popups allow-downloads',\n );\n\n return iframe;\n};\n\nexport class PluginInstance {\n public iframe: HTMLIFrameElement | null = null;\n private hotkeysAttached = false;\n private iframeOrigin: string | null = null;\n constructor(public config: PluginConfig) {}\n\n private captureHotkeysEnabled() {\n return this.config.disableHotkeysPassing !== true;\n }\n\n private onHostHotkey = (event: KeyboardEvent) => {\n if (!this.captureHotkeysEnabled() || !this.iframe?.contentWindow) {\n return;\n }\n\n const keyCode = constructKeyCode(event);\n\n if (!CORE_HOTKEYS.has(keyCode)) {\n return;\n }\n\n const target = event.target as HTMLElement | null;\n\n if (\n target &&\n (target.isContentEditable ||\n ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName))\n ) {\n return;\n }\n\n event.preventDefault();\n\n const { key, ctrlKey, metaKey, shiftKey, altKey } = event;\n\n this.postEvent('hostHotkey', {\n key,\n code: event.code,\n metaKey,\n ctrlKey,\n shiftKey,\n altKey,\n keyCode,\n });\n };\n\n private static HEARTBEAT_TIMEOUT = 4000;\n\n private promisedIframeMethod<T>(eventName: string) {\n let timer: Timeout | null = null;\n let listener: ((e: MessageEvent<MessageData>) => void) | null = null;\n\n const cleanup = () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n\n if (listener) {\n window.removeEventListener('message', listener, true);\n listener = null;\n }\n };\n\n const res = new Promise<T>((resolve, reject) => {\n const resetTimer = () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n cleanup();\n reject(\n new DraftError('timeout_error', `Action \"${eventName}\" timed out`),\n );\n }, PluginInstance.HEARTBEAT_TIMEOUT);\n };\n\n listener = (e: MessageEvent<MessageData>) => {\n if (e.source !== this.iframe?.contentWindow) return;\n\n const { data } = e;\n if (data.source !== 'DraftPlugin') return;\n\n if (data.event === 'actionPing' && data.action === eventName) {\n e.stopPropagation();\n resetTimer();\n\n return;\n }\n\n if (data.event === eventName) {\n e.stopPropagation();\n cleanup();\n\n const { source: _1, event: _2, ok, code, message, ...rest } = data;\n\n if (ok === false) {\n reject(\n new DraftError(\n code || 'unknown_error',\n message || UNKNOWN_ERROR_MESSAGE,\n ),\n );\n } else {\n resolve(rest as T);\n }\n }\n };\n\n window.addEventListener('message', listener, true);\n resetTimer();\n });\n\n this.postEvent(eventName);\n\n return res;\n }\n\n private postEvent(event: string, data: object = {}) {\n if (this.iframe && this.iframe.contentWindow && this.iframeOrigin) {\n this.iframe.contentWindow.postMessage(\n {\n ...data,\n event,\n source: 'DraftPlugin',\n },\n this.iframeOrigin,\n );\n } else if (!this.iframeOrigin) {\n throw new Error('Iframe origin is not initialized');\n }\n }\n\n private onImageUpload = async ({\n id,\n ...data\n }: UploadImageParams & { id: string }) => {\n try {\n const url = await this.config.on.uploadImage?.(data);\n let params = {};\n\n if (url) {\n params = await getImageParamsFromFileUrl(url);\n }\n\n this.postEvent('imageUploaded', { id, img: { ...params, url } });\n } catch (e) {\n this.postEvent('imageUploaded', { id });\n }\n };\n\n private onLoadPersonalization = async (requestId?: string) => {\n try {\n if (!this.config.on.loadPersonalization) {\n throw new Error('No personalization loader provided');\n }\n\n const personalizationDictionary =\n await this.config.on.loadPersonalization();\n\n this.postEvent('loadPersonalization', {\n items: personalizationDictionary,\n requestId,\n });\n } catch (e) {\n this.postEvent('loadPersonalization', { requestId });\n }\n };\n\n private onLoadSectionPersonalizationCatalog = async (requestId?: string) => {\n try {\n const handler = this.config.on.loadSectionPersonalizationCatalog;\n\n if (!handler) {\n throw new Error('No section personalization catalog loader provided');\n }\n\n const catalog = await handler();\n\n this.postEvent('loadSectionPersonalizationCatalog', {\n ok: true,\n requestId,\n catalog,\n });\n } catch (error) {\n this.postEvent('loadSectionPersonalizationCatalog', {\n ok: false,\n requestId,\n message: error instanceof Error ? error.message : UNKNOWN_ERROR_MESSAGE,\n });\n }\n };\n\n private onRenderSectionPersonalizationGroup = async (\n data: RenderSectionPersonalizationGroupInput & { requestId?: string },\n ) => {\n const { requestId, ...input } = data;\n\n try {\n const handler = this.config.on.renderSectionPersonalizationGroup;\n\n if (!handler) {\n throw new Error('No section personalization renderer provided');\n }\n\n const renderedHtml = await handler(input);\n\n this.postEvent('renderSectionPersonalizationGroup', {\n ok: true,\n requestId,\n html: renderedHtml,\n });\n } catch (error) {\n this.postEvent('renderSectionPersonalizationGroup', {\n ok: false,\n requestId,\n message: error instanceof Error ? error.message : UNKNOWN_ERROR_MESSAGE,\n });\n }\n };\n\n private onGalleryOpen = async ({ id }: { id: string }) => {\n const applyImage = async (url?: string) => {\n const imgParams = { url };\n\n if (url) {\n const params = await getImageParamsFromFileUrl(url);\n Object.assign(imgParams, params);\n }\n\n this.postEvent('imageUploaded', {\n id,\n img: imgParams,\n });\n };\n\n this.config.on.openGallery?.(applyImage);\n };\n\n private triggerEvent<H extends CallableFunction | undefined>(\n handler: H,\n params: HandlerParams<H>,\n ) {\n if (!handler) {\n return;\n }\n\n return handler(params);\n }\n\n private onMessage = (\n ev: MessageEvent<{ source: string; event: keyof Handlers }>,\n ) => {\n if (ev.source !== this.iframe?.contentWindow) {\n return;\n }\n\n const {\n data: { source, event, ...data },\n } = ev;\n\n if (source === 'DraftPlugin') {\n if (event === 'openGallery') {\n this.onGalleryOpen(data as OpenGalleryParams);\n } else if (event === 'uploadImage') {\n this.onImageUpload(data as UploadImageParams & { id: string });\n } else if (event === 'loadPersonalization') {\n this.onLoadPersonalization((data as { requestId?: string }).requestId);\n } else if (event === 'loadSectionPersonalizationCatalog') {\n this.onLoadSectionPersonalizationCatalog(\n (data as { requestId?: string }).requestId,\n );\n } else if (event === 'renderSectionPersonalizationGroup') {\n this.onRenderSectionPersonalizationGroup(\n data as RenderSectionPersonalizationGroupInput & {\n requestId?: string;\n },\n );\n } else {\n this.triggerEvent(\n this.config.on[event],\n data as HandlerParams<Handlers[typeof event]>,\n );\n }\n }\n };\n\n start({\n template,\n templateName,\n uid,\n }: {\n template: string | TemplateJSON;\n uid: string | number;\n templateName?: string;\n }) {\n const containerEl = document.querySelector(this.config.container);\n\n if (!containerEl) {\n throw new Error('Specified container not found');\n } else {\n const onInit = (msg: OnInitParams) => {\n const {\n data: { source, event },\n } = msg;\n if (source === 'DraftPlugin' && event === 'loaded') {\n if (msg.source !== this.iframe?.contentWindow) return;\n\n this.iframeOrigin = msg.origin;\n\n const {\n on,\n container,\n locale,\n autosave,\n token,\n apiUrl,\n pluginId,\n authData,\n sectionPersonalization,\n __config,\n } = this.config;\n\n verifyConfig(this.config);\n\n if (this.iframe && this.iframe.contentWindow) {\n const resolvedSectionPersonalization = {\n ...sectionPersonalization,\n enabled:\n sectionPersonalization?.enabled === true &&\n !!on.loadSectionPersonalizationCatalog &&\n !!on.renderSectionPersonalizationGroup,\n };\n\n this.postEvent('init', {\n container,\n locale,\n uid,\n autosave,\n token,\n pluginId,\n authData,\n sectionPersonalization: resolvedSectionPersonalization,\n apiUrl,\n __config,\n enabledListeners: Object.keys(on),\n template,\n templateName,\n });\n }\n\n window.addEventListener('message', this.onMessage);\n window.removeEventListener('message', onInit);\n }\n };\n\n this.iframe = createIframe(window.location.origin);\n window.addEventListener('message', onInit);\n containerEl.appendChild(this.iframe);\n\n if (this.captureHotkeysEnabled() && !this.hotkeysAttached) {\n window.addEventListener('keydown', this.onHostHotkey);\n this.hotkeysAttached = true;\n }\n }\n }\n\n destroy = () => {\n this.iframe?.remove();\n this.iframe = null;\n window.removeEventListener('message', this.onMessage);\n\n if (this.hotkeysAttached) {\n window.removeEventListener('keydown', this.onHostHotkey);\n this.hotkeysAttached = false;\n }\n };\n\n changeTemplate(\n template: string | TemplateJSON,\n options: {\n templateName?: string;\n uid?: string;\n } = {},\n ) {\n this.postEvent('changeTemplate', { ...options, template });\n }\n\n toggleGrid(state?: boolean) {\n this.postEvent('toggleGrid', { state });\n }\n\n toggleInvisibleCharacters(state?: boolean) {\n this.postEvent('toggleInvisibleCharacters', { state });\n }\n\n async isInvisibleCharactersVisible() {\n const { state } = await this.promisedIframeMethod<{ state: boolean }>(\n 'getInvisibleCharactersVisibility',\n );\n\n return state;\n }\n\n togglePreview(state?: boolean) {\n this.postEvent('togglePreview', { state });\n }\n\n toggleMenu(menu: EditorMenu | null = null) {\n this.postEvent('toggleMenu', { menu });\n }\n\n toggleViewMode(viewMode: ViewMode) {\n this.postEvent('toggleViewMode', { viewMode });\n }\n\n undo() {\n this.postEvent('undo');\n }\n\n undoToStep(targetStep: number) {\n this.postEvent('undoToStep', { targetStep });\n }\n\n redo() {\n this.postEvent('redo');\n }\n\n save() {\n return this.promisedIframeMethod<SaveParams>('saveAction');\n }\n\n exit() {\n return this.promisedIframeMethod<ExitParams>('exitAction');\n }\n\n exportContent() {\n return this.promisedIframeMethod<SaveParams>('exportContent');\n }\n\n exportAsFile() {\n return this.promisedIframeMethod<ExportAsFileParams>('exportAsFile');\n }\n}\n","import { PluginInstance } from './plugin';\nimport { PluginConfig } from './types';\nimport { version } from '../package.json';\n\nconst DEFAULT_CONFIG: Partial<PluginConfig> = {\n container: '#draft-plugin-container',\n disableHotkeysPassing: false,\n locale: 'ru',\n on: {},\n};\n\nclass PluginWrapper {\n public version = version;\n\n create(config: PluginConfig) {\n return new PluginInstance({\n ...DEFAULT_CONFIG,\n ...config,\n });\n }\n}\n\nconst DraftPlugin = new PluginWrapper();\n\ndeclare global {\n interface Window {\n DraftPlugin: PluginWrapper;\n }\n}\n\nwindow.DraftPlugin = DraftPlugin;\n\nexport default DraftPlugin;\nexport type { PluginInstance } from './plugin';\nexport * from './types';\n"],"mappings":"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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -129,6 +129,8 @@ export declare interface Handlers {
|
|
|
129
129
|
openGallery: EventHandler<(url?: string) => Promise<void>>;
|
|
130
130
|
uploadImage: AsyncEventHandler<UploadImageParams, string>;
|
|
131
131
|
loadPersonalization: AsyncEventHandler<void, PersonalizationDictionary>;
|
|
132
|
+
loadSectionPersonalizationCatalog: AsyncEventHandler<void, SectionPersonalizationCatalogNode[]>;
|
|
133
|
+
renderSectionPersonalizationGroup: AsyncEventHandler<RenderSectionPersonalizationGroupInput, string>;
|
|
132
134
|
}
|
|
133
135
|
|
|
134
136
|
export declare interface HistoryEvent {
|
|
@@ -160,6 +162,7 @@ export declare type MessageData = {
|
|
|
160
162
|
code?: string;
|
|
161
163
|
message?: string;
|
|
162
164
|
action?: string;
|
|
165
|
+
requestId?: string;
|
|
163
166
|
};
|
|
164
167
|
|
|
165
168
|
declare interface Notification_2 {
|
|
@@ -212,6 +215,7 @@ export declare interface PluginConfig {
|
|
|
212
215
|
pluginId: string;
|
|
213
216
|
apiUrl: string;
|
|
214
217
|
disableHotkeysPassing?: boolean;
|
|
218
|
+
sectionPersonalization?: SectionPersonalizationConfig;
|
|
215
219
|
__config?: object;
|
|
216
220
|
on: Partial<Handlers>;
|
|
217
221
|
}
|
|
@@ -229,6 +233,8 @@ export declare class PluginInstance {
|
|
|
229
233
|
private postEvent;
|
|
230
234
|
private onImageUpload;
|
|
231
235
|
private onLoadPersonalization;
|
|
236
|
+
private onLoadSectionPersonalizationCatalog;
|
|
237
|
+
private onRenderSectionPersonalizationGroup;
|
|
232
238
|
private onGalleryOpen;
|
|
233
239
|
private triggerEvent;
|
|
234
240
|
private onMessage;
|
|
@@ -244,6 +250,7 @@ export declare class PluginInstance {
|
|
|
244
250
|
}): void;
|
|
245
251
|
toggleGrid(state?: boolean): void;
|
|
246
252
|
toggleInvisibleCharacters(state?: boolean): void;
|
|
253
|
+
isInvisibleCharactersVisible(): Promise<boolean>;
|
|
247
254
|
togglePreview(state?: boolean): void;
|
|
248
255
|
toggleMenu(menu?: EditorMenu | null): void;
|
|
249
256
|
toggleViewMode(viewMode: ViewMode): void;
|
|
@@ -273,11 +280,59 @@ export declare interface ReadyParams extends SaveParams {
|
|
|
273
280
|
};
|
|
274
281
|
}
|
|
275
282
|
|
|
283
|
+
export declare interface RenderSectionPersonalizationGroupInput {
|
|
284
|
+
groupId: string;
|
|
285
|
+
fields: SectionPersonalizationField[];
|
|
286
|
+
variants: Array<{
|
|
287
|
+
id: string;
|
|
288
|
+
values: Record<string, SectionPersonalizationValue>;
|
|
289
|
+
html: string;
|
|
290
|
+
}>;
|
|
291
|
+
fallback?: {
|
|
292
|
+
id: string;
|
|
293
|
+
html: string;
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
276
297
|
export declare interface SaveParams {
|
|
277
298
|
json: TemplateJSON;
|
|
278
299
|
html: string;
|
|
279
300
|
}
|
|
280
301
|
|
|
302
|
+
export declare interface SectionPersonalizationCatalogField {
|
|
303
|
+
type: 'field';
|
|
304
|
+
id: string;
|
|
305
|
+
label: string;
|
|
306
|
+
valueType?: 'string' | 'number' | 'boolean' | 'date';
|
|
307
|
+
options?: SectionPersonalizationCatalogOption[];
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export declare interface SectionPersonalizationCatalogGroup {
|
|
311
|
+
type: 'group';
|
|
312
|
+
id: string;
|
|
313
|
+
label: string;
|
|
314
|
+
children: SectionPersonalizationCatalogNode[];
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export declare type SectionPersonalizationCatalogNode = SectionPersonalizationCatalogGroup | SectionPersonalizationCatalogField;
|
|
318
|
+
|
|
319
|
+
export declare interface SectionPersonalizationCatalogOption {
|
|
320
|
+
label: string;
|
|
321
|
+
value: Exclude<SectionPersonalizationValue, null>;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export declare interface SectionPersonalizationConfig {
|
|
325
|
+
enabled: boolean;
|
|
326
|
+
aboutUrl?: string;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export declare interface SectionPersonalizationField {
|
|
330
|
+
id: string;
|
|
331
|
+
operatorId: 'equals';
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export declare type SectionPersonalizationValue = string | number | boolean | null;
|
|
335
|
+
|
|
281
336
|
export declare interface SerializedTemplate {
|
|
282
337
|
[key: string]: unknown;
|
|
283
338
|
parentId: string | null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getdraft/plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0-alpha.0",
|
|
4
4
|
"main": "dist/index.cjs.js",
|
|
5
5
|
"module": "dist/index.es.js",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"vite-plugin-dts": "4.5.4",
|
|
17
17
|
"@getdraft/types": "^1.0.0",
|
|
18
|
-
"@getdraft/
|
|
19
|
-
"@getdraft/
|
|
18
|
+
"@getdraft/prettier": "^1.0.0",
|
|
19
|
+
"@getdraft/eslint-config-ts": "^1.0.0"
|
|
20
20
|
},
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"scripts": {
|