From a9ab196a18b14f0e0dcbeb73df966c9db4ee1037 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Tue, 11 Jul 2023 20:40:48 -0400 Subject: [PATCH 001/144] fix: Guard against empty attachment size I don't see how this can happen based on default props, but it does --- shared/editor/nodes/Attachment.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/editor/nodes/Attachment.tsx b/shared/editor/nodes/Attachment.tsx index 3e889e4fa9a1..e0e51c9161bc 100644 --- a/shared/editor/nodes/Attachment.tsx +++ b/shared/editor/nodes/Attachment.tsx @@ -86,7 +86,7 @@ export default class Attachment extends Node { onMouseDown={this.handleSelect(props)} context={ node.attrs.href ? ( - bytesToHumanReadable(node.attrs.size) + bytesToHumanReadable(node.attrs.size || "0") ) : ( <> Uploading… From 5c830709416de04e669fb50b2e2845be757ef322 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Tue, 11 Jul 2023 21:28:38 -0400 Subject: [PATCH 002/144] fix: Pasting rich text into image caption inherits styling --- shared/editor/nodes/Image.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/shared/editor/nodes/Image.tsx b/shared/editor/nodes/Image.tsx index c2186a95c0eb..5b825b3b2f4c 100644 --- a/shared/editor/nodes/Image.tsx +++ b/shared/editor/nodes/Image.tsx @@ -215,6 +215,14 @@ export default class Image extends SimpleImage { void downloadImageNode(node); }; + // Ensure only plain text can be pasted into input when pasting from another + // rich text source. + handlePaste = (event: React.ClipboardEvent) => { + event.preventDefault(); + const text = event.clipboardData.getData("text/plain"); + window.document.execCommand("insertText", false, text); + }; + component = (props: ComponentProps) => ( Date: Fri, 14 Jul 2023 21:46:31 -0400 Subject: [PATCH 003/144] fix: Remove no longer required unescaping, closes #5555 --- server/models/helpers/DocumentHelper.tsx | 3 +-- server/models/helpers/SearchHelper.ts | 3 +-- shared/utils/parseTitle.test.ts | 5 ----- shared/utils/parseTitle.ts | 6 +----- shared/utils/unescape.ts | 4 ---- 5 files changed, 3 insertions(+), 18 deletions(-) delete mode 100644 shared/utils/unescape.ts diff --git a/server/models/helpers/DocumentHelper.tsx b/server/models/helpers/DocumentHelper.tsx index c4e520980211..ad734f94fa45 100644 --- a/server/models/helpers/DocumentHelper.tsx +++ b/server/models/helpers/DocumentHelper.tsx @@ -13,7 +13,6 @@ import { getCurrentTimeAsString, unicodeCLDRtoBCP47, } from "@shared/utils/date"; -import unescape from "@shared/utils/unescape"; import { parser, schema } from "@server/editor"; import { trace } from "@server/logging/tracing"; import type Document from "@server/models/Document"; @@ -83,7 +82,7 @@ export default class DocumentHelper { * @returns The document title and content as a Markdown string */ static toMarkdown(document: Document | Revision) { - const text = unescape(document.text); + const text = document.text.replace(/\n\\\n/g, "\n\n"); if (document.version) { return `# ${document.title}\n\n${text}`; diff --git a/server/models/helpers/SearchHelper.ts b/server/models/helpers/SearchHelper.ts index 1ad8415fe6dd..6ac8c2e7634d 100644 --- a/server/models/helpers/SearchHelper.ts +++ b/server/models/helpers/SearchHelper.ts @@ -4,7 +4,6 @@ import { find, map } from "lodash"; import queryParser from "pg-tsquery"; import { Op, QueryTypes, WhereOptions } from "sequelize"; import { DateFilter } from "@shared/types"; -import unescape from "@shared/utils/unescape"; import { sequelize } from "@server/database/sequelize"; import Collection from "@server/models/Collection"; import Document from "@server/models/Document"; @@ -410,7 +409,7 @@ export default class SearchHelper { return { results: map(results, (result) => ({ ranking: result.searchRanking, - context: removeMarkdown(unescape(result.searchContext), { + context: removeMarkdown(result.searchContext, { stripHTML: false, }), document: find(documents, { diff --git a/shared/utils/parseTitle.test.ts b/shared/utils/parseTitle.test.ts index 94153ae489c2..c0af2ba033de 100644 --- a/shared/utils/parseTitle.test.ts +++ b/shared/utils/parseTitle.test.ts @@ -6,11 +6,6 @@ it("should trim the title", () => { it("should extract first title", () => { expect(parseTitle(`# Title one\n# Title two`).title).toBe("Title one"); }); -it("should remove escape characters", () => { - expect(parseTitle(`# Thing \\- one`).title).toBe("Thing - one"); - expect(parseTitle(`# \\[wip\\] Title`).title).toBe("[wip] Title"); - expect(parseTitle(`# \\> Title`).title).toBe("> Title"); -}); it("should parse emoji if first character", () => { const parsed = parseTitle(`# 😀 Title`); expect(parsed.title).toBe("😀 Title"); diff --git a/shared/utils/parseTitle.ts b/shared/utils/parseTitle.ts index e3bed8d6583d..e3cb4ecd2db4 100644 --- a/shared/utils/parseTitle.ts +++ b/shared/utils/parseTitle.ts @@ -1,15 +1,11 @@ import emojiRegex from "emoji-regex"; -import unescape from "./unescape"; export default function parseTitle(text = "") { const regex = emojiRegex(); // find and extract title const firstLine = text.trim().split(/\r?\n/)[0]; - const trimmedTitle = firstLine.replace(/^#/, "").trim(); - - // remove any escape characters - const title = unescape(trimmedTitle); + const title = firstLine.replace(/^#/, "").trim(); // find and extract first emoji const matches = regex.exec(title); diff --git a/shared/utils/unescape.ts b/shared/utils/unescape.ts deleted file mode 100644 index 5de2587f4a6c..000000000000 --- a/shared/utils/unescape.ts +++ /dev/null @@ -1,4 +0,0 @@ -const unescape = (text: string) => - text.replace(/\\([\\`*{}[\]()#+\-.!_>])/g, "$1").replace(/\n\\\n/g, "\n\n"); - -export default unescape; From ea07b72c7aafe948cce94ec5b34527f1b88f6279 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Fri, 14 Jul 2023 21:51:15 -0400 Subject: [PATCH 004/144] fix: Show max 3 lines of content on notification items --- .../Notifications/NotificationListItem.tsx | 4 +++- app/styles/index.ts | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/components/Notifications/NotificationListItem.tsx b/app/components/Notifications/NotificationListItem.tsx index dffe9e55ec61..661eb246915c 100644 --- a/app/components/Notifications/NotificationListItem.tsx +++ b/app/components/Notifications/NotificationListItem.tsx @@ -8,7 +8,7 @@ import { s } from "@shared/styles"; import Notification from "~/models/Notification"; import CommentEditor from "~/scenes/Document/components/CommentEditor"; import useStores from "~/hooks/useStores"; -import { hover } from "~/styles"; +import { hover, truncateMultiline } from "~/styles"; import Avatar from "../Avatar"; import { AvatarSize } from "../Avatar/Avatar"; import Flex from "../Flex"; @@ -76,6 +76,8 @@ function NotificationListItem({ notification, onNavigate }: Props) { const StyledCommentEditor = styled(CommentEditor)` font-size: 0.9em; margin-top: 4px; + + ${truncateMultiline(3)} `; const StyledAvatar = styled(Avatar)` diff --git a/app/styles/index.ts b/app/styles/index.ts index 5a8245cb88c0..3c0026d6d504 100644 --- a/app/styles/index.ts +++ b/app/styles/index.ts @@ -38,3 +38,16 @@ export const fadeOnDesktopBackgrounded = () => { body.backgrounded & { opacity: 0.75; } `; }; + +/** + * Truncate multiline text. + * + * @returns string of CSS + */ +export const truncateMultiline = (lines: number) => ` + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: ${lines}; + overflow: hidden; + overflow-wrap: anywhere; +`; From 66331d3d4f58aceee42dc0fb4c908694b3629374 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sat, 15 Jul 2023 10:15:14 -0400 Subject: [PATCH 005/144] Add csp nonce to all inline script tags (#5566) --- server/routes/app.ts | 17 +++++++++-------- server/routes/index.ts | 2 ++ server/services/web.ts | 20 ++++++++++++-------- server/static/index.html | 2 +- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/server/routes/app.ts b/server/routes/app.ts index 9596766ee940..bf0c7b32fe9e 100644 --- a/server/routes/app.ts +++ b/server/routes/app.ts @@ -67,24 +67,24 @@ export const renderApp = async ( const { shareId } = ctx.params; const page = await readIndexFile(); const environment = ` - `; const entry = "app/index.tsx"; const scriptTags = isProduction - ? `` - : `` + : ` - - + + `; ctx.body = page @@ -97,7 +97,8 @@ export const renderApp = async ( .replace(/\{prefetch\}/g, shareId ? "" : prefetchTags) .replace(/\{slack-app-id\}/g, env.SLACK_APP_ID || "") .replace(/\{cdn-url\}/g, env.CDN_URL || "") - .replace(/\{script-tags\}/g, scriptTags); + .replace(/\{script-tags\}/g, scriptTags) + .replace(/\{csp-nonce\}/g, ctx.state.cspNonce); }; export const renderShare = async (ctx: Context, next: Next) => { diff --git a/server/routes/index.ts b/server/routes/index.ts index 6daa6154c809..f2694bf0f9c3 100644 --- a/server/routes/index.ts +++ b/server/routes/index.ts @@ -156,10 +156,12 @@ koa.use(async (ctx, next) => { ctx.set("Timing-Allow-Origin", timingOrigins.join(", ")); await next(); }); + koa.use(apexRedirect()); if (env.ENVIRONMENT === "test") { koa.use(errors.routes()); } + koa.use(router.routes()); export default koa; diff --git a/server/services/web.ts b/server/services/web.ts index 377214f8dd65..bf2064dfc5af 100644 --- a/server/services/web.ts +++ b/server/services/web.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/no-var-requires */ +import crypto from "crypto"; import { Server } from "https"; import Koa from "koa"; import { @@ -27,8 +28,6 @@ const isProduction = env.ENVIRONMENT === "production"; const defaultSrc = ["'self'"]; const scriptSrc = [ "'self'", - "'unsafe-inline'", - "'unsafe-eval'", "gist.github.com", "www.googletagmanager.com", "cdn.zapier.com", @@ -103,19 +102,22 @@ export default function init(app: Koa = new Koa(), server?: Server) { // Sets common security headers by default, such as no-sniff, hsts, hide powered // by etc, these are applied after auth and api so they are only returned on // standard non-XHR accessed routes - app.use( - contentSecurityPolicy({ + app.use((ctx, next) => { + ctx.state.cspNonce = crypto.randomBytes(16).toString("hex"); + + return contentSecurityPolicy({ directives: { defaultSrc, - scriptSrc, styleSrc, + scriptSrc: [...scriptSrc, `'nonce-${ctx.state.cspNonce}'`], imgSrc: ["*", "data:", "blob:"], frameSrc: ["*", "data:"], - connectSrc: ["*"], // Do not use connect-src: because self + websockets does not work in + // Do not use connect-src: because self + websockets does not work in // Safari, ref: https://bugs.webkit.org/show_bug.cgi?id=201591 + connectSrc: ["*"], }, - }) - ); + })(ctx, next); + }); // Allow DNS prefetching for performance, we do not care about leaking requests // to our own CDN's @@ -129,6 +131,8 @@ export default function init(app: Koa = new Koa(), server?: Server) { policy: "no-referrer", }) ); + app.use(mount(routes)); + return app; } diff --git a/server/static/index.html b/server/static/index.html index b457231a4fa9..7da726054911 100644 --- a/server/static/index.html +++ b/server/static/index.html @@ -53,7 +53,7 @@
{env} - `; - const entry = "app/index.tsx"; + const scriptTags = isProduction ? `` : ` - - + + `; ctx.body = page diff --git a/server/scripts/install-local-ssl.js b/server/scripts/install-local-ssl.js new file mode 100644 index 000000000000..f6810b0cea28 --- /dev/null +++ b/server/scripts/install-local-ssl.js @@ -0,0 +1,23 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ + +const exec = require("child_process").execSync; +const fs = require("fs"); +const path = require("path"); + +const sslDir = path.join(__dirname, "..", "config", "certs"); +const sslCert = path.join(sslDir, "public.cert"); +const sslKey = path.join(sslDir, "private.key"); + +if (!fs.existsSync(sslKey) || !fs.existsSync(sslCert)) { + try { + exec( + `mkcert -cert-file ${sslDir}/public.cert -key-file ${sslDir}/private.key "*.outline.dev" && mkcert -install` + ); + console.log("🔒 Local SSL certificate created"); + } catch (e) { + console.log( + "SSL certificates could not be generated. Ensure mkcert is installed and in your PATH" + ); + console.log(e.message); + } +} diff --git a/server/utils/ssl.ts b/server/utils/ssl.ts index 4a986683e2d7..52987c764428 100644 --- a/server/utils/ssl.ts +++ b/server/utils/ssl.ts @@ -25,13 +25,15 @@ export function getSSLOptions() { ? Buffer.from(env.SSL_KEY, "base64").toString("ascii") : undefined) || safeReadFile("private.key") || - safeReadFile("private.pem"), + safeReadFile("private.pem") || + safeReadFile("server/config/certs/private.key"), cert: (env.SSL_CERT ? Buffer.from(env.SSL_CERT, "base64").toString("ascii") : undefined) || safeReadFile("public.cert") || - safeReadFile("public.pem"), + safeReadFile("public.pem") || + safeReadFile("server/config/certs/public.cert"), }; } catch (err) { return { diff --git a/vite.config.ts b/vite.config.ts index d3ca07496c61..633d1308d0b4 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,3 +1,4 @@ +import fs from "fs"; import path from "path"; // eslint-disable-next-line import/no-unresolved import { optimizeLodashImports } from "@optimize-lodash/rollup-plugin"; @@ -5,7 +6,7 @@ import react from "@vitejs/plugin-react"; import browserslistToEsbuild from "browserslist-to-esbuild"; import dotenv from "dotenv"; import { webpackStats } from "rollup-plugin-webpack-stats"; -import { defineConfig } from "vite"; +import { CommonServerOptions, defineConfig } from "vite"; import { VitePWA } from "vite-plugin-pwa"; import { viteStaticCopy } from "vite-plugin-static-copy"; @@ -14,6 +15,20 @@ dotenv.config({ silent: true, }); +let httpsConfig: CommonServerOptions["https"] | undefined; + +if (process.env.NODE_ENV === "development") { + try { + httpsConfig = { + key: fs.readFileSync("./server/config/certs/private.key"), + cert: fs.readFileSync("./server/config/certs/public.cert"), + }; + } catch (err) { + // eslint-disable-next-line no-console + console.warn("No local SSL certs found, HTTPS will not be available"); + } +} + export default () => defineConfig({ root: "./", @@ -22,6 +37,7 @@ export default () => server: { port: 3001, host: true, + https: httpsConfig, }, plugins: [ // https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#readme From ed5671209aa8f4abd5c7b7e1a1227072652638a5 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Wed, 9 Aug 2023 07:23:00 -0400 Subject: [PATCH 114/144] New Crowdin updates (#5647) --- shared/i18n/locales/cs_CZ/translation.json | 11 ++- shared/i18n/locales/da_DK/translation.json | 11 ++- shared/i18n/locales/de_DE/translation.json | 11 ++- shared/i18n/locales/es_ES/translation.json | 11 ++- shared/i18n/locales/fa_IR/translation.json | 11 ++- shared/i18n/locales/fr_FR/translation.json | 37 ++++--- shared/i18n/locales/he_IL/translation.json | 11 ++- shared/i18n/locales/id_ID/translation.json | 11 ++- shared/i18n/locales/it_IT/translation.json | 11 ++- shared/i18n/locales/ja_JP/translation.json | 11 ++- shared/i18n/locales/ko_KR/translation.json | 35 ++++--- shared/i18n/locales/nl_NL/translation.json | 11 ++- shared/i18n/locales/pl_PL/translation.json | 11 ++- shared/i18n/locales/pt_BR/translation.json | 11 ++- shared/i18n/locales/pt_PT/translation.json | 11 ++- shared/i18n/locales/sv_SE/translation.json | 109 +++++++++++---------- shared/i18n/locales/th_TH/translation.json | 11 ++- shared/i18n/locales/tr_TR/translation.json | 11 ++- shared/i18n/locales/uk_UA/translation.json | 11 ++- shared/i18n/locales/vi_VN/translation.json | 11 ++- shared/i18n/locales/zh_CN/translation.json | 11 ++- shared/i18n/locales/zh_TW/translation.json | 11 ++- 22 files changed, 294 insertions(+), 96 deletions(-) diff --git a/shared/i18n/locales/cs_CZ/translation.json b/shared/i18n/locales/cs_CZ/translation.json index 327808662094..356b87854729 100644 --- a/shared/i18n/locales/cs_CZ/translation.json +++ b/shared/i18n/locales/cs_CZ/translation.json @@ -247,6 +247,16 @@ "Save": "Uložit", "New name": "Nový název", "Name can't be empty": "Název nemůže být prázdný", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Profilový obrázek", "Insert column after": "Vložit sloupec za", "Insert column before": "Vložit sloupec před", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Zobrazeno {{ count }} krát {{ teamMembers }} lidmi", "Viewer insights": "Statistiky shlédnutí", "As an admin you can manage if team members can see who has viewed this document": "Jako správce můžete spravovat, zda členové týmu uvidí, kdo si tento dokument prohlížel", - "Sorry, it looks like you don’t have permission to access the document": "Je nám líto, zdá se, že nemáte oprávnění k přístupu k dokumentu", "Sorry, this document is too large - edits will no longer be persisted.": "Je nám líto, ale tento dokument je příliš velký - úpravy již nebudou pokračovat.", "Sorry, the last change could not be persisted – please reload the page": "Je nám líto, poslední změna nemohla být zachována - prosím znovu načtěte stránku", "This template will be permanently deleted in <2> unless restored.": "Tato šablona bude trvale odstraněna v <2> dokud nebude obnovena.", diff --git a/shared/i18n/locales/da_DK/translation.json b/shared/i18n/locales/da_DK/translation.json index c97bc7f9b640..f4b07d842bc1 100644 --- a/shared/i18n/locales/da_DK/translation.json +++ b/shared/i18n/locales/da_DK/translation.json @@ -247,6 +247,16 @@ "Save": "Save", "New name": "New name", "Name can't be empty": "Name can't be empty", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Profile picture", "Insert column after": "Insert column after", "Insert column before": "Insert column before", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Viewed {{ count }} times by {{ teamMembers }} people", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "Sorry, it looks like you don’t have permission to access the document", "Sorry, this document is too large - edits will no longer be persisted.": "Sorry, this document is too large - edits will no longer be persisted.", "Sorry, the last change could not be persisted – please reload the page": "Sorry, the last change could not be persisted – please reload the page", "This template will be permanently deleted in <2> unless restored.": "This template will be permanently deleted in <2> unless restored.", diff --git a/shared/i18n/locales/de_DE/translation.json b/shared/i18n/locales/de_DE/translation.json index f832308913d4..d5bf35b5cbe4 100644 --- a/shared/i18n/locales/de_DE/translation.json +++ b/shared/i18n/locales/de_DE/translation.json @@ -247,6 +247,16 @@ "Save": "Speichern", "New name": "Neuer Name", "Name can't be empty": "Der Name darf nicht leer sein", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Profilbild", "Insert column after": "Spalte danach einfügen", "Insert column before": "Spalte davor einfügen", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "{{ count }} Mal von {{ teamMembers }} Personen angesehen", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "Leider scheint es so, als hättest du keine Zugriffsberechtigung für dieses Dokument", "Sorry, this document is too large - edits will no longer be persisted.": "Entschuldigung, dieses Dokument ist zu groß - Änderungen werden nicht mehr beibehalten.", "Sorry, the last change could not be persisted – please reload the page": "Die letzte Änderung konnte leider nicht übernommen werden – bitte lade die Seite neu", "This template will be permanently deleted in <2> unless restored.": "Diese Vorlage wird dauerhaft in <2> gelöscht, wenn sie nicht wiederhergestellt wird.", diff --git a/shared/i18n/locales/es_ES/translation.json b/shared/i18n/locales/es_ES/translation.json index 78cf99b2c549..09ca9e176355 100644 --- a/shared/i18n/locales/es_ES/translation.json +++ b/shared/i18n/locales/es_ES/translation.json @@ -247,6 +247,16 @@ "Save": "Guardar", "New name": "Nuevo nombre", "Name can't be empty": "El nombre no puede estar vacío", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Foto de perfil", "Insert column after": "Insertar columna después", "Insert column before": "Insertar columna antes", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Visto {{ count }} veces por {{ teamMembers }} personas", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "Lo sentimos, parece que no tienes permiso para acceder al documento", "Sorry, this document is too large - edits will no longer be persisted.": "Lo sentimos, este documento es demasiado grande; las ediciones ya no se conservarán.", "Sorry, the last change could not be persisted – please reload the page": "Lo sentimos, el último cambio no se pudo guardar. Por favor, recargue la página", "This template will be permanently deleted in <2> unless restored.": "Esta plantilla se eliminará de forma permanente en <2> a menos que se restaure.", diff --git a/shared/i18n/locales/fa_IR/translation.json b/shared/i18n/locales/fa_IR/translation.json index 6c537fd54330..55680cac8ddc 100644 --- a/shared/i18n/locales/fa_IR/translation.json +++ b/shared/i18n/locales/fa_IR/translation.json @@ -247,6 +247,16 @@ "Save": "ذخیره", "New name": "New name", "Name can't be empty": "Name can't be empty", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "تصویر پروفایل", "Insert column after": "درج ستون پس از", "Insert column before": "درج ستون پیش از", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Viewed {{ count }} times by {{ teamMembers }} people", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "متأسفانه به نظر می رسد مجوز دسترسی به سند را ندارید", "Sorry, this document is too large - edits will no longer be persisted.": "Sorry, this document is too large - edits will no longer be persisted.", "Sorry, the last change could not be persisted – please reload the page": "Sorry, the last change could not be persisted – please reload the page", "This template will be permanently deleted in <2> unless restored.": "این الگو برای همیشه در <2> حذف خواهد شد، مگر اینکه بازیابی شود.", diff --git a/shared/i18n/locales/fr_FR/translation.json b/shared/i18n/locales/fr_FR/translation.json index a81fc76996dd..4ab73ec9db41 100644 --- a/shared/i18n/locales/fr_FR/translation.json +++ b/shared/i18n/locales/fr_FR/translation.json @@ -247,6 +247,16 @@ "Save": "Enregistrer", "New name": "Nouveau nom", "Name can't be empty": "Le champ Nom ne peut pas être vide", + "Previous match": "Occurence précédente", + "Next match": "Prochaine occurence", + "Find and replace": "Trouver et remplacer", + "Find": "Rechercher", + "Match case": "Respecter la casse", + "Enable regex": "Utiliser l'expression régulière", + "Replace options": "Replace options", + "Replacement": "Remplacement", + "Replace": "Remplacer", + "Replace all": "Tout remplacer", "Profile picture": "Photo de profil", "Insert column after": "Insérer une colonne après", "Insert column before": "Insérer une colonne avant", @@ -405,8 +415,8 @@ "{{ usersCount }} users and {{ groupsCount }} groups with access_plural": "{{ usersCount }} utilisateurs et {{ groupsCount }} groupes ont accès", "{{ usersCount }} users and a group have access": "{{ usersCount }} utilisateur et un groupe ont accès", "{{ usersCount }} users and a group have access_plural": "{{ usersCount }} utilisateurs et un groupe ont accès", - "{{ usersCount }} users with access": "{{ usersCount }} utilisateur a accès", - "{{ usersCount }} users with access_plural": "{{ usersCount }} utilisateurs ont accès", + "{{ usersCount }} users with access": "{{ usersCount }} utilisateur avec accès", + "{{ usersCount }} users with access_plural": "{{ usersCount }} utilisateurs avec accès", "{{ groupsCount }} groups with access": "{{ groupsCount }} groupe a accès", "{{ groupsCount }} groups with access_plural": "{{ groupsCount }} groupes ont accès", "The collection was updated": "La collection a été mise à jour", @@ -512,8 +522,7 @@ "Viewed {{ count }} times by {{ teamMembers }} people": "Vue {{ count }} fois par les membres de {{ teamMembers }}", "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Vue {{ count }} fois par les membres de {{ teamMembers }}", "Viewer insights": "Viewer insights", - "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "Désolé, il semble que vous n’ayez pas la permission d’accéder à ce document", + "As an admin you can manage if team members can see who has viewed this document": "En tant qu'administrateur, vous pouvez gérer si les membres de l'équipe peuvent voir qui a consulté ce document", "Sorry, this document is too large - edits will no longer be persisted.": "Désolé, ce document est trop volumineux - les modifications ne seront plus conservées.", "Sorry, the last change could not be persisted – please reload the page": "Désolé, la dernière modification n'a pas pu être enregistrée - veuillez recharger la page", "This template will be permanently deleted in <2> unless restored.": "Ce modèle sera définitivement supprimé dans <2> sauf s'il est restauré.", @@ -875,7 +884,7 @@ "Connect {{appName}} collections to Slack channels. Messages will be automatically posted to Slack when documents are published or updated.": "Connectez les collections {{appName}} aux canaux Slack . Les messages seront automatiquement publiés sur Slack lorsque des documents sont publiés ou mis à jour.", "Connect": "Se connecter", "The Slack integration is currently disabled. Please set the associated environment variables and restart the server to enable the integration.": "L'intégration de Slack est actuellement désactivée. Veuillez définir les variables d'environnement associées et redémarrer le serveur pour activer l'intégration.", - "How to use {{ command }}": "How to use {{ command }}", + "How to use {{ command }}": "Comment utiliser {{ command }}", "To search your knowledgebase use {{ command }}. \nYou’ve already learned how to get help with {{ command2 }}.": "Pour rechercher dans votre base de connaissances, utilisez {{ command }}. \nVous avez déjà appris comment obtenir de l'aide avec {{ command2 }}.", "Sorry, we couldn’t find an integration for your team. Head to your {{ appName }} settings to set one up.": "Désolé, nous n'avons pas trouvé d'intégration pour votre équipe. Rendez-vous dans vos paramètres {{ appName }} pour en configurer un.", "It looks like you haven’t signed in to {{ appName }} yet, so results may be limited": "Il semble que vous ne vous soyez pas encore authentifié à {{ appName }} , les résultats peuvent donc être limités", @@ -902,14 +911,14 @@ "Webhooks can be used to notify your application when events happen in {{appName}}. Events are sent as a https request with a JSON payload in near real-time.": "Les Webhooks peuvent être utilisés pour notifier votre application lorsque des événements se produisent dans {{appName}}. Les événements sont envoyés en tant que requête https contenant un bloc JSON en temps quasi réel.", "Inactive": "Inactif", "Create a webhook": "Créer un webhook", - "Never logged in": "Never logged in", - "Online now": "Online now", - "Online {{ timeAgo }}": "Online {{ timeAgo }}", - "Viewed just now": "Viewed just now", - "Viewed {{ timeAgo }}": "Viewed {{ timeAgo }}", - "You updated {{ timeAgo }}": "You updated {{ timeAgo }}", - "{{ user }} updated {{ timeAgo }}": "{{ user }} updated {{ timeAgo }}", - "You created {{ timeAgo }}": "You created {{ timeAgo }}", - "{{ user }} created {{ timeAgo }}": "{{ user }} created {{ timeAgo }}", + "Never logged in": "Jamais connecté", + "Online now": "En ligne actuellement", + "Online {{ timeAgo }}": "En ligne il y a {{ timeAgo }}", + "Viewed just now": "Vu à l'instant", + "Viewed {{ timeAgo }}": "Vu il y a {{ timeAgo }}", + "You updated {{ timeAgo }}": "Vous avez mis à jour il y a {{ timeAgo }}", + "{{ user }} updated {{ timeAgo }}": "Mis à jour par {{ user }} il y a {{ timeAgo }}", + "You created {{ timeAgo }}": "Créé par vous il y a {{ timeAgo }}", + "{{ user }} created {{ timeAgo }}": "Créé par {{ user }} il y a {{ timeAgo }}", "Uploading": "Transfert en cours" } diff --git a/shared/i18n/locales/he_IL/translation.json b/shared/i18n/locales/he_IL/translation.json index cf81f1d93e47..f85bcf9d7c61 100644 --- a/shared/i18n/locales/he_IL/translation.json +++ b/shared/i18n/locales/he_IL/translation.json @@ -247,6 +247,16 @@ "Save": "Save", "New name": "New name", "Name can't be empty": "Name can't be empty", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Profile picture", "Insert column after": "Insert column after", "Insert column before": "Insert column before", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Viewed {{ count }} times by {{ teamMembers }} people", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "Sorry, it looks like you don’t have permission to access the document", "Sorry, this document is too large - edits will no longer be persisted.": "Sorry, this document is too large - edits will no longer be persisted.", "Sorry, the last change could not be persisted – please reload the page": "Sorry, the last change could not be persisted – please reload the page", "This template will be permanently deleted in <2> unless restored.": "This template will be permanently deleted in <2> unless restored.", diff --git a/shared/i18n/locales/id_ID/translation.json b/shared/i18n/locales/id_ID/translation.json index a011ca2cff25..193e3bd84720 100644 --- a/shared/i18n/locales/id_ID/translation.json +++ b/shared/i18n/locales/id_ID/translation.json @@ -247,6 +247,16 @@ "Save": "Simpan", "New name": "Nama baru", "Name can't be empty": "Nama tidak boleh kosong", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Gambar profil", "Insert column after": "Sisipkan kolom di kanan", "Insert column before": "Sisipkan kolom di kiri", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Dilihat {{ count }} kali oleh {{ teamMembers }} orang", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "Maaf, sepertinya Anda tidak punya izin untuk mengakses dokumen", "Sorry, this document is too large - edits will no longer be persisted.": "Maaf, dokumen ini terlalu besar - pengeditan tidak dapat dilakukan.", "Sorry, the last change could not be persisted – please reload the page": "Maaf, perubahan terakhir tidak dapat disimpan – muat ulang halaman", "This template will be permanently deleted in <2> unless restored.": "Template ini akan dihapus secara permanen di <2> kecuali dipulihkan.", diff --git a/shared/i18n/locales/it_IT/translation.json b/shared/i18n/locales/it_IT/translation.json index 697619974acf..ada847713aa4 100644 --- a/shared/i18n/locales/it_IT/translation.json +++ b/shared/i18n/locales/it_IT/translation.json @@ -247,6 +247,16 @@ "Save": "Salva", "New name": "New name", "Name can't be empty": "Name can't be empty", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Immagine del profilo", "Insert column after": "Inserisci colonna dopo", "Insert column before": "Inserisci colonna prima", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Visto {{ count }} volte da {{ teamMembers }} persone", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "Spiacenti, sembra che tu non abbia i permessi per accedere al documento", "Sorry, this document is too large - edits will no longer be persisted.": "Sorry, this document is too large - edits will no longer be persisted.", "Sorry, the last change could not be persisted – please reload the page": "Spiacenti, non è stato possibile mantenere l'ultima modifica. Si prega di ricaricare la pagina", "This template will be permanently deleted in <2> unless restored.": "Questo modello verrà eliminato definitivamente in <2> salvo ripristino.", diff --git a/shared/i18n/locales/ja_JP/translation.json b/shared/i18n/locales/ja_JP/translation.json index ad9bdaee3983..f05bd3eaeae7 100644 --- a/shared/i18n/locales/ja_JP/translation.json +++ b/shared/i18n/locales/ja_JP/translation.json @@ -247,6 +247,16 @@ "Save": "保存", "New name": "New name", "Name can't be empty": "Name can't be empty", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "プロフィール写真", "Insert column after": "後に列を挿入", "Insert column before": "前に列を挿入", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "{{ teamMembers }} 人が{{ count }} 回閲覧", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "残念ながら、このドキュメントにアクセスする権限がないようです。", "Sorry, this document is too large - edits will no longer be persisted.": "Sorry, this document is too large - edits will no longer be persisted.", "Sorry, the last change could not be persisted – please reload the page": "申し訳ありませんが、最後の変更を保持できませんでした。ページをリロードしてください", "This template will be permanently deleted in <2> unless restored.": "このテンプレートは復元しない限り、<2>で永久に削除されます。", diff --git a/shared/i18n/locales/ko_KR/translation.json b/shared/i18n/locales/ko_KR/translation.json index b2694c61d7c8..1a895f303190 100644 --- a/shared/i18n/locales/ko_KR/translation.json +++ b/shared/i18n/locales/ko_KR/translation.json @@ -115,7 +115,7 @@ "Expand": "펼치기", "Type a command or search": "명령어를 입력하거나 검색", "Are you sure you want to permanently delete this entire comment thread?": "정말로 이 댓글 묶음 전체를 영구적으로 삭제하시겠습니까?", - "Are you sure you want to permanently delete this comment?": "이 댓글을 영구적으로 삭제하시겠습니까?", + "Are you sure you want to permanently delete this comment?": "정말로 이 댓글을 영구적으로 삭제하시겠습니까?", "Server connection lost": "서버 연결 끊김", "Edits you make will sync once you’re online": "온라인 상태가 되면 수정 사항이 동기화됩니다", "Submenu": "하위 메뉴", @@ -124,7 +124,7 @@ "Deleted Collection": "삭제 된 콜렉션", "Unpin": "고정 해제", "Search collections & documents": "컬렉션 및 문서 검색", - "No results found": "결과가 없습니다", + "No results found": "결과가 없습니다.", "Untitled": "제목없음", "New": "신규", "Only visible to you": "나에게만 보임", @@ -145,7 +145,7 @@ "{{ userName }} saved": "{{ userName }} 이(가) 저장함:", "Never viewed": "미조회", "Viewed": "조회", - "in": "안에", + "in": "•", "nested document": "하위 문서", "nested document_plural": "하위 문서들", "{{ total }} task": "{{ total }} 개의 일", @@ -247,6 +247,16 @@ "Save": "저장", "New name": "새 이름", "Name can't be empty": "이름은 비어 있을 수 없습니다.", + "Previous match": "이전 찾기", + "Next match": "다음 찾기", + "Find and replace": "찾아 바꾸기", + "Find": "찾기", + "Match case": "대소문자 일치", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "대체", + "Replace": "바꾸기", + "Replace all": "모두 바꾸기", "Profile picture": "프로필 사진", "Insert column after": "뒤에 열 추가", "Insert column before": "앞에 열 추가", @@ -467,7 +477,7 @@ "Reply": "답글", "Post": "게시하기", "Cancel": "취소", - "No comments yet": "아직 댓글이 없습니다", + "No comments yet": "아직 댓글이 없습니다.", "Error updating comment": "댓글을 업데이트하는 중에 오류가 발생했습니다.", "Images are still uploading.\nAre you sure you want to discard them?": "이미지가 아직 업로드 중입니다.\n변경 내용을 삭제하시겠습니까?", "{{ count }} comment": "댓글 {{ count }} 개", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "{{ teamMembers }} 명에 의해 {{ count }} 회 조회됨", "Viewer insights": "열람자 정보", "As an admin you can manage if team members can see who has viewed this document": "누가 이 문서를 열람했는지를 팀 멤버들이 볼 수 있는가를 관리자로서 관리할 수 있습니다.", - "Sorry, it looks like you don’t have permission to access the document": "죄송합니다. 문서에 액세스할 수 있는 권한이 없는 것 같습니다.", "Sorry, this document is too large - edits will no longer be persisted.": "죄송합니다. 문서가 너무 커서 수정사항이 더 이상 유지되지 않습니다.", "Sorry, the last change could not be persisted – please reload the page": "죄송합니다. 마지막 변경 사항을 유지할 수 없습니다. 페이지를 새로고침하세요.", "This template will be permanently deleted in <2> unless restored.": "이 템플릿은 복원하지 않으면 <2> 에서 영구적으로 삭제됩니다.", @@ -533,12 +542,12 @@ "Anyone with the link can view this document": "링크가 있는 모든 사용자가 이 문서를 볼 수 있습니다", "The shared link was last accessed {{ timeAgo }}.": "공유 링크가 {{ timeAgo }} 에 마지막으로 액세스 됨", "Share this document": "이 문서 공유하기", - "This document is shared because the parent <2>{documentTitle} is publicly shared.": "이 문서는 상위 <2>{documentTitle} 때문에 공유됩니다. 공개적으로 공유됩니다.", + "This document is shared because the parent <2>{documentTitle} is publicly shared.": "이 문서는 상위 문서인 <2>{documentTitle}이(가) 일반에게 공유되었기 때문에 공유됩니다.", "Share nested documents": "하위 문서 공유", "Nested documents are publicly available": "하위 문서도 공개됩니다", "Nested documents are not shared": "하위 문서는 공유되지 않습니다", - "Automatically redirect to the editor": "편집기로 자동 리디렉션됩니다.", - "Users with edit permission will be redirected to the main app": "편집 권한이 있는 사용자는 기본 앱으로 리다이렉션됩니다.", + "Automatically redirect to the editor": "자동으로 편집기로 넘어가기", + "Users with edit permission will be redirected to the main app": "편집 권한이 있는 사용자는 앱으로 넘어가게 됩니다.", "All users see the same publicly shared view": "모든 사용자에게 공개적으로 공유된 동일한 보기가 표시됨", "Custom link": "사용자 지정 링크", "The document will be accessible at <2>{{url}}": "문서는 <2>{{url}}에서 액세스할 수 있습니다.", @@ -758,7 +767,7 @@ "Manage optional and beta features. Changing these settings will affect the experience for all members of the workspace.": "선택적 기능 및 실험적 기능을 관리합니다. 이 설정을 변경하면 워크스페이스에 모든 멤버에게 영향을 미칩니다.", "Seamless editing": "매끄러운 편집", "When enabled documents are always editable for team members that have permission. When disabled there is a separate editing view.": "활성화되면 권한이 있는 팀 구성원이 문서를 항상 편집할 수 있습니다. 비활성화되면 별도의 편집 보기가 있습니다.", - "Commenting": "댓글 달기", + "Commenting": "댓글 다는 중", "When enabled team members can add comments to documents.": "활성화되면 팀 구성원이 문서에 댓글을 달 수 있습니다.", "Add a Google Analytics 4 measurement ID to send document views and analytics from the workspace to your own Google Analytics account.": "Google 애널리틱스 4에 \bMeasurement ID를 추가하여 작업공간에서 자신의 Google 애널리틱스 계정으로 문서 보기 및 분석을 전송하세요.", "Measurement ID": "Measurement ID", @@ -782,7 +791,7 @@ "Receive a notification when a document you are subscribed to is edited": "작성한 문서가 수정되면 알림을 받습니다", "Comment posted": "댓글 작성됨", "Receive a notification when a document you are subscribed to or a thread you participated in receives a comment": "구독 중인 문서 또는 참여한 스레드가 댓글을 받으면 알림을 받습니다.", - "Mentioned": "멘션한", + "Mentioned": "언급됨", "Receive a notification when someone mentions you in a document or comment": "다른 사람이 문서나 댓글에서 나를 언급하면 알림을 받습니다.", "Collection created": "컬렉션 생성됨", "Receive a notification whenever a new collection is created": "새 컬렉션이 생성될 때마다 알림을 받습니다", @@ -904,12 +913,12 @@ "Create a webhook": "웹훅 만들기", "Never logged in": "로그인 한 적 없음", "Online now": "현재 온라인", - "Online {{ timeAgo }}": "온라인 {{ timeAgo }}", + "Online {{ timeAgo }}": "{{ timeAgo }} 전에 온라인", "Viewed just now": "방금 확인함", "Viewed {{ timeAgo }}": "전에 봄 {{ timeAgo }}", - "You updated {{ timeAgo }}": "내가 업데이트 함 {{ timeAgo }}", + "You updated {{ timeAgo }}": "{{ timeAgo }} 전에 내가 업데이트 함", "{{ user }} updated {{ timeAgo }}": "{{ user }} 업데이트 됨 {{ timeAgo }}", - "You created {{ timeAgo }}": "내가 생성함 {{ timeAgo }}", + "You created {{ timeAgo }}": "{{ timeAgo }} 전에 내가 생성함", "{{ user }} created {{ timeAgo }}": "{{ user }} 이(가) {{ timeAgo }} 전에 생성", "Uploading": "업로드 중" } diff --git a/shared/i18n/locales/nl_NL/translation.json b/shared/i18n/locales/nl_NL/translation.json index 8e8b41627361..412e88e24332 100644 --- a/shared/i18n/locales/nl_NL/translation.json +++ b/shared/i18n/locales/nl_NL/translation.json @@ -247,6 +247,16 @@ "Save": "Bewaren", "New name": "Nieuwe naam", "Name can't be empty": "Naam mag niet leeg zijn", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Profielfoto", "Insert column after": "Voeg een kolom rechts in", "Insert column before": "Voeg een kolom links in", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "{{ count }} keer bekeken door {{ teamMembers }} personen", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "Als beheerder kun je instellen of teamleden kunnen zien wie dit document heeft bekeken", - "Sorry, it looks like you don’t have permission to access the document": "Sorry, het lijkt erop dat je geen toestemming hebt om het document te openen", "Sorry, this document is too large - edits will no longer be persisted.": "Sorry, dit document is te groot - bewerkingen zullen niet langer blijven bestaan.", "Sorry, the last change could not be persisted – please reload the page": "Sorry, de laatste wijziging kon niet worden bewaard - laad de pagina opnieuw", "This template will be permanently deleted in <2> unless restored.": "Dit sjabloon wordt definitief verwijderd over <2> tenzij het hersteld wordt.", diff --git a/shared/i18n/locales/pl_PL/translation.json b/shared/i18n/locales/pl_PL/translation.json index 1320de18fe30..ed27d30592dc 100644 --- a/shared/i18n/locales/pl_PL/translation.json +++ b/shared/i18n/locales/pl_PL/translation.json @@ -247,6 +247,16 @@ "Save": "Zapisz", "New name": "Nowa nazwa", "Name can't be empty": "Nazwa nie może być pusta", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Zdjęcie profilowe", "Insert column after": "Wstaw kolumnę po", "Insert column before": "Wstaw kolumnę przed", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Wyświetlono {{ count }} razy przez {{ teamMembers }} osób", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "Przepraszamy, wygląda na to, że nie masz uprawnień dostępu do dokumentu", "Sorry, this document is too large - edits will no longer be persisted.": "Przepraszamy, ten dokument jest za duży — zmiany nie będą już zachowywane.", "Sorry, the last change could not be persisted – please reload the page": "Przepraszamy, nie udało się zachować ostatniej zmiany – proszę odświeżyć stronę", "This template will be permanently deleted in <2> unless restored.": "Ten szablon zostanie trwale usunięty w <2> chyba że zostanie przywrócony.", diff --git a/shared/i18n/locales/pt_BR/translation.json b/shared/i18n/locales/pt_BR/translation.json index c941ca758ae4..9af9f3b9fb71 100644 --- a/shared/i18n/locales/pt_BR/translation.json +++ b/shared/i18n/locales/pt_BR/translation.json @@ -247,6 +247,16 @@ "Save": "Salvar", "New name": "New name", "Name can't be empty": "Name can't be empty", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Foto do perfil", "Insert column after": "Inserir coluna à esquerda", "Insert column before": "Inserir coluna à direita", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Viewed {{ count }} times by {{ teamMembers }} people", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "Desculpe, parece que você não tem permissão para acessar o documento", "Sorry, this document is too large - edits will no longer be persisted.": "Sorry, this document is too large - edits will no longer be persisted.", "Sorry, the last change could not be persisted – please reload the page": "Sorry, the last change could not be persisted – please reload the page", "This template will be permanently deleted in <2> unless restored.": "Este template será permanentemente excluído em <2>, a menos que seja restaurado.", diff --git a/shared/i18n/locales/pt_PT/translation.json b/shared/i18n/locales/pt_PT/translation.json index ad7ffa277d7a..6f23d68dae16 100644 --- a/shared/i18n/locales/pt_PT/translation.json +++ b/shared/i18n/locales/pt_PT/translation.json @@ -247,6 +247,16 @@ "Save": "Guardar", "New name": "New name", "Name can't be empty": "Name can't be empty", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Profile picture", "Insert column after": "Inserir coluna depois", "Insert column before": "Insira coluna antes", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Viewed {{ count }} times by {{ teamMembers }} people", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "Sorry, it looks like you don’t have permission to access the document", "Sorry, this document is too large - edits will no longer be persisted.": "Sorry, this document is too large - edits will no longer be persisted.", "Sorry, the last change could not be persisted – please reload the page": "Sorry, the last change could not be persisted – please reload the page", "This template will be permanently deleted in <2> unless restored.": "This template will be permanently deleted in <2> unless restored.", diff --git a/shared/i18n/locales/sv_SE/translation.json b/shared/i18n/locales/sv_SE/translation.json index 0d70ebe38ef7..1e93df778b89 100644 --- a/shared/i18n/locales/sv_SE/translation.json +++ b/shared/i18n/locales/sv_SE/translation.json @@ -9,7 +9,7 @@ "Star": "Stjärna", "Unstar": "Ta bort stjärnmärkning", "Delete": "Radera", - "Delete collection": "Delete collection", + "Delete collection": "Ta bort samling", "Delete IndexedDB cache": "Ta bort IndexedDB cache", "IndexedDB cache deleted": "IndexedDB cache borttagen", "Toggle debug logging": "Toggle debug logging", @@ -20,8 +20,8 @@ "New document": "Nytt dokument", "Publish": "Publicera", "Document published": "Document published", - "Publish document": "Publish document", - "Unpublish": "Unpublish", + "Publish document": "Publicera dokument", + "Unpublish": "Avpublicera", "Document unpublished": "Document unpublished", "Subscribe": "Prenumerera", "Subscribed to document notifications": "Prenumererat på dokumentnotifieringar", @@ -36,7 +36,7 @@ "Duplicate": "Duplicera", "Duplicate document": "Duplicera dokument", "Document duplicated": "Dokumenetet duplicerat", - "collection": "collection", + "collection": "samling", "Pin to {{collectionName}}": "Pin to {{collectionName}}", "Pinned to collection": "Fäst vid samlingen", "Pin to home": "Fäst på startsidan", @@ -50,13 +50,13 @@ "Open random document": "Öppna slumpvis dokument", "Search documents for \"{{searchQuery}}\"": "Sök dokument efter \"{{searchQuery}}\"", "Move": "Flytta", - "Move {{ documentType }}": "Move {{ documentType }}", + "Move {{ documentType }}": "Flytta {{ documentType }}", "Archive": "Arkiv", "Document archived": "Dokumentet arkiverat", "Delete {{ documentName }}": "Ta bort {{ documentName }}", "Permanently delete": "Radera permanent", "Permanently delete {{ documentName }}": "Radera {{ documentName }} permanent", - "Comments": "Comments", + "Comments": "Kommentarer", "History": "Historik", "Insights": "Insights", "Home": "Hem", @@ -73,9 +73,9 @@ "Report a bug": "Rapportera fel", "Changelog": "Ändringshistorik", "Keyboard shortcuts": "Kortkommandon", - "Download {{ platform }} app": "Download {{ platform }} app", + "Download {{ platform }} app": "Ladda ned {{ platform }} appen", "Log out": "Logga ut", - "Mark notifications as read": "Mark notifications as read", + "Mark notifications as read": "Markera alla aviseringar som lästa", "Restore revision": "Återställ version", "Copy link": "Kopiera länk", "Link copied": "Länk kopierad", @@ -85,28 +85,28 @@ "Appearance": "Utseende", "Change theme": "Ändra tema", "Change theme to": "Ändra tema till", - "Switch workspace": "Switch workspace", - "Select a workspace": "Select a workspace", - "New workspace": "New workspace", - "Create a workspace": "Create a workspace", + "Switch workspace": "Byt arbetsyta", + "Select a workspace": "Välj en arbetsyta", + "New workspace": "Ny arbetsyta", + "Create a workspace": "Skapa arbetsyta", "Invite people": "Invite people", - "Delete user": "Delete user", - "Collection": "Collection", + "Delete user": "Ta bort användare", + "Collection": "Samling", "Debug": "Debug", - "Document": "Document", + "Document": "Dokument", "Revision": "Revision", "Navigation": "Navigation", - "Notification": "Notification", + "Notification": "Avisering", "People": "People", - "Workspace": "Workspace", - "Recent searches": "Recent searches", - "currently editing": "currently editing", + "Workspace": "Arbetsyta", + "Recent searches": "Senaste sökningar", + "currently editing": "redigerar just nu", "currently viewing": "currently viewing", "previously edited": "previously edited", "You": "Du", "Viewers": "Tittare", - "I’m sure – Delete": "I’m sure – Delete", - "Deleting": "Deleting", + "I’m sure – Delete": "Jag är säker – Radera", + "Deleting": "Raderar", "Are you sure about that? Deleting the {{collectionName}} collection is permanent and cannot be restored, however all published documents within will be moved to the trash.": "Are you sure about that? Deleting the {{collectionName}} collection is permanent and cannot be restored, however all published documents within will be moved to the trash.", "Also, {{collectionName}} is being used as the start view – deleting it will reset the start view to the Home page.": "Also, {{collectionName}} is being used as the start view – deleting it will reset the start view to the Home page.", "Sorry, an error occurred saving the collection": "Tyvärr, ett fel uppstod när samlingen skulle sparas", @@ -114,8 +114,8 @@ "Collapse": "Collapse", "Expand": "Expandera", "Type a command or search": "Skriv ett kommando eller sök", - "Are you sure you want to permanently delete this entire comment thread?": "Are you sure you want to permanently delete this entire comment thread?", - "Are you sure you want to permanently delete this comment?": "Are you sure you want to permanently delete this comment?", + "Are you sure you want to permanently delete this entire comment thread?": "Är du säker på att du vill ta bort denna konversationen permanent?", + "Are you sure you want to permanently delete this comment?": "Är du säker på att du vill ta bort denna kommentaren?", "Server connection lost": "Serveranslutning förlorad", "Edits you make will sync once you’re online": "Edits you make will sync once you’re online", "Submenu": "Undermeny", @@ -123,8 +123,8 @@ "Default collection": "Default collection", "Deleted Collection": "Deleted Collection", "Unpin": "Lossa", - "Search collections & documents": "Search collections & documents", - "No results found": "No results found", + "Search collections & documents": "Sök i samlingar och dokument", + "No results found": "Inga resultat hittades", "Untitled": "Untitled", "New": "Ny", "Only visible to you": "Endast synlig för dig", @@ -147,11 +147,11 @@ "Viewed": "Sett", "in": "i", "nested document": "nästlat dokument", - "nested document_plural": "nested documents", + "nested document_plural": "nästlade dokument", "{{ total }} task": "{{ total }} uppgift", - "{{ total }} task_plural": "{{ total }} tasks", + "{{ total }} task_plural": "{{ total }} uppgifter", "{{ completed }} task done": "{{ completed }} uppgift klar", - "{{ completed }} task done_plural": "{{ completed }} tasks done", + "{{ completed }} task done_plural": "{{ completed }} uppgifter avklarade", "{{ completed }} of {{ total }} tasks": "{{ completed }} av {{ total }} uppgifter", "Template created, go ahead and customize it": "Mall skapad, gå vidare och anpassa den", "Creating": "Skapar", @@ -168,7 +168,7 @@ "our engineers have been notified": "våra ingenjörer har underrättats", "Report a Bug": "Rapportera en bugg", "Show Detail": "Visa detaljer", - "Current version": "Current version", + "Current version": "Nuvarande version", "{{userName}} edited": "{{userName}} redigerade", "{{userName}} archived": "{{userName}} arkiverade", "{{userName}} restored": "{{userName}} återställde", @@ -177,42 +177,42 @@ "{{userName}} published": "{{userName}} publicerade", "{{userName}} unpublished": "{{userName}} opublicerade", "{{userName}} moved": "{{userName}} flyttade", - "Export started": "Export started", + "Export started": "Exportering startad", "A ZIP file containing the images, and documents in the Markdown format.": "A ZIP file containing the images, and documents in the Markdown format.", "A ZIP file containing the images, and documents as HTML files.": "A ZIP file containing the images, and documents as HTML files.", "Structured data that can be used to transfer data to another compatible {{ appName }} instance.": "Structured data that can be used to transfer data to another compatible {{ appName }} instance.", "Export": "Exportera", "Exporting the collection {{collectionName}} may take some time.": "Exporting the collection {{collectionName}} may take some time.", - "You will receive an email when it's complete.": "You will receive an email when it's complete.", - "Include attachments": "Include attachments", - "Including uploaded images and files in the exported data": "Including uploaded images and files in the exported data", - "{{ count }} member": "{{ count }} member", - "{{ count }} member_plural": "{{ count }} members", - "Group members": "Group members", + "You will receive an email when it's complete.": "Du kommer att få ett e-postmeddelande när det är klart.", + "Include attachments": "Inkludera bilagor", + "Including uploaded images and files in the exported data": "Inkluderar uppladdade bilder och filer i den exporterade datan", + "{{ count }} member": "{{ count }} medlem", + "{{ count }} member_plural": "{{ count }} medlemmar", + "Group members": "Gruppmedlemmar", "Icon": "Ikon", "Show menu": "Visa meny", "Choose icon": "Välj ikon", "Loading": "Laddar", - "Select a color": "Select a color", + "Select a color": "Välj en färg", "Loading editor": "Laddar redigerare", "Search": "Sök", - "Default access": "Default access", - "View and edit": "View and edit", - "View only": "View only", - "No access": "No access", + "Default access": "Standardåtkomst", + "View and edit": "Visa och redigera", + "View only": "Endast visa", + "No access": "Ingen access", "Role": "Roll", - "Member": "Member", - "Viewer": "Läs", + "Member": "Medlem", + "Viewer": "Läsare", "Admin": "Admin", - "{{appName}} is available in your language {{optionLabel}}, would you like to change?": "{{appName}} is available in your language {{optionLabel}}, would you like to change?", - "Change Language": "Change Language", + "{{appName}} is available in your language {{optionLabel}}, would you like to change?": "{{appName}} är tillgängligt på ditt språk {{optionLabel}}, vill du ändra språk?", + "Change Language": "Byt språk", "Dismiss": "Dismiss", - "You’re offline.": "You’re offline.", - "Sorry, an error occurred.": "Sorry, an error occurred.", - "Click to retry": "Click to retry", + "You’re offline.": "Du är offline.", + "Sorry, an error occurred.": "Tyvärr, ett fel har uppstått.", + "Click to retry": "Klicka för att försöka igen", "Back": "Tillbaka", "Unknown": "Unknown", - "Mark all as read": "Mark all as read", + "Mark all as read": "Markera alla som lästa", "You're all caught up": "You're all caught up", "Documents": "Documents", "Results": "Results", @@ -247,6 +247,16 @@ "Save": "Spara", "New name": "New name", "Name can't be empty": "Name can't be empty", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Profile picture", "Insert column after": "Infoga kolumn till höger", "Insert column before": "Infoga kolumn till vänster", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Viewed {{ count }} times by {{ teamMembers }} people", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "Sorry, it looks like you don’t have permission to access the document", "Sorry, this document is too large - edits will no longer be persisted.": "Sorry, this document is too large - edits will no longer be persisted.", "Sorry, the last change could not be persisted – please reload the page": "Sorry, the last change could not be persisted – please reload the page", "This template will be permanently deleted in <2> unless restored.": "This template will be permanently deleted in <2> unless restored.", diff --git a/shared/i18n/locales/th_TH/translation.json b/shared/i18n/locales/th_TH/translation.json index 1ce2efa8102f..1b0535a60559 100644 --- a/shared/i18n/locales/th_TH/translation.json +++ b/shared/i18n/locales/th_TH/translation.json @@ -247,6 +247,16 @@ "Save": "Save", "New name": "New name", "Name can't be empty": "Name can't be empty", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Profile picture", "Insert column after": "แทรกคอลัมน์ถัดไป", "Insert column before": "แทรกคอลัมน์ก่อนหน้า", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Viewed {{ count }} times by {{ teamMembers }} people", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "Sorry, it looks like you don’t have permission to access the document", "Sorry, this document is too large - edits will no longer be persisted.": "Sorry, this document is too large - edits will no longer be persisted.", "Sorry, the last change could not be persisted – please reload the page": "Sorry, the last change could not be persisted – please reload the page", "This template will be permanently deleted in <2> unless restored.": "This template will be permanently deleted in <2> unless restored.", diff --git a/shared/i18n/locales/tr_TR/translation.json b/shared/i18n/locales/tr_TR/translation.json index 8da5a5b4ff7e..47d7d127271a 100644 --- a/shared/i18n/locales/tr_TR/translation.json +++ b/shared/i18n/locales/tr_TR/translation.json @@ -247,6 +247,16 @@ "Save": "Kaydet", "New name": "New name", "Name can't be empty": "Name can't be empty", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Profil fotoğrafı", "Insert column after": "Sağına sütun ekle", "Insert column before": "Soluna Sütun Ekle", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "{{ teamMembers }} kişi tarafından {{ count }} kez görüntülendi", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "Üzgünüz, bu dokümana erişim izniniz yok gibi görünüyor", "Sorry, this document is too large - edits will no longer be persisted.": "Sorry, this document is too large - edits will no longer be persisted.", "Sorry, the last change could not be persisted – please reload the page": "Üzgünüz, son değişiklik devam ettirilemedi - lütfen sayfayı yeniden yükleyin", "This template will be permanently deleted in <2> unless restored.": "Bu şablon, restore edilmedikçe <2> içinde kalıcı olarak silinecek.", diff --git a/shared/i18n/locales/uk_UA/translation.json b/shared/i18n/locales/uk_UA/translation.json index e363b69e7754..1cca6d7c6973 100644 --- a/shared/i18n/locales/uk_UA/translation.json +++ b/shared/i18n/locales/uk_UA/translation.json @@ -247,6 +247,16 @@ "Save": "Зберегти", "New name": "Нова назва", "Name can't be empty": "Назва не може бути незаповненою", + "Previous match": "Попередній збіг", + "Next match": "Наступний збіг", + "Find and replace": "Знайти та замінити", + "Find": "Знайти", + "Match case": "З урахуванням регістру", + "Enable regex": "Увімкнути регулярні вирази", + "Replace options": "Replace options", + "Replacement": "Заміна", + "Replace": "Замінити", + "Replace all": "Замінити все", "Profile picture": "Аватар", "Insert column after": "Додати стовпець зліва", "Insert column before": "Додати стовпець справа", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Переглянуто {{ count }} разів {{ teamMembers }} людьми", "Viewer insights": "Статистика глядачів", "As an admin you can manage if team members can see who has viewed this document": "Як адміністратор ви можете контролювати, чи можуть члени команди бачити, хто переглядав цей документ", - "Sorry, it looks like you don’t have permission to access the document": "Вибачте, схоже, у вас немає дозволу на доступ до документа", "Sorry, this document is too large - edits will no longer be persisted.": "На жаль, цей документ завеликий – зміни більше не зберігатимуться.", "Sorry, the last change could not be persisted – please reload the page": "На жаль, не вдалося зберегти останню зміну – перезавантажте сторінку", "This template will be permanently deleted in <2> unless restored.": "Цей шаблон буде остаточно видалено через <2> якщо не буде відновлено.", diff --git a/shared/i18n/locales/vi_VN/translation.json b/shared/i18n/locales/vi_VN/translation.json index 53c3e4c1a09a..e0fd694c1d48 100644 --- a/shared/i18n/locales/vi_VN/translation.json +++ b/shared/i18n/locales/vi_VN/translation.json @@ -247,6 +247,16 @@ "Save": "Lưu", "New name": "Tên mới", "Name can't be empty": "Không được để trống tên", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "Ảnh đại diện", "Insert column after": "Chèn cột sau", "Insert column before": "Chèn cột trước", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Đã xem {{ count }} lần bởi {{ teamMembers }} người", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "Xin lỗi, có vẻ như bạn không có quyền truy cập vào tài liệu", "Sorry, this document is too large - edits will no longer be persisted.": "Rất tiếc, tài liệu này quá lớn - các chỉnh sửa sẽ không còn được duy trì.", "Sorry, the last change could not be persisted – please reload the page": "Xin lỗi, không thể tiếp tục thay đổi cuối cùng - vui lòng tải lại trang", "This template will be permanently deleted in <2> unless restored.": "Mẫu này sẽ bị xóa vĩnh viễn sau <2> trừ khi được khôi phục.", diff --git a/shared/i18n/locales/zh_CN/translation.json b/shared/i18n/locales/zh_CN/translation.json index 935fa69bb03e..8d7935e17252 100644 --- a/shared/i18n/locales/zh_CN/translation.json +++ b/shared/i18n/locales/zh_CN/translation.json @@ -247,6 +247,16 @@ "Save": "保存", "New name": "新的名称", "Name can't be empty": "名称不能为空", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "个人头像", "Insert column after": "在右侧插入列", "Insert column before": "在左侧插入列", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "{{ teamMembers }} 人浏览 {{ count }} 次", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "抱歉,看起来您没有权限访问此文档", "Sorry, this document is too large - edits will no longer be persisted.": "抱歉,此文档太大 - 将不再保留所做的编辑。", "Sorry, the last change could not be persisted – please reload the page": "抱歉,无法保存上次更改 - 请重新载入页面", "This template will be permanently deleted in <2> unless restored.": "此模板将在 <2> 中永久删除,除非手动恢复。", diff --git a/shared/i18n/locales/zh_TW/translation.json b/shared/i18n/locales/zh_TW/translation.json index db2c4eedcf3f..492f345c0a33 100644 --- a/shared/i18n/locales/zh_TW/translation.json +++ b/shared/i18n/locales/zh_TW/translation.json @@ -247,6 +247,16 @@ "Save": "儲存", "New name": "新的名稱", "Name can't be empty": "名稱不可以空白", + "Previous match": "Previous match", + "Next match": "Next match", + "Find and replace": "Find and replace", + "Find": "Find", + "Match case": "Match case", + "Enable regex": "Enable regex", + "Replace options": "Replace options", + "Replacement": "Replacement", + "Replace": "Replace", + "Replace all": "Replace all", "Profile picture": "大頭貼", "Insert column after": "插入欄位於右方", "Insert column before": "插入欄位於左方", @@ -513,7 +523,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "{{ teamMembers }} 人共瀏覽過 {{ count }} 次", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, it looks like you don’t have permission to access the document": "抱歉,您似乎沒有權限存取該文件", "Sorry, this document is too large - edits will no longer be persisted.": "抱歉,這個文件太大 - 將不再保留編輯內容。", "Sorry, the last change could not be persisted – please reload the page": "抱歉,無法保留上次更改 - 請重新加載頁面", "This template will be permanently deleted in <2> unless restored.": "範本若未於 <2> 還原,將被永久刪除。", From 434812dbe37c8f2a8db4b7f7f69419acd1f6ebc8 Mon Sep 17 00:00:00 2001 From: Apoorv Mishra Date: Wed, 9 Aug 2023 21:52:44 +0530 Subject: [PATCH 115/144] Allow `vite` to serve files from workspace's parent directory (#5675) * fix: allow vite to serve files from workspace parent dir * trigger ci * trigger ci --- vite.config.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vite.config.ts b/vite.config.ts index 633d1308d0b4..50664d9e59b6 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -38,6 +38,13 @@ export default () => port: 3001, host: true, https: httpsConfig, + fs: + process.env.NODE_ENV === "development" + ? { + // Allow serving files from one level up to the project root + allow: [".."], + } + : { strict: true }, }, plugins: [ // https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#readme From f5d2c7890a90c7eb2a5bd66e8aa29ebf6aee647b Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Thu, 10 Aug 2023 15:13:40 +0200 Subject: [PATCH 116/144] fix: Unable to create collection with no access permission --- app/components/InputSelectPermission.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/InputSelectPermission.tsx b/app/components/InputSelectPermission.tsx index cc307cdef06c..5f108bacc7c7 100644 --- a/app/components/InputSelectPermission.tsx +++ b/app/components/InputSelectPermission.tsx @@ -18,7 +18,7 @@ export default function InputSelectPermission( const handleChange = React.useCallback( (value) => { if (value === "no_access") { - value = ""; + value = null; } onChange?.(value); From 8830773acb461ac91bf373e74cf163eb9effcd8d Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Fri, 11 Aug 2023 22:26:40 +0200 Subject: [PATCH 117/144] fix: Mobile styling bugs --- app/components/ContextMenu/index.tsx | 2 +- app/scenes/Document/components/Header.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/ContextMenu/index.tsx b/app/components/ContextMenu/index.tsx index 6c24ef1bb6fc..c883118e0316 100644 --- a/app/components/ContextMenu/index.tsx +++ b/app/components/ContextMenu/index.tsx @@ -151,7 +151,7 @@ const ContextMenu: React.FC = ({ ref={backgroundRef} hiddenScrollbars style={ - topAnchor + topAnchor && !isMobile ? { maxHeight, } diff --git a/app/scenes/Document/components/Header.tsx b/app/scenes/Document/components/Header.tsx index 05231e299317..f9061521abc6 100644 --- a/app/scenes/Document/components/Header.tsx +++ b/app/scenes/Document/components/Header.tsx @@ -138,7 +138,7 @@ function DocumentHeader({ to={documentEditPath(document)} neutral > - {t("Edit")} + {isMobile ? null : t("Edit")} From 4a4ea0e5310fd6a0014eccced6fcc0efeeee2cd2 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Fri, 11 Aug 2023 22:30:48 +0200 Subject: [PATCH 118/144] fix: Text alignment on collection empty state --- app/components/Text.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/Text.ts b/app/components/Text.ts index bd69efccc856..f9759745d3e9 100644 --- a/app/components/Text.ts +++ b/app/components/Text.ts @@ -14,7 +14,7 @@ type Props = { */ const Text = styled.p` margin-top: 0; - text-align: ${(props) => (props.dir ? props.dir : "initial")}; + text-align: ${(props) => (props.dir ? props.dir : "inherit")}; color: ${(props) => props.type === "secondary" ? props.theme.textSecondary From cf2f0b1b5c0179c6425a8e2c04b004f331b2f540 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Fri, 11 Aug 2023 22:34:14 +0200 Subject: [PATCH 119/144] fix: Flash of empty state in sidebar when creating a new collection --- app/scenes/CollectionNew.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/scenes/CollectionNew.tsx b/app/scenes/CollectionNew.tsx index e6293212a7a7..c78ff588ade0 100644 --- a/app/scenes/CollectionNew.tsx +++ b/app/scenes/CollectionNew.tsx @@ -56,6 +56,7 @@ class CollectionNew extends React.Component { icon: this.icon, color: this.color, permission: this.permission, + documents: [], }, this.props.collections ); From f4e499250842f7b7b4e77ff0826b8069e5c6d371 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Fri, 11 Aug 2023 22:35:38 +0200 Subject: [PATCH 120/144] fix: Remove fetch-with-proxy from DeliverWebhookTask --- plugins/webhooks/server/tasks/DeliverWebhookTask.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/webhooks/server/tasks/DeliverWebhookTask.ts b/plugins/webhooks/server/tasks/DeliverWebhookTask.ts index 6dfa66542add..c53356e6f8d0 100644 --- a/plugins/webhooks/server/tasks/DeliverWebhookTask.ts +++ b/plugins/webhooks/server/tasks/DeliverWebhookTask.ts @@ -1,5 +1,4 @@ -import fetch from "fetch-with-proxy"; -import { FetchError } from "node-fetch"; +import fetch, { FetchError } from "node-fetch"; import { useAgent } from "request-filtering-agent"; import { Op } from "sequelize"; import WebhookDisabledEmail from "@server/emails/templates/WebhookDisabledEmail"; From 9749a53558b44e21c529151bded6a1aa32818494 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sat, 12 Aug 2023 11:44:16 +0200 Subject: [PATCH 121/144] feat: Handle pasting iframe for supported embed --- shared/editor/extensions/PasteHandler.ts | 46 +++++++++++++++++++++--- shared/editor/nodes/Embed.tsx | 4 +-- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/shared/editor/extensions/PasteHandler.ts b/shared/editor/extensions/PasteHandler.ts index fe133da058e4..bc4ce2481cc4 100644 --- a/shared/editor/extensions/PasteHandler.ts +++ b/shared/editor/extensions/PasteHandler.ts @@ -9,9 +9,13 @@ import isInCode from "../queries/isInCode"; import isInList from "../queries/isInList"; import { LANGUAGES } from "./Prism"; +/** + * Checks if the HTML string is likely coming from Dropbox Paper. + * + * @param html The HTML string to check. + * @returns True if the HTML string is likely coming from Dropbox Paper. + */ function isDropboxPaper(html: string): boolean { - // The best we have to detect if a paste is likely coming from Paper - // In this case it's actually better to use the text version return html?.includes("usually-unique-id"); } @@ -23,6 +27,34 @@ function sliceSingleNode(slice: Slice) { : null; } +/** + * Parses the text contents of an HTML string and returns the src of the first + * iframe if it exists. + * + * @param text The HTML string to parse. + * @returns The src of the first iframe if it exists, or undefined. + */ +function parseSingleIframeSrc(html: string) { + try { + const parser = new DOMParser(); + const doc = parser.parseFromString(html, "text/html"); + + if ( + doc.body.children.length === 1 && + doc.body.firstElementChild?.tagName === "IFRAME" + ) { + const iframe = doc.body.firstElementChild; + const src = iframe.getAttribute("src"); + if (src) { + return src; + } + } + } catch (e) { + // Ignore the million ways parsing could fail. + } + return undefined; +} + export default class PasteHandler extends Extension { get name() { return "paste-handler"; @@ -65,10 +97,16 @@ export default class PasteHandler extends Extension { return false; } - const text = event.clipboardData.getData("text/plain"); + const { state, dispatch } = view; + const iframeSrc = parseSingleIframeSrc( + event.clipboardData.getData("text/plain") + ); + const text = + iframeSrc && !isInCode(state) + ? iframeSrc + : event.clipboardData.getData("text/plain"); const html = event.clipboardData.getData("text/html"); const vscode = event.clipboardData.getData("vscode-editor-data"); - const { state, dispatch } = view; // first check if the clipboard contents can be parsed as a single // url, this is mainly for allowing pasted urls to become embeds diff --git a/shared/editor/nodes/Embed.tsx b/shared/editor/nodes/Embed.tsx index f7c4d27759ab..0876d2f37dd1 100644 --- a/shared/editor/nodes/Embed.tsx +++ b/shared/editor/nodes/Embed.tsx @@ -27,7 +27,7 @@ export default class Embed extends Node { }, parseDOM: [ { - tag: "iframe.embed", + tag: "iframe", getAttrs: (dom: HTMLIFrameElement) => { const { embeds } = this.editor.props; const href = dom.getAttribute("src") || ""; @@ -43,7 +43,7 @@ export default class Embed extends Node { } } - return {}; + return false; }, }, ], From 6828718cf01b383802ac8deaafc6e20c969a6495 Mon Sep 17 00:00:00 2001 From: Jack Woodgate <67034721+lampy255@users.noreply.github.com> Date: Sat, 12 Aug 2023 21:45:21 +1200 Subject: [PATCH 122/144] feat: Add Google Maps Embed (#5667) (#5673) Co-authored-by: Tom Moor --- public/images/google-maps.png | Bin 0 -> 8570 bytes shared/editor/embeds/GoogleMaps.test.ts | 18 ++++++++++++++++++ shared/editor/embeds/GoogleMaps.tsx | 16 ++++++++++++++++ shared/editor/embeds/index.tsx | 8 ++++++++ 4 files changed, 42 insertions(+) create mode 100644 public/images/google-maps.png create mode 100644 shared/editor/embeds/GoogleMaps.test.ts create mode 100644 shared/editor/embeds/GoogleMaps.tsx diff --git a/public/images/google-maps.png b/public/images/google-maps.png new file mode 100644 index 0000000000000000000000000000000000000000..f2b6a1863139b08e2a1967cf8f93367732128c18 GIT binary patch literal 8570 zcmcI~cT`jDwLuWq$nU@1ZkmZXwn3v zcaYwsccct{ZSIX|} zAPHROQ7wYds-K0z?5aKN)A}IVjsDFUEy8m~mr{}+D zl&_lqjhDam{-_X7xJHh5inP$ zp#KD_t1GSLh4O`XLE&1eavV3J1YKQW(qNE?BSgf}5hx6Ti2%jK!Hz(Pgt#ye3Ia>Q zz)+Y3*y%4_H}vg8fzn5f*{MKoUSHQAs#ZOcE>%1PhCa z0U=N)xENFd3>TLW=K#Q<(oP7ZC*-D6Ts6(HH$xbC+`)o_!)&0Xs$>#4 zxs^@oYrI_3(I2wewA?gSYHmPHO%|!lL*|>SYc1HR@|`>%)M;RqM;AvH6B`D|{Xz27 z?g-S$6&_~FoxU!c@JiWwEwK;(`yhLEW>xR?qq)?#Z|{2!aj(8@hka;5cB+n@!FMj_ zeof7h)=DhQWp&HPUgU%*95QduBzjI0Lu4@Y&GtSI@D+IaFR?(<@s^--#KJ7)`QY$Y z_qm!-_9N%(>+Dd`&=#$a90Lf}j2XUliXGx6cgldm1j(8OpMdY=~tTzUSwaC#=BqzUrD*~oSeTKsmxKR zUV7R3(F?g*P$|5hI#CWjmR4uW#NQ`w-ZKwKROoZD71nU$d3Ew_dS0<_J#7&+4qiDH zXv?oOHb?@q95MNeyss?^B;)~J?5wph+2S{H!1!x3u4EQMyz+LU{vh!9#=FmESnS`i z%9OW;yOK6H1Mv@KKmQe+uOG&fLu&J_OdsngySYO;^nhGseRQSkf zWkK!}CKbaRr#Csl?t?aSnGZ0zFd;#Spd9}&bJ_&kdsp{rp9F64ubOX{vm1Pf?<3f= zDM;PGJC10Hva^VpZH^OJm}X8xItVt_^kM50iWcLj3g=5tiX0a;grF0vA0g*x@LI?; z`E1wF6Ln*}af(3`cg^-u7iw$VbQMw;V_1>wV=-Z$z3T{W;6nb(8LhQr7YGo?*ji(M zi#TuUT4MchFpNgSE^_ACnR>Z&#u|n>>W^kUS+O_Rtk|&i#Uz&5%P5Ma3JzEA%Do&v~8;?qrhSbxw$Yj=$Lb%E;By>guSib#N-;fB+dzt3*71) zVqK%xY58d`nz-|WfPy7_VE~#mKTYe@plC#7~?_#2du7>8V5r4;;?yr-ms( z4dClI6_u6#2IA>)Buo;0nn8o~XQ;3F6`i#EB`JyU_m_a4pgm3K0Atq0Y;>EM&vcPb zNZpoXDErYCBM13Ho!IJK_I2(;551rtOtdK{z;p^($-4nRS^UCFK}iep?^5}Z_P!>H zDHg?%?x@Z|qWnDU!Tt3nA@IbEA4{$Hyzt3ZFLb(XXm*{h+|Xd%OFuFYvKexXNAz6% zbJJ~*D#y%x4cXLt0_4?Z{I@t)J*R~@J`dWGcTD*W?H`6%ByZussD{a?^RM71O0n&0~Ix@g`%v;AoSN^~Z zvpm35Mk4uiqu%mjz8Q(=mU1@RSi3J!i!TLzB|1n{mn-4&Ha|k!IM4@r?$8P9nC0u` z0tZ45bCha2R+~r1^9Jj<@?+0>PKrQ=?ff?H;J4>rk0!h_Apfdtr;Fp9bT0LXE^#D! zxHCK{Gx%$i^;)e@MV-jWhR3M0ti>;pphj}OGM2>maF@bmBgzjUYJC`$&vbQ5@|B{w zTUyz&n@iUvOd#`gxKL4m7RA#wrPvuf@qTR>ed7Xvr`WYSRykW+E902Z{oRA z?t`uaM<5_Bx&d(AKH$7Ozf4pZlG~lWHcf z(}&RyNC`(AWc_}HY-ovzf~WdOd3fUM z;~~Q*NIW=d3|$XTZ#&M0M=zl8(t|p5W^|0iR)@2eA z*yrk0ANR8$Hg@<7^_W-d<{~>wHp^*^dk zKPPYL!TiM(Gg0`1opqPZPfP2(SB@0>zvL{^5Y`@Gm4%WpolIsio1rY7NJhEB6AjI5 z8=b~%|3+yy-z6H66bTeJ-p6(hDS@{kIR1x*fow+>Jq4l_LVI*2?rvBwBv}>d(MWai zhZ2aHy)E%@4}E`9W|diNYi%Fo=QBbIG3$XnA4ZmKXi4326uV+Bp%)eB{IF6SAyHC{ zQsI2Y3XHF@xL#gKo7ajbHF)PTP3R&Ltbt7~a) z%8ke@y`!yB0OpF;;5=d)>-)IHx4G1JYoRVb_Zp>nY^Obpa&yN-;r?7&Z2l2SefR=2 zDxt)YB!*wg39%$>GBJv(3bE8|%6zsTi_FzpU*obF8Z#O_VMj|eQhWW_UMSC^0-x+#J~c-Kn7M}dK3Mf z5Y~@b*6+jaCyN?TpjFpj5d4Ju+?gdkrA^igsw{u-prEU0&M_fdpUSK;wXvqKB%`?r zK=~C#Toe|6Z$O9|5fW<^4Hw6JGy2e3+m9!H#hG-RMb7-bi*}C~Q{G>xIle1$@d-pt zyM_p)D$E>(YpL_$XP-sl%ze-I^S$6*D}Fr-5dUd+!RxSEfh3O;hv$tt{=CTZ#Kr=5{#FgWqMp6RaB-u>;Py zpXPIl2YoCLQxgztSlCPpr_eD~GbP6ms=5qh$3338?`X{<9+baP(Geg6ot#)6XMLPD z@=feya19V+)h0d2bNzmxO7&lj#|(dk4&70>6l3LHk@&X(>yw*z5un8xH6-?!`8L(>rO5mBFjtO zmpRQ^+rID2V{W+$zn&2vb+{FG+`2!Q;#P-`=}k1&EcO!Cm=Sl6>CH-#H__eQ&8J}N0t^SOs{Qnf2dLCggrn3lYL;Lo1=5!b41Vl z_V&R28gHkN=k)|*5CO9D0vV=-=qtM62c@pZ2W=M^WHoGbNhWvtfpb&w5+lq~7159r6Y>2d#?OKAAc5W19L-Rio-*UdnurWVUOazxn9 z!&#ZnDp*_79;;Qy`fRQO1p^R{Bq~&Wp{l);4c3BFQ-)xo>?Kq1|_gVEAv%vCH<-{bR=(55qcK71fpZZPgpEv?_ z_RrsizL}r6Os?XKY&_k!p`Y%=$Nb1_RXl^o(Nv!B&`}E&0>pz5kS|x7Hg&Y0>nuq~ zNjJ!B=5dDBNDi5)fI?3^KdDrLu&6&>84Q2mWY2 z+$*dn`qo$;>sNm&5IK1=ebpNh$!pWD#q&MtRUuo;RlbfEq%&QX*d4A7b zrlj9|nTjQ1Jo_4A|5Px_X`cCB(}^y&i_X4Uo%l!_42nfgDC2rUrQPmO~OKCHr zikr`0$vNLUM$X?96$f<*G$PjV%sb8A$=sINA@YI)tZMlbZq2>u@CW;s6zMQBvQ8~W zm^RD2+R~4dE{eNTcFAhe;&B9eTi2?Q>UT-Qttegw4Xdz8`aIfSxSDnyxR?KHNgT(2!O1@6-k zXlQWo@+q5RTJQ?b68m%?F&y1KDBsYoURGWh3E*lcNF%;dZhR@Y>)zdUD3XzST{Fc5 zjqg>no49vu_w23mdeiIf#?Xil%%v%eXVIl_i&31k(b@sxW6pjLDdwDp3V+}QXs~Ks zG(ZSjLijjCp*y+>-mfUwheGMQbfV^=mWCEIr{Z=}mkhVH#HRJ+4;Z@U?HApgBJxW|Vi+oI68Y5K z?Bz~adrl6oX+P0v$4n=Xo1{yUT-gxle$D?R}Kvl-<~mvvaa z=ywW01t0C#%GiTMtyeW}nD|*2XhBd)T(fBvw*tjvvwUWh)767KVn}-P*4xz@lA-lK zG;KaVU!KEelGck!)OU;vG$}uf>*^kbR=%dE5cG^K_Luk$Jx>enh;262vqFeqd~865EdC?!ib&)CO)@$C-+jVJ}HFg6diBZEHq z1ZPnz-=g`SacnII8{9Rt;&Chqoc1`A`6f@`%;OKI2`%W|=u#Zh z$uHNF@XK8BrEHboii^(R%wA*3f2R2tT3ts)2tNqD9Lcy-cOF?vWSOvWHh_r;ccWbt znQi%`OO9DRd)o8n$OhXYCUU;_67?eN78r11aJ!(RWh*_5kSWnP$V)YWqDPKVcU2l)V$rTmba_i$hMjrrO6pkUVz|)f`OyfaOYYa&Ow+6sbs_kn zBwo1o-q(~tx&&e~Fc6cwqD}ocCwqWBmMY`UY-2P$h`-U&0n&mL z(nR=C)J8{dZjZ;Um;)aSX=Z265O;<=#op3z_7bx(#*pb#O5lw)T}tU(dy~IW^Bjco zeqoD5Pn*nJB_)Ty2x}N@+pWhYug(TB@CK9de*r&zpSb~e@3lq?V|v0eDB9u|U`e&T z^e(oZqLxv9B8WwgpZ~{&p709d8D}EgHoS~ti~@P$8Fh!XyxuDGX4YM%tr}tcdwN6= zC;?gd1b8CjLx$+?j3~kA&BPyGTU}9v0x`KpQE;*`JJNuwl{@}BS3xW`uM+uv_m;M; zm6?!h+qgDDxGkS%kXqyzK4V47CsQdF_gbo}EN!DBiEh5Lezy3yQkOYA@8wEbdmr{F zViUW)(iL^*q4^h+fzqeZ%QerH3&9gxl~UPqb0vJV7L}zG zwy_^5S-NZ|AP~Ud<=&|iII{Mmt9i!pi83ZG34|eT3_6}Js$Z(}REZzawPg;ak9~}7 zAuYMt=TEozY~+Wlaa+Z|ghi6~05k8@w~Umb;q~Gw6pLLKxS^e>gHwv04qwWidrJP$ z-b8e&0TJ2Q1rCF}z=OairG~bfiODJv_HM%p4xfpa=x+LSIOERpmW0URt#neMdztKb z!Jk5L$tUs#qph~3VYb0zM(oawhr||Z_Z1?o7$~<@!0GQdiLzU&aT1U4E$;Mh71ekH z%2sQ58htlx5A2oKDKWis`-`sg*jcQ%_-g~(TVr?>`|Ct$C$^zPeRY$|FxyOaxA2GO z_HI9=9cBa0-nSqtx>5I^7Q<~L%;DAX8&=mj)8g2KdaF@FWU5?xq?Eq6`g zO0>PS*N^zMYXr^8BR-QRDjS>IA97PfH(Hm#XM)G1hr8-uEY(n@rOxfUx1uEF@N!CN z_NVGg-S0`;dEzsmpAE=OCbS%)3E7s0C@eIqFL;B!LOAQ{OE&dJyQuJ2E^9A_NA}Sg zY+mm3)rzTI)Rsjfet)d)mRhG57%(22Gy_A$hCk(vR5LVf8tE-98lq3xop81DlyAA6 z>EoF%^3nA--0eawPoE~+wL|0k=TAVVy*a;z-*Bw@6M^hEqaMezQpY)DpPENF(IY&*)zARP2P>xWe@$oLG zfB!0$=^eURa#qBH8`S#zY4`U;Kc+5IW^@t5kH_?TV+&?J#Arl~5>cdk_hw7;Lr$BV z+Adyzv0rcK8YeH#`ns#xbgv1OUWV&q@`XG(w~l5`(x7ztnl6Hc>4~A3*yot^oQ!Ut zX2})r_g%>h?5%XSf=_Iqee@5vGn6P5VXA2%NF$DpGj73E!5Nz_t--ChL@O`T27tmv806t}-{f(fYZ!pKauZqc!Rw zH2it;=$MZUFD^?)V_HKR=4Fp=wl7{f{)?Qc%8?^h$Eur*0*bpyx+Iljhy`%H|-+{dyh||gK`|*3Px9`z<0fMh0L#E z?iecE;|HOsagAqpdAdTPRrV&Y-8w_(bH#e;UO2u!{Uot6?Ujq};j>npeNXBk6XuM3 zIo(dM8)CCK^V&w`s?pNV(Xd3el>lkPzo^HCR~yhHJyx6&RC{LaXes%9ls_?Ozv(MB)TGTR%nrIaP-<-`zPMV;EG2&e#g`vr}KcarUxP@6)`77?AK|1 z`s+HHh#Uvnf>qzquP*-a&JS5$jLFBhu&Kh&cGe%;h0ggt$2=_P?qV}hzrq+5ta}~W45GCAKa7o@ zp1zy9{ZM{99pl!4V5*tYdy6U!;PD9^+jb{By~f4US2{d4iY@&8?+7h5Jyo=_!_)r- Dqyxxg literal 0 HcmV?d00001 diff --git a/shared/editor/embeds/GoogleMaps.test.ts b/shared/editor/embeds/GoogleMaps.test.ts new file mode 100644 index 000000000000..20bf3372e6b5 --- /dev/null +++ b/shared/editor/embeds/GoogleMaps.test.ts @@ -0,0 +1,18 @@ +import GoogleMaps from "./GoogleMaps"; + +describe("GoogleMaps", () => { + const match = GoogleMaps.ENABLED[0]; + + test("to be enabled", () => { + expect( + "https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d50977.036904273686!2d174.74383592605594!3d-37.00825027293197!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x6d0d4fe87ef3d5bb%3A0xf00ef62249b7130!2sAuckland%20Airport!5e0!3m2!1sen!2snz!4v1691573100204!5m2!1sen!2snz".match( + match + ) + ).toBeTruthy(); + }); + + test("to not be enabled elsewhere", () => { + expect("https://www.google.com/maps/embed".match(match)).toBe(null); + expect("https://goo.gl/maps/".match(match)).toBe(null); + }); +}); diff --git a/shared/editor/embeds/GoogleMaps.tsx b/shared/editor/embeds/GoogleMaps.tsx new file mode 100644 index 000000000000..9039f6e0a7b6 --- /dev/null +++ b/shared/editor/embeds/GoogleMaps.tsx @@ -0,0 +1,16 @@ +import * as React from "react"; +import Frame from "../components/Frame"; +import { EmbedProps as Props } from "."; + +function GoogleMaps(props: Props) { + const { matches } = props.attrs; + const source = matches[0]; + + return ; +} + +GoogleMaps.ENABLED = [ + new RegExp("^https?://www\\.google\\.com/maps/embed\\?(.*)$"), +]; + +export default GoogleMaps; diff --git a/shared/editor/embeds/index.tsx b/shared/editor/embeds/index.tsx index a8b1437c4cd3..f7c1ed1f1330 100644 --- a/shared/editor/embeds/index.tsx +++ b/shared/editor/embeds/index.tsx @@ -27,6 +27,7 @@ import GoogleDrawings from "./GoogleDrawings"; import GoogleDrive from "./GoogleDrive"; import GoogleForms from "./GoogleForms"; import GoogleLookerStudio from "./GoogleLookerStudio"; +import GoogleMaps from "./GoogleMaps"; import GoogleSheets from "./GoogleSheets"; import GoogleSlides from "./GoogleSlides"; import Grist from "./Grist"; @@ -219,6 +220,13 @@ const embeds: EmbedDescriptor[] = [ icon: Diagrams.net, component: Diagrams, }), + new EmbedDescriptor({ + title: "Google Maps", + keywords: "maps", + icon: Google Maps, + component: GoogleMaps, + visible: true, + }), new EmbedDescriptor({ title: "Google Drawings", keywords: "drawings", From 3ba730943cecea9c2cac377ea9087cbacd1739bd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 12 Aug 2023 02:47:12 -0700 Subject: [PATCH 123/144] chore: Auto Compress Images (#5682) Co-authored-by: tommoor --- public/images/google-maps.png | Bin 8570 -> 7070 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/public/images/google-maps.png b/public/images/google-maps.png index f2b6a1863139b08e2a1967cf8f93367732128c18..65fb7ee5be02905f5c39b46f8057fdaa597f39e3 100644 GIT binary patch delta 11 Scmez6G|zm3#byzG(eWyul*88fz9f$o`#AX|n^rEJ+Tf4uR^c!iom9MSXWeG10ZGveIUz03D@B%!Q4hQ@gg2ms{SV?o;KGh8t00>XFXY z1{lX*hUR&XZfjoKhnFr)ulPphdU{oA{8ZQGqLTXIr7rB!;*Ll@``iQ)3npTvzL4Lj%~rW8hvaWL9*wcoIRU z%F8mvLq-!plLQf_DDs1_O^_G{1W6W-R4COjOxMaB!NkamE{7e#x`CCEj%1r9?$eZx zNy5;84n{}_pP?`zK1zJWRN|+aj@8PiV|!9%?hT2>E^CvwrKdVwf>5d05RC^Tjr>ta zP)K|q37KkN4nrLb0|=Dlsi|_|x+TlSOyjbcLGVe=ky)6^<;bOd&^5Jl?E*i_YFEFj z{+*oaXZ>!Gf!emN_qdQ<&qq*prPfaIswH`LQv&xAy1u`hYe)Kp25_*}g|AI&m!i^# zGnec=dJOLx*wtT)%l}aSdHIv}rtSE{|h+$@67-J From 2bc52be2cf83658f4f7734c198da20704a50ed9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 09:28:58 -0700 Subject: [PATCH 124/144] chore(deps): bump email-providers from 1.13.1 to 1.14.0 (#5687) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 6d6f4bdc6831..a45d52fbd3b5 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "date-fns": "^2.30.0", "dd-trace": "^3.32.1", "dotenv": "^4.0.0", - "email-providers": "^1.13.1", + "email-providers": "^1.14.0", "emoji-regex": "^10.2.1", "es6-error": "^4.1.1", "fetch-retry": "^5.0.5", diff --git a/yarn.lock b/yarn.lock index 5d5566800728..b4c64c9f078e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5939,10 +5939,10 @@ elkjs@^0.8.2: resolved "https://registry.yarnpkg.com/elkjs/-/elkjs-0.8.2.tgz#c37763c5a3e24e042e318455e0147c912a7c248e" integrity sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ== -email-providers@^1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/email-providers/-/email-providers-1.13.1.tgz#dfaea33a7744035510f0f64ed44098e7077f68c9" - integrity sha512-+BPUngcWMy9piqS33yeOcqJXYhIxet94UbK1B/uDOGfjLav4YlDAf9/RhplRypSDBSKx92STNH0PcwgCJnNATw== +email-providers@^1.14.0: + version "1.14.0" + resolved "https://registry.yarnpkg.com/email-providers/-/email-providers-1.14.0.tgz#a353f56390f9a8b42ba1843a1701c1f5fcd332ee" + integrity sha512-9PjNtvOzhnl5mtyAnxe7tUQ/SWnplbJjk0w6+8fKIjFFOQizqB+H+9dvOdwOVz07iOHt2zvl0Yb1bFAl1il0pA== emittery@^0.12.1: version "0.12.1" From 503e4e1f71b7f9e0c317b06d4407ff1af90b3856 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 10:14:40 -0700 Subject: [PATCH 125/144] chore(deps-dev): bump @typescript-eslint/eslint-plugin from 5.61.0 to 5.62.0 (#5688) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 74 ++++++++++++++-------------------------------------- 2 files changed, 21 insertions(+), 55 deletions(-) diff --git a/package.json b/package.json index a45d52fbd3b5..59f76d67a968 100644 --- a/package.json +++ b/package.json @@ -291,7 +291,7 @@ "@types/turndown": "^5.0.1", "@types/utf8": "^3.0.1", "@types/validator": "^13.7.17", - "@typescript-eslint/eslint-plugin": "^5.61.0", + "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "babel-eslint": "^10.1.0", "babel-jest": "^29.6.1", diff --git a/yarn.lock b/yarn.lock index b4c64c9f078e..6612bc1d0ca6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3555,15 +3555,15 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^5.61.0": - version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.61.0.tgz#a1a5290cf33863b4db3fb79350b3c5275a7b1223" - integrity sha512-A5l/eUAug103qtkwccSCxn8ZRwT+7RXWkFECdA4Cvl1dOlDUgTpAOfSEElZn2uSUxhdDpnCdetrf0jvU4qrL+g== +"@typescript-eslint/eslint-plugin@^5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" + integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== dependencies: "@eslint-community/regexpp" "^4.4.0" - "@typescript-eslint/scope-manager" "5.61.0" - "@typescript-eslint/type-utils" "5.61.0" - "@typescript-eslint/utils" "5.61.0" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/type-utils" "5.62.0" + "@typescript-eslint/utils" "5.62.0" debug "^4.3.4" graphemer "^1.4.0" ignore "^5.2.0" @@ -3581,14 +3581,6 @@ "@typescript-eslint/typescript-estree" "5.62.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.61.0": - version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.61.0.tgz#b670006d069c9abe6415c41f754b1b5d949ef2b2" - integrity sha512-W8VoMjoSg7f7nqAROEmTt6LoBpn81AegP7uKhhW5KzYlehs8VV0ZW0fIDVbcZRcaP3aPSW+JZFua+ysQN+m/Nw== - dependencies: - "@typescript-eslint/types" "5.61.0" - "@typescript-eslint/visitor-keys" "5.61.0" - "@typescript-eslint/scope-manager@5.62.0": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" @@ -3597,39 +3589,21 @@ "@typescript-eslint/types" "5.62.0" "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/type-utils@5.61.0": - version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.61.0.tgz#e90799eb2045c4435ea8378cb31cd8a9fddca47a" - integrity sha512-kk8u//r+oVK2Aj3ph/26XdH0pbAkC2RiSjUYhKD+PExemG4XSjpGFeyZ/QM8lBOa7O8aGOU+/yEbMJgQv/DnCg== +"@typescript-eslint/type-utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" + integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== dependencies: - "@typescript-eslint/typescript-estree" "5.61.0" - "@typescript-eslint/utils" "5.61.0" + "@typescript-eslint/typescript-estree" "5.62.0" + "@typescript-eslint/utils" "5.62.0" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.61.0": - version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.61.0.tgz#e99ff11b5792d791554abab0f0370936d8ca50c0" - integrity sha512-ldyueo58KjngXpzloHUog/h9REmHl59G1b3a5Sng1GfBo14BkS3ZbMEb3693gnP1k//97lh7bKsp6/V/0v1veQ== - "@typescript-eslint/types@5.62.0": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/typescript-estree@5.61.0": - version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.61.0.tgz#4c7caca84ce95bb41aa585d46a764bcc050b92f3" - integrity sha512-Fud90PxONnnLZ36oR5ClJBLTLfU4pIWBmnvGwTbEa2cXIqj70AEDEmOmpkFComjBZ/037ueKrOdHuYmSFVD7Rw== - dependencies: - "@typescript-eslint/types" "5.61.0" - "@typescript-eslint/visitor-keys" "5.61.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" @@ -3643,28 +3617,20 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.61.0": - version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.61.0.tgz#5064838a53e91c754fffbddd306adcca3fe0af36" - integrity sha512-mV6O+6VgQmVE6+xzlA91xifndPW9ElFW8vbSF0xCT/czPXVhwDewKila1jOyRwa9AE19zKnrr7Cg5S3pJVrTWQ== +"@typescript-eslint/utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.61.0" - "@typescript-eslint/types" "5.61.0" - "@typescript-eslint/typescript-estree" "5.61.0" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.61.0": - version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.61.0.tgz#c79414fa42158fd23bd2bb70952dc5cdbb298140" - integrity sha512-50XQ5VdbWrX06mQXhy93WywSFZZGsv3EOjq+lqp6WC2t+j3mb6A9xYVdrRxafvK88vg9k9u+CT4l6D8PEatjKg== - dependencies: - "@typescript-eslint/types" "5.61.0" - eslint-visitor-keys "^3.3.0" - "@typescript-eslint/visitor-keys@5.62.0": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" From b466f1c8bb287d31c59a1d939850a3fe371fbc5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 10:14:56 -0700 Subject: [PATCH 126/144] chore(deps): bump ws from 7.5.6 to 7.5.9 (#5686) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 59f76d67a968..9a0c6564d435 100644 --- a/package.json +++ b/package.json @@ -219,7 +219,7 @@ "vite": "^4.1.5", "vite-plugin-pwa": "^0.14.4", "winston": "^3.10.0", - "ws": "^7.5.3", + "ws": "^7.5.9", "y-indexeddb": "^9.0.11", "y-protocols": "^1.0.5", "yjs": "^13.6.1", diff --git a/yarn.lock b/yarn.lock index 6612bc1d0ca6..1f2ad033b8dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13622,10 +13622,10 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" -ws@^7.5.3: - version "7.5.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" - integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== +ws@^7.5.9: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== ws@^8.11.0, ws@^8.13.0, ws@^8.5.0: version "8.13.0" From 199fa5844e9486eccec097fe34af511f87e9a578 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 10:15:19 -0700 Subject: [PATCH 127/144] chore(deps): bump react-window from 1.8.7 to 1.8.9 (#5685) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 9a0c6564d435..68f956094041 100644 --- a/package.json +++ b/package.json @@ -186,7 +186,7 @@ "react-table": "^7.8.0", "react-virtualized-auto-sizer": "^1.0.17", "react-waypoint": "^10.3.0", - "react-window": "^1.8.7", + "react-window": "^1.8.9", "reakit": "^1.3.11", "reflect-metadata": "^0.1.13", "refractor": "^3.6.0", diff --git a/yarn.lock b/yarn.lock index 1f2ad033b8dd..8c07a6067214 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11200,10 +11200,10 @@ react-waypoint@^10.3.0: prop-types "^15.0.0" react-is "^17.0.1 || ^18.0.0" -react-window@^1.8.7: - version "1.8.7" - resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.7.tgz#5e9fd0d23f48f432d7022cdb327219353a15f0d4" - integrity sha512-JHEZbPXBpKMmoNO1bNhoXOOLg/ujhL/BU4IqVU9r8eQPcy5KQnGHIHDRkJ0ns9IM5+Aq5LNwt3j8t3tIrePQzA== +react-window@^1.8.9: + version "1.8.9" + resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.9.tgz#24bc346be73d0468cdf91998aac94e32bc7fa6a8" + integrity sha512-+Eqx/fj1Aa5WnhRfj9dJg4VYATGwIUP2ItwItiJ6zboKWA6EX3lYDAXfGF2hyNqplEprhbtjbipiADEcwQ823Q== dependencies: "@babel/runtime" "^7.0.0" memoize-one ">=3.1.1 <6" From a71ad43c3102e12fb92e0b65bd88d6ba4eee1ca6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 10:15:32 -0700 Subject: [PATCH 128/144] chore(deps): bump nodemailer and @types/nodemailer (#5689) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 4 ++-- yarn.lock | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 68f956094041..e1c3840f22fc 100644 --- a/package.json +++ b/package.json @@ -141,7 +141,7 @@ "mobx-utils": "^4.0.1", "natural-sort": "^1.0.0", "node-fetch": "2.6.12", - "nodemailer": "^6.9.1", + "nodemailer": "^6.9.4", "outline-icons": "^2.3.0", "oy-vey": "^0.12.0", "passport": "^0.6.0", @@ -265,7 +265,7 @@ "@types/natural-sort": "^0.0.21", "@types/node": "18.0.6", "@types/node-fetch": "^2.6.2", - "@types/nodemailer": "^6.4.7", + "@types/nodemailer": "^6.4.9", "@types/passport-oauth2": "^1.4.11", "@types/quoted-printable": "^1.0.0", "@types/randomstring": "^1.1.8", diff --git a/yarn.lock b/yarn.lock index 8c07a6067214..122d2b20f85c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3239,10 +3239,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.6.tgz#0ba49ac517ad69abe7a1508bc9b3a5483df9d5d7" integrity sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw== -"@types/nodemailer@^6.4.7": - version "6.4.7" - resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.7.tgz#658f4bca47c1a895b1d7e054b3b54030a5e1f5e0" - integrity sha512-f5qCBGAn/f0qtRcd4SEn88c8Fp3Swct1731X4ryPKqS61/A3LmmzN8zaEz7hneJvpjFbUUgY7lru/B/7ODTazg== +"@types/nodemailer@^6.4.9": + version "6.4.9" + resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.9.tgz#38e22cc2e62006170df0966fb8762fbf5cec6cbf" + integrity sha512-XYG8Gv+sHjaOtUpiuytahMy2mM3rectgroNbs6R3djZEKmPNiIJwe9KqOJBGzKKnNZNKvnuvmugBgpq3w/S0ig== dependencies: "@types/node" "*" @@ -9827,10 +9827,10 @@ node-releases@^2.0.8: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== -nodemailer@^6.9.1: - version "6.9.1" - resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.9.1.tgz#8249d928a43ed85fec17b13d2870c8f758a126ed" - integrity sha512-qHw7dOiU5UKNnQpXktdgQ1d3OFgRAekuvbJLcdG5dnEo/GtcTHRYM7+UfJARdOFU9WUQO8OiIamgWPmiSFHYAA== +nodemailer@^6.9.4: + version "6.9.4" + resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.9.4.tgz#93bd4a60eb0be6fa088a0483340551ebabfd2abf" + integrity sha512-CXjQvrQZV4+6X5wP6ZIgdehJamI63MFoYFGGPtHudWym9qaEHDNdPzaj5bfMCvxG1vhAileSWW90q7nL0N36mA== nodemon@^2.0.22: version "2.0.22" From b7bfc4bb1ade7729ee5b3cabdd5a2d85de859b4e Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Mon, 14 Aug 2023 14:44:58 -0400 Subject: [PATCH 129/144] chore: Remove optimize imports to allow vite upgrade (#5691) --- .eslintrc | 3 +- app/actions/index.ts | 2 +- app/components/Analytics.tsx | 2 +- app/components/Collaborators.tsx | 5 +- app/components/DocumentExplorer.tsx | 7 ++- app/components/DocumentViews.tsx | 2 +- app/components/Editor.tsx | 4 +- app/components/Header.tsx | 2 +- app/components/Highlight.tsx | 2 +- app/components/LanguagePrompt.tsx | 2 +- app/components/List/Placeholder.tsx | 2 +- app/components/PaginatedList.tsx | 2 +- app/components/SearchPopover.tsx | 2 +- app/components/Sidebar/Settings.tsx | 2 +- app/components/Table.tsx | 2 +- app/components/WebsocketProvider.tsx | 2 +- app/editor/components/SelectionToolbar.tsx | 2 +- app/editor/components/SuggestionsMenu.tsx | 2 +- app/hooks/useCommandBarActions.ts | 2 +- app/hooks/useEmbeds.ts | 2 +- app/hooks/useIdle.ts | 2 +- app/hooks/useMenuContext.tsx | 2 +- app/hooks/useMousePosition.ts | 2 +- app/hooks/useWindowScrollPosition.ts | 2 +- app/models/BaseModel.ts | 2 +- app/models/Collection.ts | 2 +- app/models/Document.ts | 2 +- app/scenes/Collection/MembershipPreview.tsx | 2 +- app/scenes/CollectionNew.tsx | 2 +- .../AddGroupsToCollection.tsx | 2 +- .../Document/components/CommentThread.tsx | 2 +- app/scenes/Document/components/Document.tsx | 2 +- .../Document/components/MultiplayerEditor.tsx | 2 +- .../Document/components/SharePopover.tsx | 3 +- app/scenes/DocumentMove.tsx | 2 +- app/scenes/DocumentPublish.tsx | 2 +- app/scenes/GroupMembers/AddPeopleToGroup.tsx | 2 +- app/scenes/Login/index.tsx | 2 +- app/scenes/Search/Search.tsx | 2 +- app/scenes/Settings/Details.tsx | 2 +- app/scenes/Settings/GoogleAnalytics.tsx | 2 +- app/scenes/Settings/Members.tsx | 2 +- app/scenes/Settings/Notifications.tsx | 2 +- app/scenes/Settings/Security.tsx | 2 +- app/scenes/Settings/SelfHosted.tsx | 2 +- app/scenes/Settings/Shares.tsx | 2 +- .../Settings/components/UserStatusFilter.tsx | 2 +- app/stores/BaseStore.ts | 3 +- app/stores/CollectionsStore.ts | 5 +- app/stores/CommentsStore.ts | 3 +- app/stores/DocumentsStore.ts | 6 ++- app/stores/EventsStore.ts | 3 +- app/stores/FileOperationsStore.ts | 2 +- app/stores/GroupMembershipsStore.ts | 2 +- app/stores/GroupsStore.ts | 2 +- app/stores/IntegrationsStore.ts | 2 +- app/stores/NotificationsStore.ts | 3 +- app/stores/RevisionsStore.ts | 2 +- app/stores/SearchesStore.ts | 2 +- app/stores/SharesStore.ts | 5 +- app/stores/ToastsStore.ts | 2 +- app/stores/UsersStore.ts | 3 +- app/stores/ViewsStore.ts | 5 +- app/utils/ApiClient.ts | 2 +- app/utils/date.ts | 2 +- package.json | 2 +- plugins/google/server/auth/google.ts | 2 +- plugins/oidc/server/auth/oidc.ts | 2 +- plugins/slack/client/Settings.tsx | 2 +- .../slack/client/components/SlackListItem.tsx | 2 +- plugins/slack/server/api/hooks.ts | 2 +- .../components/WebhookSubscriptionForm.tsx | 6 +-- .../server/api/webhookSubscriptions.ts | 3 +- .../commands/documentCollaborativeUpdater.ts | 2 +- server/commands/documentImporter.ts | 2 +- server/commands/documentPermanentDeleter.ts | 2 +- server/commands/notificationUpdater.ts | 2 +- server/commands/teamUpdater.ts | 2 +- server/commands/userInviter.ts | 2 +- server/index.ts | 2 +- server/logging/Logger.ts | 5 +- server/middlewares/rateLimiter.ts | 2 +- server/models/Collection.ts | 5 +- server/models/Document.ts | 3 +- server/models/WebhookSubscription.ts | 2 +- server/models/decorators/Encrypted.ts | 2 +- server/models/helpers/AuthenticationHelper.ts | 3 +- server/models/helpers/DocumentHelper.tsx | 3 +- server/models/helpers/SearchHelper.ts | 3 +- server/models/validators/Length.ts | 2 +- server/models/validators/TextLength.ts | 2 +- server/onerror.ts | 4 +- server/policies/collection.ts | 2 +- server/presenters/policy.ts | 2 +- server/queues/tasks/ExportJSONTask.ts | 2 +- server/queues/tasks/ExportTask.ts | 2 +- server/queues/tasks/ImportJSONTask.ts | 3 +- server/queues/tasks/ImportMarkdownZipTask.ts | 2 +- server/queues/tasks/ImportNotionTask.ts | 3 +- server/queues/tasks/ImportTask.ts | 2 +- .../tasks/RevisionCreatedNotificationsTask.ts | 2 +- server/redis.ts | 2 +- server/routes/api/attachments/schema.ts | 2 +- server/routes/api/auth/auth.ts | 2 +- server/routes/api/collections/schema.ts | 2 +- server/routes/api/cron/schema.ts | 2 +- server/routes/api/documents/schema.ts | 2 +- server/routes/api/fileOperations/schema.ts | 2 +- .../routes/api/notifications/notifications.ts | 3 +- server/routes/api/notifications/schema.ts | 2 +- server/routes/api/revisions/schema.ts | 2 +- server/routes/api/searches/schema.ts | 2 +- server/routes/api/shares/schema.ts | 2 +- server/routes/api/shares/shares.ts | 2 +- server/routes/api/stars/schema.ts | 2 +- server/routes/api/urls/schema.ts | 2 +- server/routes/app.ts | 2 +- server/test/factories.ts | 3 +- server/utils/ShutdownHelper.ts | 2 +- server/utils/ZipHelper.ts | 2 +- server/utils/authentication.ts | 2 +- server/utils/koa.ts | 2 +- server/utils/parseAttachmentIds.ts | 3 +- server/utils/queue.ts | 2 +- server/utils/s3.ts | 2 +- server/utils/startup.ts | 2 +- .../utils/turndown/confluence-code-block.ts | 2 +- server/utils/unfurl.ts | 2 +- server/validation.ts | 2 +- shared/editor/extensions/FindAndReplace.ts | 2 +- shared/editor/extensions/Prism.ts | 3 +- shared/editor/lib/headingToSlug.ts | 2 +- shared/editor/rules/attachments.ts | 2 +- shared/utils/domains.ts | 2 +- shared/utils/naturalSort.ts | 2 +- shared/utils/urls.ts | 2 +- vite.config.ts | 4 -- yarn.lock | 49 ++++++++----------- 138 files changed, 207 insertions(+), 171 deletions(-) diff --git a/.eslintrc b/.eslintrc index 4357f694611b..e02b839b6da1 100644 --- a/.eslintrc +++ b/.eslintrc @@ -21,7 +21,7 @@ "eslint-plugin-import", "eslint-plugin-node", "eslint-plugin-react", - "import" + "eslint-plugin-lodash" ], "rules": { "eqeqeq": 2, @@ -55,6 +55,7 @@ ], "padding-line-between-statements": ["error", { "blankLine": "always", "prev": "*", "next": "export" }], "lines-between-class-members": ["error", "always", { "exceptAfterSingleLine": true }], + "lodash/import-scope": ["warn", "method"], "import/no-named-as-default": "off", "import/no-named-as-default-member": "off", "import/newline-after-import": 2, diff --git a/app/actions/index.ts b/app/actions/index.ts index 82064dd1d66e..e0762a5b9949 100644 --- a/app/actions/index.ts +++ b/app/actions/index.ts @@ -1,4 +1,4 @@ -import { flattenDeep } from "lodash"; +import flattenDeep from "lodash/flattenDeep"; import * as React from "react"; import { Optional } from "utility-types"; import { v4 as uuidv4 } from "uuid"; diff --git a/app/components/Analytics.tsx b/app/components/Analytics.tsx index b1da7e3c0cb6..4d6f56cb6d37 100644 --- a/app/components/Analytics.tsx +++ b/app/components/Analytics.tsx @@ -1,6 +1,6 @@ /* eslint-disable prefer-rest-params */ /* global ga */ -import { escape } from "lodash"; +import escape from "lodash/escape"; import * as React from "react"; import { IntegrationService } from "@shared/types"; import env from "~/env"; diff --git a/app/components/Collaborators.tsx b/app/components/Collaborators.tsx index 7075ce1aeef0..b49aabd67dc2 100644 --- a/app/components/Collaborators.tsx +++ b/app/components/Collaborators.tsx @@ -1,4 +1,7 @@ -import { sortBy, filter, uniq, isEqual } from "lodash"; +import filter from "lodash/filter"; +import isEqual from "lodash/isEqual"; +import sortBy from "lodash/sortBy"; +import uniq from "lodash/uniq"; import { observer } from "mobx-react"; import * as React from "react"; import { useTranslation } from "react-i18next"; diff --git a/app/components/DocumentExplorer.tsx b/app/components/DocumentExplorer.tsx index 54a4377e9869..06069dfd86b4 100644 --- a/app/components/DocumentExplorer.tsx +++ b/app/components/DocumentExplorer.tsx @@ -1,5 +1,10 @@ import FuzzySearch from "fuzzy-search"; -import { includes, difference, concat, filter, map, fill } from "lodash"; +import concat from "lodash/concat"; +import difference from "lodash/difference"; +import fill from "lodash/fill"; +import filter from "lodash/filter"; +import includes from "lodash/includes"; +import map from "lodash/map"; import { observer } from "mobx-react"; import { StarredIcon, DocumentIcon } from "outline-icons"; import * as React from "react"; diff --git a/app/components/DocumentViews.tsx b/app/components/DocumentViews.tsx index 20d3068151a1..15377291c5ee 100644 --- a/app/components/DocumentViews.tsx +++ b/app/components/DocumentViews.tsx @@ -1,4 +1,4 @@ -import { sortBy } from "lodash"; +import sortBy from "lodash/sortBy"; import { observer } from "mobx-react"; import * as React from "react"; import { useTranslation } from "react-i18next"; diff --git a/app/components/Editor.tsx b/app/components/Editor.tsx index 1445d6de0f16..d53745021409 100644 --- a/app/components/Editor.tsx +++ b/app/components/Editor.tsx @@ -1,4 +1,6 @@ -import { deburr, difference, sortBy } from "lodash"; +import deburr from "lodash/deburr"; +import difference from "lodash/difference"; +import sortBy from "lodash/sortBy"; import { observer } from "mobx-react"; import { DOMParser as ProsemirrorDOMParser } from "prosemirror-model"; import { TextSelection } from "prosemirror-state"; diff --git a/app/components/Header.tsx b/app/components/Header.tsx index 330f0000ae46..0ffc82cc798e 100644 --- a/app/components/Header.tsx +++ b/app/components/Header.tsx @@ -1,4 +1,4 @@ -import { throttle } from "lodash"; +import throttle from "lodash/throttle"; import { observer } from "mobx-react"; import { MenuIcon } from "outline-icons"; import { transparentize } from "polished"; diff --git a/app/components/Highlight.tsx b/app/components/Highlight.tsx index f65ff125a5bd..f57e7135f581 100644 --- a/app/components/Highlight.tsx +++ b/app/components/Highlight.tsx @@ -1,4 +1,4 @@ -import { escapeRegExp } from "lodash"; +import escapeRegExp from "lodash/escapeRegExp"; import * as React from "react"; import replace from "string-replace-to-array"; import styled from "styled-components"; diff --git a/app/components/LanguagePrompt.tsx b/app/components/LanguagePrompt.tsx index f062d3a64793..73425f4ed5ae 100644 --- a/app/components/LanguagePrompt.tsx +++ b/app/components/LanguagePrompt.tsx @@ -1,4 +1,4 @@ -import { find } from "lodash"; +import find from "lodash/find"; import * as React from "react"; import { Trans, useTranslation } from "react-i18next"; import styled from "styled-components"; diff --git a/app/components/List/Placeholder.tsx b/app/components/List/Placeholder.tsx index 9f7fe76af367..780dc504311f 100644 --- a/app/components/List/Placeholder.tsx +++ b/app/components/List/Placeholder.tsx @@ -1,4 +1,4 @@ -import { times } from "lodash"; +import times from "lodash/times"; import * as React from "react"; import styled from "styled-components"; import Fade from "~/components/Fade"; diff --git a/app/components/PaginatedList.tsx b/app/components/PaginatedList.tsx index ac2bb9d7a0da..4e30ec5303cd 100644 --- a/app/components/PaginatedList.tsx +++ b/app/components/PaginatedList.tsx @@ -1,4 +1,4 @@ -import { isEqual } from "lodash"; +import isEqual from "lodash/isEqual"; import { observable, action } from "mobx"; import { observer } from "mobx-react"; import * as React from "react"; diff --git a/app/components/SearchPopover.tsx b/app/components/SearchPopover.tsx index c02b42f6c17f..ad696a9a0c86 100644 --- a/app/components/SearchPopover.tsx +++ b/app/components/SearchPopover.tsx @@ -1,4 +1,4 @@ -import { debounce } from "lodash"; +import debounce from "lodash/debounce"; import { observer } from "mobx-react"; import * as React from "react"; import { useTranslation } from "react-i18next"; diff --git a/app/components/Sidebar/Settings.tsx b/app/components/Sidebar/Settings.tsx index 71c33d9d76f2..573340fecb90 100644 --- a/app/components/Sidebar/Settings.tsx +++ b/app/components/Sidebar/Settings.tsx @@ -1,4 +1,4 @@ -import { groupBy } from "lodash"; +import groupBy from "lodash/groupBy"; import { observer } from "mobx-react"; import { BackIcon } from "outline-icons"; import * as React from "react"; diff --git a/app/components/Table.tsx b/app/components/Table.tsx index c7f6f1f3081a..66b00b777589 100644 --- a/app/components/Table.tsx +++ b/app/components/Table.tsx @@ -1,4 +1,4 @@ -import { isEqual } from "lodash"; +import isEqual from "lodash/isEqual"; import { observer } from "mobx-react"; import { CollapsedIcon } from "outline-icons"; import * as React from "react"; diff --git a/app/components/WebsocketProvider.tsx b/app/components/WebsocketProvider.tsx index cac32016538e..6c19b0629e27 100644 --- a/app/components/WebsocketProvider.tsx +++ b/app/components/WebsocketProvider.tsx @@ -1,5 +1,5 @@ import invariant from "invariant"; -import { find } from "lodash"; +import find from "lodash/find"; import { action, observable } from "mobx"; import { observer } from "mobx-react"; import * as React from "react"; diff --git a/app/editor/components/SelectionToolbar.tsx b/app/editor/components/SelectionToolbar.tsx index 2ade810d016e..90c77a182b39 100644 --- a/app/editor/components/SelectionToolbar.tsx +++ b/app/editor/components/SelectionToolbar.tsx @@ -1,4 +1,4 @@ -import { some } from "lodash"; +import some from "lodash/some"; import { EditorState, NodeSelection, TextSelection } from "prosemirror-state"; import * as React from "react"; import createAndInsertLink from "@shared/editor/commands/createAndInsertLink"; diff --git a/app/editor/components/SuggestionsMenu.tsx b/app/editor/components/SuggestionsMenu.tsx index 4e4b4dcffdfa..86f756bdb145 100644 --- a/app/editor/components/SuggestionsMenu.tsx +++ b/app/editor/components/SuggestionsMenu.tsx @@ -1,5 +1,5 @@ import commandScore from "command-score"; -import { capitalize } from "lodash"; +import capitalize from "lodash/capitalize"; import * as React from "react"; import { Trans } from "react-i18next"; import { VisuallyHidden } from "reakit/VisuallyHidden"; diff --git a/app/hooks/useCommandBarActions.ts b/app/hooks/useCommandBarActions.ts index 9722f73a6cc7..48dcd11ef625 100644 --- a/app/hooks/useCommandBarActions.ts +++ b/app/hooks/useCommandBarActions.ts @@ -1,5 +1,5 @@ import { useRegisterActions } from "kbar"; -import { flattenDeep } from "lodash"; +import flattenDeep from "lodash/flattenDeep"; import { useLocation } from "react-router-dom"; import { actionToKBar } from "~/actions"; import { Action } from "~/types"; diff --git a/app/hooks/useEmbeds.ts b/app/hooks/useEmbeds.ts index 5c55668eb2c1..5526b9369688 100644 --- a/app/hooks/useEmbeds.ts +++ b/app/hooks/useEmbeds.ts @@ -1,4 +1,4 @@ -import { find } from "lodash"; +import find from "lodash/find"; import * as React from "react"; import embeds, { EmbedDescriptor } from "@shared/editor/embeds"; import { IntegrationType } from "@shared/types"; diff --git a/app/hooks/useIdle.ts b/app/hooks/useIdle.ts index 90847c98fc76..a1452962f072 100644 --- a/app/hooks/useIdle.ts +++ b/app/hooks/useIdle.ts @@ -1,4 +1,4 @@ -import { throttle } from "lodash"; +import throttle from "lodash/throttle"; import * as React from "react"; import { Minute } from "@shared/utils/time"; diff --git a/app/hooks/useMenuContext.tsx b/app/hooks/useMenuContext.tsx index cb7cb1b974e9..eb408f7a5def 100644 --- a/app/hooks/useMenuContext.tsx +++ b/app/hooks/useMenuContext.tsx @@ -1,4 +1,4 @@ -import { noop } from "lodash"; +import noop from "lodash/noop"; import React from "react"; type MenuContextType = { diff --git a/app/hooks/useMousePosition.ts b/app/hooks/useMousePosition.ts index 55041bc6d175..46effdfc7f1a 100644 --- a/app/hooks/useMousePosition.ts +++ b/app/hooks/useMousePosition.ts @@ -1,4 +1,4 @@ -import { throttle } from "lodash"; +import throttle from "lodash/throttle"; import * as React from "react"; import useEventListener from "./useEventListener"; import useIsMounted from "./useIsMounted"; diff --git a/app/hooks/useWindowScrollPosition.ts b/app/hooks/useWindowScrollPosition.ts index d48ef11495b6..e006413096b7 100644 --- a/app/hooks/useWindowScrollPosition.ts +++ b/app/hooks/useWindowScrollPosition.ts @@ -1,6 +1,6 @@ // Based on https://github.com/rehooks/window-scroll-position which is no longer // maintained. -import { throttle } from "lodash"; +import throttle from "lodash/throttle"; import { useState, useEffect } from "react"; import { supportsPassiveListener } from "~/utils/browser"; diff --git a/app/models/BaseModel.ts b/app/models/BaseModel.ts index 265644c8db3a..5c1c70e90945 100644 --- a/app/models/BaseModel.ts +++ b/app/models/BaseModel.ts @@ -1,4 +1,4 @@ -import { pick } from "lodash"; +import pick from "lodash/pick"; import { set, observable } from "mobx"; import Logger from "~/utils/Logger"; import { getFieldsForModel } from "./decorators/Field"; diff --git a/app/models/Collection.ts b/app/models/Collection.ts index dc4350d353f9..b7c43099d9c4 100644 --- a/app/models/Collection.ts +++ b/app/models/Collection.ts @@ -1,4 +1,4 @@ -import { trim } from "lodash"; +import trim from "lodash/trim"; import { action, computed, observable, reaction, runInAction } from "mobx"; import { CollectionPermission, diff --git a/app/models/Document.ts b/app/models/Document.ts index a501700fcfb5..56a1b09ccbe2 100644 --- a/app/models/Document.ts +++ b/app/models/Document.ts @@ -1,5 +1,5 @@ import { addDays, differenceInDays } from "date-fns"; -import { floor } from "lodash"; +import floor from "lodash/floor"; import { action, autorun, computed, observable, set } from "mobx"; import { ExportContentType } from "@shared/types"; import type { NavigationNode } from "@shared/types"; diff --git a/app/scenes/Collection/MembershipPreview.tsx b/app/scenes/Collection/MembershipPreview.tsx index 8276ddaed15a..881487df8c23 100644 --- a/app/scenes/Collection/MembershipPreview.tsx +++ b/app/scenes/Collection/MembershipPreview.tsx @@ -1,4 +1,4 @@ -import { sortBy } from "lodash"; +import sortBy from "lodash/sortBy"; import { observer } from "mobx-react"; import * as React from "react"; import { useTranslation } from "react-i18next"; diff --git a/app/scenes/CollectionNew.tsx b/app/scenes/CollectionNew.tsx index c78ff588ade0..bdbc8181e82f 100644 --- a/app/scenes/CollectionNew.tsx +++ b/app/scenes/CollectionNew.tsx @@ -1,4 +1,4 @@ -import { intersection } from "lodash"; +import intersection from "lodash/intersection"; import { observable } from "mobx"; import { observer } from "mobx-react"; import * as React from "react"; diff --git a/app/scenes/CollectionPermissions/AddGroupsToCollection.tsx b/app/scenes/CollectionPermissions/AddGroupsToCollection.tsx index f9a875f16a14..d78947d416d5 100644 --- a/app/scenes/CollectionPermissions/AddGroupsToCollection.tsx +++ b/app/scenes/CollectionPermissions/AddGroupsToCollection.tsx @@ -1,4 +1,4 @@ -import { debounce } from "lodash"; +import debounce from "lodash/debounce"; import { observer } from "mobx-react"; import * as React from "react"; import { useTranslation } from "react-i18next"; diff --git a/app/scenes/Document/components/CommentThread.tsx b/app/scenes/Document/components/CommentThread.tsx index d34aa404352e..ab00a50ebbb0 100644 --- a/app/scenes/Document/components/CommentThread.tsx +++ b/app/scenes/Document/components/CommentThread.tsx @@ -1,4 +1,4 @@ -import { throttle } from "lodash"; +import throttle from "lodash/throttle"; import { observer } from "mobx-react"; import * as React from "react"; import { useTranslation } from "react-i18next"; diff --git a/app/scenes/Document/components/Document.tsx b/app/scenes/Document/components/Document.tsx index a826b4077990..ee0e7f10dd5b 100644 --- a/app/scenes/Document/components/Document.tsx +++ b/app/scenes/Document/components/Document.tsx @@ -1,4 +1,4 @@ -import { debounce } from "lodash"; +import debounce from "lodash/debounce"; import { action, observable } from "mobx"; import { observer } from "mobx-react"; import { AllSelection } from "prosemirror-state"; diff --git a/app/scenes/Document/components/MultiplayerEditor.tsx b/app/scenes/Document/components/MultiplayerEditor.tsx index 83341155f906..8660ccff9d47 100644 --- a/app/scenes/Document/components/MultiplayerEditor.tsx +++ b/app/scenes/Document/components/MultiplayerEditor.tsx @@ -1,5 +1,5 @@ import { HocuspocusProvider, WebSocketStatus } from "@hocuspocus/provider"; -import { throttle } from "lodash"; +import throttle from "lodash/throttle"; import * as React from "react"; import { useTranslation } from "react-i18next"; import { useHistory } from "react-router-dom"; diff --git a/app/scenes/Document/components/SharePopover.tsx b/app/scenes/Document/components/SharePopover.tsx index a20775f3641b..a4ca2fd80cf2 100644 --- a/app/scenes/Document/components/SharePopover.tsx +++ b/app/scenes/Document/components/SharePopover.tsx @@ -1,5 +1,6 @@ import invariant from "invariant"; -import { debounce, isEmpty } from "lodash"; +import debounce from "lodash/debounce"; +import isEmpty from "lodash/isEmpty"; import { observer } from "mobx-react"; import { ExpandedIcon, GlobeIcon, PadlockIcon } from "outline-icons"; import * as React from "react"; diff --git a/app/scenes/DocumentMove.tsx b/app/scenes/DocumentMove.tsx index 85f38c0077f6..abd05775a019 100644 --- a/app/scenes/DocumentMove.tsx +++ b/app/scenes/DocumentMove.tsx @@ -1,4 +1,4 @@ -import { flatten } from "lodash"; +import flatten from "lodash/flatten"; import { observer } from "mobx-react"; import * as React from "react"; import { useTranslation, Trans } from "react-i18next"; diff --git a/app/scenes/DocumentPublish.tsx b/app/scenes/DocumentPublish.tsx index 90e19ff63eae..36a2083d49d8 100644 --- a/app/scenes/DocumentPublish.tsx +++ b/app/scenes/DocumentPublish.tsx @@ -1,4 +1,4 @@ -import { flatten } from "lodash"; +import flatten from "lodash/flatten"; import { observer } from "mobx-react"; import * as React from "react"; import { useTranslation, Trans } from "react-i18next"; diff --git a/app/scenes/GroupMembers/AddPeopleToGroup.tsx b/app/scenes/GroupMembers/AddPeopleToGroup.tsx index b6a3e15829c6..1b673678a403 100644 --- a/app/scenes/GroupMembers/AddPeopleToGroup.tsx +++ b/app/scenes/GroupMembers/AddPeopleToGroup.tsx @@ -1,4 +1,4 @@ -import { debounce } from "lodash"; +import debounce from "lodash/debounce"; import { observer } from "mobx-react"; import * as React from "react"; import { useTranslation } from "react-i18next"; diff --git a/app/scenes/Login/index.tsx b/app/scenes/Login/index.tsx index e62cb6dfa92c..ca9500614e4b 100644 --- a/app/scenes/Login/index.tsx +++ b/app/scenes/Login/index.tsx @@ -1,4 +1,4 @@ -import { find } from "lodash"; +import find from "lodash/find"; import { observer } from "mobx-react"; import { BackIcon, EmailIcon } from "outline-icons"; import * as React from "react"; diff --git a/app/scenes/Search/Search.tsx b/app/scenes/Search/Search.tsx index 304e96175bc1..74965370e813 100644 --- a/app/scenes/Search/Search.tsx +++ b/app/scenes/Search/Search.tsx @@ -1,4 +1,4 @@ -import { isEqual } from "lodash"; +import isEqual from "lodash/isEqual"; import { observable, action } from "mobx"; import { observer } from "mobx-react"; import queryString from "query-string"; diff --git a/app/scenes/Settings/Details.tsx b/app/scenes/Settings/Details.tsx index 7ffa010d6593..1caa6620ad6e 100644 --- a/app/scenes/Settings/Details.tsx +++ b/app/scenes/Settings/Details.tsx @@ -1,5 +1,5 @@ import { isHexColor } from "class-validator"; -import { pickBy } from "lodash"; +import pickBy from "lodash/pickBy"; import { observer } from "mobx-react"; import { TeamIcon } from "outline-icons"; import { useRef, useState } from "react"; diff --git a/app/scenes/Settings/GoogleAnalytics.tsx b/app/scenes/Settings/GoogleAnalytics.tsx index b1fc6412243b..22e6a3c31882 100644 --- a/app/scenes/Settings/GoogleAnalytics.tsx +++ b/app/scenes/Settings/GoogleAnalytics.tsx @@ -1,4 +1,4 @@ -import { find } from "lodash"; +import find from "lodash/find"; import { observer } from "mobx-react"; import * as React from "react"; import { useForm } from "react-hook-form"; diff --git a/app/scenes/Settings/Members.tsx b/app/scenes/Settings/Members.tsx index 5697601c7f2f..da970d8be15c 100644 --- a/app/scenes/Settings/Members.tsx +++ b/app/scenes/Settings/Members.tsx @@ -1,4 +1,4 @@ -import { sortBy } from "lodash"; +import sortBy from "lodash/sortBy"; import { observer } from "mobx-react"; import { PlusIcon, UserIcon } from "outline-icons"; import * as React from "react"; diff --git a/app/scenes/Settings/Notifications.tsx b/app/scenes/Settings/Notifications.tsx index 91e13789847e..76287e63debe 100644 --- a/app/scenes/Settings/Notifications.tsx +++ b/app/scenes/Settings/Notifications.tsx @@ -1,4 +1,4 @@ -import { debounce } from "lodash"; +import debounce from "lodash/debounce"; import { observer } from "mobx-react"; import { AcademicCapIcon, diff --git a/app/scenes/Settings/Security.tsx b/app/scenes/Settings/Security.tsx index d8b242f56746..78e0acc9fd3e 100644 --- a/app/scenes/Settings/Security.tsx +++ b/app/scenes/Settings/Security.tsx @@ -1,4 +1,4 @@ -import { debounce } from "lodash"; +import debounce from "lodash/debounce"; import { observer } from "mobx-react"; import { CheckboxIcon, EmailIcon, PadlockIcon } from "outline-icons"; import { useState } from "react"; diff --git a/app/scenes/Settings/SelfHosted.tsx b/app/scenes/Settings/SelfHosted.tsx index 41fd079262c2..45c8cb38f745 100644 --- a/app/scenes/Settings/SelfHosted.tsx +++ b/app/scenes/Settings/SelfHosted.tsx @@ -1,4 +1,4 @@ -import { find } from "lodash"; +import find from "lodash/find"; import { observer } from "mobx-react"; import { BuildingBlocksIcon } from "outline-icons"; import * as React from "react"; diff --git a/app/scenes/Settings/Shares.tsx b/app/scenes/Settings/Shares.tsx index df29e09d015a..63396ce1109d 100644 --- a/app/scenes/Settings/Shares.tsx +++ b/app/scenes/Settings/Shares.tsx @@ -1,4 +1,4 @@ -import { sortBy } from "lodash"; +import sortBy from "lodash/sortBy"; import { observer } from "mobx-react"; import { LinkIcon, WarningIcon } from "outline-icons"; import * as React from "react"; diff --git a/app/scenes/Settings/components/UserStatusFilter.tsx b/app/scenes/Settings/components/UserStatusFilter.tsx index 6aa89f5af018..53717073e480 100644 --- a/app/scenes/Settings/components/UserStatusFilter.tsx +++ b/app/scenes/Settings/components/UserStatusFilter.tsx @@ -1,4 +1,4 @@ -import { compact } from "lodash"; +import compact from "lodash/compact"; import { observer } from "mobx-react"; import * as React from "react"; import { useTranslation } from "react-i18next"; diff --git a/app/stores/BaseStore.ts b/app/stores/BaseStore.ts index 70fd6ec5db19..96c96f5a27d8 100644 --- a/app/stores/BaseStore.ts +++ b/app/stores/BaseStore.ts @@ -1,5 +1,6 @@ import invariant from "invariant"; -import { lowerFirst, orderBy } from "lodash"; +import lowerFirst from "lodash/lowerFirst"; +import orderBy from "lodash/orderBy"; import { observable, action, computed, runInAction } from "mobx"; import { Class } from "utility-types"; import RootStore from "~/stores/RootStore"; diff --git a/app/stores/CollectionsStore.ts b/app/stores/CollectionsStore.ts index 3b80d0b66a41..908d633f24ac 100644 --- a/app/stores/CollectionsStore.ts +++ b/app/stores/CollectionsStore.ts @@ -1,5 +1,8 @@ import invariant from "invariant"; -import { concat, find, last, sortBy } from "lodash"; +import concat from "lodash/concat"; +import find from "lodash/find"; +import last from "lodash/last"; +import sortBy from "lodash/sortBy"; import { computed, action } from "mobx"; import { CollectionPermission, diff --git a/app/stores/CommentsStore.ts b/app/stores/CommentsStore.ts index 275ecb78a8d8..fd88d508b6c8 100644 --- a/app/stores/CommentsStore.ts +++ b/app/stores/CommentsStore.ts @@ -1,5 +1,6 @@ import invariant from "invariant"; -import { filter, orderBy } from "lodash"; +import filter from "lodash/filter"; +import orderBy from "lodash/orderBy"; import { action, runInAction, computed } from "mobx"; import Comment from "~/models/Comment"; import Document from "~/models/Document"; diff --git a/app/stores/DocumentsStore.ts b/app/stores/DocumentsStore.ts index e630bbf39e90..fed26338d8d5 100644 --- a/app/stores/DocumentsStore.ts +++ b/app/stores/DocumentsStore.ts @@ -1,5 +1,9 @@ import invariant from "invariant"; -import { find, orderBy, filter, compact, omitBy } from "lodash"; +import compact from "lodash/compact"; +import filter from "lodash/filter"; +import find from "lodash/find"; +import omitBy from "lodash/omitBy"; +import orderBy from "lodash/orderBy"; import { observable, action, computed, runInAction } from "mobx"; import { DateFilter, NavigationNode, PublicTeam } from "@shared/types"; import { subtractDate } from "@shared/utils/date"; diff --git a/app/stores/EventsStore.ts b/app/stores/EventsStore.ts index d8c17c89d65b..5c9f1c35657f 100644 --- a/app/stores/EventsStore.ts +++ b/app/stores/EventsStore.ts @@ -1,4 +1,5 @@ -import { sortBy, filter } from "lodash"; +import filter from "lodash/filter"; +import sortBy from "lodash/sortBy"; import { computed } from "mobx"; import Event from "~/models/Event"; import BaseStore, { RPCAction } from "./BaseStore"; diff --git a/app/stores/FileOperationsStore.ts b/app/stores/FileOperationsStore.ts index 18133a922157..d4ec7feb3cc7 100644 --- a/app/stores/FileOperationsStore.ts +++ b/app/stores/FileOperationsStore.ts @@ -1,4 +1,4 @@ -import { orderBy } from "lodash"; +import orderBy from "lodash/orderBy"; import { computed } from "mobx"; import { FileOperationType } from "@shared/types"; import FileOperation from "~/models/FileOperation"; diff --git a/app/stores/GroupMembershipsStore.ts b/app/stores/GroupMembershipsStore.ts index 8681ac907a30..992e3163aeb2 100644 --- a/app/stores/GroupMembershipsStore.ts +++ b/app/stores/GroupMembershipsStore.ts @@ -1,5 +1,5 @@ import invariant from "invariant"; -import { filter } from "lodash"; +import filter from "lodash/filter"; import { action, runInAction } from "mobx"; import GroupMembership from "~/models/GroupMembership"; import { PaginationParams } from "~/types"; diff --git a/app/stores/GroupsStore.ts b/app/stores/GroupsStore.ts index 8da97a1ba7ea..8dc9e7b28c65 100644 --- a/app/stores/GroupsStore.ts +++ b/app/stores/GroupsStore.ts @@ -1,5 +1,5 @@ import invariant from "invariant"; -import { filter } from "lodash"; +import filter from "lodash/filter"; import { action, runInAction, computed } from "mobx"; import naturalSort from "@shared/utils/naturalSort"; import Group from "~/models/Group"; diff --git a/app/stores/IntegrationsStore.ts b/app/stores/IntegrationsStore.ts index ceb36795f13a..2460bcda5948 100644 --- a/app/stores/IntegrationsStore.ts +++ b/app/stores/IntegrationsStore.ts @@ -1,4 +1,4 @@ -import { filter } from "lodash"; +import filter from "lodash/filter"; import { computed } from "mobx"; import { IntegrationService } from "@shared/types"; import naturalSort from "@shared/utils/naturalSort"; diff --git a/app/stores/NotificationsStore.ts b/app/stores/NotificationsStore.ts index 9eee1e542a27..7470f0df0949 100644 --- a/app/stores/NotificationsStore.ts +++ b/app/stores/NotificationsStore.ts @@ -1,5 +1,6 @@ import invariant from "invariant"; -import { orderBy, sortBy } from "lodash"; +import orderBy from "lodash/orderBy"; +import sortBy from "lodash/sortBy"; import { action, computed, runInAction } from "mobx"; import Notification from "~/models/Notification"; import { PaginationParams } from "~/types"; diff --git a/app/stores/RevisionsStore.ts b/app/stores/RevisionsStore.ts index 53ad62af0568..dcac76b6637f 100644 --- a/app/stores/RevisionsStore.ts +++ b/app/stores/RevisionsStore.ts @@ -1,5 +1,5 @@ import invariant from "invariant"; -import { filter } from "lodash"; +import filter from "lodash/filter"; import { action, runInAction } from "mobx"; import BaseStore, { RPCAction } from "~/stores/BaseStore"; import RootStore from "~/stores/RootStore"; diff --git a/app/stores/SearchesStore.ts b/app/stores/SearchesStore.ts index 3f41b31fe26a..5498db2a3493 100644 --- a/app/stores/SearchesStore.ts +++ b/app/stores/SearchesStore.ts @@ -1,4 +1,4 @@ -import { uniqBy } from "lodash"; +import uniqBy from "lodash/uniqBy"; import { computed } from "mobx"; import SearchQuery from "~/models/SearchQuery"; import BaseStore, { RPCAction } from "./BaseStore"; diff --git a/app/stores/SharesStore.ts b/app/stores/SharesStore.ts index c244ed283278..23ee81b8c48b 100644 --- a/app/stores/SharesStore.ts +++ b/app/stores/SharesStore.ts @@ -1,5 +1,8 @@ import invariant from "invariant"; -import { sortBy, filter, find, isUndefined } from "lodash"; +import filter from "lodash/filter"; +import find from "lodash/find"; +import isUndefined from "lodash/isUndefined"; +import sortBy from "lodash/sortBy"; import { action, computed } from "mobx"; import Share from "~/models/Share"; import { client } from "~/utils/ApiClient"; diff --git a/app/stores/ToastsStore.ts b/app/stores/ToastsStore.ts index 81dc347a57f9..ce3d16a4aab2 100644 --- a/app/stores/ToastsStore.ts +++ b/app/stores/ToastsStore.ts @@ -1,4 +1,4 @@ -import { orderBy } from "lodash"; +import orderBy from "lodash/orderBy"; import { observable, action, computed } from "mobx"; import { v4 as uuidv4 } from "uuid"; import { Toast, ToastOptions } from "~/types"; diff --git a/app/stores/UsersStore.ts b/app/stores/UsersStore.ts index 8d7ed923f370..727c9232b8d4 100644 --- a/app/stores/UsersStore.ts +++ b/app/stores/UsersStore.ts @@ -1,5 +1,6 @@ import invariant from "invariant"; -import { filter, orderBy } from "lodash"; +import filter from "lodash/filter"; +import orderBy from "lodash/orderBy"; import { observable, computed, action, runInAction } from "mobx"; import { Role } from "@shared/types"; import User from "~/models/User"; diff --git a/app/stores/ViewsStore.ts b/app/stores/ViewsStore.ts index 05a2d2855998..7c098db19886 100644 --- a/app/stores/ViewsStore.ts +++ b/app/stores/ViewsStore.ts @@ -1,4 +1,7 @@ -import { reduce, filter, find, orderBy } from "lodash"; +import filter from "lodash/filter"; +import find from "lodash/find"; +import orderBy from "lodash/orderBy"; +import reduce from "lodash/reduce"; import View from "~/models/View"; import BaseStore, { RPCAction } from "./BaseStore"; import RootStore from "./RootStore"; diff --git a/app/utils/ApiClient.ts b/app/utils/ApiClient.ts index 39a66d61f704..810869c52098 100644 --- a/app/utils/ApiClient.ts +++ b/app/utils/ApiClient.ts @@ -1,5 +1,5 @@ import retry from "fetch-retry"; -import { trim } from "lodash"; +import trim from "lodash/trim"; import queryString from "query-string"; import EDITOR_VERSION from "@shared/editor/version"; import stores from "~/stores"; diff --git a/app/utils/date.ts b/app/utils/date.ts index dd1a01023a76..e94357146f74 100644 --- a/app/utils/date.ts +++ b/app/utils/date.ts @@ -7,7 +7,7 @@ import { format as formatDate, } from "date-fns"; import { TFunction } from "i18next"; -import { startCase } from "lodash"; +import startCase from "lodash/startCase"; import { getCurrentDateAsString, getCurrentDateTimeAsString, diff --git a/package.json b/package.json index e1c3840f22fc..5e1ea31dab9c 100644 --- a/package.json +++ b/package.json @@ -229,7 +229,6 @@ "@babel/cli": "^7.21.5", "@babel/preset-typescript": "^7.21.4", "@getoutline/jest-runner-serial": "^2.0.0", - "@optimize-lodash/rollup-plugin": "4.0.3", "@relative-ci/agent": "^4.1.3", "@types/addressparser": "^1.0.1", "@types/body-scroll-lock": "^3.1.0", @@ -308,6 +307,7 @@ "eslint-plugin-es": "^4.1.0", "eslint-plugin-import": "^2.26.0", "eslint-plugin-jsx-a11y": "^6.1.0", + "eslint-plugin-lodash": "^7.4.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.20.0", diff --git a/plugins/google/server/auth/google.ts b/plugins/google/server/auth/google.ts index 040f188902d1..7bf8c2edcd88 100644 --- a/plugins/google/server/auth/google.ts +++ b/plugins/google/server/auth/google.ts @@ -1,7 +1,7 @@ import passport from "@outlinewiki/koa-passport"; import type { Context } from "koa"; import Router from "koa-router"; -import { capitalize } from "lodash"; +import capitalize from "lodash/capitalize"; import { Profile } from "passport"; import { Strategy as GoogleStrategy } from "passport-google-oauth2"; import { slugifyDomain } from "@shared/utils/domains"; diff --git a/plugins/oidc/server/auth/oidc.ts b/plugins/oidc/server/auth/oidc.ts index cda07f4f5bd2..d9167216afa3 100644 --- a/plugins/oidc/server/auth/oidc.ts +++ b/plugins/oidc/server/auth/oidc.ts @@ -1,7 +1,7 @@ import passport from "@outlinewiki/koa-passport"; import type { Context } from "koa"; import Router from "koa-router"; -import { get } from "lodash"; +import get from "lodash/get"; import { Strategy } from "passport-oauth2"; import { slugifyDomain } from "@shared/utils/domains"; import accountProvisioner from "@server/commands/accountProvisioner"; diff --git a/plugins/slack/client/Settings.tsx b/plugins/slack/client/Settings.tsx index 11d3da844578..9476880644a8 100644 --- a/plugins/slack/client/Settings.tsx +++ b/plugins/slack/client/Settings.tsx @@ -1,4 +1,4 @@ -import { find } from "lodash"; +import find from "lodash/find"; import { observer } from "mobx-react"; import * as React from "react"; import { useTranslation, Trans } from "react-i18next"; diff --git a/plugins/slack/client/components/SlackListItem.tsx b/plugins/slack/client/components/SlackListItem.tsx index dd93c4e54508..096fcc7c679e 100644 --- a/plugins/slack/client/components/SlackListItem.tsx +++ b/plugins/slack/client/components/SlackListItem.tsx @@ -1,4 +1,4 @@ -import { uniq } from "lodash"; +import uniq from "lodash/uniq"; import { observer } from "mobx-react"; import * as React from "react"; import { Trans, useTranslation } from "react-i18next"; diff --git a/plugins/slack/server/api/hooks.ts b/plugins/slack/server/api/hooks.ts index 30bb69f3d7b8..afa78658101e 100644 --- a/plugins/slack/server/api/hooks.ts +++ b/plugins/slack/server/api/hooks.ts @@ -1,6 +1,6 @@ import { t } from "i18next"; import Router from "koa-router"; -import { escapeRegExp } from "lodash"; +import escapeRegExp from "lodash/escapeRegExp"; import { Op } from "sequelize"; import { IntegrationService } from "@shared/types"; import env from "@server/env"; diff --git a/plugins/webhooks/client/components/WebhookSubscriptionForm.tsx b/plugins/webhooks/client/components/WebhookSubscriptionForm.tsx index dfe4f98ce487..1bc0e5f2b3cb 100644 --- a/plugins/webhooks/client/components/WebhookSubscriptionForm.tsx +++ b/plugins/webhooks/client/components/WebhookSubscriptionForm.tsx @@ -1,4 +1,6 @@ -import { isEqual, filter, includes } from "lodash"; +import filter from "lodash/filter"; +import includes from "lodash/includes"; +import isEqual from "lodash/isEqual"; import randomstring from "randomstring"; import * as React from "react"; import { useEffect } from "react"; @@ -269,9 +271,7 @@ function WebhookSubscriptionForm({ handleSubmit, webhookSubscription }: Props) { needs to function. - -
{Object.entries(WEBHOOK_EVENTS) diff --git a/plugins/webhooks/server/api/webhookSubscriptions.ts b/plugins/webhooks/server/api/webhookSubscriptions.ts index 58dc2c86f084..47332ecc689a 100644 --- a/plugins/webhooks/server/api/webhookSubscriptions.ts +++ b/plugins/webhooks/server/api/webhookSubscriptions.ts @@ -1,5 +1,6 @@ import Router from "koa-router"; -import { compact, isEmpty } from "lodash"; +import compact from "lodash/compact"; +import isEmpty from "lodash/isEmpty"; import { ValidationError } from "@server/errors"; import auth from "@server/middlewares/authentication"; import { WebhookSubscription, Event } from "@server/models"; diff --git a/server/commands/documentCollaborativeUpdater.ts b/server/commands/documentCollaborativeUpdater.ts index 8c1ae8141a67..64df3c30b205 100644 --- a/server/commands/documentCollaborativeUpdater.ts +++ b/server/commands/documentCollaborativeUpdater.ts @@ -1,5 +1,5 @@ import { yDocToProsemirrorJSON } from "@getoutline/y-prosemirror"; -import { uniq } from "lodash"; +import uniq from "lodash/uniq"; import { Node } from "prosemirror-model"; import * as Y from "yjs"; import { sequelize } from "@server/database/sequelize"; diff --git a/server/commands/documentImporter.ts b/server/commands/documentImporter.ts index e12252f34baf..7af02a1f15c7 100644 --- a/server/commands/documentImporter.ts +++ b/server/commands/documentImporter.ts @@ -1,6 +1,6 @@ import path from "path"; import emojiRegex from "emoji-regex"; -import { truncate } from "lodash"; +import truncate from "lodash/truncate"; import mammoth from "mammoth"; import quotedPrintable from "quoted-printable"; import { Transaction } from "sequelize"; diff --git a/server/commands/documentPermanentDeleter.ts b/server/commands/documentPermanentDeleter.ts index 15475a047c9c..5de4ab3f5f12 100644 --- a/server/commands/documentPermanentDeleter.ts +++ b/server/commands/documentPermanentDeleter.ts @@ -1,4 +1,4 @@ -import { uniq } from "lodash"; +import uniq from "lodash/uniq"; import { QueryTypes } from "sequelize"; import { sequelize } from "@server/database/sequelize"; import Logger from "@server/logging/Logger"; diff --git a/server/commands/notificationUpdater.ts b/server/commands/notificationUpdater.ts index 367f4f2fabef..2e00040931d0 100644 --- a/server/commands/notificationUpdater.ts +++ b/server/commands/notificationUpdater.ts @@ -1,4 +1,4 @@ -import { isUndefined } from "lodash"; +import isUndefined from "lodash/isUndefined"; import { Transaction } from "sequelize"; import { Event, Notification } from "@server/models"; diff --git a/server/commands/teamUpdater.ts b/server/commands/teamUpdater.ts index 73f41bd48aee..3d9b30a4d71e 100644 --- a/server/commands/teamUpdater.ts +++ b/server/commands/teamUpdater.ts @@ -1,4 +1,4 @@ -import { has } from "lodash"; +import has from "lodash/has"; import { Transaction } from "sequelize"; import { TeamPreference } from "@shared/types"; import env from "@server/env"; diff --git a/server/commands/userInviter.ts b/server/commands/userInviter.ts index 072e0f6a9e92..d0ed86b1c891 100644 --- a/server/commands/userInviter.ts +++ b/server/commands/userInviter.ts @@ -1,4 +1,4 @@ -import { uniqBy } from "lodash"; +import uniqBy from "lodash/uniqBy"; import { Role } from "@shared/types"; import InviteEmail from "@server/emails/templates/InviteEmail"; import env from "@server/env"; diff --git a/server/index.ts b/server/index.ts index e6480af9f02a..05ea9e80dcbd 100644 --- a/server/index.ts +++ b/server/index.ts @@ -10,7 +10,7 @@ import Koa from "koa"; import helmet from "koa-helmet"; import logger from "koa-logger"; import Router from "koa-router"; -import { uniq } from "lodash"; +import uniq from "lodash/uniq"; import { AddressInfo } from "net"; import stoppable from "stoppable"; import throng from "throng"; diff --git a/server/logging/Logger.ts b/server/logging/Logger.ts index d25b69d36a4e..e1150686b951 100644 --- a/server/logging/Logger.ts +++ b/server/logging/Logger.ts @@ -1,7 +1,10 @@ /* eslint-disable no-console */ import { IncomingMessage } from "http"; import chalk from "chalk"; -import { isEmpty, isArray, isObject, isString } from "lodash"; +import isArray from "lodash/isArray"; +import isEmpty from "lodash/isEmpty"; +import isObject from "lodash/isObject"; +import isString from "lodash/isString"; import winston from "winston"; import env from "@server/env"; import Metrics from "@server/logging/Metrics"; diff --git a/server/middlewares/rateLimiter.ts b/server/middlewares/rateLimiter.ts index d302e61432ca..3bc620a6ded7 100644 --- a/server/middlewares/rateLimiter.ts +++ b/server/middlewares/rateLimiter.ts @@ -1,5 +1,5 @@ import { Context, Next } from "koa"; -import { defaults } from "lodash"; +import defaults from "lodash/defaults"; import env from "@server/env"; import { RateLimitExceededError } from "@server/errors"; import Logger from "@server/logging/Logger"; diff --git a/server/models/Collection.ts b/server/models/Collection.ts index cfaa8441e11b..7eca2962429c 100644 --- a/server/models/Collection.ts +++ b/server/models/Collection.ts @@ -1,4 +1,7 @@ -import { find, findIndex, remove, uniq } from "lodash"; +import find from "lodash/find"; +import findIndex from "lodash/findIndex"; +import remove from "lodash/remove"; +import uniq from "lodash/uniq"; import randomstring from "randomstring"; import { Identifier, Transaction, Op, FindOptions } from "sequelize"; import { diff --git a/server/models/Document.ts b/server/models/Document.ts index 6cb961a0cec7..230ec4c1c65a 100644 --- a/server/models/Document.ts +++ b/server/models/Document.ts @@ -1,4 +1,5 @@ -import { compact, uniq } from "lodash"; +import compact from "lodash/compact"; +import uniq from "lodash/uniq"; import randomstring from "randomstring"; import type { SaveOptions } from "sequelize"; import { diff --git a/server/models/WebhookSubscription.ts b/server/models/WebhookSubscription.ts index 744e40b7c294..acf94c1f1937 100644 --- a/server/models/WebhookSubscription.ts +++ b/server/models/WebhookSubscription.ts @@ -1,5 +1,5 @@ import crypto from "crypto"; -import { isEmpty } from "lodash"; +import isEmpty from "lodash/isEmpty"; import { SaveOptions } from "sequelize"; import { Column, diff --git a/server/models/decorators/Encrypted.ts b/server/models/decorators/Encrypted.ts index 3318d7b4694a..02ab7d382f61 100644 --- a/server/models/decorators/Encrypted.ts +++ b/server/models/decorators/Encrypted.ts @@ -1,4 +1,4 @@ -import { isNil } from "lodash"; +import isNil from "lodash/isNil"; import vaults from "@server/database/vaults"; import Logger from "@server/logging/Logger"; diff --git a/server/models/helpers/AuthenticationHelper.ts b/server/models/helpers/AuthenticationHelper.ts index 9a56e610102c..c20b5c281b08 100644 --- a/server/models/helpers/AuthenticationHelper.ts +++ b/server/models/helpers/AuthenticationHelper.ts @@ -2,7 +2,8 @@ import path from "path"; import { glob } from "glob"; import Router from "koa-router"; -import { find, sortBy } from "lodash"; +import find from "lodash/find"; +import sortBy from "lodash/sortBy"; import env from "@server/env"; import Team from "@server/models/Team"; diff --git a/server/models/helpers/DocumentHelper.tsx b/server/models/helpers/DocumentHelper.tsx index ad734f94fa45..358041a63ae4 100644 --- a/server/models/helpers/DocumentHelper.tsx +++ b/server/models/helpers/DocumentHelper.tsx @@ -3,7 +3,8 @@ import { yDocToProsemirrorJSON, } from "@getoutline/y-prosemirror"; import { JSDOM } from "jsdom"; -import { escapeRegExp, startCase } from "lodash"; +import escapeRegExp from "lodash/escapeRegExp"; +import startCase from "lodash/startCase"; import { Node } from "prosemirror-model"; import * as Y from "yjs"; import textBetween from "@shared/editor/lib/textBetween"; diff --git a/server/models/helpers/SearchHelper.ts b/server/models/helpers/SearchHelper.ts index 6ac8c2e7634d..5ecee4f7438c 100644 --- a/server/models/helpers/SearchHelper.ts +++ b/server/models/helpers/SearchHelper.ts @@ -1,6 +1,7 @@ import removeMarkdown from "@tommoor/remove-markdown"; import invariant from "invariant"; -import { find, map } from "lodash"; +import find from "lodash/find"; +import map from "lodash/map"; import queryParser from "pg-tsquery"; import { Op, QueryTypes, WhereOptions } from "sequelize"; import { DateFilter } from "@shared/types"; diff --git a/server/models/validators/Length.ts b/server/models/validators/Length.ts index a36ff6652198..572fcd7a0de1 100644 --- a/server/models/validators/Length.ts +++ b/server/models/validators/Length.ts @@ -1,4 +1,4 @@ -import { size } from "lodash"; +import size from "lodash/size"; import { addAttributeOptions } from "sequelize-typescript"; /** diff --git a/server/models/validators/TextLength.ts b/server/models/validators/TextLength.ts index a22d235b75d7..6dcc6eaacd00 100644 --- a/server/models/validators/TextLength.ts +++ b/server/models/validators/TextLength.ts @@ -1,4 +1,4 @@ -import { size } from "lodash"; +import size from "lodash/size"; import { Node } from "prosemirror-model"; import { addAttributeOptions } from "sequelize-typescript"; import { ProsemirrorData } from "@shared/types"; diff --git a/server/onerror.ts b/server/onerror.ts index c167b2b1d2d7..97f0f2972ee8 100644 --- a/server/onerror.ts +++ b/server/onerror.ts @@ -2,7 +2,9 @@ import fs from "fs"; import http from "http"; import path from "path"; import Koa, { Context } from "koa"; -import { isNil, escape, snakeCase } from "lodash"; +import escape from "lodash/escape"; +import isNil from "lodash/isNil"; +import snakeCase from "lodash/snakeCase"; import { ValidationError, EmptyResultError } from "sequelize"; import env from "@server/env"; import { InternalError } from "@server/errors"; diff --git a/server/policies/collection.ts b/server/policies/collection.ts index 70420ab447a8..42cac6fc64d2 100644 --- a/server/policies/collection.ts +++ b/server/policies/collection.ts @@ -1,5 +1,5 @@ import invariant from "invariant"; -import { some } from "lodash"; +import some from "lodash/some"; import { CollectionPermission } from "@shared/types"; import { Collection, User, Team } from "@server/models"; import { AdminRequiredError } from "../errors"; diff --git a/server/presenters/policy.ts b/server/presenters/policy.ts index 472b7975cb57..e120ec6613bc 100644 --- a/server/presenters/policy.ts +++ b/server/presenters/policy.ts @@ -1,4 +1,4 @@ -import { compact } from "lodash"; +import compact from "lodash/compact"; import { traceFunction } from "@server/logging/tracing"; import { User } from "@server/models"; diff --git a/server/queues/tasks/ExportJSONTask.ts b/server/queues/tasks/ExportJSONTask.ts index 8ee6e64d5cbd..53be31092292 100644 --- a/server/queues/tasks/ExportJSONTask.ts +++ b/server/queues/tasks/ExportJSONTask.ts @@ -1,5 +1,5 @@ import JSZip from "jszip"; -import { omit } from "lodash"; +import omit from "lodash/omit"; import { NavigationNode } from "@shared/types"; import { parser } from "@server/editor"; import env from "@server/env"; diff --git a/server/queues/tasks/ExportTask.ts b/server/queues/tasks/ExportTask.ts index 906b2d15b735..c24ffed598a6 100644 --- a/server/queues/tasks/ExportTask.ts +++ b/server/queues/tasks/ExportTask.ts @@ -1,5 +1,5 @@ import fs from "fs"; -import { truncate } from "lodash"; +import truncate from "lodash/truncate"; import { FileOperationState, NotificationEventType } from "@shared/types"; import ExportFailureEmail from "@server/emails/templates/ExportFailureEmail"; import ExportSuccessEmail from "@server/emails/templates/ExportSuccessEmail"; diff --git a/server/queues/tasks/ImportJSONTask.ts b/server/queues/tasks/ImportJSONTask.ts index e6d8b82ba430..fb4c6869e969 100644 --- a/server/queues/tasks/ImportJSONTask.ts +++ b/server/queues/tasks/ImportJSONTask.ts @@ -1,5 +1,6 @@ import JSZip from "jszip"; -import { escapeRegExp, find } from "lodash"; +import escapeRegExp from "lodash/escapeRegExp"; +import find from "lodash/find"; import mime from "mime-types"; import { Node } from "prosemirror-model"; import { v4 as uuidv4 } from "uuid"; diff --git a/server/queues/tasks/ImportMarkdownZipTask.ts b/server/queues/tasks/ImportMarkdownZipTask.ts index 112a723f89d6..dfa725bd22f3 100644 --- a/server/queues/tasks/ImportMarkdownZipTask.ts +++ b/server/queues/tasks/ImportMarkdownZipTask.ts @@ -1,5 +1,5 @@ import JSZip from "jszip"; -import { escapeRegExp } from "lodash"; +import escapeRegExp from "lodash/escapeRegExp"; import mime from "mime-types"; import { v4 as uuidv4 } from "uuid"; import documentImporter from "@server/commands/documentImporter"; diff --git a/server/queues/tasks/ImportNotionTask.ts b/server/queues/tasks/ImportNotionTask.ts index ada3e2d659a8..d90f668afd10 100644 --- a/server/queues/tasks/ImportNotionTask.ts +++ b/server/queues/tasks/ImportNotionTask.ts @@ -1,6 +1,7 @@ import path from "path"; import JSZip from "jszip"; -import { compact, escapeRegExp } from "lodash"; +import compact from "lodash/compact"; +import escapeRegExp from "lodash/escapeRegExp"; import mime from "mime-types"; import { v4 as uuidv4 } from "uuid"; import documentImporter from "@server/commands/documentImporter"; diff --git a/server/queues/tasks/ImportTask.ts b/server/queues/tasks/ImportTask.ts index c92d7446a522..6b818f837dd8 100644 --- a/server/queues/tasks/ImportTask.ts +++ b/server/queues/tasks/ImportTask.ts @@ -1,5 +1,5 @@ import { S3 } from "aws-sdk"; -import { truncate } from "lodash"; +import truncate from "lodash/truncate"; import { CollectionPermission, CollectionSort, diff --git a/server/queues/tasks/RevisionCreatedNotificationsTask.ts b/server/queues/tasks/RevisionCreatedNotificationsTask.ts index f4f44ac3e404..354e59833fee 100644 --- a/server/queues/tasks/RevisionCreatedNotificationsTask.ts +++ b/server/queues/tasks/RevisionCreatedNotificationsTask.ts @@ -1,5 +1,5 @@ import { subHours } from "date-fns"; -import { differenceBy } from "lodash"; +import differenceBy from "lodash/differenceBy"; import { Op } from "sequelize"; import { NotificationEventType } from "@shared/types"; import { createSubscriptionsForDocument } from "@server/commands/subscriptionCreator"; diff --git a/server/redis.ts b/server/redis.ts index ef8027a3efae..1a7536db0a1c 100644 --- a/server/redis.ts +++ b/server/redis.ts @@ -1,5 +1,5 @@ import Redis, { RedisOptions } from "ioredis"; -import { defaults } from "lodash"; +import defaults from "lodash/defaults"; import env from "@server/env"; import Logger from "@server/logging/Logger"; diff --git a/server/routes/api/attachments/schema.ts b/server/routes/api/attachments/schema.ts index 8604f0ad2023..6bc3edcd56ba 100644 --- a/server/routes/api/attachments/schema.ts +++ b/server/routes/api/attachments/schema.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "lodash"; +import isEmpty from "lodash/isEmpty"; import { z } from "zod"; import { AttachmentPreset } from "@shared/types"; import BaseSchema from "@server/routes/api/BaseSchema"; diff --git a/server/routes/api/auth/auth.ts b/server/routes/api/auth/auth.ts index 4244d3b80204..5467260d918b 100644 --- a/server/routes/api/auth/auth.ts +++ b/server/routes/api/auth/auth.ts @@ -1,6 +1,6 @@ import { subHours, subMinutes } from "date-fns"; import Router from "koa-router"; -import { uniqBy } from "lodash"; +import uniqBy from "lodash/uniqBy"; import { TeamPreference } from "@shared/types"; import { getCookieDomain, parseDomain } from "@shared/utils/domains"; import env from "@server/env"; diff --git a/server/routes/api/collections/schema.ts b/server/routes/api/collections/schema.ts index 37e4d6ee566a..0084371ae72b 100644 --- a/server/routes/api/collections/schema.ts +++ b/server/routes/api/collections/schema.ts @@ -1,4 +1,4 @@ -import { isUndefined } from "lodash"; +import isUndefined from "lodash/isUndefined"; import { z } from "zod"; import { randomElement } from "@shared/random"; import { CollectionPermission, FileOperationFormat } from "@shared/types"; diff --git a/server/routes/api/cron/schema.ts b/server/routes/api/cron/schema.ts index 7f61253853bf..7c798935919b 100644 --- a/server/routes/api/cron/schema.ts +++ b/server/routes/api/cron/schema.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "lodash"; +import isEmpty from "lodash/isEmpty"; import { z } from "zod"; import BaseSchema from "../BaseSchema"; diff --git a/server/routes/api/documents/schema.ts b/server/routes/api/documents/schema.ts index ef3411eab96e..5932682d5b42 100644 --- a/server/routes/api/documents/schema.ts +++ b/server/routes/api/documents/schema.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "lodash"; +import isEmpty from "lodash/isEmpty"; import isUUID from "validator/lib/isUUID"; import { z } from "zod"; import { SHARE_URL_SLUG_REGEX } from "@shared/utils/urlHelpers"; diff --git a/server/routes/api/fileOperations/schema.ts b/server/routes/api/fileOperations/schema.ts index 08ae41dcdff6..36299df00357 100644 --- a/server/routes/api/fileOperations/schema.ts +++ b/server/routes/api/fileOperations/schema.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "lodash"; +import isEmpty from "lodash/isEmpty"; import z from "zod"; import { FileOperationType } from "@shared/types"; import { FileOperation } from "@server/models"; diff --git a/server/routes/api/notifications/notifications.ts b/server/routes/api/notifications/notifications.ts index f65c617f26c0..0ae25c3e4de3 100644 --- a/server/routes/api/notifications/notifications.ts +++ b/server/routes/api/notifications/notifications.ts @@ -1,5 +1,6 @@ import Router from "koa-router"; -import { isNull, isUndefined } from "lodash"; +import isNull from "lodash/isNull"; +import isUndefined from "lodash/isUndefined"; import { WhereOptions, Op } from "sequelize"; import { NotificationEventType } from "@shared/types"; import notificationUpdater from "@server/commands/notificationUpdater"; diff --git a/server/routes/api/notifications/schema.ts b/server/routes/api/notifications/schema.ts index 726816bd485d..ac0cfa636ba3 100644 --- a/server/routes/api/notifications/schema.ts +++ b/server/routes/api/notifications/schema.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "lodash"; +import isEmpty from "lodash/isEmpty"; import { z } from "zod"; import { NotificationEventType } from "@shared/types"; import BaseSchema from "../BaseSchema"; diff --git a/server/routes/api/revisions/schema.ts b/server/routes/api/revisions/schema.ts index 5d3df7fe36e0..76b874d9aff6 100644 --- a/server/routes/api/revisions/schema.ts +++ b/server/routes/api/revisions/schema.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "lodash"; +import isEmpty from "lodash/isEmpty"; import { z } from "zod"; import { Revision } from "@server/models"; import BaseSchema from "@server/routes/api/BaseSchema"; diff --git a/server/routes/api/searches/schema.ts b/server/routes/api/searches/schema.ts index c99fc4973628..a8e184e336c8 100644 --- a/server/routes/api/searches/schema.ts +++ b/server/routes/api/searches/schema.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "lodash"; +import isEmpty from "lodash/isEmpty"; import { z } from "zod"; import BaseSchema from "../BaseSchema"; diff --git a/server/routes/api/shares/schema.ts b/server/routes/api/shares/schema.ts index a865d9b4fb30..6b4076176e3a 100644 --- a/server/routes/api/shares/schema.ts +++ b/server/routes/api/shares/schema.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "lodash"; +import isEmpty from "lodash/isEmpty"; import isUUID from "validator/lib/isUUID"; import { z } from "zod"; import { SHARE_URL_SLUG_REGEX, SLUG_URL_REGEX } from "@shared/utils/urlHelpers"; diff --git a/server/routes/api/shares/shares.ts b/server/routes/api/shares/shares.ts index ba7df7816a85..f2c883a7c3f1 100644 --- a/server/routes/api/shares/shares.ts +++ b/server/routes/api/shares/shares.ts @@ -1,5 +1,5 @@ import Router from "koa-router"; -import { isUndefined } from "lodash"; +import isUndefined from "lodash/isUndefined"; import { Op, WhereOptions } from "sequelize"; import { NotFoundError } from "@server/errors"; import auth from "@server/middlewares/authentication"; diff --git a/server/routes/api/stars/schema.ts b/server/routes/api/stars/schema.ts index 0cd460c8d648..42573081f1f3 100644 --- a/server/routes/api/stars/schema.ts +++ b/server/routes/api/stars/schema.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "lodash"; +import isEmpty from "lodash/isEmpty"; import { z } from "zod"; import { ValidateDocumentId, ValidateIndex } from "@server/validation"; import BaseSchema from "../BaseSchema"; diff --git a/server/routes/api/urls/schema.ts b/server/routes/api/urls/schema.ts index ce7857c1bd25..d531e427b773 100644 --- a/server/routes/api/urls/schema.ts +++ b/server/routes/api/urls/schema.ts @@ -1,4 +1,4 @@ -import { isNil } from "lodash"; +import isNil from "lodash/isNil"; import { z } from "zod"; import { isUrl } from "@shared/utils/urls"; import { ValidateURL } from "@server/validation"; diff --git a/server/routes/app.ts b/server/routes/app.ts index e3f3e2e92dc6..01a91429e0e7 100644 --- a/server/routes/app.ts +++ b/server/routes/app.ts @@ -2,7 +2,7 @@ import fs from "fs"; import path from "path"; import util from "util"; import { Context, Next } from "koa"; -import { escape } from "lodash"; +import escape from "lodash/escape"; import { Sequelize } from "sequelize"; import isUUID from "validator/lib/isUUID"; import { IntegrationType, TeamPreference } from "@shared/types"; diff --git a/server/test/factories.ts b/server/test/factories.ts index 5cafc31adbb9..42f1cc7efc3d 100644 --- a/server/test/factories.ts +++ b/server/test/factories.ts @@ -1,4 +1,5 @@ -import { isNil, isNull } from "lodash"; +import isNil from "lodash/isNil"; +import isNull from "lodash/isNull"; import { v4 as uuidv4 } from "uuid"; import { CollectionPermission, diff --git a/server/utils/ShutdownHelper.ts b/server/utils/ShutdownHelper.ts index a8b553d3fe2d..67befd21e029 100644 --- a/server/utils/ShutdownHelper.ts +++ b/server/utils/ShutdownHelper.ts @@ -1,4 +1,4 @@ -import { groupBy } from "lodash"; +import groupBy from "lodash/groupBy"; import Logger from "@server/logging/Logger"; import { timeout } from "./timers"; diff --git a/server/utils/ZipHelper.ts b/server/utils/ZipHelper.ts index fac62b246cbe..20666269ad0c 100644 --- a/server/utils/ZipHelper.ts +++ b/server/utils/ZipHelper.ts @@ -1,7 +1,7 @@ import fs from "fs"; import path from "path"; import JSZip from "jszip"; -import { find } from "lodash"; +import find from "lodash/find"; import tmp from "tmp"; import { bytesToHumanReadable } from "@shared/utils/files"; import { ValidationError } from "@server/errors"; diff --git a/server/utils/authentication.ts b/server/utils/authentication.ts index ad3b4a0a761b..39c09b6da911 100644 --- a/server/utils/authentication.ts +++ b/server/utils/authentication.ts @@ -1,7 +1,7 @@ import querystring from "querystring"; import { addMonths } from "date-fns"; import { Context } from "koa"; -import { pick } from "lodash"; +import pick from "lodash/pick"; import { Client } from "@shared/types"; import { getCookieDomain } from "@shared/utils/domains"; import env from "@server/env"; diff --git a/server/utils/koa.ts b/server/utils/koa.ts index 14a48bb9bc69..1f71d8547e1b 100644 --- a/server/utils/koa.ts +++ b/server/utils/koa.ts @@ -1,6 +1,6 @@ import formidable from "formidable"; import { Request } from "koa"; -import { isArray } from "lodash"; +import isArray from "lodash/isArray"; /** * Get the first file from an incoming koa request diff --git a/server/utils/parseAttachmentIds.ts b/server/utils/parseAttachmentIds.ts index a97871d006cf..832cdfb54cbc 100644 --- a/server/utils/parseAttachmentIds.ts +++ b/server/utils/parseAttachmentIds.ts @@ -1,4 +1,5 @@ -import { uniq, compact } from "lodash"; +import compact from "lodash/compact"; +import uniq from "lodash/uniq"; const attachmentRedirectRegex = /\/api\/attachments\.redirect\?id=(?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/gi; diff --git a/server/utils/queue.ts b/server/utils/queue.ts index 1f96de822896..f325e30870a4 100644 --- a/server/utils/queue.ts +++ b/server/utils/queue.ts @@ -1,5 +1,5 @@ import Queue from "bull"; -import { snakeCase } from "lodash"; +import snakeCase from "lodash/snakeCase"; import { Second } from "@shared/utils/time"; import env from "@server/env"; import Metrics from "@server/logging/Metrics"; diff --git a/server/utils/s3.ts b/server/utils/s3.ts index c106fd438ce3..3dbcb3b39db2 100644 --- a/server/utils/s3.ts +++ b/server/utils/s3.ts @@ -1,7 +1,7 @@ import util from "util"; import AWS, { S3 } from "aws-sdk"; import fetch from "fetch-with-proxy"; -import { compact } from "lodash"; +import compact from "lodash/compact"; import { useAgent } from "request-filtering-agent"; import { v4 as uuidv4 } from "uuid"; import Logger from "@server/logging/Logger"; diff --git a/server/utils/startup.ts b/server/utils/startup.ts index c8a609347979..1dacb54f436e 100644 --- a/server/utils/startup.ts +++ b/server/utils/startup.ts @@ -1,5 +1,5 @@ import chalk from "chalk"; -import { isEmpty } from "lodash"; +import isEmpty from "lodash/isEmpty"; import { migrations } from "@server/database/sequelize"; import env from "@server/env"; import Logger from "@server/logging/Logger"; diff --git a/server/utils/turndown/confluence-code-block.ts b/server/utils/turndown/confluence-code-block.ts index 50f295178d74..986a5df5177c 100644 --- a/server/utils/turndown/confluence-code-block.ts +++ b/server/utils/turndown/confluence-code-block.ts @@ -1,4 +1,4 @@ -import { repeat } from "lodash"; +import repeat from "lodash/repeat"; import TurndownService from "turndown"; const highlightRegExp = /brush: ([a-z0-9]+);/; diff --git a/server/utils/unfurl.ts b/server/utils/unfurl.ts index b17f3b99547f..dd3684dea6af 100644 --- a/server/utils/unfurl.ts +++ b/server/utils/unfurl.ts @@ -1,7 +1,7 @@ import { existsSync } from "fs"; import path from "path"; import glob from "glob"; -import { startCase } from "lodash"; +import startCase from "lodash/startCase"; import env from "@server/env"; import Logger from "@server/logging/Logger"; import { UnfurlResolver } from "@server/types"; diff --git a/server/validation.ts b/server/validation.ts index 59932e9a47a3..a05f09e7ec30 100644 --- a/server/validation.ts +++ b/server/validation.ts @@ -1,4 +1,4 @@ -import { isArrayLike } from "lodash"; +import isArrayLike from "lodash/isArrayLike"; import { Primitive } from "utility-types"; import validator from "validator"; import isUUID from "validator/lib/isUUID"; diff --git a/shared/editor/extensions/FindAndReplace.ts b/shared/editor/extensions/FindAndReplace.ts index df0e7cedc412..f70215989408 100644 --- a/shared/editor/extensions/FindAndReplace.ts +++ b/shared/editor/extensions/FindAndReplace.ts @@ -1,4 +1,4 @@ -import { escapeRegExp } from "lodash"; +import escapeRegExp from "lodash/escapeRegExp"; import { Node } from "prosemirror-model"; import { Command, Plugin, PluginKey } from "prosemirror-state"; import { Decoration, DecorationSet } from "prosemirror-view"; diff --git a/shared/editor/extensions/Prism.ts b/shared/editor/extensions/Prism.ts index 39f1c32be7a3..b7b32046d726 100644 --- a/shared/editor/extensions/Prism.ts +++ b/shared/editor/extensions/Prism.ts @@ -1,4 +1,5 @@ -import { flattenDeep, padStart } from "lodash"; +import flattenDeep from "lodash/flattenDeep"; +import padStart from "lodash/padStart"; import { Node } from "prosemirror-model"; import { Plugin, PluginKey, Transaction } from "prosemirror-state"; import { Decoration, DecorationSet } from "prosemirror-view"; diff --git a/shared/editor/lib/headingToSlug.ts b/shared/editor/lib/headingToSlug.ts index 9cfc42fdfd6a..1a5a53a43de3 100644 --- a/shared/editor/lib/headingToSlug.ts +++ b/shared/editor/lib/headingToSlug.ts @@ -1,4 +1,4 @@ -import { escape } from "lodash"; +import escape from "lodash/escape"; import { Node } from "prosemirror-model"; import slugify from "slugify"; diff --git a/shared/editor/rules/attachments.ts b/shared/editor/rules/attachments.ts index 59f3d0f19e69..5ceb92228d21 100644 --- a/shared/editor/rules/attachments.ts +++ b/shared/editor/rules/attachments.ts @@ -26,8 +26,8 @@ function isAttachment(token: Token) { return ( // internal - href?.startsWith("/api/attachments.redirect") || // external (public share are pre-signed and this is a reasonable way of detecting them) + href?.startsWith("/api/attachments.redirect") || ((href?.startsWith(env.AWS_S3_UPLOAD_BUCKET_URL) || href?.startsWith(env.AWS_S3_ACCELERATE_URL)) && href?.includes("X-Amz-Signature")) diff --git a/shared/utils/domains.ts b/shared/utils/domains.ts index 0dc96c5fd73c..69a2a5a49232 100644 --- a/shared/utils/domains.ts +++ b/shared/utils/domains.ts @@ -1,4 +1,4 @@ -import { trim } from "lodash"; +import trim from "lodash/trim"; import env from "../env"; type Domain = { diff --git a/shared/utils/naturalSort.ts b/shared/utils/naturalSort.ts index 8cb7ad11b279..110e901f9cf9 100644 --- a/shared/utils/naturalSort.ts +++ b/shared/utils/naturalSort.ts @@ -1,5 +1,5 @@ import emojiRegex from "emoji-regex"; -import { deburr } from "lodash"; +import deburr from "lodash/deburr"; import naturalSort from "natural-sort"; type NaturalSortOptions = { diff --git a/shared/utils/urls.ts b/shared/utils/urls.ts index 14f80c0fbc4c..d8a280ee027f 100644 --- a/shared/utils/urls.ts +++ b/shared/utils/urls.ts @@ -1,4 +1,4 @@ -import { escapeRegExp } from "lodash"; +import escapeRegExp from "lodash/escapeRegExp"; import env from "../env"; import { parseDomain } from "./domains"; diff --git a/vite.config.ts b/vite.config.ts index 50664d9e59b6..60600d4fdef8 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,7 +1,5 @@ import fs from "fs"; import path from "path"; -// eslint-disable-next-line import/no-unresolved -import { optimizeLodashImports } from "@optimize-lodash/rollup-plugin"; import react from "@vitejs/plugin-react"; import browserslistToEsbuild from "browserslist-to-esbuild"; import dotenv from "dotenv"; @@ -124,8 +122,6 @@ export default () => ], }, }), - // Convert lodash imports to single imports - optimizeLodashImports(), // Generate a stats.json file for webpack that will be consumed by RelativeCI webpackStats(), ], diff --git a/yarn.lock b/yarn.lock index 122d2b20f85c..123ddf71b5d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2089,22 +2089,6 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.1.tgz#3d745996b2bd11095b515515fd3d68d46092a02d" integrity sha512-n8Kur1/CZlYG32YCEj30CoUqA8R7UyDVZzoEU6SDP+13+kXDT2kFVu6MpcnEUTyGP3i058ID6Qjp5h6IJxdPPQ== -"@optimize-lodash/rollup-plugin@4.0.3": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@optimize-lodash/rollup-plugin/-/rollup-plugin-4.0.3.tgz#dbee2c7294802a833fc5c52432614e2b7d3f2bea" - integrity sha512-zp9Yj8LL0QlUBXFmSI2EUI0phg9KvW9x1ZdsEhYuyxhNC1KiEUQR8ZEdH/GF8ZRPiKAL1fUJ8195wYlzhFsspA== - dependencies: - "@optimize-lodash/transform" "3.0.2" - "@rollup/pluginutils" "~5.0.2" - -"@optimize-lodash/transform@3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@optimize-lodash/transform/-/transform-3.0.2.tgz#90d2db478b0a68e285d0dbdeaf0654f5ae8282c3" - integrity sha512-wkRhFMnzY9BQDc6mK1ORw+NN+v2DYY8HRI1P5n9Lvh7iwXzGeef5XKHQYIMFggGLPkGjlX14tjlXiEzb4SqJPg== - dependencies: - estree-walker "2.x" - magic-string "0.27.x" - "@outlinewiki/koa-passport@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@outlinewiki/koa-passport/-/koa-passport-4.2.1.tgz#4798f9f67cddc1b52ce4201f1032d455b493025c" @@ -2516,7 +2500,7 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@rollup/pluginutils@^5.0.1", "@rollup/pluginutils@~5.0.2": +"@rollup/pluginutils@^5.0.1": version "5.0.2" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.2.tgz#012b8f53c71e4f6f9cb317e311df1404f56e7a33" integrity sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA== @@ -6390,6 +6374,13 @@ eslint-plugin-jsx-a11y@^6.1.0: jsx-ast-utils "^3.1.0" language-tags "^1.0.5" +eslint-plugin-lodash@^7.4.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-lodash/-/eslint-plugin-lodash-7.4.0.tgz#14a761547f126c92ff56789662a20a44f8bb6290" + integrity sha512-Tl83UwVXqe1OVeBRKUeWcfg6/pCW1GTRObbdnbEJgYwjxp5Q92MEWQaH9+dmzbRt6kvYU1Mp893E79nJiCSM8A== + dependencies: + lodash "^4.17.21" + eslint-plugin-node@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" @@ -6545,16 +6536,16 @@ estraverse@^5.1.0, estraverse@^5.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== -estree-walker@2.x, estree-walker@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" - integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== - estree-walker@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -9396,13 +9387,6 @@ luxon@^3.0.1: resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.2.1.tgz#14f1af209188ad61212578ea7e3d518d18cee45f" integrity sha512-QrwPArQCNLAKGO/C+ZIilgIuDnEnKx5QYODdDtbFaxzsbZcc/a7WFq7MhsVYgRlwawLtvOUESTlfJ+hc/USqPg== -magic-string@0.27.x, magic-string@^0.27.0: - version "0.27.0" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" - integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== - dependencies: - "@jridgewell/sourcemap-codec" "^1.4.13" - magic-string@^0.25.0, magic-string@^0.25.7: version "0.25.9" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" @@ -9410,6 +9394,13 @@ magic-string@^0.25.0, magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.8" +magic-string@^0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" + integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.13" + make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" From c38e045df25d275109635860f162449b1444d60b Mon Sep 17 00:00:00 2001 From: Philip Standt Date: Mon, 14 Aug 2023 20:46:24 +0200 Subject: [PATCH 130/144] feat: support self hosted grist (#5655) Co-authored-by: Tom Moor --- app/scenes/Settings/SelfHosted.tsx | 50 ++++++++++++++++--- server/models/Integration.ts | 1 + .../api/integrations/integrations.test.ts | 45 ++++++++++++++++- shared/editor/embeds/Grist.tsx | 2 + shared/i18n/locales/en_US/translation.json | 2 + shared/types.ts | 1 + 6 files changed, 93 insertions(+), 8 deletions(-) diff --git a/app/scenes/Settings/SelfHosted.tsx b/app/scenes/Settings/SelfHosted.tsx index 45c8cb38f745..ce56859daf86 100644 --- a/app/scenes/Settings/SelfHosted.tsx +++ b/app/scenes/Settings/SelfHosted.tsx @@ -16,6 +16,7 @@ import SettingRow from "./components/SettingRow"; type FormData = { drawIoUrl: string; + gristUrl: string; }; function SelfHosted() { @@ -23,11 +24,16 @@ function SelfHosted() { const { t } = useTranslation(); const { showToast } = useToasts(); - const integration = find(integrations.orderedData, { + const integrationDiagrams = find(integrations.orderedData, { type: IntegrationType.Embed, service: IntegrationService.Diagrams, }) as Integration | undefined; + const integrationGrist = find(integrations.orderedData, { + type: IntegrationType.Embed, + service: IntegrationService.Grist, + }) as Integration | undefined; + const { register, reset, @@ -36,7 +42,8 @@ function SelfHosted() { } = useForm({ mode: "all", defaultValues: { - drawIoUrl: integration?.settings.url, + drawIoUrl: integrationDiagrams?.settings.url, + gristUrl: integrationGrist?.settings.url, }, }); @@ -47,15 +54,18 @@ function SelfHosted() { }, [integrations]); React.useEffect(() => { - reset({ drawIoUrl: integration?.settings.url }); - }, [integration, reset]); + reset({ + drawIoUrl: integrationDiagrams?.settings.url, + gristUrl: integrationGrist?.settings.url, + }); + }, [integrationDiagrams, integrationGrist, reset]); const handleSubmit = React.useCallback( async (data: FormData) => { try { if (data.drawIoUrl) { await integrations.save({ - id: integration?.id, + id: integrationDiagrams?.id, type: IntegrationType.Embed, service: IntegrationService.Diagrams, settings: { @@ -63,7 +73,20 @@ function SelfHosted() { }, }); } else { - await integration?.delete(); + await integrationDiagrams?.delete(); + } + + if (data.gristUrl) { + await integrations.save({ + id: integrationGrist?.id, + type: IntegrationType.Embed, + service: IntegrationService.Grist, + settings: { + url: data.gristUrl, + }, + }); + } else { + await integrationGrist?.delete(); } showToast(t("Settings saved"), { @@ -75,7 +98,7 @@ function SelfHosted() { }); } }, - [integrations, integration, t, showToast] + [integrations, integrationDiagrams, integrationGrist, t, showToast] ); return ( @@ -98,6 +121,19 @@ function SelfHosted() { /> + + + + diff --git a/server/models/Integration.ts b/server/models/Integration.ts index 1d188e9a9c4f..4906cc8bd2e6 100644 --- a/server/models/Integration.ts +++ b/server/models/Integration.ts @@ -18,6 +18,7 @@ import Fix from "./decorators/Fix"; export enum UserCreatableIntegrationService { Diagrams = "diagrams", + Grist = "grist", GoogleAnalytics = "google-analytics", } diff --git a/server/routes/api/integrations/integrations.test.ts b/server/routes/api/integrations/integrations.test.ts index 792e83abb350..7ef32d690d2c 100644 --- a/server/routes/api/integrations/integrations.test.ts +++ b/server/routes/api/integrations/integrations.test.ts @@ -49,7 +49,7 @@ describe("#integrations.update", () => { expect(res.status).toEqual(403); }); - it("should succeed with status 200 ok when settings are updated", async () => { + it("should succeed with status 200 ok when diagram integration settings are updated", async () => { const admin = await buildAdmin(); const integration = await buildIntegration({ @@ -72,6 +72,30 @@ describe("#integrations.update", () => { expect(body.data.id).toEqual(integration.id); expect(body.data.settings.url).toEqual("https://foo.bar"); }); + + it("should succeed with status 200 ok when grist integration settings are updated", async () => { + const admin = await buildAdmin(); + + const integration = await buildIntegration({ + userId: admin.id, + teamId: admin.teamId, + service: IntegrationService.Grist, + type: IntegrationType.Embed, + settings: { url: "https://example.com" }, + }); + + const res = await server.post("/api/integrations.update", { + body: { + token: admin.getJwtToken(), + id: integration.id, + settings: { url: "https://grist.example.com" }, + }, + }); + + const body = await res.json(); + expect(body.data.id).toEqual(integration.id); + expect(body.data.settings.url).toEqual("https://grist.example.com"); + }); }); describe("#integrations.create", () => { @@ -111,6 +135,25 @@ describe("#integrations.create", () => { expect(body.data.settings).not.toBeFalsy(); expect(body.data.settings.measurementId).toEqual("123"); }); + + it("should succeed with status 200 ok for an grist integration", async () => { + const admin = await buildAdmin(); + + const res = await server.post("/api/integrations.create", { + body: { + token: admin.getJwtToken(), + type: IntegrationType.Embed, + service: UserCreatableIntegrationService.Grist, + settings: { url: "https://grist.example.com" }, + }, + }); + const body = await res.json(); + expect(res.status).toEqual(200); + expect(body.data.type).toEqual(IntegrationType.Embed); + expect(body.data.service).toEqual(UserCreatableIntegrationService.Grist); + expect(body.data.settings).not.toBeFalsy(); + expect(body.data.settings.url).toEqual("https://grist.example.com"); + }); }); describe("#integrations.delete", () => { diff --git a/shared/editor/embeds/Grist.tsx b/shared/editor/embeds/Grist.tsx index 5f6c1972e381..851ee0d10984 100644 --- a/shared/editor/embeds/Grist.tsx +++ b/shared/editor/embeds/Grist.tsx @@ -24,4 +24,6 @@ function Grist(props: Props) { Grist.ENABLED = [new RegExp("^https?://([a-z.-]+\\.)?getgrist\\.com/(.+)$")]; +Grist.URL_PATH_REGEX = /(.+)/; + export default Grist; diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json index 513c6c2b430e..dc3634231d10 100644 --- a/shared/i18n/locales/en_US/translation.json +++ b/shared/i18n/locales/en_US/translation.json @@ -851,6 +851,8 @@ "Allow members to create new collections within the knowledge base": "Allow members to create new collections within the knowledge base", "Draw.io deployment": "Draw.io deployment", "Add your self-hosted draw.io installation url here to enable automatic embedding of diagrams within documents.": "Add your self-hosted draw.io installation url here to enable automatic embedding of diagrams within documents.", + "Grist deployment": "Grist deployment", + "Add your self-hosted grist installation URL here.": "Add your self-hosted grist installation URL here.", "Sharing is currently disabled.": "Sharing is currently disabled.", "You can globally enable and disable public document sharing in the security settings.": "You can globally enable and disable public document sharing in the security settings.", "Documents that have been shared are listed below. Anyone that has the public link can access a read-only version of the document until the link has been revoked.": "Documents that have been shared are listed below. Anyone that has the public link can access a read-only version of the document until the link has been revoked.", diff --git a/shared/types.ts b/shared/types.ts index a2af6fd227e8..1d32d40650f6 100644 --- a/shared/types.ts +++ b/shared/types.ts @@ -79,6 +79,7 @@ export enum IntegrationType { export enum IntegrationService { Diagrams = "diagrams", + Grist = "grist", Slack = "slack", GoogleAnalytics = "google-analytics", } From 4edfab20fecc77ff12e6086a76593c218edd3ebd Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Mon, 14 Aug 2023 20:48:49 +0200 Subject: [PATCH 131/144] fix: Bug with local dynamic reloading since moving to SSL --- server/services/web.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/services/web.ts b/server/services/web.ts index bf2064dfc5af..44f97b1947e8 100644 --- a/server/services/web.ts +++ b/server/services/web.ts @@ -42,7 +42,7 @@ const styleSrc = [ // Allow to load assets from Vite if (!isProduction) { - scriptSrc.push("127.0.0.1:3001"); + scriptSrc.push(env.URL.replace(`:${env.PORT}`, ":3001")); scriptSrc.push("localhost:3001"); } From 9f0534d5443d019479598579621c166087ef6045 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Mon, 14 Aug 2023 20:51:08 +0200 Subject: [PATCH 132/144] chore: Bump vite Reduces full page reloads in dev, increase perf --- package.json | 2 +- yarn.lock | 269 +++++++++++++++++++++++++-------------------------- 2 files changed, 135 insertions(+), 136 deletions(-) diff --git a/package.json b/package.json index 5e1ea31dab9c..4a0dbc73ce5f 100644 --- a/package.json +++ b/package.json @@ -216,7 +216,7 @@ "utility-types": "^3.10.0", "uuid": "^8.3.2", "validator": "13.9.0", - "vite": "^4.1.5", + "vite": "^4.4.9", "vite-plugin-pwa": "^0.14.4", "winston": "^3.10.0", "ws": "^7.5.9", diff --git a/yarn.lock b/yarn.lock index 123ddf71b5d5..caf6c38729a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1341,226 +1341,226 @@ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== -"@esbuild/android-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz#cf91e86df127aa3d141744edafcba0abdc577d23" - integrity sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg== - "@esbuild/android-arm64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.11.tgz#52c3e6cabc19c5e4c1c0c01cb58f0442338e1c14" integrity sha512-QnK4d/zhVTuV4/pRM4HUjcsbl43POALU2zvBynmrrqZt9LPcLA3x1fTZPBg2RRguBQnJcnU059yKr+bydkntjg== -"@esbuild/android-arm@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.16.17.tgz#025b6246d3f68b7bbaa97069144fb5fb70f2fff2" - integrity sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw== +"@esbuild/android-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622" + integrity sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ== "@esbuild/android-arm@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.11.tgz#f3fc768235aecbeb840d0049fdf13cd28592105f" integrity sha512-CdyX6sRVh1NzFCsf5vw3kULwlAhfy9wVt8SZlrhQ7eL2qBjGbFhRBWkkAzuZm9IIEOCKJw4DXA6R85g+qc8RDw== -"@esbuild/android-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.16.17.tgz#c820e0fef982f99a85c4b8bfdd582835f04cd96e" - integrity sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ== +"@esbuild/android-arm@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz#fedb265bc3a589c84cc11f810804f234947c3682" + integrity sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw== "@esbuild/android-x64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.11.tgz#443ed47771a7e917e4282469ba350d117473550c" integrity sha512-3PL3HKtsDIXGQcSCKtWD/dy+mgc4p2Tvo2qKgKHj9Yf+eniwFnuoQ0OUhlSfAEpKAFzF9N21Nwgnap6zy3L3MQ== -"@esbuild/darwin-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz#edef4487af6b21afabba7be5132c26d22379b220" - integrity sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w== +"@esbuild/android-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.20.tgz#35cf419c4cfc8babe8893d296cd990e9e9f756f2" + integrity sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg== "@esbuild/darwin-arm64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.11.tgz#0e8c78d94d5759a48521dbfd83189d2ed3499a16" integrity sha512-pJ950bNKgzhkGNO3Z9TeHzIFtEyC2GDQL3wxkMApDEghYx5Qers84UTNc1bAxWbRkuJOgmOha5V0WUeh8G+YGw== -"@esbuild/darwin-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz#42829168730071c41ef0d028d8319eea0e2904b4" - integrity sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg== +"@esbuild/darwin-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz#08172cbeccf95fbc383399a7f39cfbddaeb0d7c1" + integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA== "@esbuild/darwin-x64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.11.tgz#2405cfdf70eb961c7cf973463ca7263dc2004c88" integrity sha512-iB0dQkIHXyczK3BZtzw1tqegf0F0Ab5texX2TvMQjiJIWXAfM4FQl7D909YfXWnB92OQz4ivBYQ2RlxBJrMJOw== -"@esbuild/freebsd-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz#1f4af488bfc7e9ced04207034d398e793b570a27" - integrity sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw== +"@esbuild/darwin-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz#d70d5790d8bf475556b67d0f8b7c5bdff053d85d" + integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ== "@esbuild/freebsd-arm64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.11.tgz#d5138e873e15f87bd4564c024dfa00ef37e623fd" integrity sha512-7EFzUADmI1jCHeDRGKgbnF5sDIceZsQGapoO6dmw7r/ZBEKX7CCDnIz8m9yEclzr7mFsd+DyasHzpjfJnmBB1Q== -"@esbuild/freebsd-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz#636306f19e9bc981e06aa1d777302dad8fddaf72" - integrity sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug== +"@esbuild/freebsd-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz#98755cd12707f93f210e2494d6a4b51b96977f54" + integrity sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw== "@esbuild/freebsd-x64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.11.tgz#e850b58b8fabf8e9ef0e125af3c25229ad2d6c38" integrity sha512-iPgenptC8i8pdvkHQvXJFzc1eVMR7W2lBPrTE6GbhR54sLcF42mk3zBOjKPOodezzuAz/KSu8CPyFSjcBMkE9g== -"@esbuild/linux-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz#a003f7ff237c501e095d4f3a09e58fc7b25a4aca" - integrity sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g== +"@esbuild/freebsd-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz#c1eb2bff03915f87c29cece4c1a7fa1f423b066e" + integrity sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ== "@esbuild/linux-arm64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.11.tgz#2bfb93d0809ec2357c12ebb27736b750c9ae0aa5" integrity sha512-Qxth3gsWWGKz2/qG2d5DsW/57SeA2AmpSMhdg9TSB5Svn2KDob3qxfQSkdnWjSd42kqoxIPy3EJFs+6w1+6Qjg== -"@esbuild/linux-arm@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz#b591e6a59d9c4fe0eeadd4874b157ab78cf5f196" - integrity sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ== +"@esbuild/linux-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz#bad4238bd8f4fc25b5a021280c770ab5fc3a02a0" + integrity sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA== "@esbuild/linux-arm@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.11.tgz#e56fb3b76828317a704f4a167c5bd790fe5314e7" integrity sha512-M9iK/d4lgZH0U5M1R2p2gqhPV/7JPJcRz+8O8GBKVgqndTzydQ7B2XGDbxtbvFkvIs53uXTobOhv+RyaqhUiMg== -"@esbuild/linux-ia32@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz#24333a11027ef46a18f57019450a5188918e2a54" - integrity sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg== +"@esbuild/linux-arm@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz#3e617c61f33508a27150ee417543c8ab5acc73b0" + integrity sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg== "@esbuild/linux-ia32@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.11.tgz#59fa1c49b271793d14eb5effc757e8c0d0cb2cab" integrity sha512-dB1nGaVWtUlb/rRDHmuDQhfqazWE0LMro/AIbT2lWM3CDMHJNpLckH+gCddQyhhcLac2OYw69ikUMO34JLt3wA== -"@esbuild/linux-loong64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz#d5ad459d41ed42bbd4d005256b31882ec52227d8" - integrity sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ== +"@esbuild/linux-ia32@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz#699391cccba9aee6019b7f9892eb99219f1570a7" + integrity sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA== "@esbuild/linux-loong64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.11.tgz#89575bc189099c03a36daa54f3f481780c7fd502" integrity sha512-aCWlq70Q7Nc9WDnormntGS1ar6ZFvUpqr8gXtO+HRejRYPweAFQN615PcgaSJkZjhHp61+MNLhzyVALSF2/Q0g== -"@esbuild/linux-mips64el@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz#4e5967a665c38360b0a8205594377d4dcf9c3726" - integrity sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw== +"@esbuild/linux-loong64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz#e6fccb7aac178dd2ffb9860465ac89d7f23b977d" + integrity sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg== "@esbuild/linux-mips64el@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.11.tgz#0e18ca039dc7e4645efd8edc1b10952933eb6b1b" integrity sha512-cGeGNdQxqY8qJwlYH1BP6rjIIiEcrM05H7k3tR7WxOLmD1ZxRMd6/QIOWMb8mD2s2YJFNRuNQ+wjMhgEL2oCEw== -"@esbuild/linux-ppc64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz#206443a02eb568f9fdf0b438fbd47d26e735afc8" - integrity sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g== +"@esbuild/linux-mips64el@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz#eeff3a937de9c2310de30622a957ad1bd9183231" + integrity sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ== "@esbuild/linux-ppc64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.11.tgz#2d152cb3a253afb8c100a165ad132dc96f36cb11" integrity sha512-BdlziJQPW/bNe0E8eYsHB40mYOluS+jULPCjlWiHzDgr+ZBRXPtgMV1nkLEGdpjrwgmtkZHEGEPaKdS/8faLDA== -"@esbuild/linux-riscv64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz#c351e433d009bf256e798ad048152c8d76da2fc9" - integrity sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw== +"@esbuild/linux-ppc64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz#2f7156bde20b01527993e6881435ad79ba9599fb" + integrity sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA== "@esbuild/linux-riscv64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.11.tgz#c6ac494a81221d53d65b33e665c7df1747952d3c" integrity sha512-MDLwQbtF+83oJCI1Cixn68Et/ME6gelmhssPebC40RdJaect+IM+l7o/CuG0ZlDs6tZTEIoxUe53H3GmMn8oMA== -"@esbuild/linux-s390x@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz#661f271e5d59615b84b6801d1c2123ad13d9bd87" - integrity sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w== +"@esbuild/linux-riscv64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz#6628389f210123d8b4743045af8caa7d4ddfc7a6" + integrity sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A== "@esbuild/linux-s390x@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.11.tgz#4bad33894bc7415cea4be8fa90fe456226a424ad" integrity sha512-4N5EMESvws0Ozr2J94VoUD8HIRi7X0uvUv4c0wpTHZyZY9qpaaN7THjosdiW56irQ4qnJ6Lsc+i+5zGWnyqWqQ== -"@esbuild/linux-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz#e4ba18e8b149a89c982351443a377c723762b85f" - integrity sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw== +"@esbuild/linux-s390x@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz#255e81fb289b101026131858ab99fba63dcf0071" + integrity sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ== "@esbuild/linux-x64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.11.tgz#903fda743459f530a16a6c6ee8d2c0f6c1a12fc7" integrity sha512-rM/v8UlluxpytFSmVdbCe1yyKQd/e+FmIJE2oPJvbBo+D0XVWi1y/NQ4iTNx+436WmDHQBjVLrbnAQLQ6U7wlw== -"@esbuild/netbsd-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz#7d4f4041e30c5c07dd24ffa295c73f06038ec775" - integrity sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA== +"@esbuild/linux-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz#c7690b3417af318a9b6f96df3031a8865176d338" + integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w== "@esbuild/netbsd-x64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.11.tgz#b589239fe7d9b16ee03c5e191f3f5b640f1518a1" integrity sha512-4WaAhuz5f91h3/g43VBGdto1Q+X7VEZfpcWGtOFXnggEuLvjV+cP6DyLRU15IjiU9fKLLk41OoJfBFN5DhPvag== -"@esbuild/openbsd-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz#970fa7f8470681f3e6b1db0cc421a4af8060ec35" - integrity sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg== +"@esbuild/netbsd-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz#30e8cd8a3dded63975e2df2438ca109601ebe0d1" + integrity sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A== "@esbuild/openbsd-x64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.11.tgz#b355019754116bef39ec688f8fd2fe6471b9779b" integrity sha512-UBj135Nx4FpnvtE+C8TWGp98oUgBcmNmdYgl5ToKc0mBHxVVqVE7FUS5/ELMImOp205qDAittL6Ezhasc2Ev/w== -"@esbuild/sunos-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz#abc60e7c4abf8b89fb7a4fe69a1484132238022c" - integrity sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw== +"@esbuild/openbsd-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz#7812af31b205055874c8082ea9cf9ab0da6217ae" + integrity sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg== "@esbuild/sunos-x64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.11.tgz#2ea47fb592e68406e5025a7696dc714fc6a115dc" integrity sha512-1/gxTifDC9aXbV2xOfCbOceh5AlIidUrPsMpivgzo8P8zUtczlq1ncFpeN1ZyQJ9lVs2hILy1PG5KPp+w8QPPg== -"@esbuild/win32-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz#7b0ff9e8c3265537a7a7b1fd9a24e7bd39fcd87a" - integrity sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw== +"@esbuild/sunos-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz#d5c275c3b4e73c9b0ecd38d1ca62c020f887ab9d" + integrity sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ== "@esbuild/win32-arm64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.11.tgz#47e6fdab17c4c52e6e0d606dd9cb843b29826325" integrity sha512-vtSfyx5yRdpiOW9yp6Ax0zyNOv9HjOAw8WaZg3dF5djEHKKm3UnoohftVvIJtRh0Ec7Hso0RIdTqZvPXJ7FdvQ== -"@esbuild/win32-ia32@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz#e90fe5267d71a7b7567afdc403dfd198c292eb09" - integrity sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig== +"@esbuild/win32-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz#73bc7f5a9f8a77805f357fab97f290d0e4820ac9" + integrity sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg== "@esbuild/win32-ia32@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.11.tgz#a97273aa3164c8d8f501899f55cc75a4a79599a3" integrity sha512-GFPSLEGQr4wHFTiIUJQrnJKZhZjjq4Sphf+mM76nQR6WkQn73vm7IsacmBRPkALfpOCHsopSvLgqdd4iUW2mYw== -"@esbuild/win32-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz#c5a1a4bfe1b57f0c3e61b29883525c6da3e5c091" - integrity sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q== +"@esbuild/win32-ia32@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz#ec93cbf0ef1085cc12e71e0d661d20569ff42102" + integrity sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g== "@esbuild/win32-x64@0.17.11": version "0.17.11" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.11.tgz#9be796d93ae27b636da32d960899a4912bca27a1" integrity sha512-N9vXqLP3eRL8BqSy8yn4Y98cZI2pZ8fyuHx6lKjiG2WABpT2l01TXdzq5Ma2ZUBzfB7tx5dXVhge8X9u0S70ZQ== +"@esbuild/win32-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d" + integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ== + "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -6184,34 +6184,6 @@ es6-weak-map@^2.0.3: es6-iterator "^2.0.3" es6-symbol "^3.1.1" -esbuild@^0.16.14: - version "0.16.17" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.16.17.tgz#fc2c3914c57ee750635fee71b89f615f25065259" - integrity sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg== - optionalDependencies: - "@esbuild/android-arm" "0.16.17" - "@esbuild/android-arm64" "0.16.17" - "@esbuild/android-x64" "0.16.17" - "@esbuild/darwin-arm64" "0.16.17" - "@esbuild/darwin-x64" "0.16.17" - "@esbuild/freebsd-arm64" "0.16.17" - "@esbuild/freebsd-x64" "0.16.17" - "@esbuild/linux-arm" "0.16.17" - "@esbuild/linux-arm64" "0.16.17" - "@esbuild/linux-ia32" "0.16.17" - "@esbuild/linux-loong64" "0.16.17" - "@esbuild/linux-mips64el" "0.16.17" - "@esbuild/linux-ppc64" "0.16.17" - "@esbuild/linux-riscv64" "0.16.17" - "@esbuild/linux-s390x" "0.16.17" - "@esbuild/linux-x64" "0.16.17" - "@esbuild/netbsd-x64" "0.16.17" - "@esbuild/openbsd-x64" "0.16.17" - "@esbuild/sunos-x64" "0.16.17" - "@esbuild/win32-arm64" "0.16.17" - "@esbuild/win32-ia32" "0.16.17" - "@esbuild/win32-x64" "0.16.17" - esbuild@^0.17.0: version "0.17.11" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.11.tgz#9f3122643b21d7e7731e42f18576c10bfa28152b" @@ -6240,6 +6212,34 @@ esbuild@^0.17.0: "@esbuild/win32-ia32" "0.17.11" "@esbuild/win32-x64" "0.17.11" +esbuild@^0.18.10: + version "0.18.20" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.18.20.tgz#4709f5a34801b43b799ab7d6d82f7284a9b7a7a6" + integrity sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA== + optionalDependencies: + "@esbuild/android-arm" "0.18.20" + "@esbuild/android-arm64" "0.18.20" + "@esbuild/android-x64" "0.18.20" + "@esbuild/darwin-arm64" "0.18.20" + "@esbuild/darwin-x64" "0.18.20" + "@esbuild/freebsd-arm64" "0.18.20" + "@esbuild/freebsd-x64" "0.18.20" + "@esbuild/linux-arm" "0.18.20" + "@esbuild/linux-arm64" "0.18.20" + "@esbuild/linux-ia32" "0.18.20" + "@esbuild/linux-loong64" "0.18.20" + "@esbuild/linux-mips64el" "0.18.20" + "@esbuild/linux-ppc64" "0.18.20" + "@esbuild/linux-riscv64" "0.18.20" + "@esbuild/linux-s390x" "0.18.20" + "@esbuild/linux-x64" "0.18.20" + "@esbuild/netbsd-x64" "0.18.20" + "@esbuild/openbsd-x64" "0.18.20" + "@esbuild/sunos-x64" "0.18.20" + "@esbuild/win32-arm64" "0.18.20" + "@esbuild/win32-ia32" "0.18.20" + "@esbuild/win32-x64" "0.18.20" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -9726,10 +9726,10 @@ mz@^2.4.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nanoid@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" - integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== +nanoid@^3.3.6: + version "3.3.6" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" + integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== natural-compare-lite@^1.4.0: version "1.4.0" @@ -10525,12 +10525,12 @@ postcss-value-parser@^4.0.2: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.4.21: - version "8.4.21" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4" - integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg== +postcss@^8.4.27: + version "8.4.27" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057" + integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ== dependencies: - nanoid "^3.3.4" + nanoid "^3.3.6" picocolors "^1.0.0" source-map-js "^1.0.2" @@ -11605,7 +11605,7 @@ rollup-plugin-webpack-stats@^0.2.0: resolved "https://registry.yarnpkg.com/rollup-plugin-webpack-stats/-/rollup-plugin-webpack-stats-0.2.0.tgz#840bffdbb9e5492d3ac0d7020f08dd864e966ad8" integrity sha512-WDQ9ra6qWjeH/7D3q7lY/r5i9/HPt8OlZvvoQzS7Jdarh2v5+Fgw1BdAU2pBW0LB26J+vNYwdEdyJnkBhbQ2PQ== -rollup@^0.41.4, rollup@^2.43.1, rollup@^3.10.0, rollup@^3.14.0, rollup@^3.7.2: +rollup@^0.41.4, rollup@^2.43.1, rollup@^3.14.0, rollup@^3.27.1, rollup@^3.7.2: version "3.14.0" resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.14.0.tgz#f5925255f3b6e8de1dba3916d7619c7da5708d95" integrity sha512-o23sdgCLcLSe3zIplT9nQ1+r97okuaiR+vmAPZPTDYB7/f3tgWIYNyiQveMsZwshBT0is4eGax/HH83Q7CG+/Q== @@ -13221,15 +13221,14 @@ vite-plugin-static-copy@^0.17.0: fs-extra "^11.1.0" picocolors "^1.0.0" -vite@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/vite/-/vite-4.1.5.tgz#9c93d579f62179ab99c4182fa37acf1b380a374b" - integrity sha512-zJ0RiVkf61kpd7O+VtU6r766xgnTaIknP/lR6sJTZq3HtVJ3HGnTo5DaJhTUtYoTyS/CQwZ6yEVdc/lrmQT7dQ== +vite@^4.4.9: + version "4.4.9" + resolved "https://registry.yarnpkg.com/vite/-/vite-4.4.9.tgz#1402423f1a2f8d66fd8d15e351127c7236d29d3d" + integrity sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA== dependencies: - esbuild "^0.16.14" - postcss "^8.4.21" - resolve "^1.22.1" - rollup "^3.10.0" + esbuild "^0.18.10" + postcss "^8.4.27" + rollup "^3.27.1" optionalDependencies: fsevents "~2.3.2" From 28ae1af2a345b8825808189847f24c0d8c3defac Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Mon, 14 Aug 2023 16:16:12 -0400 Subject: [PATCH 133/144] fix: `ctrl+a` does not work on Windows in code block (#5692) --- app/actions/definitions/navigation.tsx | 2 +- app/components/Header.tsx | 2 +- .../Sidebar/components/HistoryNavigation.tsx | 2 +- app/hooks/useWindowScrollPosition.ts | 2 +- .../Document/components/MultiplayerEditor.tsx | 2 +- app/scenes/KeyboardShortcuts.tsx | 2 +- app/styles/index.ts | 2 +- app/utils/Desktop.ts | 2 +- app/utils/keyboard.ts | 2 +- shared/editor/lib/isModKey.ts | 6 ------ shared/editor/nodes/CodeFence.ts | 15 ++++++++++++--- {app => shared}/utils/browser.ts | 10 +++++++++- 12 files changed, 30 insertions(+), 19 deletions(-) delete mode 100644 shared/editor/lib/isModKey.ts rename {app => shared}/utils/browser.ts (89%) diff --git a/app/actions/definitions/navigation.tsx b/app/actions/definitions/navigation.tsx index 234a23bdaf7d..d2f0c6dda992 100644 --- a/app/actions/definitions/navigation.tsx +++ b/app/actions/definitions/navigation.tsx @@ -14,6 +14,7 @@ import { BrowserIcon, } from "outline-icons"; import * as React from "react"; +import { isMac } from "@shared/utils/browser"; import { developersUrl, changelogUrl, @@ -26,7 +27,6 @@ import KeyboardShortcuts from "~/scenes/KeyboardShortcuts"; import { createAction } from "~/actions"; import { NavigationSection, RecentSearchesSection } from "~/actions/sections"; import Desktop from "~/utils/Desktop"; -import { isMac } from "~/utils/browser"; import history from "~/utils/history"; import isCloudHosted from "~/utils/isCloudHosted"; import { diff --git a/app/components/Header.tsx b/app/components/Header.tsx index 0ffc82cc798e..e86e634beeb9 100644 --- a/app/components/Header.tsx +++ b/app/components/Header.tsx @@ -6,6 +6,7 @@ import * as React from "react"; import styled from "styled-components"; import breakpoint from "styled-components-breakpoint"; import { depths, s } from "@shared/styles"; +import { supportsPassiveListener } from "@shared/utils/browser"; import Button from "~/components/Button"; import Fade from "~/components/Fade"; import Flex from "~/components/Flex"; @@ -14,7 +15,6 @@ import useMobile from "~/hooks/useMobile"; import useStores from "~/hooks/useStores"; import { draggableOnDesktop, fadeOnDesktopBackgrounded } from "~/styles"; import Desktop from "~/utils/Desktop"; -import { supportsPassiveListener } from "~/utils/browser"; type Props = { left?: React.ReactNode; diff --git a/app/components/Sidebar/components/HistoryNavigation.tsx b/app/components/Sidebar/components/HistoryNavigation.tsx index 1bd8640cfc08..7e73945d6f97 100644 --- a/app/components/Sidebar/components/HistoryNavigation.tsx +++ b/app/components/Sidebar/components/HistoryNavigation.tsx @@ -3,12 +3,12 @@ import * as React from "react"; import { useTranslation } from "react-i18next"; import styled from "styled-components"; import { s } from "@shared/styles"; +import { isMac } from "@shared/utils/browser"; import Flex from "~/components/Flex"; import NudeButton from "~/components/NudeButton"; import Tooltip from "~/components/Tooltip"; import useKeyDown from "~/hooks/useKeyDown"; import Desktop from "~/utils/Desktop"; -import { isMac } from "~/utils/browser"; function HistoryNavigation(props: React.ComponentProps) { const { t } = useTranslation(); diff --git a/app/hooks/useWindowScrollPosition.ts b/app/hooks/useWindowScrollPosition.ts index e006413096b7..4f3cf2b333a9 100644 --- a/app/hooks/useWindowScrollPosition.ts +++ b/app/hooks/useWindowScrollPosition.ts @@ -2,7 +2,7 @@ // maintained. import throttle from "lodash/throttle"; import { useState, useEffect } from "react"; -import { supportsPassiveListener } from "~/utils/browser"; +import { supportsPassiveListener } from "@shared/utils/browser"; const getPosition = () => ({ x: window.pageXOffset, diff --git a/app/scenes/Document/components/MultiplayerEditor.tsx b/app/scenes/Document/components/MultiplayerEditor.tsx index 8660ccff9d47..9b508b59f82d 100644 --- a/app/scenes/Document/components/MultiplayerEditor.tsx +++ b/app/scenes/Document/components/MultiplayerEditor.tsx @@ -6,6 +6,7 @@ import { useHistory } from "react-router-dom"; import { IndexeddbPersistence } from "y-indexeddb"; import * as Y from "yjs"; import MultiplayerExtension from "@shared/editor/extensions/Multiplayer"; +import { supportsPassiveListener } from "@shared/utils/browser"; import Editor, { Props as EditorProps } from "~/components/Editor"; import env from "~/env"; import useCurrentUser from "~/hooks/useCurrentUser"; @@ -16,7 +17,6 @@ import useStores from "~/hooks/useStores"; import useToasts from "~/hooks/useToasts"; import { AwarenessChangeEvent } from "~/types"; import Logger from "~/utils/Logger"; -import { supportsPassiveListener } from "~/utils/browser"; import { homePath } from "~/utils/routeHelpers"; type Props = EditorProps & { diff --git a/app/scenes/KeyboardShortcuts.tsx b/app/scenes/KeyboardShortcuts.tsx index 385c0ff3230b..f7ae2f2800d3 100644 --- a/app/scenes/KeyboardShortcuts.tsx +++ b/app/scenes/KeyboardShortcuts.tsx @@ -2,10 +2,10 @@ import * as React from "react"; import { useTranslation } from "react-i18next"; import styled from "styled-components"; import { s } from "@shared/styles"; +import { isMac } from "@shared/utils/browser"; import Flex from "~/components/Flex"; import InputSearch from "~/components/InputSearch"; import Key from "~/components/Key"; -import { isMac } from "~/utils/browser"; import { metaDisplay, altDisplay } from "~/utils/keyboard"; function KeyboardShortcuts() { diff --git a/app/styles/index.ts b/app/styles/index.ts index 3c0026d6d504..296e17477679 100644 --- a/app/styles/index.ts +++ b/app/styles/index.ts @@ -1,5 +1,5 @@ +import { isTouchDevice } from "@shared/utils/browser"; import Desktop from "~/utils/Desktop"; -import { isTouchDevice } from "~/utils/browser"; /** * Returns "hover" on a non-touch device and "active" on a touch device. To diff --git a/app/utils/Desktop.ts b/app/utils/Desktop.ts index e0dd6081649a..d31809d6e34d 100644 --- a/app/utils/Desktop.ts +++ b/app/utils/Desktop.ts @@ -1,4 +1,4 @@ -import { isMac, isWindows } from "./browser"; +import { isMac, isWindows } from "@shared/utils/browser"; export default class Desktop { /** diff --git a/app/utils/keyboard.ts b/app/utils/keyboard.ts index 627ea1ba53b2..d90944c05dac 100644 --- a/app/utils/keyboard.ts +++ b/app/utils/keyboard.ts @@ -1,4 +1,4 @@ -import { isMac } from "~/utils/browser"; +import { isMac } from "@shared/utils/browser"; export const altDisplay = isMac() ? "⌥" : "Alt"; diff --git a/shared/editor/lib/isModKey.ts b/shared/editor/lib/isModKey.ts deleted file mode 100644 index 468a0af6b2d4..000000000000 --- a/shared/editor/lib/isModKey.ts +++ /dev/null @@ -1,6 +0,0 @@ -const SSR = typeof window === "undefined"; -const isMac = !SSR && window.navigator.platform === "MacIntel"; - -export default function isModKey(event: KeyboardEvent | MouseEvent): boolean { - return isMac ? event.metaKey : event.ctrlKey; -} diff --git a/shared/editor/nodes/CodeFence.ts b/shared/editor/nodes/CodeFence.ts index 2dbc2fb2f439..fd1a452a84ee 100644 --- a/shared/editor/nodes/CodeFence.ts +++ b/shared/editor/nodes/CodeFence.ts @@ -58,6 +58,7 @@ import { Primitive } from "utility-types"; import { Dictionary } from "~/hooks/useDictionary"; import { UserPreferences } from "../../types"; import Storage from "../../utils/Storage"; +import { isMac } from "../../utils/browser"; import { newlineInCode, insertSpaceTab, @@ -208,14 +209,22 @@ export default class CodeFence extends Node { } keys({ type, schema }: { type: NodeType; schema: Schema }) { - return { + const output = { "Shift-Ctrl-\\": toggleBlockType(type, schema.nodes.paragraph), Tab: insertSpaceTab, Enter: newlineInCode, "Shift-Enter": newlineInCode, - "Ctrl-a": moveToPreviousNewline, - "Ctrl-e": moveToNextNewline, }; + + if (isMac()) { + return { + ...output, + "Ctrl-a": moveToPreviousNewline, + "Ctrl-e": moveToNextNewline, + }; + } + + return output; } get plugins() { diff --git a/app/utils/browser.ts b/shared/utils/browser.ts similarity index 89% rename from app/utils/browser.ts rename to shared/utils/browser.ts index ac642149ac2e..42c4aed340c3 100644 --- a/app/utils/browser.ts +++ b/shared/utils/browser.ts @@ -1,8 +1,10 @@ +const SSR = typeof window === "undefined"; + /** * Returns true if the client is a touch device. */ export function isTouchDevice(): boolean { - if (typeof window === "undefined") { + if (SSR) { return false; } return window.matchMedia?.("(hover: none) and (pointer: coarse)")?.matches; @@ -12,6 +14,9 @@ export function isTouchDevice(): boolean { * Returns true if the client is running on a Mac. */ export function isMac(): boolean { + if (SSR) { + return false; + } return window.navigator.platform === "MacIntel"; } @@ -19,6 +24,9 @@ export function isMac(): boolean { * Returns true if the client is running on Windows. */ export function isWindows(): boolean { + if (SSR) { + return false; + } return window.navigator.platform === "Win32"; } From fce90df3aaa2b0c23db67109be67146661a3c1c5 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Tue, 15 Aug 2023 11:26:48 +0200 Subject: [PATCH 134/144] chore: Update browserslist --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index caf6c38729a0..a329c6ba51e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4501,9 +4501,9 @@ cancan@3.1.0: is-plain-obj "^1.1.0" caniuse-lite@^1.0.30001449: - version "1.0.30001451" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001451.tgz#2e197c698fc1373d63e1406d6607ea4617c613f1" - integrity sha512-XY7UbUpGRatZzoRft//5xOa69/1iGJRBlrieH6QYrkKLIFn3m7OVEJ81dSrKoy2BnKsdbX5cLrOispZNYo9v2w== + version "1.0.30001520" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001520.tgz" + integrity sha512-tahF5O9EiiTzwTUqAeFjIZbn4Dnqxzz7ktrgGlMYNLH43Ul26IgTMH/zvL3DG0lZxBYnlT04axvInszUsZULdA== chalk@5.2.0: version "5.2.0" From 8bff566c30f2c0e81d16d126654b6ed405c8c191 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Tue, 15 Aug 2023 11:32:19 +0200 Subject: [PATCH 135/144] fix: Sidebar item misalignment --- app/components/Sidebar/components/SidebarLink.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/Sidebar/components/SidebarLink.tsx b/app/components/Sidebar/components/SidebarLink.tsx index 8d160607ac47..2e4ecc5d4b90 100644 --- a/app/components/Sidebar/components/SidebarLink.tsx +++ b/app/components/Sidebar/components/SidebarLink.tsx @@ -292,7 +292,7 @@ const Label = styled.div` position: relative; width: 100%; max-height: 4.8em; - line-height: 1.6; + line-height: 24px; * { unicode-bidi: plaintext; From 0047384d707fe729315437f43da76635d7ae053d Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Tue, 15 Aug 2023 19:52:16 +0200 Subject: [PATCH 136/144] fix: Code blocks nested in list do not get line numbers --- shared/editor/extensions/Prism.ts | 7 ++++--- shared/editor/queries/findChildren.ts | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/shared/editor/extensions/Prism.ts b/shared/editor/extensions/Prism.ts index b7b32046d726..31c9e969e109 100644 --- a/shared/editor/extensions/Prism.ts +++ b/shared/editor/extensions/Prism.ts @@ -74,9 +74,10 @@ function getDecorations({ lineNumbers?: boolean; }) { const decorations: Decoration[] = []; - const blocks: { node: Node; pos: number }[] = findBlockNodes(doc).filter( - (item) => item.node.type.name === name - ); + const blocks: { node: Node; pos: number }[] = findBlockNodes( + doc, + true + ).filter((item) => item.node.type.name === name); function parseNodes( nodes: refractor.RefractorNode[], diff --git a/shared/editor/queries/findChildren.ts b/shared/editor/queries/findChildren.ts index da2717e2befb..c3757a1ae008 100644 --- a/shared/editor/queries/findChildren.ts +++ b/shared/editor/queries/findChildren.ts @@ -50,8 +50,9 @@ export function findChildren( * are blocks. * * @param node The node to iterate over + * @param descend Whether to descend into a node * @returns Child nodes that are blocks */ -export function findBlockNodes(node: Node): NodeWithPos[] { - return findChildren(node, (child) => child.isBlock); +export function findBlockNodes(node: Node, descend = false): NodeWithPos[] { + return findChildren(node, (child) => child.isBlock, descend); } From fd600ced09ad2f42031498d71f2b63540f6dffdf Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Tue, 15 Aug 2023 21:39:01 +0200 Subject: [PATCH 137/144] fix: Flash of 'not found' screen when deleting a collection --- app/components/CollectionDeleteDialog.tsx | 9 +++++++-- shared/i18n/locales/en_US/translation.json | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/components/CollectionDeleteDialog.tsx b/app/components/CollectionDeleteDialog.tsx index f51da8ed2610..1468faa1ff6b 100644 --- a/app/components/CollectionDeleteDialog.tsx +++ b/app/components/CollectionDeleteDialog.tsx @@ -7,6 +7,7 @@ import ConfirmationDialog from "~/components/ConfirmationDialog"; import Text from "~/components/Text"; import useCurrentTeam from "~/hooks/useCurrentTeam"; import useStores from "~/hooks/useStores"; +import useToasts from "~/hooks/useToasts"; import { homePath } from "~/utils/routeHelpers"; type Props = { @@ -17,16 +18,20 @@ type Props = { function CollectionDeleteDialog({ collection, onSubmit }: Props) { const team = useCurrentTeam(); const { ui } = useStores(); + const { showToast } = useToasts(); const history = useHistory(); const { t } = useTranslation(); const handleSubmit = async () => { const redirect = collection.id === ui.activeCollectionId; - await collection.delete(); - onSubmit(); + if (redirect) { history.push(homePath()); } + + await collection.delete(); + onSubmit(); + showToast(t("Collection deleted"), { type: "success" }); }; return ( diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json index dc3634231d10..7ab62ccd913c 100644 --- a/shared/i18n/locales/en_US/translation.json +++ b/shared/i18n/locales/en_US/translation.json @@ -105,6 +105,7 @@ "previously edited": "previously edited", "You": "You", "Viewers": "Viewers", + "Collection deleted": "Collection deleted", "I’m sure – Delete": "I’m sure – Delete", "Deleting": "Deleting", "Are you sure about that? Deleting the {{collectionName}} collection is permanent and cannot be restored, however all published documents within will be moved to the trash.": "Are you sure about that? Deleting the {{collectionName}} collection is permanent and cannot be restored, however all published documents within will be moved to the trash.", From 5f00b4f7440febfbc7281c8a8208370ff574e3f2 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Wed, 16 Aug 2023 15:39:56 -0400 Subject: [PATCH 138/144] fix: Incorrect error shown to user when connection limit is reached (#5695) --- app/components/ConnectionStatus.tsx | 43 ++++++++++++++++--- .../Document/components/MultiplayerEditor.tsx | 21 +++++---- app/stores/UiStore.ts | 9 +++- server/collaboration/CloseEvents.ts | 4 ++ .../collaboration/ConnectionLimitExtension.ts | 33 ++++++++------ shared/i18n/locales/en_US/translation.json | 9 +++- 6 files changed, 89 insertions(+), 30 deletions(-) create mode 100644 server/collaboration/CloseEvents.ts diff --git a/app/components/ConnectionStatus.tsx b/app/components/ConnectionStatus.tsx index 705716f5657f..b09018d7d220 100644 --- a/app/components/ConnectionStatus.tsx +++ b/app/components/ConnectionStatus.tsx @@ -14,15 +14,48 @@ function ConnectionStatus() { const theme = useTheme(); const { t } = useTranslation(); + const codeToMessage = { + 1009: { + title: t("Document is too large"), + body: t( + "This document has reached the maximum size and can no longer be edited" + ), + }, + 4401: { + title: t("Authentication failed"), + body: t("Please try logging out and back in again"), + }, + 4403: { + title: t("Authorization failed"), + body: t("You may have lost access to this document, try reloading"), + }, + 4503: { + title: t("Too many users connected to document"), + body: t("Your edits will sync once other users leave the document"), + }, + }; + + const message = ui.multiplayerErrorCode + ? codeToMessage[ui.multiplayerErrorCode] + : undefined; + return ui.multiplayerStatus === "connecting" || ui.multiplayerStatus === "disconnected" ? ( - {t("Server connection lost")} -
- {t("Edits you make will sync once you’re online")} - + message ? ( + + {message.title} +
+ {message.body} +
+ ) : ( + + {t("Server connection lost")} +
+ {t("Edits you make will sync once you’re online")} +
+ ) } placement="bottom" > diff --git a/app/scenes/Document/components/MultiplayerEditor.tsx b/app/scenes/Document/components/MultiplayerEditor.tsx index 9b508b59f82d..443425b59487 100644 --- a/app/scenes/Document/components/MultiplayerEditor.tsx +++ b/app/scenes/Document/components/MultiplayerEditor.tsx @@ -135,13 +135,10 @@ function MultiplayerEditor({ onSynced, ...props }: Props, ref: any) { }); provider.on("close", (ev: MessageEvent) => { - if ("code" in ev.event && ev.event.code === 1009) { - provider.shouldConnect = false; - showToast( - t( - "Sorry, this document is too large - edits will no longer be persisted." - ) - ); + if ("code" in ev.event) { + provider.shouldConnect = + ev.event.code !== 1009 && ev.event.code !== 4401; + ui.setMultiplayerStatus("disconnected", ev.event.code); } }); @@ -164,9 +161,11 @@ function MultiplayerEditor({ onSynced, ...props }: Props, ref: any) { ); } - provider.on("status", (ev: ConnectionStatusEvent) => - ui.setMultiplayerStatus(ev.status) - ); + provider.on("status", (ev: ConnectionStatusEvent) => { + if (ui.multiplayerStatus !== ev.status) { + ui.setMultiplayerStatus(ev.status, undefined); + } + }); setRemoteProvider(provider); @@ -177,7 +176,7 @@ function MultiplayerEditor({ onSynced, ...props }: Props, ref: any) { provider?.destroy(); void localProvider?.destroy(); setRemoteProvider(null); - ui.setMultiplayerStatus(undefined); + ui.setMultiplayerStatus(undefined, undefined); }; }, [ history, diff --git a/app/stores/UiStore.ts b/app/stores/UiStore.ts index a9f5b966fcd8..7abf4acf1f25 100644 --- a/app/stores/UiStore.ts +++ b/app/stores/UiStore.ts @@ -69,6 +69,9 @@ class UiStore { @observable multiplayerStatus: ConnectionStatus; + @observable + multiplayerErrorCode?: number; + constructor() { // Rehydrate const data: Partial = Storage.get(UI_STORE) || {}; @@ -133,8 +136,12 @@ class UiStore { }; @action - setMultiplayerStatus = (status: ConnectionStatus): void => { + setMultiplayerStatus = ( + status: ConnectionStatus, + errorCode?: number + ): void => { this.multiplayerStatus = status; + this.multiplayerErrorCode = errorCode; }; @action diff --git a/server/collaboration/CloseEvents.ts b/server/collaboration/CloseEvents.ts new file mode 100644 index 000000000000..3e61b6aa50f2 --- /dev/null +++ b/server/collaboration/CloseEvents.ts @@ -0,0 +1,4 @@ +export const TooManyConnections = { + code: 4503, + reason: "Too Many Connections", +}; diff --git a/server/collaboration/ConnectionLimitExtension.ts b/server/collaboration/ConnectionLimitExtension.ts index 8e4405666a23..778f71098625 100644 --- a/server/collaboration/ConnectionLimitExtension.ts +++ b/server/collaboration/ConnectionLimitExtension.ts @@ -6,28 +6,36 @@ import { import env from "@server/env"; import Logger from "@server/logging/Logger"; import { trace } from "@server/logging/tracing"; +import { TooManyConnections } from "./CloseEvents"; @trace() export class ConnectionLimitExtension implements Extension { /** * Map of documentId -> connection count */ - connectionsByDocument: Map = new Map(); + connectionsByDocument: Map> = new Map(); /** * onDisconnect hook * @param data The disconnect payload */ onDisconnect(data: onDisconnectPayload) { - const { documentName } = data; + const { documentName, socketId } = data; + + const connections = this.connectionsByDocument.get(documentName); + if (connections) { + connections.delete(socketId); - const currConnections = this.connectionsByDocument.get(documentName) || 0; - const newConnections = currConnections - 1; - this.connectionsByDocument.set(documentName, newConnections); + if (connections.size === 0) { + this.connectionsByDocument.delete(documentName); + } else { + this.connectionsByDocument.set(documentName, connections); + } + } Logger.debug( "multiplayer", - `${newConnections} connections to "${documentName}"` + `${connections?.size} connections to "${documentName}"` ); return Promise.resolve(); @@ -40,23 +48,24 @@ export class ConnectionLimitExtension implements Extension { onConnect(data: onConnectPayload) { const { documentName } = data; - const currConnections = this.connectionsByDocument.get(documentName) || 0; - if (currConnections >= env.COLLABORATION_MAX_CLIENTS_PER_DOCUMENT) { + const connections = + this.connectionsByDocument.get(documentName) || new Set(); + if (connections?.size >= env.COLLABORATION_MAX_CLIENTS_PER_DOCUMENT) { Logger.info( "multiplayer", `Rejected connection to "${documentName}" because it has reached the maximum number of connections` ); // Rejecting the promise will cause the connection to be dropped. - return Promise.reject(); + return Promise.reject(TooManyConnections); } - const newConnections = currConnections + 1; - this.connectionsByDocument.set(documentName, newConnections); + connections.add(data.socketId); + this.connectionsByDocument.set(documentName, connections); Logger.debug( "multiplayer", - `${newConnections} connections to "${documentName}"` + `${connections.size} connections to "${documentName}"` ); return Promise.resolve(); diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json index 7ab62ccd913c..838dab6c83da 100644 --- a/shared/i18n/locales/en_US/translation.json +++ b/shared/i18n/locales/en_US/translation.json @@ -117,6 +117,14 @@ "Type a command or search": "Type a command or search", "Are you sure you want to permanently delete this entire comment thread?": "Are you sure you want to permanently delete this entire comment thread?", "Are you sure you want to permanently delete this comment?": "Are you sure you want to permanently delete this comment?", + "Document is too large": "Document is too large", + "This document has reached the maximum size and can no longer be edited": "This document has reached the maximum size and can no longer be edited", + "Authentication failed": "Authentication failed", + "Please try logging out and back in again": "Please try logging out and back in again", + "Authorization failed": "Authorization failed", + "You may have lost access to this document, try reloading": "You may have lost access to this document, try reloading", + "Too many users connected to document": "Too many users connected to document", + "Your edits will sync once other users leave the document": "Your edits will sync once other users leave the document", "Server connection lost": "Server connection lost", "Edits you make will sync once you’re online": "Edits you make will sync once you’re online", "Submenu": "Submenu", @@ -524,7 +532,6 @@ "Viewed {{ count }} times by {{ teamMembers }} people_plural": "Viewed {{ count }} times by {{ teamMembers }} people", "Viewer insights": "Viewer insights", "As an admin you can manage if team members can see who has viewed this document": "As an admin you can manage if team members can see who has viewed this document", - "Sorry, this document is too large - edits will no longer be persisted.": "Sorry, this document is too large - edits will no longer be persisted.", "Sorry, the last change could not be persisted – please reload the page": "Sorry, the last change could not be persisted – please reload the page", "This template will be permanently deleted in <2> unless restored.": "This template will be permanently deleted in <2> unless restored.", "This document will be permanently deleted in <2> unless restored.": "This document will be permanently deleted in <2> unless restored.", From 4788ab3bd6ed458a8e9abad21be6525930e14a3c Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Wed, 16 Aug 2023 22:20:55 +0200 Subject: [PATCH 139/144] fix: Add support for Airtable share links with app ID --- shared/editor/embeds/Airtable.test.ts | 8 ++++++++ shared/editor/embeds/Airtable.tsx | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/shared/editor/embeds/Airtable.test.ts b/shared/editor/embeds/Airtable.test.ts index efb1e716b18c..4b8c0c507069 100644 --- a/shared/editor/embeds/Airtable.test.ts +++ b/shared/editor/embeds/Airtable.test.ts @@ -5,6 +5,14 @@ describe("Airtable", () => { test("to be enabled on share link", () => { expect("https://airtable.com/shrEoQs3erLnppMie".match(match)).toBeTruthy(); + expect( + "https://airtable.com/shrEoQs3erLnppMie/tbl232i54yebXpr1J".match(match) + ).toBeTruthy(); + expect( + "https://airtable.com/app0lrLlMprqMbz11/shrEoQs3erLnppMie/tbl232i54yebXpr1J".match( + match + ) + ).toBeTruthy(); }); test("to be enabled on embed link", () => { diff --git a/shared/editor/embeds/Airtable.tsx b/shared/editor/embeds/Airtable.tsx index 856025b1cc41..9dcf99b23719 100644 --- a/shared/editor/embeds/Airtable.tsx +++ b/shared/editor/embeds/Airtable.tsx @@ -2,7 +2,9 @@ import * as React from "react"; import Frame from "../components/Frame"; import { EmbedProps as Props } from "."; -const URL_REGEX = new RegExp("^https://airtable.com/(?:embed/)?(shr.*)$"); +const URL_REGEX = new RegExp( + "^https://airtable.com/(?:app.*/)?(?:embed/)?(shr.*)$" +); function Airtable(props: Props) { const { matches } = props.attrs; From 41c346d10508b49a04c18cd274f292db7f0c830f Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Thu, 17 Aug 2023 10:41:36 +0200 Subject: [PATCH 140/144] Revert "chore: Update browserslist" This reverts commit fce90df3aaa2b0c23db67109be67146661a3c1c5. --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index a329c6ba51e3..caf6c38729a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4501,9 +4501,9 @@ cancan@3.1.0: is-plain-obj "^1.1.0" caniuse-lite@^1.0.30001449: - version "1.0.30001520" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001520.tgz" - integrity sha512-tahF5O9EiiTzwTUqAeFjIZbn4Dnqxzz7ktrgGlMYNLH43Ul26IgTMH/zvL3DG0lZxBYnlT04axvInszUsZULdA== + version "1.0.30001451" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001451.tgz#2e197c698fc1373d63e1406d6607ea4617c613f1" + integrity sha512-XY7UbUpGRatZzoRft//5xOa69/1iGJRBlrieH6QYrkKLIFn3m7OVEJ81dSrKoy2BnKsdbX5cLrOispZNYo9v2w== chalk@5.2.0: version "5.2.0" From 13b067fb3f45c01f16cae688bc12e4c619ee10b6 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Thu, 17 Aug 2023 22:46:40 +0200 Subject: [PATCH 141/144] fix: Document importer only replaces first base64 encoded image when there are multiple identical images in a document closes #5653 --- server/commands/documentImporter.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/commands/documentImporter.ts b/server/commands/documentImporter.ts index 7af02a1f15c7..5e64c379372b 100644 --- a/server/commands/documentImporter.ts +++ b/server/commands/documentImporter.ts @@ -1,5 +1,6 @@ import path from "path"; import emojiRegex from "emoji-regex"; +import escapeRegExp from "lodash/escapeRegExp"; import truncate from "lodash/truncate"; import mammoth from "mammoth"; import quotedPrintable from "quoted-printable"; @@ -221,7 +222,10 @@ async function documentImporter({ ip, transaction, }); - text = text.replace(uri, attachment.redirectUrl); + text = text.replace( + new RegExp(escapeRegExp(uri), "g"), + attachment.redirectUrl + ); } // It's better to truncate particularly long titles than fail the import From 7e349c9db167137debf155e4f2bfe5652f639e1a Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Thu, 17 Aug 2023 23:14:02 +0200 Subject: [PATCH 142/144] perf: Do not load state to calculate navigation node --- server/models/Document.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server/models/Document.ts b/server/models/Document.ts index 230ec4c1c65a..99e5ea707955 100644 --- a/server/models/Document.ts +++ b/server/models/Document.ts @@ -767,11 +767,12 @@ class Document extends ParanoidModel { * @param options Optional transaction to use for the query * @returns Promise resolving to a NavigationNode */ - toNavigationNode = async (options?: { - transaction?: Transaction | null | undefined; - }): Promise => { + toNavigationNode = async ( + options?: FindOptions + ): Promise => { const childDocuments = await (this.constructor as typeof Document) .unscoped() + .scope("withoutState") .findAll({ where: { teamId: this.teamId, From c68d55f49bf856d036b3bedaa67834ccbd0b1aa7 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Thu, 17 Aug 2023 23:30:42 +0200 Subject: [PATCH 143/144] fix: Inopperable image toolbar appears in read-only mode --- app/editor/components/SelectionToolbar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/editor/components/SelectionToolbar.tsx b/app/editor/components/SelectionToolbar.tsx index 90c77a182b39..ac9e2c0019e8 100644 --- a/app/editor/components/SelectionToolbar.tsx +++ b/app/editor/components/SelectionToolbar.tsx @@ -231,7 +231,7 @@ export default function SelectionToolbar(props: Props) { } else if (rowIndex !== undefined) { items = getTableRowMenuItems(state, rowIndex, dictionary); } else if (isImageSelection) { - items = getImageMenuItems(state, dictionary); + items = readOnly ? [] : getImageMenuItems(state, dictionary); } else if (isDividerSelection) { items = getDividerMenuItems(state, dictionary); } else if (readOnly) { From 5e7ea165b4f76552a06f806fa163a1aab77070b4 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Fri, 18 Aug 2023 11:11:32 +0200 Subject: [PATCH 144/144] 0.71.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4a0dbc73ce5f..b2ec527579ae 100644 --- a/package.json +++ b/package.json @@ -340,5 +340,5 @@ "qs": "6.9.7", "rollup": "^3.14.0" }, - "version": "0.70.2" + "version": "0.71.0" }