mirror of
https://github.com/ershisan99/DevToysWeb.git
synced 2025-12-16 20:49:23 +00:00
feat: implement text diff tool
This commit is contained in:
17
app/text/diff/layout.tsx
Normal file
17
app/text/diff/layout.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Metadata } from "next";
|
||||||
|
|
||||||
|
import { toolGroups } from "@/config/tools";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: toolGroups.text.tools.inspector_and_case_converter.longTitle,
|
||||||
|
description: toolGroups.text.tools.inspector_and_case_converter.description,
|
||||||
|
robots: {
|
||||||
|
googleBot: {
|
||||||
|
index: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
140
app/text/diff/page.tsx
Normal file
140
app/text/diff/page.tsx
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useCallback, useMemo, useState } from "react";
|
||||||
|
import { Panel, PanelGroup } from "react-resizable-panels";
|
||||||
|
|
||||||
|
import { PERSISTENCE_KEY } from "@/config/persistence-keys";
|
||||||
|
import { toolGroups } from "@/config/tools";
|
||||||
|
import { cn } from "@/lib/style";
|
||||||
|
import { DiffEditor } from "@/components/ui/diff-editor";
|
||||||
|
import { Editor } from "@/components/ui/editor";
|
||||||
|
import * as Button from "@/components/buttons";
|
||||||
|
import { Configuration } from "@/components/configuration";
|
||||||
|
import { Configurations } from "@/components/configurations";
|
||||||
|
import { ControlMenu } from "@/components/control-menu";
|
||||||
|
import * as Icon from "@/components/icons";
|
||||||
|
import * as icons from "@/components/icons";
|
||||||
|
import { Rows } from "@/components/icons";
|
||||||
|
import { LabeledSwitch } from "@/components/labeled-switch";
|
||||||
|
import { PageRootSection } from "@/components/page-root-section";
|
||||||
|
import { PageSection } from "@/components/page-section";
|
||||||
|
import { PanelResizeHandle } from "@/components/panel-resize-handler";
|
||||||
|
|
||||||
|
/** No particular reason for these sizes, just feels like a good balance */
|
||||||
|
const VERTICAL_PANEL_MAX_SIZE = 80;
|
||||||
|
const HORIZONTAL_PANEL_MAX_SIZE = 90;
|
||||||
|
const PANEL_FULL_SIZE = 100;
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
const [input1, setInput1] = useState<string | undefined>("Hello world");
|
||||||
|
const [input2, setInput2] = useState<string | undefined>("Hello, World!");
|
||||||
|
const [diffFullHeight, setDiffFullHeight] = useState(false);
|
||||||
|
const [inlineMode, setInlineMode] = useState(false);
|
||||||
|
const diffPanelMaxSize = useMemo(
|
||||||
|
() => (diffFullHeight ? PANEL_FULL_SIZE : VERTICAL_PANEL_MAX_SIZE),
|
||||||
|
[diffFullHeight]
|
||||||
|
);
|
||||||
|
|
||||||
|
const clearInput1 = useCallback(() => setInput1(""), [setInput1]);
|
||||||
|
const clearInput2 = useCallback(() => setInput2(""), [setInput2]);
|
||||||
|
const toggleFullHeight = useCallback(() => setDiffFullHeight(prev => !prev), [setDiffFullHeight]);
|
||||||
|
|
||||||
|
const inlineModeConfig = useMemo(
|
||||||
|
() => (
|
||||||
|
<Configuration
|
||||||
|
icon={<icons.Rows size={24} />}
|
||||||
|
title="Inline mode"
|
||||||
|
control={
|
||||||
|
<LabeledSwitch
|
||||||
|
id="uppercase-switch"
|
||||||
|
label={inlineMode ? "On" : "Off"}
|
||||||
|
checked={inlineMode}
|
||||||
|
onCheckedChange={setInlineMode}
|
||||||
|
aria-label="toggle whether to show diff in inline mode"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[inlineMode, setInlineMode]
|
||||||
|
);
|
||||||
|
const input1Control = useMemo(
|
||||||
|
() => (
|
||||||
|
<ControlMenu
|
||||||
|
list={[
|
||||||
|
<Button.Paste onClipboardRead={setInput1} />,
|
||||||
|
<Button.File onFileRead={setInput1} iconOnly aria-label="load a file with old text" />,
|
||||||
|
<Button.Clear onClick={clearInput1} iconOnly aria-label="clear old text input" />,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[setInput1, clearInput1]
|
||||||
|
);
|
||||||
|
const input2Control = useMemo(
|
||||||
|
() => (
|
||||||
|
<ControlMenu
|
||||||
|
list={[
|
||||||
|
<Button.Paste onClipboardRead={setInput2} />,
|
||||||
|
<Button.File onFileRead={setInput2} iconOnly aria-label="load a file with new text" />,
|
||||||
|
<Button.Clear onClick={clearInput2} iconOnly aria-label="clear new text input" />,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[setInput2, clearInput2]
|
||||||
|
);
|
||||||
|
|
||||||
|
const diffControl = useMemo(
|
||||||
|
() => (
|
||||||
|
<ControlMenu
|
||||||
|
list={[
|
||||||
|
<Button.ToggleFullSize iconOnly onClick={toggleFullHeight} expanded={diffFullHeight} />,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[diffFullHeight, toggleFullHeight]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageRootSection
|
||||||
|
className="h-full"
|
||||||
|
title={toolGroups.text.tools.inspector_and_case_converter.longTitle}
|
||||||
|
>
|
||||||
|
<PageSection title="Configuration" className={cn(diffFullHeight && "hidden")}>
|
||||||
|
<Configurations list={[inlineModeConfig]} />
|
||||||
|
</PageSection>
|
||||||
|
<PanelGroup direction="vertical" autoSaveId={PERSISTENCE_KEY.panels.textDiff.vertical}>
|
||||||
|
<Panel maxSize={VERTICAL_PANEL_MAX_SIZE} className={cn(diffFullHeight && "hidden")}>
|
||||||
|
<PanelGroup
|
||||||
|
direction="horizontal"
|
||||||
|
autoSaveId={PERSISTENCE_KEY.panels.textDiff.horizontal}
|
||||||
|
>
|
||||||
|
<Panel maxSize={HORIZONTAL_PANEL_MAX_SIZE}>
|
||||||
|
<PageSection className="h-full" title="Old text" control={input1Control}>
|
||||||
|
<Editor value={input1} onChange={setInput1} />
|
||||||
|
</PageSection>
|
||||||
|
</Panel>
|
||||||
|
<PanelResizeHandle direction="vertical" className="mt-[42px]" />
|
||||||
|
|
||||||
|
<Panel maxSize={HORIZONTAL_PANEL_MAX_SIZE}>
|
||||||
|
<PageSection className="h-full" title="New text" control={input2Control}>
|
||||||
|
<Editor value={input2} onChange={setInput2} />
|
||||||
|
</PageSection>
|
||||||
|
</Panel>
|
||||||
|
</PanelGroup>
|
||||||
|
</Panel>
|
||||||
|
<PanelResizeHandle direction="horizontal" className={cn(diffFullHeight && "hidden")} />
|
||||||
|
<Panel maxSize={diffPanelMaxSize}>
|
||||||
|
<PageSection className="h-full" title="Difference" control={diffControl}>
|
||||||
|
<DiffEditor
|
||||||
|
original={input1}
|
||||||
|
modified={input2}
|
||||||
|
options={{
|
||||||
|
readOnly: true,
|
||||||
|
renderSideBySide: !inlineMode,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</PageSection>
|
||||||
|
</Panel>
|
||||||
|
</PanelGroup>
|
||||||
|
</PageRootSection>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,3 +2,4 @@ export * from "./clear";
|
|||||||
export * from "./copy";
|
export * from "./copy";
|
||||||
export * from "./file";
|
export * from "./file";
|
||||||
export * from "./paste";
|
export * from "./paste";
|
||||||
|
export * from "./toggle-full-size";
|
||||||
|
|||||||
22
components/buttons/toggle-full-size.tsx
Normal file
22
components/buttons/toggle-full-size.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { memo } from "react";
|
||||||
|
import equal from "react-fast-compare";
|
||||||
|
|
||||||
|
import * as Icon from "@/components/icons";
|
||||||
|
|
||||||
|
import { Base, BaseProps } from "./base";
|
||||||
|
|
||||||
|
export type ToggleFullSizeProps = Omit<BaseProps, "icon" | "labelText"> & {
|
||||||
|
expanded: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
function RawToggleFullSize({ expanded, ...props }: ToggleFullSizeProps) {
|
||||||
|
return (
|
||||||
|
<Base
|
||||||
|
{...props}
|
||||||
|
icon={expanded ? <Icon.Minimize size={16} /> : <Icon.Maximize size={16} />}
|
||||||
|
labelText={expanded ? "Collapse" : "Expand"}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ToggleFullSize = memo(RawToggleFullSize, equal);
|
||||||
@@ -14,15 +14,21 @@ export const ChevronDown = memo(icons.ChevronDown, equal);
|
|||||||
export const Clipboard = memo(icons.Clipboard, equal);
|
export const Clipboard = memo(icons.Clipboard, equal);
|
||||||
export const Code = memo(icons.Code2, equal);
|
export const Code = memo(icons.Code2, equal);
|
||||||
export const Copy = memo(icons.Copy, equal);
|
export const Copy = memo(icons.Copy, equal);
|
||||||
|
export const Diff = memo(icons.Diff, equal);
|
||||||
export const Equal = memo(icons.Equal, equal);
|
export const Equal = memo(icons.Equal, equal);
|
||||||
export const File = memo(icons.FileIcon, equal);
|
export const File = memo(icons.FileIcon, equal);
|
||||||
export const Fingerprint = memo(icons.Fingerprint, equal);
|
export const Fingerprint = memo(icons.Fingerprint, equal);
|
||||||
|
export const GripHorizontal = memo(icons.GripHorizontal, equal);
|
||||||
|
export const GripVertical = memo(icons.GripVertical, equal);
|
||||||
export const Hash = memo(icons.Hash, equal);
|
export const Hash = memo(icons.Hash, equal);
|
||||||
export const Home = memo(icons.Home, equal);
|
export const Home = memo(icons.Home, equal);
|
||||||
export const Key = memo(icons.Key, equal);
|
export const Key = memo(icons.Key, equal);
|
||||||
export const Link = memo(icons.Link2, equal);
|
export const Link = memo(icons.Link2, equal);
|
||||||
|
export const Maximize = memo(icons.Maximize2, equal);
|
||||||
|
export const Minimize = memo(icons.Minimize2, equal);
|
||||||
export const PackagePlus = memo(icons.PackagePlus, equal);
|
export const PackagePlus = memo(icons.PackagePlus, equal);
|
||||||
export const Paintbrush = memo(icons.Paintbrush2, equal);
|
export const Paintbrush = memo(icons.Paintbrush2, equal);
|
||||||
|
export const Rows = memo(icons.Rows, equal);
|
||||||
export const Search = memo(icons.Search, equal);
|
export const Search = memo(icons.Search, equal);
|
||||||
export const Settings = memo(icons.Settings, equal);
|
export const Settings = memo(icons.Settings, equal);
|
||||||
export const Settings2 = memo(icons.Settings2, equal);
|
export const Settings2 = memo(icons.Settings2, equal);
|
||||||
|
|||||||
36
components/panel-resize-handler.tsx
Normal file
36
components/panel-resize-handler.tsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { ComponentPropsWithoutRef, useMemo } from "react";
|
||||||
|
import { PanelResizeHandle as PanelResizeHandlePrimitive } from "react-resizable-panels";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/style";
|
||||||
|
import * as Icon from "@/components/icons";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
direction?: "vertical" | "horizontal";
|
||||||
|
} & ComponentPropsWithoutRef<typeof PanelResizeHandlePrimitive>;
|
||||||
|
|
||||||
|
export const PanelResizeHandle = ({ direction = "vertical", className, ...props }: Props) => {
|
||||||
|
const isVertical = direction === "vertical";
|
||||||
|
const isHorizontal = direction === "horizontal";
|
||||||
|
|
||||||
|
const classNames = useMemo(
|
||||||
|
() =>
|
||||||
|
cn(
|
||||||
|
isVertical && "w-4",
|
||||||
|
isHorizontal && "h-4",
|
||||||
|
"flex items-center justify-center",
|
||||||
|
"data-[resize-handle-state=drag]:bg-neutral-200",
|
||||||
|
"dark:data-[resize-handle-state=drag]:bg-neutral-600",
|
||||||
|
"data-[resize-handle-state=hover]:bg-neutral-300",
|
||||||
|
"dark:data-[resize-handle-state=hover]:bg-neutral-700",
|
||||||
|
className
|
||||||
|
),
|
||||||
|
[isVertical, isHorizontal, className]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PanelResizeHandlePrimitive className={classNames} {...props}>
|
||||||
|
{isVertical && <Icon.GripVertical size={12} />}
|
||||||
|
{isHorizontal && <Icon.GripHorizontal size={12} />}
|
||||||
|
</PanelResizeHandlePrimitive>
|
||||||
|
);
|
||||||
|
};
|
||||||
8
config/persistence-keys.ts
Normal file
8
config/persistence-keys.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export const PERSISTENCE_KEY = {
|
||||||
|
panels: {
|
||||||
|
textDiff: {
|
||||||
|
vertical: "panels/text-diff/vertical",
|
||||||
|
horizontal: "panels/text-diff/horizontal",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
@@ -55,7 +55,7 @@ export const toolGroups = {
|
|||||||
shortTitle: "HTML",
|
shortTitle: "HTML",
|
||||||
longTitle: "HTML Encoder / Decoder",
|
longTitle: "HTML Encoder / Decoder",
|
||||||
description:
|
description:
|
||||||
"Encode or decode all the applicable characters to their corresponding HTML entities",
|
"Encode or decode all the applicable characters to their corresponding HTML entities",
|
||||||
keywords: "html encoder escaper decocder unescaper",
|
keywords: "html encoder escaper decocder unescaper",
|
||||||
href: "/encoders-decoders/html",
|
href: "/encoders-decoders/html",
|
||||||
},
|
},
|
||||||
@@ -64,7 +64,7 @@ export const toolGroups = {
|
|||||||
shortTitle: "URL",
|
shortTitle: "URL",
|
||||||
longTitle: "URL Encoder / Decoder",
|
longTitle: "URL Encoder / Decoder",
|
||||||
description:
|
description:
|
||||||
"Encode or decode all the applicable characters to their corresponding URL entities",
|
"Encode or decode all the applicable characters to their corresponding URL entities",
|
||||||
keywords: "url encoder escaper decocder unescaper",
|
keywords: "url encoder escaper decocder unescaper",
|
||||||
href: "/encoders-decoders/url",
|
href: "/encoders-decoders/url",
|
||||||
},
|
},
|
||||||
@@ -137,6 +137,14 @@ export const toolGroups = {
|
|||||||
keywords: "case converter convert text inspector inspect",
|
keywords: "case converter convert text inspector inspect",
|
||||||
href: "/text/inspector",
|
href: "/text/inspector",
|
||||||
},
|
},
|
||||||
|
diff: {
|
||||||
|
Icon: icons.Diff,
|
||||||
|
shortTitle: "Text diff",
|
||||||
|
longTitle: "Text Inspector & Case Converter",
|
||||||
|
description: "Analyze text and convert it to a different case",
|
||||||
|
keywords: "case converter convert text inspector inspect",
|
||||||
|
href: "/text/diff",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as const satisfies ToolGroups;
|
} as const satisfies ToolGroups;
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
"react-day-picker": "^8.7.1",
|
"react-day-picker": "^8.7.1",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-fast-compare": "^3.2.2",
|
"react-fast-compare": "^3.2.2",
|
||||||
|
"react-resizable-panels": "^2.0.19",
|
||||||
"sharp": "^0.32.1",
|
"sharp": "^0.32.1",
|
||||||
"tailwindcss-animate": "^1.0.5",
|
"tailwindcss-animate": "^1.0.5",
|
||||||
"url-slug": "^4.0.1",
|
"url-slug": "^4.0.1",
|
||||||
|
|||||||
52
pnpm-lock.yaml
generated
52
pnpm-lock.yaml
generated
@@ -1,9 +1,5 @@
|
|||||||
lockfileVersion: '6.0'
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
settings:
|
|
||||||
autoInstallPeers: true
|
|
||||||
excludeLinksFromLockfile: false
|
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@monaco-editor/react':
|
'@monaco-editor/react':
|
||||||
specifier: ^4.5.1
|
specifier: ^4.5.1
|
||||||
@@ -86,6 +82,9 @@ dependencies:
|
|||||||
react-fast-compare:
|
react-fast-compare:
|
||||||
specifier: ^3.2.2
|
specifier: ^3.2.2
|
||||||
version: 3.2.2
|
version: 3.2.2
|
||||||
|
react-resizable-panels:
|
||||||
|
specifier: ^2.0.19
|
||||||
|
version: 2.0.19(react-dom@18.2.0)(react@18.2.0)
|
||||||
sharp:
|
sharp:
|
||||||
specifier: ^0.32.1
|
specifier: ^0.32.1
|
||||||
version: 0.32.1
|
version: 0.32.1
|
||||||
@@ -2831,35 +2830,6 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/eslint-module-utils@2.8.0(@typescript-eslint/parser@5.59.7)(eslint-import-resolver-node@0.3.9)(eslint@8.41.0):
|
|
||||||
resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
|
|
||||||
engines: {node: '>=4'}
|
|
||||||
peerDependencies:
|
|
||||||
'@typescript-eslint/parser': '*'
|
|
||||||
eslint: '*'
|
|
||||||
eslint-import-resolver-node: '*'
|
|
||||||
eslint-import-resolver-typescript: '*'
|
|
||||||
eslint-import-resolver-webpack: '*'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@typescript-eslint/parser':
|
|
||||||
optional: true
|
|
||||||
eslint:
|
|
||||||
optional: true
|
|
||||||
eslint-import-resolver-node:
|
|
||||||
optional: true
|
|
||||||
eslint-import-resolver-typescript:
|
|
||||||
optional: true
|
|
||||||
eslint-import-resolver-webpack:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
'@typescript-eslint/parser': 5.59.7(eslint@8.41.0)(typescript@5.0.4)
|
|
||||||
debug: 3.2.7
|
|
||||||
eslint: 8.41.0
|
|
||||||
eslint-import-resolver-node: 0.3.9
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.59.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0):
|
/eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.59.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0):
|
||||||
resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==}
|
resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@@ -2912,7 +2882,7 @@ packages:
|
|||||||
doctrine: 2.1.0
|
doctrine: 2.1.0
|
||||||
eslint: 8.41.0
|
eslint: 8.41.0
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.59.7)(eslint-import-resolver-node@0.3.9)(eslint@8.41.0)
|
eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.59.7)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0)
|
||||||
has: 1.0.4
|
has: 1.0.4
|
||||||
is-core-module: 2.13.0
|
is-core-module: 2.13.0
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
@@ -4563,6 +4533,16 @@ packages:
|
|||||||
use-sidecar: 1.1.2(@types/react@18.2.7)(react@18.2.0)
|
use-sidecar: 1.1.2(@types/react@18.2.7)(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/react-resizable-panels@2.0.19(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-v3E41kfKSuCPIvJVb4nL4mIZjjKIn/gh6YqZF/gDfQDolv/8XnhJBek4EiV2gOr3hhc5A3kOGOayk3DhanpaQw==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.14.0 || ^17.0.0 || ^18.0.0
|
||||||
|
react-dom: ^16.14.0 || ^17.0.0 || ^18.0.0
|
||||||
|
dependencies:
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/react-style-singleton@2.2.1(@types/react@18.2.7)(react@18.2.0):
|
/react-style-singleton@2.2.1(@types/react@18.2.7)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==}
|
resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -5506,3 +5486,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
settings:
|
||||||
|
autoInstallPeers: true
|
||||||
|
excludeLinksFromLockfile: false
|
||||||
|
|||||||
Reference in New Issue
Block a user