import React from 'react'; import ReactDOM from 'react-dom'; import $ from 'jquery'; import html2canvas from 'html2canvas'; import * as html2pdf from 'html2pdf.js'; import { Text, Node } from '@src/components/slate-packages/slate'; import { ELTYPE, HEADING_TYPES, slateDefaultValue } from './components/docs/plugins/config'; import Docs from './Docs'; import './style/less/slatedocs-sdk.less'; import { addApiListener } from './utils/apiListener'; import storage from './utils/storage'; import '@src/style/less/slatedocs.less'; import MdDocs from './MdDocs'; import { getCache, setCache } from './utils/cacheUtils'; import { getDefaultValueByBase64 } from './utils/getDefaultValue'; import { createUUID } from './utils/randomId'; import sessStorage from './utils/sessStorage'; export const Editor = function (opt: Options, container: any) { if (typeof window !== 'object') { return; } const options = { ...opt }; const { onSlateChange = function onSlateChange() {}, titleCallback = function titleCallback() {}, initCallback = function initCallback() {}, mentionCallback = function mentionCallback() {}, roomUsersCallback = function roomUsersCallback() {}, commentCallback = function commentCallback() {}, shareCallback = function shareCallback() {}, docStatusCallback = function docStatusCallback() {}, getDocHistoryCallback = function getDocHistoryCallback() {}, getDocBlobByVersionCallback = function getDocBlobByVersionCallback() {}, restoreDocCallback = function restoreDocCallback() {}, mdRefreshDocCallback = function mdRefreshDocCallback() {}, getDocToken = async function getDocToken() { return Promise.resolve(null); }, getUserList = null, linkClickCallBack = async function linkClickCallBack() { return Promise.resolve([]); }, lang = 'zh', } = options; console.log(`tripdocs start init, version:` + require('../package.json').version); window.tripdocs.lang = lang; if (!window.tripdocs.cache.console) { try { window.tripdocs.cache.console = console; const proxy = new Proxy(window.tripdocs.cache.console.error, { apply(target, thisArg, ...args) { try { const errStr = args.toString(); if (errStr && errStr.indexOf('Warning:') !== 0 && errStr.indexOf('ErrorBoundary') === -1 && errStr.indexOf('[handleSlateError]') !== 0) { let errFormat = '\n----\n' + errStr + '\n----\n'; try { throw new Error(); } catch (error: any) { errFormat += '\n----\n' + error.stack + '\n----\n'; } console.log('proxy err stack:', errFormat); let newStack: any[] = []; const stack: any[] = getCache(options.docId, 'changeEditorStack') || []; if (stack.length >= 1) { newStack.push(stack[0]); for (let i = 1; i < stack.length; i++) { newStack.push({ content: [], operations: stack[i].operations, }); } } else { newStack = stack; } const id = createUUID(); sessStorage.set('tripdocs_sdk/ubtErrorId', id); sessStorage.set('tripdocs_sdk/ubtError', errFormat + '\n id:' + id); const str = JSON.stringify(newStack); const sliceLen = 10 * 1000; const num = Math.ceil(str.length / sliceLen); for (let i = 0; i < num; i++) {} } } catch (error) { } finally { return Reflect.apply(target, thisArg, ...args); } }, }); console.error = proxy; } catch (error) { console.error(error); } } verifyOptions(options); polyfillJs(); const { employee, userName: name } = options.userInfo; const dom = container || document.getElementById(`editorContainer-${options.docId}`); let isDOM = typeof HTMLElement === 'object' ? function (obj) { return obj instanceof HTMLElement; } : function (obj) { return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string'; }; if (!isDOM(dom)) { console.error('dom err', dom); return; } window.tripdocs.editorsMap = window.tripdocs.editorsMap ? { ...window.tripdocs.editorsMap, [options.docId]: { ...options } } : { [options.docId]: { ...options } }; window.tripdocs.editorsMap[options.docId].cache = { textValue: '', commentId: '', timeCheck: true, docContentQueue: [], }; setCache(options.docId, 'options', options); const initTimestamp = new Date().getTime(); console.log('[time check] benchmark timestamp: ', initTimestamp); setCache(options.docId, 'initTimestamp', initTimestamp); dom.addEventListener( 'unload', () => { delete window.tripdocs.editorsMap[options.docId]; }, { once: true } ); if (!options) { ReactDOM.render(
init error,your options is null
, dom); return; } window.tripdocs.editorsMap[options.docId].api = {}; addApiListener(onSlateChange, options.docId); addApiListener(initCallback, options.docId); addApiListener(mentionCallback, options.docId); addApiListener(roomUsersCallback, options.docId); addApiListener(commentCallback, options.docId); addApiListener(shareCallback, options.docId); addApiListener(docStatusCallback, options.docId); addApiListener(getDocHistoryCallback, options.docId); addApiListener(getDocBlobByVersionCallback, options.docId); addApiListener(restoreDocCallback, options.docId); addApiListener(mdRefreshDocCallback, options.docId); if (options.isMdEditor) { ReactDOM.render(, dom); } else { ReactDOM.render(, dom); } window.tripdocs.editorsMap[options.docId].api.getContent = getContentForID(options.docId); window.tripdocs.editorsMap[options.docId].api.getTitle = getTitleForID(options.docId); window.tripdocs.editorsMap[options.docId].api.getMentions = getAllMentionsForID(options.docId); window.tripdocs.editorsMap[options.docId].api.getHeadings = getHeadingsForID(options.docId); window.tripdocs.editorsMap[options.docId].api.getComments = getAllComment(options.docId); window.tripdocs.editorsMap[options.docId].api.destroy = destroy(options.docId); window.tripdocs.editorsMap[options.docId].api.reload = reload(options); window.tripdocs.editorsMap[options.docId].api.scrollToViewByAnchorId = scrollToViewByAnchorId(options.docId); window.tripdocs.editorsMap[options.docId].api.scrollToViewByRangeId = scrollToViewByRangeId(options.docId); window.tripdocs.editorsMap[options.docId].api.getUserList = getUserList; window.tripdocs.editorsMap[options.docId].api.linkClickCallBack = linkClickCallBack; window.tripdocs.editorsMap[options.docId].api.titleCallback = titleCallback; window.tripdocs.editorsMap[options.docId].api.getDocToken = getDocToken; window.tripdocs.editorsMap[options.docId].api.compareDocContentWithDefault = compareDocContentWithDefault(options.docId); window.tripdocs.editorsMap[options.docId].api.setContent = setContent(options.docId); window.tripdocs.editorsMap[options.docId].api.getContentByBase64 = getDefaultValueByBase64; window.tripdocs.editorsMap[options.docId].api.getEditorBottomDom = getEditorBottomDom(options.docId); window.tripdocs.editorsMap[options.docId].api.joinDevGroup = options?.joinDevGroup; return window.tripdocs.editorsMap[options.docId]; }; window.tripdocs = { Editor, cache: {}, lang: 'zh', rrwebRecord: { upload: () => {} }, }; function dynamicLoadJs(url, callback?: Function) { if (document.getElementsByTagName('head')[0].outerHTML.includes(url)) { return; } let head = document.getElementsByTagName('head')[0]; let script: any = document.createElement('script'); script.type = 'text/javascript'; script.src = url; if (typeof callback == 'function') { script.onload = script.onreadystatechange = function () { if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') { callback(); script.onload = script.onreadystatechange = null; } }; } head.appendChild(script); } function getContentForID(docId = 'default') { return () => window.tripdocs.editorsMap[docId]?.editor?.children; } function getTitleForID(docId = 'default') { return () => Node.string(window.tripdocs.editorsMap[docId]?.editor?.children[0]); } function getAllMentionsForID(docId = 'default') { return () => { const { SlateEditor: Editor, editor } = window.tripdocs.editorsMap[docId]; if (!editor) { return; } const arr = []; for (let node of editor.children) { if (node.type === ELTYPE.MENTION) { console.log('getMentions editor.--------------', node); arr.push(node); } } return arr; }; } function getHeadingsForID(docId = 'default') { return () => { const { SlateEditor: Editor, editor } = window.tripdocs.editorsMap[docId]; const arr = []; for (let node of editor.children) { if (HEADING_TYPES.includes(node.type)) { console.log('getHeadings editor.--------------', node); arr.push({ string: Node.string(node), type: node.type, }); } } return arr; }; } function getAllComment(docId = 'default') { return () => { return window.tripdocs.editorsMap[docId].commentData; }; } function destroy(docId = 'default') { return () => { window.tripdocs.editorsMap[docId] && window.tripdocs.editorsMap[docId]?.socket?.provider?.disconnect && window.tripdocs.editorsMap[docId]?.socket?.provider?.destroy(); const container = document.getElementById(`editorContainer-${docId}`); if (container) { ReactDOM.unmountComponentAtNode(container); } delete window.tripdocs.editorsMap[docId]; }; } function reload(options) { return () => { const { docId } = options; const container = document.getElementById(`editorContainer-${docId}`); ReactDOM.unmountComponentAtNode(container); const editor = new window.tripdocs.Editor(options, container); return editor; }; } function scrollToViewByAnchorId(docId = 'default') { return (anchorId: string) => { const { SlateEditor: Editor, editor, ReactEditor } = window.tripdocs.editorsMap[docId]; const curNodeEntry = Editor.nodes(editor, { at: [], match: (n: any) => n?.anchorId === anchorId, }).next().value; const anchorItemEl = ReactEditor.toDOMNode(editor, curNodeEntry[0]); anchorItemEl.scrollIntoView({ behavior: 'smooth', block: 'center' }); $(anchorItemEl).on('webkitAnimationEnd animationEnd', function () { $(this).removeClass('anchor-target'); }); $(anchorItemEl).addClass('anchor-target'); }; } function scrollToViewByRangeId(docId = 'default') { return (rangeId: string) => { const json = JSON.parse(rangeId); const { SlateEditor: Editor, editor, ReactEditor } = window.tripdocs.editorsMap[docId]; const curNodeEntry = Editor.nodes(editor, { at: [], match: (n: any) => n?.anchorId === json.anchorId, }).next().value; const anchorItemEl = ReactEditor.toDOMNode(editor, curNodeEntry[0]); anchorItemEl.scrollIntoView({ behavior: 'smooth', block: 'center' }); $(anchorItemEl).on('webkitAnimationEnd animationEnd', function () { $(this).removeClass('anchor-target'); }); $(anchorItemEl).addClass('anchor-target'); }; } function compareDocContentWithDefault(docId = 'default') { return () => { const undos = window.tripdocs.editorsMap[docId].editor.history.undos as any[][]; const result = undos.some(arr => { return arr.some(op => { if (op.type !== 'set_selection') { return true; } return false; }); }); return result; }; } function setContent(docId = 'default') { return (obj: any, mode: string = 'json', loading: boolean) => { if (!window.tripdocs.editorsMap[docId].api.setTemplate) { console.error('setContent setTemplate function undefined'); return; } const api = window.tripdocs.editorsMap[docId]?.api; loading && api && api?.setLoading(true); if (mode === 'json') { const newJson = execModalParam(docId, obj); api?.setTemplate(newJson); return; } const json = getDefaultValueByBase64(obj); const newJson = execModalParam(docId, json); console.log('setContent ::', newJson); api?.setTemplate(newJson); }; } export function execModalParam(docId: string, content: any[]) { const options = getCache(docId, 'options'); try { if (options.openModalParam && Array.isArray(content)) { if (Node.string(content[0]) === '$name') { const name = options?.userInfo?.userName; const title = { ...content[0], children: [{ text: name }] }; return [title, ...content.slice(1)]; } } } catch (error) { console.error('execModalParam error'); return content; } return content; } function getEditorBottomDom(docId = 'default') { return () => { try { const dom = document.getElementById('editorContainer-bottom-' + docId); return dom; } catch (error) { console.log(error); } }; } function verifyOptions(options: Options) { const containerVerify = document.getElementById(`editorContainer-${options.docId}`); if (!options.docId || !containerVerify) { console.error('没有 docId,或者 editorContainer-${docId}无法获取 dom,不可以初始化'); return; } if (!options.allUserList) { options.allUserList = []; } if (!options.openModalParam) { options.openModalParam = true; } if (!options.useTripdocsFileUpload) { options.useTripdocsFileUpload = false; } if (typeof options.historyVersionShortKey !== 'boolean') { options.historyVersionShortKey = false; } if (!options.defaultTitle) { options.defaultTitle = ''; } if (!options.reloadCallback) { options.reloadCallback = function () {}; } if (!options.spellcheck) { options.spellcheck = false; } if (!options.defaultUserList) { options.defaultUserList = []; } if (!options.banCommentNesting) { options.banCommentNesting = false; } if (!options.openAutoRecover) { options.openAutoRecover = false; } if (options.isWideMode === undefined) { options.isWideMode = false; } if (!options.defaultCommentData) { options.defaultCommentData = []; } if (!options.toolbar) { options.toolbar = []; } if (!options.socketUrl) { options.socketUrl = 'offline'; } if (!options.socketUrl) { options.socketUrl = 'offline'; } if (!options.userInfo) { options.userInfo = { employee: 'TEST00', userName: '游客', }; } if (!options.safeAreaBottom) { options.safeAreaBottom = 0; } if (!options.showTopMenuOnlyRead) { options.showTopMenuOnlyRead = false; } if (typeof options.useIMEInput !== 'boolean') { options.useIMEInput = true; } if (!options.tocPlacement) { options.tocPlacement = 'left'; } if (!options.deepestDisplayAnchorHeading) { options.deepestDisplayAnchorHeading = 6; } if (!options.errorRecoverCallback) { options.errorRecoverCallback = function errorRecoverCallback() { console.log('errorRecoverCallback'); }; } if (!options.fallbackCallback) { options.fallbackCallback = function fallbackCallback() { console.log('fallbackCallback'); }; } if (!options.isMdEditor) { options.isMdEditor = false; } if (!options.joinDevGroup) { options.joinDevGroup = () => {}; } if (options.showGlobalComment === undefined) { options.showGlobalComment = true; } if (options.showHoveringCommentButton === undefined) { options.showHoveringCommentButton = true; } if (!options.showHelpBlock) { options.showHelpBlock = false; } if (!options.openRrweb) { options.openRrweb = false; } if (!options.cssTarget) { options.cssTarget = ''; } if (options.useValidationWorker === undefined) { options.useValidationWorker = true; } if (options.defaultValue2) { options.defaultValue = getDefaultValueByBase64(options.defaultValue2); console.log('options.defaultValue', options.defaultValue); } options.socketUrl = options.socketUrl || 'offline'; options.socketUrl = options.socketUrl.replace(/https*:\/\//, ''); console.log('options.socketUrl', options.socketUrl); options.secure = !!options.secure; options.fake = !!options.fake; if (!options.defaultValue) { if (options.defaultTitle) { slateDefaultValue[0].children = [{ text: options.defaultTitle }]; options.defaultValue = slateDefaultValue; } else { options.defaultValue = slateDefaultValue; } console.log('options.defaultValue', options.defaultValue); } if (!options.defaultMDValue) { if (options.defaultMDValue === null) { options.defaultMDValue = ''; } } } function polyfillJs() { if (!String.prototype.matchAll) { String.prototype.matchAll = function (rx) { if (typeof rx === 'string') rx = new RegExp(rx, 'g'); rx = new RegExp(rx); let cap = []; let all = []; while ((cap = rx.exec(this)) !== null) all.push(cap); return all; } as any; } }