(selector, shallowEqual);\n","import { useSelector } from 'react-redux';\nimport { useMemo } from 'react';\nimport { selectUser } from '../store';\nimport { MyUserViewModel } from '../services';\n\nexport const useMyUser = () => {\n const { user } = useSelector(selectUser);\n\n return useMemo(() => {\n if (!user) return null;\n\n // Not sure with this solution.\n // View model keeps some extra logic\n const userVm = new MyUserViewModel();\n userVm.id = user.id;\n userVm.roles = user.roles ?? [];\n userVm.orgID = user.orgID;\n userVm.email = user.email;\n userVm.userName = user.userName;\n\n return userVm;\n }, [user]);\n};\n","import type { DocumentId } from 'core/types';\nimport { documentsActions } from 'core/store';\nimport { useNavigate } from 'react-router';\nimport { useDispatch } from 'react-redux';\n\nexport const useNavigateWithExpand = () => {\n const navigate = useNavigate();\n const dispatch = useDispatch();\n\n return (documentId: DocumentId) => {\n dispatch(documentsActions.getDocument(documentId));\n dispatch(\n documentsActions.expandParents({\n documentId,\n onSuccess: () => {\n navigate(`/${documentId}`);\n },\n }),\n );\n };\n};\n","/* eslint-disable class-methods-use-this */\nexport class OnlineOfflineSingleton {\n _status: boolean | undefined;\n private static instance: any = null;\n\n handleOnline = () => {\n this._status = true;\n };\n\n handleOffline = () => {\n this._status = false;\n };\n\n get status() {\n return this._status;\n }\n\n constructor() {\n if (OnlineOfflineSingleton.instance) {\n return OnlineOfflineSingleton.instance;\n }\n\n this._status = window.navigator.onLine;\n\n window.addEventListener('online', this.handleOnline);\n window.addEventListener('offline', this.handleOffline);\n\n OnlineOfflineSingleton.instance = this;\n }\n}\n","export const defaultHtml = `\n Plugins
\n Type @, and keep typing to connect plugins to this part of your workspace:
\n \n Aliases\n
\n
\n References
\n Data plugins will look for familiar links here, and try to make the content they point to browsable
\n \n - Replace me with an URL to some data
\n
\n
\n Aliases
\n The Aliases plugin will look for definitions here, and let you interact with them in your documents
\n \n \n \n Keyword | \n Content | \n
\n \n \n \n iQx | \n \n \n | \n
\n \n
\n`;\n","import React from 'react';\nimport { renderToString } from 'react-dom/server';\nimport type { TributeClientItem, TributeOptions } from 'core/types';\n\nconst options: TributeOptions = {\n trigger: '@',\n lookup: 'name',\n values: [],\n fillAttr: 'name',\n allowSpaces: true,\n selectTemplate: (item: TributeClientItem) => {\n // @ts-ignore\n return renderToString({item.original.name});\n },\n};\n\nexport default options;\n","import tributeOptions from 'core/includes/plugins/tribute-options';\nimport type { PluginInjection } from 'core/types';\nimport { getPluginByCode } from './get-plugin';\n\nexport function populateTribute(pluginsCodes: string[], docAttrs: any = {}) {\n const pluginsList: PluginInjection[] = [];\n\n let i = 0;\n pluginsCodes.forEach(code => {\n const plugin = getPluginByCode(code, docAttrs);\n\n if (plugin) {\n pluginsList.push({\n key: i,\n ...plugin,\n });\n\n i++;\n }\n });\n\n tributeOptions.values = pluginsList;\n\n return tributeOptions;\n}\n","export const DEFAULT_CDN_CSS =\n 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css';\n","import type { WindowProps } from './interface';\n\nimport { DEFAULT_CDN_CSS } from '../constants';\n\nexport const openWindow = ({ body, links = [], title }: WindowProps) =>\n new Promise(resolve => {\n const styleLinks = [DEFAULT_CDN_CSS, ...links].reduce(\n (acc, link) => `${acc}`,\n '',\n );\n\n const page: any = window.open();\n const content = `\n \n ${title}\n ${styleLinks}\n \n ${body}\n `;\n\n page.document.write(content);\n\n page.document.close();\n resolve();\n });\n","export default ({ loaded, total }: any) => Math.round((loaded * 100) / total);\n","import type { AxiosRequestConfig } from 'axios';\nimport axios from 'axios';\nimport { env } from 'core/utils';\nimport { loadingHide, loadingSetMessage, showAlert } from 'core/store/modules/common/actions';\nimport { API_ERROR_MESSAGE } from 'core/store/modules/common/literals';\nimport download from 'downloadjs';\n\nimport type { PdfProps } from './interface';\nimport getProcessResult from './utils/get-process-result';\nimport makeFilename from './utils/make-filename';\nimport mergePdfFiles from './utils/merge-pdf-files';\n\nimport { DEFAULT_CDN_CSS } from '../constants';\nimport { PDF_IS_DOWNLOADING, PDF_IS_GENERATING, PDF_IS_READY, PDF_IS_UPLOADING } from '../literals';\n\nexport const downloadPdf = (\n { chunks = [], filename, css = [], options = {}, pdf = [] }: PdfProps,\n dispatch: any,\n) => {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n const url = `${env.PDF_SERVICE_URI}/api/v1`;\n\n const pdfFiles = mergePdfFiles(chunks);\n\n const config: AxiosRequestConfig = {\n url,\n data: {\n chunks,\n options,\n css: [DEFAULT_CDN_CSS, ...css],\n pdf: [...pdf, ...pdfFiles],\n },\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n },\n responseType: 'blob',\n onUploadProgress: (progressEvent: any) => {\n const total = getProcessResult(progressEvent);\n\n const message = total !== 100 ? `${PDF_IS_UPLOADING} ${total}%` : PDF_IS_GENERATING;\n\n dispatch(loadingSetMessage(message));\n },\n onDownloadProgress: (progressEvent: any) => {\n const total = getProcessResult(progressEvent);\n\n dispatch(loadingSetMessage(`${PDF_IS_DOWNLOADING} ${total}%`));\n },\n };\n\n const file: string = makeFilename(filename);\n const contentType = 'application/pdf';\n\n axios(config)\n .then(({ data }: any) => {\n download(data, file, contentType);\n dispatch(showAlert(PDF_IS_READY, { variant: 'success' }));\n })\n .catch((error: any) => {\n dispatch(\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n showAlert(`${API_ERROR_MESSAGE}. ${error}`, {\n variant: 'error',\n timeout: 10,\n }),\n );\n })\n .then(() => {\n dispatch(loadingHide());\n });\n};\n","export default (chunks: string[]) => {\n const body = chunks.join('');\n const matches: any = body.matchAll(/src=\"(.*?\\.pdf)\"|href=\"(.*?\\.pdf)\"/gi);\n\n const pdfs = [...matches];\n\n if (!pdfs.length) {\n return [];\n }\n\n return pdfs.map((item: any) => item[2] ?? item[1]);\n};\n","export const PDF_IS_READY = 'The PDF is ready to download';\nexport const PDF_IS_GENERATING = 'Generating PDF';\nexport const PDF_IS_UPLOADING = 'Uploading data';\nexport const PDF_IS_DOWNLOADING = 'Downloading';\n","export default (name: string) => `${name}-${new Date().toISOString().split('T')[0]}.pdf`;\n","export default (path: number[]) => {\n const number = path.filter((value: any) => value).join('.');\n\n return number ? `${number}.` : '';\n};\n","const ALLOWED_SHORTCODES: any = {\n 'toc.figures': 1,\n 'toc.chapters': 1,\n 'toc.tables': 1,\n};\n\nexport default (html: string) => {\n if (!html) {\n return html;\n }\n\n const re = /.*?<\\/span>/g;\n\n const code = re.exec(html);\n\n if (!code) {\n return html;\n }\n\n const shortcode = code[1];\n\n if (!ALLOWED_SHORTCODES[shortcode]) {\n return html;\n }\n\n const replaceValue = `@${shortcode}
`;\n\n return html.replace(re, replaceValue);\n};\n","import chapter from './chapter';\nimport findShortcode from './find-shortcode';\n\nimport type { ShortcodeProps } from '../interface';\n\nexport default (data: ShortcodeProps) => {\n const html = chapter(data);\n\n return findShortcode(html);\n};\n","import chapterFormat from './chapter-format';\n\nimport type { ShortcodeProps } from '../interface';\n\nexport default ({ html, id, path }: ShortcodeProps) => {\n if (!html) {\n return html;\n }\n\n const level = path.length;\n const number = chapterFormat(path);\n\n const re = /(.*?)<\\/h1>/g;\n const replaceValue = `${number} $1`;\n\n return html.replace(re, replaceValue);\n};\n","import { findDocument } from './find-document';\n\nimport { TYPE_CHAPTER } from '../constants';\n\nconst traverse = async ({ data, items, level, path }: any, callback: any) => {\n let number = 1;\n\n for (const { children, id } of data) {\n // find the current item\n const item = findDocument(items, id);\n\n // skip onther numbers\n const index = item.type === TYPE_CHAPTER ? number++ : null;\n\n const count = path.length - level;\n\n if (count > 0) {\n for (let counter = 0; counter < count; counter++) {\n path.pop();\n }\n }\n\n await callback({ ...item, path: [...path, index] });\n\n if (children) {\n if (!level) {\n // eslint-disable-next-line no-param-reassign\n path = [];\n }\n\n path.push(index);\n\n await traverse({ items, data: children, level: level + 1, path }, callback);\n }\n }\n};\n\nexport default traverse;\n","export const TYPE_COVER = 'cover';\nexport const TYPE_CHAPTER = 'chapter';\nexport const TYPE_CHAPTERS = 'chapters';\n","import React from 'react';\nimport ReactDOMServer from 'react-dom/server';\nimport { generate } from 'short-uuid';\nimport { DocumentType } from 'core/types/document';\nimport executePlugin from '../plugins/utils/execution';\n\nimport { TYPE_CHAPTERS, TYPE_COVER } from './constants';\nimport { findDocument } from './utils/find-document';\nimport shortcodes from './utils/shortcodes';\nimport traverse from './utils/traverse';\nimport findPluginsRefDocument from '../plugins/utils/find';\n\nexport const htmlRedner = async ({ items, tree }: any, call: any = (item: any) => item) => {\n const content: any[] = [];\n const { _id, title, type: chapterType, parent } = findDocument(items, tree.id);\n const pluginsDocument = findPluginsRefDocument(_id, parent, items);\n\n // escape showing the first type chapters\n const data = chapterType === TYPE_CHAPTERS ? tree?.children || [] : [tree];\n\n await traverse({ items, data, level: 0, path: [] }, async (item: any) => {\n const { _id: id, html, path, type } = await call(item);\n\n const executedHTML =\n type === DocumentType.PLUGINS ? '' : await executePlugin(html, pluginsDocument);\n\n const key = generate();\n const el: JSX.Element = React.createElement('div', {\n className: type,\n id: type !== TYPE_COVER ? key : '',\n key,\n dangerouslySetInnerHTML: { __html: shortcodes({ html: executedHTML, path, id }) },\n });\n\n content.push(ReactDOMServer.renderToString(el));\n });\n\n const body = content.join('');\n\n return {\n title,\n body,\n };\n};\n","/* eslint-disable no-restricted-syntax */\nimport { getHTMLDocument } from 'core/includes/html/utils/dom';\nimport { getPluginByName } from './get-plugin';\n\nexport default async function executePlugin(elHTML: string, pluginsDocument: any) {\n const htmlDoc = getHTMLDocument(elHTML);\n const plugins = htmlDoc.querySelectorAll('plugin');\n\n // @ts-ignore\n const pluginsArray = [...plugins];\n\n for (const pluginEl of pluginsArray) {\n const { innerHTML: name } = pluginEl;\n // @ts-ignore\n const plugin = getPluginByName(name);\n\n if (plugin?.call) {\n try {\n // eslint-disable-next-line no-await-in-loop\n const result = await plugin.call(elHTML, pluginsDocument);\n pluginEl.outerHTML = result;\n } catch (error) {\n console.error(error);\n pluginEl.outerHTML = '';\n }\n }\n }\n\n return htmlDoc.body.innerHTML;\n}\n","import { Provider } from 'react-redux';\nimport { PersistGate } from 'redux-persist/lib/integration/react';\nimport type { PropsWithChildren } from 'react';\nimport type { AnyAction, EnhancedStore } from '@reduxjs/toolkit';\nimport type { Persistor } from 'redux-persist/lib/types';\nimport type { Middleware } from 'redux';\nimport type { SagaMiddleware } from 'redux-saga';\nimport { Loader } from './components';\nimport { CoreMetricsProvider, CoreProviders, LoggerProvider } from './providers';\nimport { useApp } from './hooks';\nimport { LoggerService } from './services';\nimport { terminateAPP } from './store/modules/common/actions';\n\ntype InitStore = () => {\n store: EnhancedStore)[]>; // TODO: add context type\n persistor: Persistor;\n saga: SagaMiddleware