Merge branch 'main' of github.com:outline/outline

This commit is contained in:
Tom Moor
2022-12-24 12:41:15 +00:00
8 changed files with 427 additions and 132 deletions

View File

@@ -75,7 +75,7 @@
"autotrack": "^2.4.1",
"aws-sdk": "^2.1189.0",
"babel-plugin-lodash": "^3.3.4",
"babel-plugin-styled-components": "^1.11.1",
"babel-plugin-styled-components": "^2.0.7",
"babel-plugin-transform-class-properties": "^6.24.1",
"body-scroll-lock": "^4.0.0-beta.0",
"bull": "^4.10.2",
@@ -92,7 +92,7 @@
"email-providers": "^1.13.1",
"emoji-regex": "^10.0.0",
"es6-error": "^4.1.1",
"exports-loader": "^0.6.4",
"exports-loader": "^1.1.1",
"fetch-retry": "^5.0.3",
"fetch-with-proxy": "^3.0.1",
"file-loader": "^1.1.6",
@@ -112,7 +112,7 @@
"is-printable-key-event": "^1.0.0",
"jsdom": "^20.0.3",
"json-loader": "0.5.7",
"jsonwebtoken": "^8.5.0",
"jsonwebtoken": "^9.0.0",
"jszip": "^3.10.1",
"katex": "^0.16.3",
"kbar": "0.1.0-beta.28",
@@ -152,7 +152,7 @@
"pg-tsquery": "^8.4.0",
"polished": "^4.2.2",
"prosemirror-commands": "1.2.2",
"prosemirror-dropcursor": "^1.4.0",
"prosemirror-dropcursor": "^1.6.1",
"prosemirror-gapcursor": "^1.3.1",
"prosemirror-history": "^1.2.0",
"prosemirror-inputrules": "^1.1.3",
@@ -266,7 +266,7 @@
"@types/nodemailer": "^6.4.4",
"@types/passport-oauth2": "^1.4.11",
"@types/prosemirror-commands": "^1.0.4",
"@types/prosemirror-dropcursor": "^1.0.0",
"@types/prosemirror-dropcursor": "^1.5.0",
"@types/prosemirror-gapcursor": "^1.0.1",
"@types/prosemirror-history": "^1.0.1",
"@types/prosemirror-inputrules": "^1.0.2",

View File

@@ -333,3 +333,139 @@ describe("#searchForUser", () => {
expect(totalCount).toBe("0");
});
});
describe("#searchTitlesForUser", () => {
test("should return search results from collections", async () => {
const team = await buildTeam();
const user = await buildUser({
teamId: team.id,
});
const collection = await buildCollection({
userId: user.id,
teamId: team.id,
});
const document = await buildDocument({
userId: user.id,
teamId: team.id,
collectionId: collection.id,
title: "test",
});
const documents = await SearchHelper.searchTitlesForUser(user, "test");
expect(documents.length).toBe(1);
expect(documents[0]?.id).toBe(document.id);
});
test("should filter to specific collection", async () => {
const team = await buildTeam();
const user = await buildUser({
teamId: team.id,
});
const collection = await buildCollection({
userId: user.id,
teamId: team.id,
});
const collection1 = await buildCollection({
userId: user.id,
teamId: team.id,
});
const document = await buildDocument({
userId: user.id,
teamId: team.id,
collectionId: collection.id,
title: "test",
});
await buildDraftDocument({
teamId: team.id,
userId: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: team.id,
collectionId: collection1.id,
title: "test",
});
const documents = await SearchHelper.searchTitlesForUser(user, "test", {
collectionId: collection.id,
});
expect(documents.length).toBe(1);
expect(documents[0]?.id).toBe(document.id);
});
test("should handle no collections", async () => {
const team = await buildTeam();
const user = await buildUser({
teamId: team.id,
});
const documents = await SearchHelper.searchTitlesForUser(user, "test");
expect(documents.length).toBe(0);
});
test("should search only drafts created by user", async () => {
const user = await buildUser();
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "test",
});
const documents = await SearchHelper.searchTitlesForUser(user, "test", {
includeDrafts: true,
});
expect(documents.length).toBe(1);
});
test("should not include drafts", async () => {
const user = await buildUser();
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "test",
});
const documents = await SearchHelper.searchTitlesForUser(user, "test", {
includeDrafts: false,
});
expect(documents.length).toBe(0);
});
test("should include results from drafts as well", async () => {
const user = await buildUser();
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "not test",
});
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "test",
});
const documents = await SearchHelper.searchTitlesForUser(user, "test", {
includeDrafts: true,
});
expect(documents.length).toBe(2);
});
test("should not include results from drafts", async () => {
const user = await buildUser();
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "not test",
});
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "test",
});
const documents = await SearchHelper.searchTitlesForUser(user, "test", {
includeDrafts: false,
});
expect(documents.length).toBe(1);
});
});

