diff --git a/web/ASC.Web.Editor/src/helpers/utils.js b/web/ASC.Web.Editor/src/helpers/utils.js index 151ef8fe59..af54d4e396 100644 --- a/web/ASC.Web.Editor/src/helpers/utils.js +++ b/web/ASC.Web.Editor/src/helpers/utils.js @@ -83,21 +83,19 @@ export const initDocEditor = async (req) => { const actionLink = config?.editorConfig?.actionLink || null; return { - props: { - fileInfo, - docApiUrl, - config, - personal, - successAuth, - user, - error, - actionLink, - isSharingAccess, - url, - doc, - fileId, - view, - }, + fileInfo, + docApiUrl, + config, + personal, + successAuth, + user, + error, + actionLink, + isSharingAccess, + url, + doc, + fileId, + view, }; } catch (err) { error = { errorMessage: typeof err === "string" ? err : err.message }; diff --git a/web/ASC.Web.Editor/src/server/app.js b/web/ASC.Web.Editor/src/server/app.js deleted file mode 100644 index 54a624506e..0000000000 --- a/web/ASC.Web.Editor/src/server/app.js +++ /dev/null @@ -1,140 +0,0 @@ -const express = require("express"); -const fs = require("fs"); -const path = require("path"); -const React = require("react"); -const ReactDOMServer = require("react-dom/server"); -const compression = require("compression"); -const i18nextMiddleware = require("i18next-express-middleware"); -const i18next = require("i18next"); -const Backend = require("i18next-fs-backend"); -const process = require("process"); -const { ServerStyleSheet } = require("styled-components"); -const pkg = require("../../package.json"); -const title = pkg.title; -const { App } = require("../client/App"); -const initDocEditor = require("./lib/initDocEditor"); - -const loadPath = (lng, ns) => { - let resourcePath = path.resolve( - process.cwd(), - `dist/locales/${lng}/${ns}.json` - ); - if (ns === "Common") - resourcePath = path.join( - __dirname, - `../../../../public/locales/${lng}/${ns}.json` - ); - - return resourcePath; -}; - -const app = express(); -const port = process.env.PORT || 5013; - -i18next.use(Backend).init({ - backend: { - loadPath: loadPath, - allowMultiLoading: true, - crossDomain: false, - }, - fallbackLng: "en", - load: "currentOnly", - - saveMissing: true, - ns: ["Editor", "Common"], - defaultNS: "Editor", - - interpolation: { - escapeValue: false, // not needed for react as it escapes by default - format: function (value, format) { - if (format === "lowercase") return value.toLowerCase(); - return value; - }, - }, -}); - -app.set("view engine", "ejs"); -app.set("views", path.join(__dirname, "views")); - -// app.get( -// /\.(js|css|map|ico)$/, -// express.static(path.resolve(process.cwd(), "dist")) -// ); - -app.use(i18nextMiddleware.handle(i18next)); -app.use(compression()); - -app.use( - "/products/files/doceditor/", - express.static(path.resolve(process.cwd(), "dist")) -); -//app.use(express.static(path.resolve(process.cwd(), "dist"))); - -app.get("/products/files/doceditor", async (req, res) => { - const manifest = fs.readFileSync( - path.join(process.cwd(), "dist/manifest.json"), - "utf-8" - ); - const initialState = await initDocEditor(req); - - const assets = JSON.parse(manifest); - const sheet = new ServerStyleSheet(); - const component = ReactDOMServer.renderToString( - sheet.collectStyles(React.createElement(App)) - ); - const styleTags = sheet.getStyleTags(); - const userLng = initialState?.props?.user?.cultureName || "en"; - const initialI18nStore = {}; - - i18next.changeLanguage(userLng).then(() => { - const initialLanguage = userLng; - const usedNamespaces = req.i18n.reportNamespaces - ? req.i18n.reportNamespaces.getUsedNamespaces() - : ["Common", "Editor"]; - - initialI18nStore[initialLanguage] = {}; - usedNamespaces.forEach((namespace) => { - initialI18nStore[initialLanguage][namespace] = - req.i18n.services.resourceStore.data[initialLanguage][namespace]; - }); - - const parsedI18nStore = JSON.stringify(initialI18nStore); - const parsedInitialState = JSON.stringify(initialState); - const docApiUrl = initialState?.props?.docApiUrl || ""; - - res.render("editor", { - assets, - component, - title, - parsedI18nStore, - initialLanguage, - parsedInitialState, - docApiUrl, - styleTags, - }); - }); -}); - -const server = app.listen(port, () => { - console.log(`Server is listening on port `); -}); - -if (process.env.NODE_ENV === "development") { - const ws = require("./websocket"); - - const wss = ws(server); - const manifestFile = path.resolve(process.cwd(), "dist/manifest.json"); - - let fsWait = false; - fs.watch(manifestFile, (event, filename) => { - if (filename && event === "change") { - if (fsWait) return; - fsWait = true; - fsWait = setTimeout(() => { - fsWait = false; - }, 100); - - wss.broadcast("reload"); - } - }); -} diff --git a/web/ASC.Web.Editor/src/server/index.js b/web/ASC.Web.Editor/src/server/index.js index e077cbd9ee..6e1e27cb51 100644 --- a/web/ASC.Web.Editor/src/server/index.js +++ b/web/ASC.Web.Editor/src/server/index.js @@ -1,107 +1,104 @@ -// import express from "express"; -// import template from "./template"; -// import render from "./render"; -// import i18nextMiddleware from "i18next-express-middleware"; -// import i18next from "i18next"; -// import Backend from "i18next-fs-backend"; -// import path from "path"; -// import compression from "compression"; -// // import webpack from "webpack"; -// // import WebpackDevMiddleware from "webpack-dev-middleware"; -// // import WebpackHotMiddleware from "webpack-hot-middleware"; +import express from "express"; +import template from "./render"; +import initMiddleware from "./initMiddleware"; +import i18nextMiddleware from "i18next-express-middleware"; +import i18next from "i18next"; +import Backend from "i18next-fs-backend"; +import path from "path"; +import compression from "compression"; +import ws from "./websocket"; +import fs from "fs"; -// const loadPath = (lng, ns) => { -// let resourcePath = -// path.resolve(process.cwd(), "dist/client") + `/locales/${lng}/${ns}.json`; -// if (ns === "Common") -// resourcePath = path.join( -// __dirname, -// `../../../../public/locales/${lng}/${ns}.json` -// ); +const loadPath = (lng, ns) => { + let resourcePath = + path.resolve(process.cwd(), "dist/client") + `/locales/${lng}/${ns}.json`; + if (ns === "Common") + resourcePath = path.resolve( + process.cwd(), + `../../public/locales/${lng}/${ns}.json` + ); -// return resourcePath; -// }; + return resourcePath; +}; -// const app = express(); -// const port = process.env.PORT || 5013; +const port = PORT || 5013; +const app = express(); -// i18next.use(Backend).init({ -// backend: { -// loadPath: loadPath, -// allowMultiLoading: true, -// crossDomain: false, -// }, -// fallbackLng: "en", -// load: "currentOnly", +i18next.use(Backend).init({ + backend: { + loadPath: loadPath, + allowMultiLoading: true, + crossDomain: false, + }, + fallbackLng: "en", + load: "currentOnly", -// saveMissing: true, -// ns: ["Editor", "Common"], -// defaultNS: "Editor", + saveMissing: true, + ns: ["Editor", "Common"], + defaultNS: "Editor", -// interpolation: { -// escapeValue: false, // not needed for react as it escapes by default -// format: function (value, format) { -// if (format === "lowercase") return value.toLowerCase(); -// return value; -// }, -// }, -// }); - -// // if (process.env.NODE_ENV === "development") { -// // const webpackConfig = require("../../webpack/dev/webpack.dev.client.js"); -// // const compiler = webpack(webpackConfig); -// // app.use( -// // WebpackDevMiddleware(compiler, { -// // publicPath: webpackConfig.output.publicPath, -// // serverSideRender: true, -// // }) -// // ); - -// // -// // } - -// app.use(i18nextMiddleware.handle(i18next)); -// app.use(compression()); -// app.use( -// "/products/files/doceditor/static/", -// express.static(path.resolve(__dirname, "../../dist/client/static")) -// ); -// app.use(express.static(path.resolve(__dirname, "../../dist/client"))); - -// app.get("/products/files/doceditor", async (req, res) => { -// const { props, content, styleTags, extractor } = await render(req); -// const userLng = props?.user?.cultureName || "en"; -// const initialI18nStore = {}; - -// i18next.changeLanguage(userLng).then(() => { -// const initialLanguage = userLng; - -// const usedNamespaces = req.i18n.reportNamespaces.getUsedNamespaces(); - -// initialI18nStore[initialLanguage] = {}; -// usedNamespaces.forEach((namespace) => { -// initialI18nStore[initialLanguage][namespace] = -// req.i18n.services.resourceStore.data[initialLanguage][namespace]; -// }); -// const response = template( -// props, -// content, -// styleTags, -// initialI18nStore, -// initialLanguage, -// extractor -// ); - -// res.send(response); -// }); -// }); - -// app.listen(port, () => { -// console.log(`Server is listening on port ${port}`); -// }); -const path = require("path"); - -require("@babel/register")({ - configFile: path.resolve(__dirname, "../../babel.config.js"), + interpolation: { + escapeValue: false, + format: function (value, format) { + if (format === "lowercase") return value.toLowerCase(); + return value; + }, + }, }); -require("./app.js"); + +app.use(i18nextMiddleware.handle(i18next)); +app.use(compression()); +app.use( + "/products/files/doceditor/static/", + express.static(path.resolve(process.cwd(), "dist/client/static")) +); +app.use(express.static(path.resolve(process.cwd(), "dist/client"))); +app.use(initMiddleware); +app.get("/products/files/doceditor", async (req, res) => { + const { i18n, initialState, appComponent, styleTags, assets } = req; + const userLng = initialState?.user?.cultureName || "en"; + const initialI18nStore = {}; + + await i18next.changeLanguage(userLng); + const usedNamespaces = i18n.reportNamespaces.getUsedNamespaces(); + + initialI18nStore[userLng] = {}; + usedNamespaces.forEach((namespace) => { + initialI18nStore[namespace] = + i18n.services.resourceStore.data[userLng][namespace]; + }); + + const htmlString = template( + initialState, + appComponent, + styleTags, + initialI18nStore, + userLng, + assets + ); + + res.send(htmlString); +}); + +const server = app.listen(port, () => { + console.log(`Server is listening on port ${port}`); +}); + +if (IS_DEVELOPMENT) { + const wss = ws(server); + + const manifestFile = path.resolve(process.cwd(), "dist/client/manifest.json"); + + let fsWait = false; + fs.watch(manifestFile, (event, filename) => { + if (filename && event === "change") { + if (fsWait) return; + fsWait = true; + fsWait = setTimeout(() => { + fsWait = false; + }, 100); + + wss.broadcast("reload"); + } + }); +} diff --git a/web/ASC.Web.Editor/src/server/initMiddleware.js b/web/ASC.Web.Editor/src/server/initMiddleware.js new file mode 100644 index 0000000000..bc464a9fc7 --- /dev/null +++ b/web/ASC.Web.Editor/src/server/initMiddleware.js @@ -0,0 +1,56 @@ +import React from "react"; +import { renderToString } from "react-dom/server"; +import App from "../client/Editor.js"; +import { initDocEditor } from "../helpers/utils"; +import { ServerStyleSheet, createGlobalStyle } from "styled-components"; +import path from "path"; +import { I18nextProvider } from "react-i18next"; +import fs from "fs"; + +const GlobalStyle = createGlobalStyle` + html, + body { + height: 100%; + } + + #root { + min-height: 100%; + + .pageLoader { + position: fixed; + left: calc(50% - 20px); + top: 35%; + } + } + body { + margin: 0; + } + + body.loading * { + cursor: wait !important; + } +`; + +const sheet = new ServerStyleSheet(); + +export default async (req, res, next) => { + const manifest = fs.readFileSync( + path.join(process.cwd(), "dist/client/manifest.json"), + "utf-8" + ); + + req.initialState = await initDocEditor(req); + req.assets = JSON.parse(manifest); + + req.appComponent = renderToString( + sheet.collectStyles( + + + + + ) + ); + req.styleTags = sheet.getStyleTags(); + + next(); +}; diff --git a/web/ASC.Web.Editor/src/server/lib/api/encoder.js b/web/ASC.Web.Editor/src/server/lib/api/encoder.js deleted file mode 100644 index e9435cefb3..0000000000 --- a/web/ASC.Web.Editor/src/server/lib/api/encoder.js +++ /dev/null @@ -1,1144 +0,0 @@ -module.exports = { - EncodeType: "entity", - isEmpty: function (val) { - if (val) { - return val === null || val.length == 0 || /^\s+$/.test(val); - } else { - return true; - } - }, - HTML2Numerical: function (s) { - var arr1 = new Array( - " ", - "¡", - "¢", - "£", - "¤", - "¥", - "¦", - "§", - "¨", - "©", - "ª", - "«", - "¬", - "­", - "®", - "¯", - "°", - "±", - "²", - "³", - "´", - "µ", - "¶", - "·", - "¸", - "¹", - "º", - "»", - "¼", - "½", - "¾", - "¿", - "à", - "á", - "â", - "ã", - "Ä", - "å", - "æ", - "ç", - "è", - "é", - "ê", - "ë", - "ì", - "í", - "î", - "ï", - "ð", - "ñ", - "ò", - "ó", - "ô", - "õ", - "Ö", - "×", - "ø", - "ù", - "ú", - "û", - "Ü", - "ý", - "þ", - "ß", - "à", - "á", - "â", - "ã", - "ä", - "å", - "æ", - "ç", - "è", - "é", - "ê", - "ë", - "ì", - "í", - "î", - "ï", - "ð", - "ñ", - "ò", - "ó", - "ô", - "õ", - "ö", - "÷", - "Ø", - "ù", - "ú", - "û", - "ü", - "ý", - "þ", - "ÿ", - """, - "&", - "<", - ">", - "œ", - "œ", - "š", - "š", - "ÿ", - "ˆ", - "˜", - " ", - " ", - " ", - "‌", - "‍", - "‎", - "‏", - "–", - "—", - "‘", - "’", - "‚", - "“", - "”", - "„", - "†", - "†", - "‰", - "‹", - "›", - "€", - "ƒ", - "α", - "β", - "γ", - "δ", - "ε", - "ζ", - "η", - "θ", - "ι", - "κ", - "λ", - "μ", - "ν", - "ξ", - "ο", - "π", - "ρ", - "σ", - "τ", - "υ", - "φ", - "χ", - "ψ", - "ω", - "α", - "β", - "γ", - "δ", - "ε", - "ζ", - "η", - "θ", - "ι", - "κ", - "λ", - "μ", - "ν", - "ξ", - "ο", - "π", - "ρ", - "ς", - "σ", - "τ", - "υ", - "φ", - "χ", - "ψ", - "ω", - "ϑ", - "ϒ", - "ϖ", - "•", - "…", - "′", - "′", - "‾", - "⁄", - "℘", - "ℑ", - "ℜ", - "™", - "ℵ", - "←", - "↑", - "→", - "↓", - "↔", - "↵", - "←", - "↑", - "→", - "↓", - "↔", - "∀", - "∂", - "∃", - "∅", - "∇", - "∈", - "∉", - "∋", - "∏", - "∑", - "−", - "∗", - "√", - "∝", - "∞", - "∠", - "∧", - "∨", - "∩", - "∪", - "∫", - "∴", - "∼", - "≅", - "≈", - "≠", - "≡", - "≤", - "≥", - "⊂", - "⊃", - "⊄", - "⊆", - "⊇", - "⊕", - "⊗", - "⊥", - "⋅", - "⌈", - "⌉", - "⌊", - "⌋", - "⟨", - "⟩", - "◊", - "♠", - "♣", - "♥", - "♦" - ); - var arr2 = new Array( - " ", - "¡", - "¢", - "£", - "¤", - "¥", - "¦", - "§", - "¨", - "©", - "ª", - "«", - "¬", - "­", - "®", - "¯", - "°", - "±", - "²", - "³", - "´", - "µ", - "¶", - "·", - "¸", - "¹", - "º", - "»", - "¼", - "½", - "¾", - "¿", - "À", - "Á", - "Â", - "Ã", - "Ä", - "Å", - "Æ", - "Ç", - "È", - "É", - "Ê", - "Ë", - "Ì", - "Í", - "Î", - "Ï", - "Ð", - "Ñ", - "Ò", - "Ó", - "Ô", - "Õ", - "Ö", - "×", - "Ø", - "Ù", - "Ú", - "Û", - "Ü", - "Ý", - "Þ", - "ß", - "à", - "á", - "â", - "ã", - "ä", - "å", - "æ", - "ç", - "è", - "é", - "ê", - "ë", - "ì", - "í", - "î", - "ï", - "ð", - "ñ", - "ò", - "ó", - "ô", - "õ", - "ö", - "÷", - "ø", - "ù", - "ú", - "û", - "ü", - "ý", - "þ", - "ÿ", - """, - "&", - "<", - ">", - "Œ", - "œ", - "Š", - "š", - "Ÿ", - "ˆ", - "˜", - " ", - " ", - " ", - "‌", - "‍", - "‎", - "‏", - "–", - "—", - "‘", - "’", - "‚", - "“", - "”", - "„", - "†", - "‡", - "‰", - "‹", - "›", - "€", - "ƒ", - "Α", - "Β", - "Γ", - "Δ", - "Ε", - "Ζ", - "Η", - "Θ", - "Ι", - "Κ", - "Λ", - "Μ", - "Ν", - "Ξ", - "Ο", - "Π", - "Ρ", - "Σ", - "Τ", - "Υ", - "Φ", - "Χ", - "Ψ", - "Ω", - "α", - "β", - "γ", - "δ", - "ε", - "ζ", - "η", - "θ", - "ι", - "κ", - "λ", - "μ", - "ν", - "ξ", - "ο", - "π", - "ρ", - "ς", - "σ", - "τ", - "υ", - "φ", - "χ", - "ψ", - "ω", - "ϑ", - "ϒ", - "ϖ", - "•", - "…", - "′", - "″", - "‾", - "⁄", - "℘", - "ℑ", - "ℜ", - "™", - "ℵ", - "←", - "↑", - "→", - "↓", - "↔", - "↵", - "⇐", - "⇑", - "⇒", - "⇓", - "⇔", - "∀", - "∂", - "∃", - "∅", - "∇", - "∈", - "∉", - "∋", - "∏", - "∑", - "−", - "∗", - "√", - "∝", - "∞", - "∠", - "∧", - "∨", - "∩", - "∪", - "∫", - "∴", - "∼", - "≅", - "≈", - "≠", - "≡", - "≤", - "≥", - "⊂", - "⊃", - "⊄", - "⊆", - "⊇", - "⊕", - "⊗", - "⊥", - "⋅", - "⌈", - "⌉", - "⌊", - "⌋", - "〈", - "〉", - "◊", - "♠", - "♣", - "♥", - "♦" - ); - return this.swapArrayVals(s, arr1, arr2); - }, - NumericalToHTML: function (s) { - var arr1 = new Array( - " ", - "¡", - "¢", - "£", - "¤", - "¥", - "¦", - "§", - "¨", - "©", - "ª", - "«", - "¬", - "­", - "®", - "¯", - "°", - "±", - "²", - "³", - "´", - "µ", - "¶", - "·", - "¸", - "¹", - "º", - "»", - "¼", - "½", - "¾", - "¿", - "À", - "Á", - "Â", - "Ã", - "Ä", - "Å", - "Æ", - "Ç", - "È", - "É", - "Ê", - "Ë", - "Ì", - "Í", - "Î", - "Ï", - "Ð", - "Ñ", - "Ò", - "Ó", - "Ô", - "Õ", - "Ö", - "×", - "Ø", - "Ù", - "Ú", - "Û", - "Ü", - "Ý", - "Þ", - "ß", - "à", - "á", - "â", - "ã", - "ä", - "å", - "æ", - "ç", - "è", - "é", - "ê", - "ë", - "ì", - "í", - "î", - "ï", - "ð", - "ñ", - "ò", - "ó", - "ô", - "õ", - "ö", - "÷", - "ø", - "ù", - "ú", - "û", - "ü", - "ý", - "þ", - "ÿ", - """, - "&", - "<", - ">", - "Œ", - "œ", - "Š", - "š", - "Ÿ", - "ˆ", - "˜", - " ", - " ", - " ", - "‌", - "‍", - "‎", - "‏", - "–", - "—", - "‘", - "’", - "‚", - "“", - "”", - "„", - "†", - "‡", - "‰", - "‹", - "›", - "€", - "ƒ", - "Α", - "Β", - "Γ", - "Δ", - "Ε", - "Ζ", - "Η", - "Θ", - "Ι", - "Κ", - "Λ", - "Μ", - "Ν", - "Ξ", - "Ο", - "Π", - "Ρ", - "Σ", - "Τ", - "Υ", - "Φ", - "Χ", - "Ψ", - "Ω", - "α", - "β", - "γ", - "δ", - "ε", - "ζ", - "η", - "θ", - "ι", - "κ", - "λ", - "μ", - "ν", - "ξ", - "ο", - "π", - "ρ", - "ς", - "σ", - "τ", - "υ", - "φ", - "χ", - "ψ", - "ω", - "ϑ", - "ϒ", - "ϖ", - "•", - "…", - "′", - "″", - "‾", - "⁄", - "℘", - "ℑ", - "ℜ", - "™", - "ℵ", - "←", - "↑", - "→", - "↓", - "↔", - "↵", - "⇐", - "⇑", - "⇒", - "⇓", - "⇔", - "∀", - "∂", - "∃", - "∅", - "∇", - "∈", - "∉", - "∋", - "∏", - "∑", - "−", - "∗", - "√", - "∝", - "∞", - "∠", - "∧", - "∨", - "∩", - "∪", - "∫", - "∴", - "∼", - "≅", - "≈", - "≠", - "≡", - "≤", - "≥", - "⊂", - "⊃", - "⊄", - "⊆", - "⊇", - "⊕", - "⊗", - "⊥", - "⋅", - "⌈", - "⌉", - "⌊", - "⌋", - "〈", - "〉", - "◊", - "♠", - "♣", - "♥", - "♦" - ); - var arr2 = new Array( - " ", - "¡", - "¢", - "£", - "¤", - "¥", - "¦", - "§", - "¨", - "©", - "ª", - "«", - "¬", - "­", - "®", - "¯", - "°", - "±", - "²", - "³", - "´", - "µ", - "¶", - "·", - "¸", - "¹", - "º", - "»", - "¼", - "½", - "¾", - "¿", - "à", - "á", - "â", - "ã", - "Ä", - "å", - "æ", - "ç", - "è", - "é", - "ê", - "ë", - "ì", - "í", - "î", - "ï", - "ð", - "ñ", - "ò", - "ó", - "ô", - "õ", - "Ö", - "×", - "ø", - "ù", - "ú", - "û", - "Ü", - "ý", - "þ", - "ß", - "à", - "á", - "â", - "ã", - "ä", - "å", - "æ", - "ç", - "è", - "é", - "ê", - "ë", - "ì", - "í", - "î", - "ï", - "ð", - "ñ", - "ò", - "ó", - "ô", - "õ", - "ö", - "÷", - "Ø", - "ù", - "ú", - "û", - "ü", - "ý", - "þ", - "ÿ", - """, - "&", - "<", - ">", - "œ", - "œ", - "š", - "š", - "ÿ", - "ˆ", - "˜", - " ", - " ", - " ", - "‌", - "‍", - "‎", - "‏", - "–", - "—", - "‘", - "’", - "‚", - "“", - "”", - "„", - "†", - "†", - "‰", - "‹", - "›", - "€", - "ƒ", - "α", - "β", - "γ", - "δ", - "ε", - "ζ", - "η", - "θ", - "ι", - "κ", - "λ", - "μ", - "ν", - "ξ", - "ο", - "π", - "ρ", - "σ", - "τ", - "υ", - "φ", - "χ", - "ψ", - "ω", - "α", - "β", - "γ", - "δ", - "ε", - "ζ", - "η", - "θ", - "ι", - "κ", - "λ", - "μ", - "ν", - "ξ", - "ο", - "π", - "ρ", - "ς", - "σ", - "τ", - "υ", - "φ", - "χ", - "ψ", - "ω", - "ϑ", - "ϒ", - "ϖ", - "•", - "…", - "′", - "′", - "‾", - "⁄", - "℘", - "ℑ", - "ℜ", - "™", - "ℵ", - "←", - "↑", - "→", - "↓", - "↔", - "↵", - "←", - "↑", - "→", - "↓", - "↔", - "∀", - "∂", - "∃", - "∅", - "∇", - "∈", - "∉", - "∋", - "∏", - "∑", - "−", - "∗", - "√", - "∝", - "∞", - "∠", - "∧", - "∨", - "∩", - "∪", - "∫", - "∴", - "∼", - "≅", - "≈", - "≠", - "≡", - "≤", - "≥", - "⊂", - "⊃", - "⊄", - "⊆", - "⊇", - "⊕", - "⊗", - "⊥", - "⋅", - "⌈", - "⌉", - "⌊", - "⌋", - "⟨", - "⟩", - "◊", - "♠", - "♣", - "♥", - "♦" - ); - return this.swapArrayVals(s, arr1, arr2); - }, - numEncode: function (s) { - if (this.isEmpty(s)) return ""; - var e = ""; - for (var i = 0; i < s.length; i++) { - var c = s.charAt(i); - if (c < " " || c > "~") { - c = "&#" + c.charCodeAt() + ";"; - } - e += c; - } - return e; - }, - htmlDecode: function (s) { - var c, - m, - d = s; - if (this.isEmpty(d)) return ""; - d = this.HTML2Numerical(d); - const arr = d.match(/&#[0-9]{1,5};/g); - if (arr != null) { - for (var x = 0; x < arr.length; x++) { - m = arr[x]; - c = m.substring(2, m.length - 1); - if (c >= -32768 && c <= 65535) { - d = d.replace(m, String.fromCharCode(c)); - } else { - d = d.replace(m, ""); - } - } - } - return d; - }, - htmlEncode: function (s, dbl) { - if (this.isEmpty(s)) return ""; - dbl = dbl | false; - if (dbl) { - if (this.EncodeType == "numerical") { - s = s.replace(/&/g, "&"); - } else { - s = s.replace(/&/g, "&"); - } - } - s = this.XSSEncode(s, false); - if (this.EncodeType == "numerical" || !dbl) { - s = this.HTML2Numerical(s); - } - s = this.numEncode(s); - if (!dbl) { - s = s.replace(/&#/g, "##AMPHASH##"); - if (this.EncodeType == "numerical") { - s = s.replace(/&/g, "&"); - } else { - s = s.replace(/&/g, "&"); - } - s = s.replace(/##AMPHASH##/g, "&#"); - } - s = s.replace(/&#\d*([^\d;]|$)/g, "$1"); - if (!dbl) { - s = this.correctEncoding(s); - } - if (this.EncodeType == "entity") { - s = this.NumericalToHTML(s); - } - return s; - }, - XSSEncode: function (s, en) { - if (!this.isEmpty(s)) { - en = en || true; - if (en) { - s = s.replace(/\'/g, "'"); - s = s.replace(/\"/g, """); - s = s.replace(//g, ">"); - } else { - s = s.replace(/\'/g, "'"); - s = s.replace(/\"/g, """); - s = s.replace(//g, ">"); - } - return s; - } else { - return ""; - } - }, - hasEncoded: function (s) { - if (/&#[0-9]{1,5};/g.test(s)) { - return true; - } else if (/&[A-Z]{2,6};/gi.test(s)) { - return true; - } else { - return false; - } - }, - stripUnicode: function (s) { - return s.replace(/[^\x20-\x7E]/g, ""); - }, - correctEncoding: function (s) { - return s.replace(/(&)(amp;)+/, "$1"); - }, - swapArrayVals: function (s, arr1, arr2) { - if (this.isEmpty(s)) return ""; - var re; - if (arr1 && arr2) { - if (arr1.length == arr2.length) { - for (var x = 0, i = arr1.length; x < i; x++) { - re = new RegExp(arr1[x], "g"); - s = s.replace(re, arr2[x]); - } - } - } - return s; - }, -}; diff --git a/web/ASC.Web.Editor/src/server/lib/api/init.js b/web/ASC.Web.Editor/src/server/lib/api/init.js deleted file mode 100644 index 79e2cf6556..0000000000 --- a/web/ASC.Web.Editor/src/server/lib/api/init.js +++ /dev/null @@ -1,63 +0,0 @@ -const request = require("./requestManager"); -const Encoder = require("./encoder"); -exports.getDocServiceUrl = (headers) => { - return request({ method: "get", url: `/files/docservice`, headers }); -}; - -exports.getFileInfo = (fileId, headers) => { - const options = { - method: "get", - url: `/files/file/${fileId}`, - headers, - }; - - return request(options); -}; - -exports.openEdit = (fileId, version, doc, view, headers) => { - const params = []; // doc ? `?doc=${doc}` : ""; - - if (view) { - params.push(`view=${view}`); - } - - if (version) { - params.push(`version=${version}`); - } - - if (doc) { - params.push(`doc=${doc}`); - } - - const paramsString = params.length > 0 ? `?${params.join("&")}` : ""; - - const options = { - method: "get", - url: `/files/file/${fileId}/openedit${paramsString}`, - headers, - }; - - return request(options); -}; - -exports.getSettings = (headers) => { - return request({ - method: "get", - url: "/settings.json", - headers, - }); -}; - -exports.getUser = (userName = null, headers) => { - return request({ - method: "get", - url: `/people/${userName || "@self"}.json`, - skipUnauthorized: true, - headers, - }).then((user) => { - if (user && user.displayName) { - user.displayName = Encoder.htmlDecode(user.displayName); - } - return user; - }); -}; diff --git a/web/ASC.Web.Editor/src/server/lib/api/requestManager.js b/web/ASC.Web.Editor/src/server/lib/api/requestManager.js deleted file mode 100644 index aad855044e..0000000000 --- a/web/ASC.Web.Editor/src/server/lib/api/requestManager.js +++ /dev/null @@ -1,48 +0,0 @@ -const axios = require("axios"); -const apiPrefixURL = "/api/2.0"; -const apiTimeout = 30000; - -module.exports = (options) => { - const basePath = options.basePath; - const xRewriterUrl = options.headers["x-rewriter-url"]; - const url = `${xRewriterUrl}${apiPrefixURL}${options.url}`; - - const axiosOptions = { - baseURL: url, - responseType: "json", - timeout: apiTimeout, - headers: options.headers, - }; - - const getResponseError = (res) => { - if (!res) return; - - if (res.data && res.data.error) { - return res.data.error.message; - } - - if (res.isAxiosError && res.message) { - return res.message; - } - }; - - const onSuccess = (response) => { - const error = getResponseError(response); - if (error) throw new Error(error); - - if (!response || !response.data || response.isAxiosError) return null; - if (response.request.responseType === "text") return response.data; - - return response.data.response; - }; - - const onError = (error) => { - const errorText = error.response - ? getResponseError(error.response) - : error.message; - return Promise.reject(errorText || error); - }; - - const request = axios.create(axiosOptions); - return request().then(onSuccess).catch(onError); -}; diff --git a/web/ASC.Web.Editor/src/server/lib/initDocEditor.js b/web/ASC.Web.Editor/src/server/lib/initDocEditor.js deleted file mode 100644 index 87df4c40f4..0000000000 --- a/web/ASC.Web.Editor/src/server/lib/initDocEditor.js +++ /dev/null @@ -1,110 +0,0 @@ -const { - getDocServiceUrl, - getFileInfo, - openEdit, - getUser, - getSettings, -} = require("./api/init"); - -const combineUrl = (host = "", ...params) => { - let url = host.replace(/\/+$/, ""); - - params.forEach((part) => { - const newPart = part.trim().replace(/^\/+/, ""); - url += newPart - ? url.length > 0 && url[url.length - 1] === "/" - ? newPart - : `/${newPart}` - : ""; - }); - - return url; -}; - -module.exports = async (req) => { - if (!req) return false; - - const { headers, url, query } = req; - const { version, desktop: isDesktop } = query; - let error = null; - - try { - const decodedId = query.fileId || query.fileid || null; - const fileId = - typeof decodedId === "string" ? encodeURIComponent(decodedId) : decodedId; - - if (!fileId) { - return { - props: { - needLoader: true, - }, - }; - } - - const doc = query?.doc || null; - const view = url.indexOf("action=view") !== -1; - const fileVersion = version || null; - - const [user, settings] = await Promise.all([ - getUser(null, headers), - getSettings(headers), - ]); - - const successAuth = !!user; - const personal = settings?.personal; - - if (!successAuth && !doc) { - error = { - unAuthorized: true, - redirectPath: combineUrl( - "", //AppServerConfig.proxyURL, - personal ? "/sign-in" : "/login" - ), - }; - return { - props: { - error, - }, - }; - } - - let [config, docApiUrl, fileInfo] = await Promise.all([ - openEdit(fileId, fileVersion, doc, view, headers), - getDocServiceUrl(headers), - getFileInfo(fileId, headers), - ]); - - const isSharingAccess = fileInfo && fileInfo.canShare; - - if (view) { - config.editorConfig.mode = "view"; - } - - const actionLink = config?.editorConfig?.actionLink || null; - - return { - props: { - fileInfo, - docApiUrl, - config, - personal, - successAuth, - user, - error, - actionLink, - isSharingAccess, - url, - doc, - fileId, - view, - }, - }; - } catch (err) { - error = { errorMessage: typeof err === "string" ? err : err.message }; - return { - props: { - error, - }, - }; - } -}; diff --git a/web/ASC.Web.Editor/src/server/render.js b/web/ASC.Web.Editor/src/server/render.js index 54acd6cd4d..4f408fce46 100644 --- a/web/ASC.Web.Editor/src/server/render.js +++ b/web/ASC.Web.Editor/src/server/render.js @@ -1,57 +1,372 @@ -import React from "react"; -import { renderToString } from "react-dom/server"; -import App from "../client/Editor.js"; -import { initDocEditor } from "../helpers/utils"; -import { ServerStyleSheet, createGlobalStyle } from "styled-components"; -import { ChunkExtractor, ChunkExtractorManager } from "@loadable/server"; -import path from "path"; -import { I18nextProvider } from "react-i18next"; +import { getFavicon } from "../helpers/utils"; +import pkg from "../../package.json"; -const GlobalStyle = createGlobalStyle` - html, - body { - height: 100%; - } +export default function template( + initialState = {}, + appComponent = "", + styleTags, + initialI18nStore, + initialLanguage, + assets +) { + const { title } = pkg; + const { docApiUrl } = initialState; + const faviconHref = getFavicon(initialState?.config?.documentType); - #root { - min-height: 100%; + const scripts = ` + + + + + + `; + // + // + const page = ` + + + + + ${title} + + + + + + + + + ${styleTags} + + + +
${appComponent}
+ +
+
+
+
+
+
+
+
+
+ ${scripts} -const sheet = new ServerStyleSheet(); -const loadableJson = path.resolve(__dirname, "./client/loadable-stats.json"); -export default async (req) => { - const props = await initDocEditor(req); + + + `; - const extractor = new ChunkExtractor({ - statsFile: loadableJson, - entrypoints: ["client"], - }); - - const content = renderToString( - sheet.collectStyles( - - - - - - - ) - ); - const styleTags = sheet.getStyleTags(); - - return { ...props, content, styleTags, extractor }; -}; + return page; +} diff --git a/web/ASC.Web.Editor/src/server/template.js b/web/ASC.Web.Editor/src/server/template.js deleted file mode 100644 index 5a15e34ab3..0000000000 --- a/web/ASC.Web.Editor/src/server/template.js +++ /dev/null @@ -1,56 +0,0 @@ -import { getFavicon } from "../helpers/utils"; -import pkg from "../../package.json"; - -export default function template( - initialState = {}, - content = "", - styleTags, - //scriptTags, - initialI18nStore, - initialLanguage, - extractor -) { - const { title } = pkg; - const { docApiUrl } = initialState; - const faviconHref = getFavicon(initialState?.config?.documentType); - - const scripts = ` - - - - ${extractor.getScriptTags()} -`; - - const page = ` - - - - - ${title} - - - - - - - - - ${styleTags} - - -
${content}
- ${scripts} - - - `; - - return page; -} diff --git a/web/ASC.Web.Editor/src/server/views/editor.ejs b/web/ASC.Web.Editor/src/server/views/editor.ejs deleted file mode 100644 index e84f948360..0000000000 --- a/web/ASC.Web.Editor/src/server/views/editor.ejs +++ /dev/null @@ -1,351 +0,0 @@ - - - - <%- styleTags %> - - - - - - - - - - - - - - <%- title %> - - - -
-
-
-
-
-
-
-
-
-
<%- component %>
- - - - - - - \ No newline at end of file