mirror of
https://github.com/outline/outline.git
synced 2026-01-06 02:59:54 -06:00
Add table cell merge/unmerge functionality (#9322)
* Add table cell merge/unmerge functionality - Add new tableCell menu with merge and unmerge options - Update SelectionToolbar to show tableCell menu for CellSelection - Add mergeCells and splitCell commands to Table node - Add dictionary entries for merge/split cell tooltips - Use placeholder icons (PlusIcon for merge, MoreIcon for split) Fixes #6977 * fixes * fix: Header cells end up floating with some effort * refactor * collapse --------- Co-authored-by: codegen-sh[bot] <131295404+codegen-sh[bot]@users.noreply.github.com> Co-authored-by: Tom Moor <tom@getoutline.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import some from "lodash/some";
|
||||
import { EditorState, NodeSelection, TextSelection } from "prosemirror-state";
|
||||
import { CellSelection } from "prosemirror-tables";
|
||||
import * as React from "react";
|
||||
import filterExcessSeparators from "@shared/editor/lib/filterExcessSeparators";
|
||||
import { getMarkRange } from "@shared/editor/queries/getMarkRange";
|
||||
@@ -22,6 +23,7 @@ import getImageMenuItems from "../menus/image";
|
||||
import getNoticeMenuItems from "../menus/notice";
|
||||
import getReadOnlyMenuItems from "../menus/readOnly";
|
||||
import getTableMenuItems from "../menus/table";
|
||||
import getTableCellMenuItems from "../menus/tableCell";
|
||||
import getTableColMenuItems from "../menus/tableCol";
|
||||
import getTableRowMenuItems from "../menus/tableRow";
|
||||
import { useEditor } from "./EditorContext";
|
||||
@@ -183,6 +185,7 @@ export default function SelectionToolbar(props: Props) {
|
||||
const colIndex = getColumnIndex(state);
|
||||
const rowIndex = getRowIndex(state);
|
||||
const isTableSelection = colIndex !== undefined && rowIndex !== undefined;
|
||||
const isCellSelection = selection instanceof CellSelection;
|
||||
const link = getMarkRange(selection.$from, state.schema.marks.link);
|
||||
const isImageSelection =
|
||||
selection instanceof NodeSelection && selection.node.type.name === "image";
|
||||
@@ -202,6 +205,8 @@ export default function SelectionToolbar(props: Props) {
|
||||
items = getTableColMenuItems(state, colIndex, rtl, dictionary);
|
||||
} else if (rowIndex !== undefined) {
|
||||
items = getTableRowMenuItems(state, rowIndex, dictionary);
|
||||
} else if (isCellSelection) {
|
||||
items = getTableCellMenuItems(state, dictionary);
|
||||
} else if (isImageSelection) {
|
||||
items = readOnly ? [] : getImageMenuItems(state, dictionary);
|
||||
} else if (isAttachmentSelection) {
|
||||
|
||||
36
app/editor/menus/tableCell.tsx
Normal file
36
app/editor/menus/tableCell.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { TableSplitCellsIcon, TableMergeCellsIcon } from "outline-icons";
|
||||
import { EditorState } from "prosemirror-state";
|
||||
import { CellSelection } from "prosemirror-tables";
|
||||
import {
|
||||
isMergedCellSelection,
|
||||
isMultipleCellSelection,
|
||||
} from "@shared/editor/queries/table";
|
||||
import { MenuItem } from "@shared/editor/types";
|
||||
import { Dictionary } from "~/hooks/useDictionary";
|
||||
|
||||
export default function tableCellMenuItems(
|
||||
state: EditorState,
|
||||
dictionary: Dictionary
|
||||
): MenuItem[] {
|
||||
const { selection } = state;
|
||||
|
||||
// Only show menu items if we have a CellSelection
|
||||
if (!(selection instanceof CellSelection)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
name: "mergeCells",
|
||||
label: dictionary.mergeCells,
|
||||
icon: <TableMergeCellsIcon />,
|
||||
visible: isMultipleCellSelection(state),
|
||||
},
|
||||
{
|
||||
name: "splitCell",
|
||||
label: dictionary.splitCell,
|
||||
icon: <TableSplitCellsIcon />,
|
||||
visible: isMergedCellSelection(state),
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -8,10 +8,17 @@ import {
|
||||
ArrowIcon,
|
||||
MoreIcon,
|
||||
TableHeaderColumnIcon,
|
||||
TableMergeCellsIcon,
|
||||
TableSplitCellsIcon,
|
||||
} from "outline-icons";
|
||||
import { EditorState } from "prosemirror-state";
|
||||
import { CellSelection } from "prosemirror-tables";
|
||||
import styled from "styled-components";
|
||||
import { isNodeActive } from "@shared/editor/queries/isNodeActive";
|
||||
import {
|
||||
isMergedCellSelection,
|
||||
isMultipleCellSelection,
|
||||
} from "@shared/editor/queries/table";
|
||||
import { MenuItem } from "@shared/editor/types";
|
||||
import { Dictionary } from "~/hooks/useDictionary";
|
||||
|
||||
@@ -21,7 +28,11 @@ export default function tableColMenuItems(
|
||||
rtl: boolean,
|
||||
dictionary: Dictionary
|
||||
): MenuItem[] {
|
||||
const { schema } = state;
|
||||
const { schema, selection } = state;
|
||||
|
||||
if (!(selection instanceof CellSelection)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
@@ -96,6 +107,21 @@ export default function tableColMenuItems(
|
||||
icon: <InsertRightIcon />,
|
||||
attrs: { index },
|
||||
},
|
||||
{
|
||||
name: "mergeCells",
|
||||
label: dictionary.mergeCells,
|
||||
icon: <TableMergeCellsIcon />,
|
||||
visible: isMultipleCellSelection(state),
|
||||
},
|
||||
{
|
||||
name: "splitCell",
|
||||
label: dictionary.splitCell,
|
||||
icon: <TableSplitCellsIcon />,
|
||||
visible: isMergedCellSelection(state),
|
||||
},
|
||||
{
|
||||
name: "separator",
|
||||
},
|
||||
{
|
||||
name: "deleteColumn",
|
||||
dangerous: true,
|
||||
|
||||
@@ -4,8 +4,15 @@ import {
|
||||
InsertBelowIcon,
|
||||
MoreIcon,
|
||||
TableHeaderRowIcon,
|
||||
TableSplitCellsIcon,
|
||||
TableMergeCellsIcon,
|
||||
} from "outline-icons";
|
||||
import { EditorState } from "prosemirror-state";
|
||||
import { CellSelection } from "prosemirror-tables";
|
||||
import {
|
||||
isMergedCellSelection,
|
||||
isMultipleCellSelection,
|
||||
} from "@shared/editor/queries/table";
|
||||
import { MenuItem } from "@shared/editor/types";
|
||||
import { Dictionary } from "~/hooks/useDictionary";
|
||||
|
||||
@@ -14,6 +21,11 @@ export default function tableRowMenuItems(
|
||||
index: number,
|
||||
dictionary: Dictionary
|
||||
): MenuItem[] {
|
||||
const { selection } = state;
|
||||
if (!(selection instanceof CellSelection)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
icon: <MoreIcon />,
|
||||
@@ -36,6 +48,21 @@ export default function tableRowMenuItems(
|
||||
icon: <InsertBelowIcon />,
|
||||
attrs: { index },
|
||||
},
|
||||
{
|
||||
name: "mergeCells",
|
||||
label: dictionary.mergeCells,
|
||||
icon: <TableMergeCellsIcon />,
|
||||
visible: isMultipleCellSelection(state),
|
||||
},
|
||||
{
|
||||
name: "splitCell",
|
||||
label: dictionary.splitCell,
|
||||
icon: <TableSplitCellsIcon />,
|
||||
visible: isMergedCellSelection(state),
|
||||
},
|
||||
{
|
||||
name: "separator",
|
||||
},
|
||||
{
|
||||
name: "deleteRow",
|
||||
label: dictionary.deleteRow,
|
||||
|
||||
@@ -87,6 +87,8 @@ export default function useDictionary() {
|
||||
toggleHeader: t("Toggle header"),
|
||||
mathInline: t("Math inline (LaTeX)"),
|
||||
mathBlock: t("Math block (LaTeX)"),
|
||||
mergeCells: t("Merge cells"),
|
||||
splitCell: t("Split cell"),
|
||||
tip: t("Tip"),
|
||||
tipNotice: t("Tip notice"),
|
||||
warning: t("Warning"),
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
"node-fetch": "2.7.0",
|
||||
"nodemailer": "^6.10.0",
|
||||
"octokit": "^3.2.1",
|
||||
"outline-icons": "^3.10.0",
|
||||
"outline-icons": "^3.12.0",
|
||||
"oy-vey": "^0.12.1",
|
||||
"passport": "^0.7.0",
|
||||
"passport-google-oauth2": "^0.2.0",
|
||||
|
||||
@@ -17,6 +17,8 @@ import {
|
||||
deleteRow,
|
||||
deleteColumn,
|
||||
deleteTable,
|
||||
mergeCells,
|
||||
splitCell,
|
||||
} from "prosemirror-tables";
|
||||
import { ProsemirrorHelper } from "../../utils/ProsemirrorHelper";
|
||||
import { CSVHelper } from "../../utils/csv";
|
||||
@@ -597,3 +599,21 @@ export function deleteCellSelection(
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A command that splits a cell and collapses the selection.
|
||||
*
|
||||
* @returns The command
|
||||
*/
|
||||
export function splitCellAndCollapse(): Command {
|
||||
return chainTransactions(splitCell, collapseSelection());
|
||||
}
|
||||
|
||||
/**
|
||||
* A command that merges selected cells and collapses the selection.
|
||||
*
|
||||
* @returns The command
|
||||
*/
|
||||
export function mergeCellsAndCollapse(): Command {
|
||||
return chainTransactions(mergeCells, collapseSelection());
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ import {
|
||||
moveOutOfTable,
|
||||
createTableInner,
|
||||
deleteTableIfSelected,
|
||||
splitCellAndCollapse,
|
||||
mergeCellsAndCollapse,
|
||||
} from "../commands/table";
|
||||
import { MarkdownSerializerState } from "../lib/markdown/serializer";
|
||||
import { FixTablesPlugin } from "../plugins/FixTables";
|
||||
@@ -89,6 +91,8 @@ export default class Table extends Node {
|
||||
exportTable,
|
||||
toggleHeaderColumn: () => toggleHeader("column"),
|
||||
toggleHeaderRow: () => toggleHeader("row"),
|
||||
mergeCells: () => mergeCellsAndCollapse(),
|
||||
splitCell: () => splitCellAndCollapse(),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -5,16 +5,19 @@ import { changedDescendants } from "../lib/changedDescendants";
|
||||
import { getCellsInColumn } from "../queries/table";
|
||||
|
||||
/**
|
||||
* A ProseMirror plugin that fixes the last column in a table to ensure it fills the remaining width.
|
||||
* A ProseMirror plugin that fixes various ways that tables can end up in an incorrect state:
|
||||
*
|
||||
* - The last column in a table should fill the remaining width
|
||||
* - Header cells should only exist in the first row or column
|
||||
*/
|
||||
export class FixTablesPlugin extends Plugin {
|
||||
constructor() {
|
||||
super({
|
||||
appendTransaction: (_transactions, oldState, state) => {
|
||||
let tr: Transaction | undefined;
|
||||
const check = (node: Node) => {
|
||||
const check = (node: Node, pos: number) => {
|
||||
if (node.type.spec.tableRole === "table") {
|
||||
tr = this.fixTable(state, node, tr);
|
||||
tr = this.fixTable(state, node, pos, tr);
|
||||
}
|
||||
};
|
||||
if (!oldState) {
|
||||
@@ -30,6 +33,7 @@ export class FixTablesPlugin extends Plugin {
|
||||
private fixTable(
|
||||
state: EditorState,
|
||||
table: Node,
|
||||
pos: number,
|
||||
tr: Transaction | undefined
|
||||
): Transaction | undefined {
|
||||
let fixed = false;
|
||||
@@ -41,11 +45,11 @@ export class FixTablesPlugin extends Plugin {
|
||||
// If the table has only one column, remove the colwidth attribute on all cells
|
||||
if (map.width === 1) {
|
||||
const cells = getCellsInColumn(0)(state);
|
||||
cells.forEach((pos) => {
|
||||
cells.forEach((cellPos) => {
|
||||
const node = state.doc.nodeAt(pos);
|
||||
if (node?.attrs.colspan) {
|
||||
fixed = true;
|
||||
tr = tr!.setNodeMarkup(pos, undefined, {
|
||||
tr = tr!.setNodeMarkup(cellPos, undefined, {
|
||||
...node?.attrs,
|
||||
colwidth: null,
|
||||
});
|
||||
@@ -53,6 +57,28 @@ export class FixTablesPlugin extends Plugin {
|
||||
});
|
||||
}
|
||||
|
||||
// If the table has header cells that are not in the first row or column
|
||||
// then convert them to regular cells
|
||||
const cellPositions = map.cellsInRect({
|
||||
left: 1,
|
||||
top: 1,
|
||||
right: map.width,
|
||||
bottom: map.height,
|
||||
});
|
||||
|
||||
for (let i = 0; i < cellPositions.length; i++) {
|
||||
const cellPos = cellPositions[i];
|
||||
const cell = table.nodeAt(cellPos);
|
||||
if (cell && cell.type === state.schema.nodes.th) {
|
||||
fixed = true;
|
||||
tr = tr!.setNodeMarkup(
|
||||
cellPos + pos + 1,
|
||||
state.schema.nodes.td,
|
||||
cell.attrs
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return fixed ? tr : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,3 +174,46 @@ export function isTableSelected(state: EditorState): boolean {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if multiple cells are selected in the editor.
|
||||
*
|
||||
* @param state The editor state
|
||||
* @returns Boolean indicating if multiple cells are selected
|
||||
*/
|
||||
export function isMultipleCellSelection(state: EditorState): boolean {
|
||||
const { selection } = state;
|
||||
|
||||
return (
|
||||
selection instanceof CellSelection &&
|
||||
(selection.isColSelection() ||
|
||||
selection.isRowSelection() ||
|
||||
selection.$anchorCell.pos !== selection.$headCell.pos)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the selection spans multiple merged cells.
|
||||
*
|
||||
* @param state The editor state
|
||||
* @returns Boolean indicating if a merged cell is selected
|
||||
*/
|
||||
export function isMergedCellSelection(state: EditorState): boolean {
|
||||
const { selection } = state;
|
||||
if (selection instanceof CellSelection) {
|
||||
// Check if any cell in the selection has a colspan or rowspan > 1
|
||||
let hasMergedCells = false;
|
||||
selection.forEachCell((cell) => {
|
||||
if (cell.attrs.colspan > 1 || cell.attrs.rowspan > 1) {
|
||||
hasMergedCells = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
return hasMergedCells;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -497,6 +497,8 @@
|
||||
"Toggle header": "Toggle header",
|
||||
"Math inline (LaTeX)": "Math inline (LaTeX)",
|
||||
"Math block (LaTeX)": "Math block (LaTeX)",
|
||||
"Merge cells": "Merge cells",
|
||||
"Split cell": "Split cell",
|
||||
"Tip": "Tip",
|
||||
"Tip notice": "Tip notice",
|
||||
"Warning": "Warning",
|
||||
|
||||
59
yarn.lock
59
yarn.lock
@@ -2236,30 +2236,18 @@
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz#b17a2171f9074df9e91bfb07ef99a892ac06412a"
|
||||
integrity sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==
|
||||
|
||||
"@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"
|
||||
integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==
|
||||
dependencies:
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@eslint-community/eslint-utils@^4.7.0":
|
||||
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.7.0":
|
||||
version "4.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz#607084630c6c033992a082de6e6fbc1a8b52175a"
|
||||
integrity sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==
|
||||
dependencies:
|
||||
eslint-visitor-keys "^3.4.3"
|
||||
|
||||
"@eslint-community/regexpp@^4.10.0":
|
||||
"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1":
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0"
|
||||
integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==
|
||||
|
||||
"@eslint-community/regexpp@^4.6.1":
|
||||
version "4.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63"
|
||||
integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==
|
||||
|
||||
"@eslint/eslintrc@^2.1.4":
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad"
|
||||
@@ -3578,7 +3566,7 @@
|
||||
"@radix-ui/react-primitive" "2.0.1"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||
|
||||
"@radix-ui/react-portal@1.1.4", "@radix-ui/react-portal@^1.0.1":
|
||||
"@radix-ui/react-portal@1.1.4":
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.4.tgz#ff5401ff63c8a825c46eea96d3aef66074b8c0c8"
|
||||
integrity sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==
|
||||
@@ -3586,7 +3574,7 @@
|
||||
"@radix-ui/react-primitive" "2.0.2"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||
|
||||
"@radix-ui/react-portal@1.1.9":
|
||||
"@radix-ui/react-portal@1.1.9", "@radix-ui/react-portal@^1.0.1":
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.9.tgz#14c3649fe48ec474ac51ed9f2b9f5da4d91c4472"
|
||||
integrity sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==
|
||||
@@ -3869,20 +3857,13 @@
|
||||
dependencies:
|
||||
"@radix-ui/react-primitive" "2.0.1"
|
||||
|
||||
"@radix-ui/react-visually-hidden@1.2.3":
|
||||
"@radix-ui/react-visually-hidden@1.2.3", "@radix-ui/react-visually-hidden@^1.2.2":
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz#a8c38c8607735dc9f05c32f87ab0f9c2b109efbf"
|
||||
integrity sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==
|
||||
dependencies:
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
|
||||
"@radix-ui/react-visually-hidden@^1.2.2":
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.2.tgz#aa6d0f95b0cd50f08b02393d25132f52ca7861dc"
|
||||
integrity sha512-ORCmRUbNiZIv6uV5mhFrhsIKw4UX/N3syZtyqvry61tbGm4JlgQuSn0hk5TwCARsCjkcnuRkSdCE3xfb+ADHew==
|
||||
dependencies:
|
||||
"@radix-ui/react-primitive" "2.1.2"
|
||||
|
||||
"@radix-ui/rect@0.1.1":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-0.1.1.tgz#95b5ba51f469bea6b1b841e2d427e17e37d38419"
|
||||
@@ -7691,12 +7672,7 @@ content-disposition@~0.5.2:
|
||||
dependencies:
|
||||
safe-buffer "5.1.2"
|
||||
|
||||
content-type@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||
integrity "sha1-4TjMdeBAxyexlm/l5fjJruJW/js= sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
|
||||
|
||||
content-type@^1.0.5:
|
||||
content-type@^1.0.4, content-type@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
|
||||
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
|
||||
@@ -7833,16 +7809,7 @@ cross-fetch@^3.0.4, cross-fetch@^3.1.5:
|
||||
dependencies:
|
||||
node-fetch "^2.6.11"
|
||||
|
||||
cross-spawn@^7.0.2, cross-spawn@^7.0.3:
|
||||
version "7.0.5"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.5.tgz#910aac880ff5243da96b728bc6521a5f6c2f2f82"
|
||||
integrity sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==
|
||||
dependencies:
|
||||
path-key "^3.1.0"
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
cross-spawn@^7.0.6:
|
||||
cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.6:
|
||||
version "7.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
|
||||
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
|
||||
@@ -12402,12 +12369,12 @@ micromatch@4.0.5, micromatch@^4.0.2, micromatch@^4.0.4:
|
||||
braces "^3.0.2"
|
||||
picomatch "^2.3.1"
|
||||
|
||||
mime-db@1.52.0, "mime-db@>= 1.43.0 < 2":
|
||||
mime-db@1.52.0:
|
||||
version "1.52.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||
integrity "sha1-u6vNwChZ9JhzAchW4zh85exDv3A= sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
|
||||
|
||||
mime-db@^1.54.0:
|
||||
"mime-db@>= 1.43.0 < 2", mime-db@^1.54.0:
|
||||
version "1.54.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5"
|
||||
integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==
|
||||
@@ -12949,10 +12916,10 @@ os-tmpdir@~1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||
integrity "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="
|
||||
|
||||
outline-icons@^3.10.0:
|
||||
version "3.10.0"
|
||||
resolved "https://registry.yarnpkg.com/outline-icons/-/outline-icons-3.10.0.tgz#625ee232a807ccbc1cca2eda87849cf77ca25160"
|
||||
integrity sha512-LSHIlZRgNtFoFHj5lDG6hfflNpVpO5kQl/jV7dYSytTcVVjfOECEDACSFsQ34JP7HT1vFaubp1EZSVrKFnIyVw==
|
||||
outline-icons@^3.12.0:
|
||||
version "3.12.0"
|
||||
resolved "https://registry.yarnpkg.com/outline-icons/-/outline-icons-3.12.0.tgz#2bcc086c0086057b57b21991774d44ce826d2116"
|
||||
integrity sha512-WnJr/yiJmWKLN2mol7tTcNkNwttYbQqldnAmBPjpHnH2aGJrXBlBEn35KsaiTLd664XDlWzU7XMfWDwhzrtbsA==
|
||||
|
||||
own-keys@^1.0.0:
|
||||
version "1.0.1"
|
||||
|
||||
Reference in New Issue
Block a user