feat: implement text diff tool

This commit is contained in:
2024-05-14 22:35:27 +02:00
parent 91fe326261
commit 9582eab403
4 changed files with 47 additions and 19 deletions

View File

@@ -1,10 +1,11 @@
import { PropsWithChildren } from "react";
import { Metadata } from "next"; import { Metadata } from "next";
import { toolGroups } from "@/config/tools"; import { toolGroups } from "@/config/tools";
export const metadata: Metadata = { export const metadata: Metadata = {
title: toolGroups.text.tools.inspector_and_case_converter.longTitle, title: toolGroups.text.tools.diff.longTitle,
description: toolGroups.text.tools.inspector_and_case_converter.description, description: toolGroups.text.tools.diff.description,
robots: { robots: {
googleBot: { googleBot: {
index: true, index: true,
@@ -12,6 +13,6 @@ export const metadata: Metadata = {
}, },
}; };
export default function Layout({ children }: { children: React.ReactNode }) { export default function Layout({ children }: PropsWithChildren) {
return children; return children;
} }

View File

@@ -5,16 +5,13 @@ import { Panel, PanelGroup } from "react-resizable-panels";
import { PERSISTENCE_KEY } from "@/config/persistence-keys"; import { PERSISTENCE_KEY } from "@/config/persistence-keys";
import { toolGroups } from "@/config/tools"; import { toolGroups } from "@/config/tools";
import { cn } from "@/lib/style";
import { DiffEditor } from "@/components/ui/diff-editor"; import { DiffEditor } from "@/components/ui/diff-editor";
import { Editor } from "@/components/ui/editor"; import { Editor } from "@/components/ui/editor";
import * as Button from "@/components/buttons"; import * as Button from "@/components/buttons";
import { Configuration } from "@/components/configuration"; import { Configuration } from "@/components/configuration";
import { Configurations } from "@/components/configurations"; import { Configurations } from "@/components/configurations";
import { ControlMenu } from "@/components/control-menu"; import { ControlMenu } from "@/components/control-menu";
import * as Icon from "@/components/icons";
import * as icons from "@/components/icons"; import * as icons from "@/components/icons";
import { Rows } from "@/components/icons";
import { LabeledSwitch } from "@/components/labeled-switch"; import { LabeledSwitch } from "@/components/labeled-switch";
import { PageRootSection } from "@/components/page-root-section"; import { PageRootSection } from "@/components/page-root-section";
import { PageSection } from "@/components/page-section"; import { PageSection } from "@/components/page-section";
@@ -69,6 +66,7 @@ export default function Page() {
), ),
[setInput1, clearInput1] [setInput1, clearInput1]
); );
const input2Control = useMemo( const input2Control = useMemo(
() => ( () => (
<ControlMenu <ControlMenu
@@ -93,16 +91,15 @@ export default function Page() {
[diffFullHeight, toggleFullHeight] [diffFullHeight, toggleFullHeight]
); );
const hiddenInFullHeightMode = useMemo(() => (diffFullHeight ? "hidden" : ""), [diffFullHeight]);
return ( return (
<PageRootSection <PageRootSection className="h-full" title={toolGroups.text.tools.diff.longTitle}>
className="h-full" <PageSection title="Configuration" className={hiddenInFullHeightMode}>
title={toolGroups.text.tools.inspector_and_case_converter.longTitle}
>
<PageSection title="Configuration" className={cn(diffFullHeight && "hidden")}>
<Configurations list={[inlineModeConfig]} /> <Configurations list={[inlineModeConfig]} />
</PageSection> </PageSection>
<PanelGroup direction="vertical" autoSaveId={PERSISTENCE_KEY.panels.textDiff.vertical}> <PanelGroup direction="vertical" autoSaveId={PERSISTENCE_KEY.panels.textDiff.vertical}>
<Panel maxSize={VERTICAL_PANEL_MAX_SIZE} className={cn(diffFullHeight && "hidden")}> <Panel maxSize={VERTICAL_PANEL_MAX_SIZE} className={hiddenInFullHeightMode}>
<PanelGroup <PanelGroup
direction="horizontal" direction="horizontal"
autoSaveId={PERSISTENCE_KEY.panels.textDiff.horizontal} autoSaveId={PERSISTENCE_KEY.panels.textDiff.horizontal}
@@ -121,7 +118,7 @@ export default function Page() {
</Panel> </Panel>
</PanelGroup> </PanelGroup>
</Panel> </Panel>
<PanelResizeHandle direction="horizontal" className={cn(diffFullHeight && "hidden")} /> <PanelResizeHandle direction="horizontal" className={hiddenInFullHeightMode} />
<Panel maxSize={diffPanelMaxSize}> <Panel maxSize={diffPanelMaxSize}>
<PageSection className="h-full" title="Difference" control={diffControl}> <PageSection className="h-full" title="Difference" control={diffControl}>
<DiffEditor <DiffEditor

View File

@@ -0,0 +1,30 @@
"use client";
import { ComponentPropsWithoutRef, forwardRef } from "react";
import { DiffEditor as MonacoDiffEditor } from "@monaco-editor/react";
import { useTheme } from "next-themes";
export type EditorProps = ComponentPropsWithoutRef<typeof MonacoDiffEditor>;
export const DiffEditor = forwardRef<HTMLTextAreaElement, EditorProps>(
({ options, theme, ...props }, ref) => {
const { theme: appTheme } = useTheme();
const themeToUse = theme ?? (appTheme === "light" ? "light" : "vs-dark");
return (
<MonacoDiffEditor
{...{ ref }}
theme={themeToUse}
options={{
tabFocusMode: true,
automaticLayout: true,
scrollBeyondLastLine: false,
...options, // NOTE: merge shallowly
}}
{...props}
/>
);
}
);
DiffEditor.displayName = "Editor";

View File

@@ -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",
}, },
@@ -139,10 +139,10 @@ export const toolGroups = {
}, },
diff: { diff: {
Icon: icons.Diff, Icon: icons.Diff,
shortTitle: "Text diff", shortTitle: "Text Diff",
longTitle: "Text Inspector & Case Converter", longTitle: "Text Comparer",
description: "Analyze text and convert it to a different case", description: "Compare two texts and highlight the differences",
keywords: "case converter convert text inspector inspect", keywords: "text comparer compare diff highlight",
href: "/text/diff", href: "/text/diff",
}, },
}, },