View File

@@ -2,7 +2,7 @@ import removeMarkdown from "@tommoor/remove-markdown";
import invariant from "invariant";
import { find, map } from "lodash";
import queryParser from "pg-tsquery";
import { Op, QueryTypes } from "sequelize";
import { Op, QueryTypes, WhereOptions } from "sequelize";
import { DateFilter } from "@shared/types";
import unescape from "@shared/utils/unescape";
import { sequelize } from "@server/database/sequelize";
@@ -170,6 +170,128 @@ export default class SearchHelper {
return SearchHelper.buildResponse(results, documents, count);
}
public static async searchTitlesForUser(
user: User,
query: string,
options: SearchOptions = {}
): Promise<Document[]> {
const { limit = 15, offset = 0 } = options;
let where: WhereOptions<Document> = {
title: {
[Op.iLike]: `%${query}%`,
},
};
// Ensure we're filtering by the users accessible collections. If
// collectionId is passed as an option it is assumed that the authorization
// has already been done in the router
if (options.collectionId) {
where = {
...where,
collectionId: options.collectionId,
};
} else {
// @ts-expect-error doesn't like OR null
where = {
...where,
[Op.or]: [
{
collectionId: {
[Op.in]: await user.collectionIds(),
},
},
{
collectionId: {
[Op.is]: null,
},
createdById: user.id,
},
],
};
}
if (options.dateFilter) {
where = {
...where,
updatedAt: {
[Op.gt]: sequelize.literal(
`now() - interval '1 ${options.dateFilter}'`
),
},
};
}
if (!options.includeArchived) {
where = {
...where,
archivedAt: {
[Op.is]: null,
},
};
}
if (options.includeDrafts) {
where = {
...where,
[Op.or]: [
{
publishedAt: {
[Op.ne]: null,
},
},
{
createdById: user.id,
},
],
};
} else {
where = {
...where,
publishedAt: {
[Op.ne]: null,
},
};
}
if (options.collaboratorIds) {
where = {
...where,
collaboratorIds: {
[Op.contains]: options.collaboratorIds,
},
};
}
return await Document.scope([
"withoutState",
"withDrafts",
{
method: ["withViews", user.id],
},
{
method: ["withCollectionPermissions", user.id],
},
]).findAll({
where,
order: [["updatedAt", "DESC"]],
include: [
{
model: User,
as: "createdBy",
paranoid: false,
},
{
model: User,
as: "updatedBy",
paranoid: false,
},
],
offset,
limit,
});
}
public static async searchForUser(
user: User,
query: string,

View File

@@ -1,3 +1,4 @@
import { subDays } from "date-fns";
import { CollectionPermission } from "@shared/types";
import {
Document,
@@ -1048,6 +1049,88 @@ describe("#documents.search_titles", () => {
expect(body.data[0].id).toEqual(document.id);
});
it("should allow filtering of results by date", async () => {
const user = await buildUser();
await buildDocument({
userId: user.id,
teamId: user.teamId,
title: "Super secret",
createdAt: subDays(new Date(), 365),
updatedAt: subDays(new Date(), 365),
});
const res = await server.post("/api/documents.search_titles", {
body: {
token: user.getJwtToken(),
query: "SECRET",
dateFilter: "day",
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(0);
});
it("should allow filtering to include archived", async () => {
const user = await buildUser();
const document = await buildDocument({
userId: user.id,
teamId: user.teamId,
title: "Super secret",
archivedAt: new Date(),
});
const res = await server.post("/api/documents.search_titles", {
body: {
token: user.getJwtToken(),
query: "SECRET",
includeArchived: true,
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].id).toEqual(document.id);
});
it("should allow filtering to include drafts", async () => {
const user = await buildUser();
const document = await buildDraftDocument({
userId: user.id,
teamId: user.teamId,
title: "Super secret",
});
const res = await server.post("/api/documents.search_titles", {
body: {
token: user.getJwtToken(),
query: "SECRET",
includeDrafts: true,
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].id).toEqual(document.id);
});
it("should allow filtering to include a user", async () => {
const user = await buildUser();
const document = await buildDocument({
userId: user.id,
teamId: user.teamId,
title: "Super secret",
});
const res = await server.post("/api/documents.search_titles", {
body: {
token: user.getJwtToken(),
query: "SECRET",
userId: user.id,
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].id).toEqual(document.id);
});
it("should not include archived or deleted documents", async () => {
const user = await buildUser();
await buildDocument({

View File

@@ -588,43 +588,37 @@ router.post(
"documents.search_titles",
auth(),
pagination(),
validate(T.DocumentsSearchTitlesSchema),
async (ctx: APIContext<T.DocumentsSearchTitlesReq>) => {
const { query } = ctx.input;
validate(T.DocumentsSearchSchema),
async (ctx: APIContext<T.DocumentsSearchReq>) => {
const {
query,
includeArchived,
includeDrafts,
dateFilter,
collectionId,
userId,
} = ctx.input;
const { offset, limit } = ctx.state.pagination;
const { user } = ctx.state;
let collaboratorIds = undefined;
const collectionIds = await user.collectionIds();
const documents = await Document.scope([
{
method: ["withViews", user.id],
},
{
method: ["withCollectionPermissions", user.id],
},
]).findAll({
where: {
title: {
[Op.iLike]: `%${query}%`,
},
collectionId: collectionIds,
archivedAt: {
[Op.is]: null,
},
},
order: [["updatedAt", "DESC"]],
include: [
{
model: User,
as: "createdBy",
paranoid: false,
},
{
model: User,
as: "updatedBy",
paranoid: false,
},
],
if (collectionId) {
const collection = await Collection.scope({
method: ["withMembership", user.id],
}).findByPk(collectionId);
authorize(user, "read", collection);
}
if (userId) {
collaboratorIds = [userId];
}
const documents = await SearchHelper.searchTitlesForUser(user, query, {
includeArchived,
includeDrafts,
dateFilter,
collectionId,
collaboratorIds,
offset,
limit,
});

View File

@@ -138,12 +138,6 @@ export const DocumentsRestoreSchema = BaseIdSchema.extend({
export type DocumentsRestoreReq = z.infer<typeof DocumentsRestoreSchema>;
export const DocumentsSearchTitlesSchema = SearchQuerySchema.extend({});
export type DocumentsSearchTitlesReq = z.infer<
typeof DocumentsSearchTitlesSchema
>;
export const DocumentsSearchSchema = SearchQuerySchema.merge(
DateFilterSchema
).extend({

View File

@@ -365,14 +365,19 @@ export async function buildDocument(
}
count++;
return Document.create({
title: `Document ${count}`,
text: "This is the text in an example document",
publishedAt: isNull(overrides.collectionId) ? null : new Date(),
lastModifiedById: overrides.userId,
createdById: overrides.userId,
...overrides,
});
return Document.create(
{
title: `Document ${count}`,
text: "This is the text in an example document",
publishedAt: isNull(overrides.collectionId) ? null : new Date(),
lastModifiedById: overrides.userId,
createdById: overrides.userId,
...overrides,
},
{
silent: overrides.createdAt || overrides.updatedAt ? true : false,
}
);
}
export async function buildFileOperation(

117
yarn.lock
View File

@@ -85,7 +85,7 @@
"@jridgewell/gen-mapping" "^0.3.2"
jsesc "^2.5.1"
"@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.16.0", "@babel/helper-annotate-as-pure@^7.18.6":
"@babel/helper-annotate-as-pure@^7.16.0", "@babel/helper-annotate-as-pure@^7.18.6":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb"
integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==
@@ -3179,12 +3179,12 @@
"@types/prosemirror-state" "*"
"@types/prosemirror-view" "*"
"@types/prosemirror-dropcursor@^1.0.0":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@types/prosemirror-dropcursor/-/prosemirror-dropcursor-1.0.3.tgz#49250849b8a0b86e8c29eb1ba70a463e53e46947"
integrity sha512-b0/8njnJ4lwyHKcGuCMf3x7r1KjxyugB1R/c2iMCjplsJHSC7UY9+OysqgJR5uUXRekUSGniiLgBtac/lvH6wg==
"@types/prosemirror-dropcursor@^1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@types/prosemirror-dropcursor/-/prosemirror-dropcursor-1.5.0.tgz#5633fb20e7c1bf27edbdb64781b09bfb9f150f25"
integrity sha512-Xa13THoY0YkvYP/peH995ahT79w3ErdsmFUIaTY21nshxxnn5mdSgG+RTpkqXwZ85v+n28MvNfLF2gm+c8RZ1A==
dependencies:
"@types/prosemirror-state" "*"
prosemirror-dropcursor "*"
"@types/prosemirror-gapcursor@^1.0.1":
version "1.0.4"
@@ -4456,15 +4456,16 @@ babel-plugin-polyfill-regenerator@^0.2.2, babel-plugin-polyfill-regenerator@^0.2
dependencies:
"@babel/helper-define-polyfill-provider" "^0.2.4"
"babel-plugin-styled-components@>= 1.12.0", babel-plugin-styled-components@^1.11.1:
version "1.12.0"
resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.12.0.tgz#1dec1676512177de6b827211e9eda5a30db4f9b9"
integrity sha512-FEiD7l5ZABdJPpLssKXjBUJMYqzbcNzBowfXDCdJhOpbhWiewapUaY+LZGT8R4Jg2TwOjGjG4RKeyrO5p9sBkA==
"babel-plugin-styled-components@>= 1.12.0", babel-plugin-styled-components@^2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz#c81ef34b713f9da2b7d3f5550df0d1e19e798086"
integrity sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==
dependencies:
"@babel/helper-annotate-as-pure" "^7.0.0"
"@babel/helper-module-imports" "^7.0.0"
"@babel/helper-annotate-as-pure" "^7.16.0"
"@babel/helper-module-imports" "^7.16.0"
babel-plugin-syntax-jsx "^6.18.0"
lodash "^4.17.11"
picomatch "^2.3.0"
babel-plugin-syntax-class-properties@^6.8.0:
version "6.13.0"
@@ -7475,13 +7476,14 @@ expect@^28.1.3:
jest-message-util "^28.1.3"
jest-util "^28.1.3"
exports-loader@^0.6.4:
version "0.6.4"
resolved "https://registry.yarnpkg.com/exports-loader/-/exports-loader-0.6.4.tgz#d70fc6121975b35fc12830cf52754be2740fc886"
integrity sha1-1w/GEhl1s1/BKDDPUnVL4nQPyIY=
exports-loader@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/exports-loader/-/exports-loader-1.1.1.tgz#88c9a6877ee6a5519d7c41a016bdd99148421e69"
integrity sha512-CmyhIR2sJ3KOfVsHjsR0Yvo+0lhRhRMAevCbB8dhTVLHsZPs0lCQTvRmR9YNvBXDBxUuhmCE2f54KqEjZUaFrg==
dependencies:
loader-utils "^1.0.2"
source-map "0.5.x"
loader-utils "^2.0.0"
schema-utils "^3.0.0"
source-map "^0.6.1"
express-useragent@^1.0.15:
version "1.0.15"
@@ -10036,21 +10038,15 @@ jsonpointer@^5.0.0:
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.0.tgz#f802669a524ec4805fa7389eadbc9921d5dc8072"
integrity sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==
jsonwebtoken@^8.5.0:
version "8.5.1"
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
jsonwebtoken@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz#d0faf9ba1cc3a56255fe49c0961a67e520c1926d"
integrity sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==
dependencies:
jws "^3.2.2"
lodash.includes "^4.3.0"
lodash.isboolean "^3.0.3"
lodash.isinteger "^4.0.4"
lodash.isnumber "^3.0.3"
lodash.isplainobject "^4.0.6"
lodash.isstring "^4.0.1"
lodash.once "^4.0.0"
lodash "^4.17.21"
ms "^2.1.1"
semver "^5.6.0"
semver "^7.3.8"
"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.1.0:
version "3.1.0"
@@ -10562,46 +10558,16 @@ lodash.flattendeep@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"
integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=
lodash.includes@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=
lodash.isarguments@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=
lodash.isboolean@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
lodash.isinteger@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=
lodash.isnumber@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=
lodash.isplainobject@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
lodash.isstring@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
lodash.kebabcase@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36"
@@ -10617,11 +10583,6 @@ lodash.mergewith@4.6.2:
resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55"
integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==
lodash.once@^4.0.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
lodash.pick@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
@@ -12089,10 +12050,10 @@ picocolors@^1.0.0:
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3:
version "2.3.0"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
pidtree@^0.5.0:
version "0.5.0"
@@ -12377,10 +12338,10 @@ prosemirror-commands@1.2.2:
prosemirror-state "^1.0.0"
prosemirror-transform "^1.0.0"
prosemirror-dropcursor@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.4.0.tgz#91a859d4ee79c99b1c0ba6ee61c093b195c0d9f0"
integrity sha512-6+YwTjmqDwlA/Dm+5wK67ezgqgjA/MhSDgaNxKUzH97SmeuWFXyLeDRxxOPZeSo7yTxcDGUCWTEjmQZsVBuMrQ==
prosemirror-dropcursor@*, prosemirror-dropcursor@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.6.1.tgz#31f696172105f232bd17543ccf305e0f33e59d1d"
integrity sha512-LtyqQpkIknaT7NnZl3vDr3TpkNcG4ABvGRXx37XJ8tJNUGtcrZBh40A0344rDwlRTfUEmynQS/grUsoSWz+HgA==
dependencies:
prosemirror-state "^1.0.0"
prosemirror-transform "^1.1.0"
@@ -13624,10 +13585,10 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
semver@^7.2.1, semver@^7.3.2, semver@^7.3.5, semver@^7.3.7:
version "7.3.7"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
semver@^7.2.1, semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8:
version "7.3.8"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
dependencies:
lru-cache "^6.0.0"
@@ -14050,7 +14011,7 @@ source-map-url@^0.4.0:
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.6:
source-map@^0.5.0, source-map@^0.5.6:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=