diff --git a/src/client/components/ActivityTimeline.tsx b/src/client/components/ActivityTimeline.tsx index 1846be57..5e64f56a 100644 --- a/src/client/components/ActivityTimeline.tsx +++ b/src/client/components/ActivityTimeline.tsx @@ -52,7 +52,7 @@ export const ActivityTimeline = (props: ActivityDetailProps) => { } = {} } = play; - let scrobbleSummary: JSX.Element, + let scrobbleSummary: React.JSX.Element, scrobbleIconProps: Record = { color: 'green.focusRing' }; diff --git a/src/client/components/CodeBlock.tsx b/src/client/components/CodeBlock.tsx index 59b770f9..433207ce 100644 --- a/src/client/components/CodeBlock.tsx +++ b/src/client/components/CodeBlock.tsx @@ -126,7 +126,7 @@ export const ChakraPlainBlock = (props: ChakraPlainBlockProps) => { return safeStringify(code); }, [code]); - let header: JSX.Element | null; + let header: React.JSX.Element | null; if(props.title === undefined && maxLines === undefined) { header = null; } else { diff --git a/src/client/components/MSCollapsible.tsx b/src/client/components/MSCollapsible.tsx index bbcb7c74..4a10870a 100644 --- a/src/client/components/MSCollapsible.tsx +++ b/src/client/components/MSCollapsible.tsx @@ -6,7 +6,7 @@ import { LuChevronRight } from "react-icons/lu" //padding="0" borderWidth="0px" interface MSCollapsibleInternalProps { - indicator?: string | JSX.Element + indicator?: string | React.JSX.Element boxProps?: object triggerProps?: object indicatorProps?: object diff --git a/src/client/components/PlayData.tsx b/src/client/components/PlayData.tsx index 2c443271..d764aa91 100644 --- a/src/client/components/PlayData.tsx +++ b/src/client/components/PlayData.tsx @@ -49,7 +49,7 @@ export const PlayData = (props?: PlayInfoProps) => { const [codeMode, setCodeMode] = useState(false); - let code: JSX.Element | null = null; + let code: React.JSX.Element | null = null; const comparable = showCompare && final !== undefined; @@ -95,7 +95,7 @@ export const PlayDataDataList = (props: { play: JsonPlayObject, dates: DisplayDa } = props; - let albumArtistElm: JSX.Element; + let albumArtistElm: React.JSX.Element; if (play.data.albumArtists !== undefined && play.data.albumArtists.length > 0) { albumArtistElm = ( @@ -133,7 +133,7 @@ export const PlayDataDataList = (props: { play: JsonPlayObject, dates: DisplayDa } = {} } = play; - let titleElm: JSX.Element; + let titleElm: React.JSX.Element; if(webUrl !== undefined || originUrl !== undefined) { titleElm = {track} } else { @@ -154,7 +154,7 @@ export const PlayDataDataList = (props: { play: JsonPlayObject, dates: DisplayDa {play.data.artists.map((x, index) => { return ( - {x} + {x.name} ); })}} @@ -210,7 +210,7 @@ export const PlayDatesStack = (props: { play: JsonPlayObject, dates: DisplayDate dates } = props; - let datesItem: JSX.Element | null; + let datesItem: React.JSX.Element | null; if (dates === false) { datesItem = null; } else { @@ -246,11 +246,11 @@ export const PlayDatesFooter = (props: { play: JsonPlayObject, dates: DisplayDat dates } = props; - let dateElm: JSX.Element; + let dateElm: React.JSX.Element; if (dates !== false) { - let playDate: JSX.Element, - seenDate: JSX.Element; + let playDate: React.JSX.Element, + seenDate: React.JSX.Element; if (play.data.playDate !== undefined && ['all', 'played'].includes(dates)) { playDate = {`Played ${shortTodayAwareFormat(dayjs(play.data.playDate))}`} } diff --git a/src/client/components/ScrobbleActionResult.tsx b/src/client/components/ScrobbleActionResult.tsx index 4e342ea1..b1b0a59c 100644 --- a/src/client/components/ScrobbleActionResult.tsx +++ b/src/client/components/ScrobbleActionResult.tsx @@ -33,9 +33,9 @@ export const ScrobbleActionResult = (props: ScrobbleActionResultProps) => { collapsibleOpen } = props; - let responseSuffix: JSX.Element, - warningsElm: JSX.Element, - errorElm: JSX.Element | null; + let responseSuffix: React.JSX.Element, + warningsElm: React.JSX.Element, + errorElm: React.JSX.Element | null; if (warnings.length > 0) { warningsElm = warnings diff --git a/src/client/components/TransformSteps.tsx b/src/client/components/TransformSteps.tsx index 86996140..fe244fe3 100644 --- a/src/client/components/TransformSteps.tsx +++ b/src/client/components/TransformSteps.tsx @@ -18,12 +18,12 @@ export interface LifeycleStepsTimelineProps extends MSCollapsibleExternalProps { original: JsonPlayObject } -const diffElements = (original: JsonPlayObject, steps: LifecycleStep[]): [JSX.Element[], JsonPlayObject?] => { +const diffElements = (original: JsonPlayObject, steps: LifecycleStep[]): [React.JSX.Element[], JsonPlayObject?] => { let currentPlay: JsonPlayObject = structuredClone(original); // JSON.parse(JSON.stringify(original)); let patchFailed = false; - const diffElements: JSX.Element[] | null = []; + const diffElements: React.JSX.Element[] | null = []; let index = 0; for (const step of steps) { @@ -100,9 +100,9 @@ export const TransformSteps = (props: LifeycleStepsTimelineProps) => { name } = x; - let timelineIcon: JSX.Element, + let timelineIcon: React.JSX.Element, iconProps: Record, - summary: JSX.Element, + summary: React.JSX.Element, alertStatus: "error" | "info" | "warning" | "success" | "neutral"; if(error === undefined) { timelineIcon = ; -- 2.51.2 From 31c35647dd8e698cd4ddfe77f7465dbcacb135d5 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Fri, 29 May 2026 19:42:03 +0000 Subject: [PATCH 2/4] feat(ui): Update artist rendering to use credits --- src/client/components/ArtistCreditDisplay.tsx | 38 +++++++++++++++ src/client/components/ChakraTooltip.tsx | 46 +++++++++++++++++++ src/client/components/PlayData.tsx | 19 ++------ .../components/playActivity/PlayList.tsx | 6 +-- src/stories/PlayInfo.stories.tsx | 6 ++- 5 files changed, 95 insertions(+), 20 deletions(-) create mode 100644 src/client/components/ArtistCreditDisplay.tsx create mode 100644 src/client/components/ChakraTooltip.tsx diff --git a/src/client/components/ArtistCreditDisplay.tsx b/src/client/components/ArtistCreditDisplay.tsx new file mode 100644 index 00000000..5b6d53a4 --- /dev/null +++ b/src/client/components/ArtistCreditDisplay.tsx @@ -0,0 +1,38 @@ +import React, { Fragment } from 'react'; +import { ArtistCredit as AC } from '../../core/Atomic'; + +import { HStack, Tag } from "@chakra-ui/react" +import { SiMusicbrainz } from "react-icons/si"; +import { Tooltip } from './ChakraTooltip'; + +export const ArtistCredit = (props: { data: AC, showIdLink?: boolean }) => { + + const { + data, + showIdLink = true + } = props; + + if (!showIdLink || Object.keys(data).length === 1) { + return data.name; + } + + return + + {data.name} + + {data.mbid !== undefined ? : null} + + + + +} + +export const ArtistCreditTags = (props: { data: AC[], showIdLink?: boolean }) => { + return {props.data.map((x, index) => { + return ( + + + + ); + })} +} \ No newline at end of file diff --git a/src/client/components/ChakraTooltip.tsx b/src/client/components/ChakraTooltip.tsx new file mode 100644 index 00000000..0129778d --- /dev/null +++ b/src/client/components/ChakraTooltip.tsx @@ -0,0 +1,46 @@ +import { Tooltip as ChakraTooltip, Portal } from "@chakra-ui/react" +import * as React from "react" + +export interface TooltipProps extends ChakraTooltip.RootProps { + showArrow?: boolean + portalled?: boolean + portalRef?: React.RefObject + content: React.ReactNode + contentProps?: ChakraTooltip.ContentProps + disabled?: boolean +} + +export const Tooltip = React.forwardRef( + function Tooltip(props, ref) { + const { + showArrow, + children, + disabled, + portalled = true, + content, + contentProps, + portalRef, + ...rest + } = props + + if (disabled) return children + + return ( + + {children} + + + + {showArrow && ( + + + + )} + {content} + + + + + ) + }, +) diff --git a/src/client/components/PlayData.tsx b/src/client/components/PlayData.tsx index d764aa91..f387d412 100644 --- a/src/client/components/PlayData.tsx +++ b/src/client/components/PlayData.tsx @@ -1,5 +1,5 @@ import React, { Fragment, useMemo, useState } from 'react'; -import { EmptyState, DataList, HStack, Tag, Tabs, Wrap, Box, Flex, SegmentGroup, Stack, Text, Separator, IconButton, Container, SimpleGrid, Float, Spacer, Icon, Link, Span, Show } from "@chakra-ui/react" +import { EmptyState, DataList, HStack, Tag, Tabs, Wrap, Box, Flex, SegmentGroup, Stack, Text, Tooltip, Separator, IconButton, Container, SimpleGrid, Float, Spacer, Icon, Link, Span, Show } from "@chakra-ui/react" import { LuCode, LuText, LuCheck, LuX } from "react-icons/lu" import { JsonPlayObject, PlayObjectLifecycleless } from '../../core/Atomic.js'; import { shortTodayAwareFormat, timeToHumanTimestamp } from '../../core/TimeUtils.js'; @@ -8,6 +8,7 @@ import { ChakraCodeBlock } from './CodeBlock.js'; import { TextMuted } from './TextMuted.js'; import { formatNumber } from '../../core/DataUtils.js'; import { Muted } from './Typography.js'; +import { ArtistCreditTags } from './ArtistCreditDisplay.js'; const EmptyPlayData = () => { return ( @@ -102,13 +103,7 @@ export const PlayDataDataList = (props: { play: JsonPlayObject, dates: DisplayDa Album Artists - {play.data.albumArtists.map((x, index) => { - return ( - - {x} - - ); - })} + ); @@ -151,13 +146,7 @@ export const PlayDataDataList = (props: { play: JsonPlayObject, dates: DisplayDa Artists {artists.length === 0 ? (No Artists) : - {play.data.artists.map((x, index) => { - return ( - - {x.name} - - ); - })}} + } {albumArtistElm} diff --git a/src/client/components/playActivity/PlayList.tsx b/src/client/components/playActivity/PlayList.tsx index 94549c4e..7b7a2c14 100644 --- a/src/client/components/playActivity/PlayList.tsx +++ b/src/client/components/playActivity/PlayList.tsx @@ -168,7 +168,7 @@ const VirtualizedCollapse = (props: { data: PlayActivity[] }) => { {play.data.track} - {play.data.artists.join(' / ')} + {play.data.artists.map(x => x.name).join(' / ')} {play.meta?.source} @@ -260,7 +260,7 @@ const VirtualizedAccordian = (props: { data: PlayActivity[] }) => { {play.data.track} - {play.data.artists.join(' / ')} + {play.data.artists.map(x => x.name).join(' / ')} {play.meta?.source} @@ -331,7 +331,7 @@ const PlainAccordian = (props: { data: PlayActivity[], sortBy: 'played' | 'seen' {play.data.track} - {play.data.artists.join(' / ')} + {play.data.artists.map(x => x.name).join(' / ')} {play.meta?.source} diff --git a/src/stories/PlayInfo.stories.tsx b/src/stories/PlayInfo.stories.tsx index c8f71270..b5196a0f 100644 --- a/src/stories/PlayInfo.stories.tsx +++ b/src/stories/PlayInfo.stories.tsx @@ -5,14 +5,16 @@ import { fn } from 'storybook/test'; import { PlayData } from "../client/components/PlayData.js"; import {Provider} from "../client/components/Provider"; import { Container } from '@chakra-ui/react'; -import { generateArtists, generateJsonPlay, generatePlay, withBrainz } from "../core/PlayTestUtils.js" +import { generateArtistCredits, generateArtists, generateJsonPlay, generatePlay, withBrainz } from "../core/PlayTestUtils.js" import clone from "clone"; import { asJsonPlayObject } from '../core/PlayMarshalUtils.js'; +import { JsonPlayObject } from "../core/Atomic.js"; type PropsAndCustomArgs = React.ComponentProps & { includeAlbumArtists?: boolean; defaultFinal?: boolean brainz?: boolean + play: JsonPlayObject }; // More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export const meta = preview.type<{args: PropsAndCustomArgs}>().meta({ @@ -48,7 +50,7 @@ export const PlayInfoStory = meta.story({ } if(args.includeAlbumArtists && (args.play.data.albumArtists === undefined || args.play.data.albumArtists.length === 0)) { - const aa = generateArtists(undefined, 2); + const aa = generateArtistCredits(undefined, 2, {mbidVal: true}); args.play.data.albumArtists = aa; if(args.final !== undefined) { args.final.data.albumArtists = aa; -- 2.51.2 From d54e169a14adcb122358455fd0a1e4365e1e57c5 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Fri, 29 May 2026 20:00:12 +0000 Subject: [PATCH 3/4] fix for transformstep date --- src/stories/TransformSteps.stories.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/stories/TransformSteps.stories.tsx b/src/stories/TransformSteps.stories.tsx index aafa70e3..5ae566c2 100644 --- a/src/stories/TransformSteps.stories.tsx +++ b/src/stories/TransformSteps.stories.tsx @@ -5,7 +5,7 @@ import { fn } from 'storybook/test'; import { Container } from '@chakra-ui/react'; import { TransformSteps } from "../client/components/TransformSteps.js"; import {Provider} from "../client/components/Provider"; -import { generateJsonPlays } from "../core/PlayTestUtils.js"; +import { generateJsonPlays, generatePlay } from "../core/PlayTestUtils.js"; import { ErrorLike, JsonPlayObject, PlayLifecycle } from "../core/Atomic.js"; import { examplePlay, lastfmErrorExample } from "./storyUtils.js"; import {generatePlayWithLifecycle} from '../core/tests/utils/fixtures' @@ -28,12 +28,13 @@ decorators: [ // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#story-args }); -const multiPlay = asJsonPlayObject(generatePlayWithLifecycle({lifecycleSteps: { preCompare: 2}})); +const original = generatePlay(); +const multiPlay = asJsonPlayObject(generatePlayWithLifecycle({lifecycleSteps: { preCompare: 2}, original})); // More on writing stories with args: https://storybook.js.org/docs/writing-stories/args export const Multiple = meta.story({ args: { - steps: multiPlay.meta.lifecycle.steps, - original: multiPlay.meta.lifecycle.original, + steps: multiPlay.meta!.lifecycle!.steps, + original: asJsonPlayObject(original), collapsibleOpen: true } //render: function Render(args) { return () } -- 2.51.2 From 004400d7eae385a87effcd332f7316a8032ce392 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Sat, 30 May 2026 20:02:20 +0000 Subject: [PATCH 4/4] refactor: Replace jsondiffpatch-react with @pierre/diffs Good ridance. --- package-lock.json | 316 +++++++++--------- package.json | 6 +- src/client/components/JsonDiff.css | 17 - src/client/components/JsonDiff.tsx | 43 --- src/client/components/MSCollapsible.tsx | 1 - .../components/ScrobbleActionResult.tsx | 1 - src/client/components/ScrobbleMatchResult.tsx | 1 - src/client/components/TransformSteps.tsx | 8 +- src/client/components/diffs/JsonDiff.tsx | 80 +++++ src/client/components/diffs/PlayDiff.tsx | 0 src/client/recent/RecentPage.tsx | 1 - src/core/Atomic.ts | 1 - 12 files changed, 236 insertions(+), 239 deletions(-) delete mode 100644 src/client/components/JsonDiff.css delete mode 100644 src/client/components/JsonDiff.tsx create mode 100644 src/client/components/diffs/JsonDiff.tsx create mode 100644 src/client/components/diffs/PlayDiff.tsx diff --git a/package-lock.json b/package-lock.json index 240701c3..a89d34a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "@kenyip/backoff-strategies": "^1.0.4", "@keyv/valkey": "^1.0.8", "@lukehagar/plexjs": "^0.39.0", + "@pierre/diffs": "^1.2.4", "@supercharge/promise-pool": "^3.0.0", "@svrooij/sonos": "^2.5.0", "@xhayper/discord-rpc": "^1.3.0", @@ -152,7 +153,6 @@ "eslint-plugin-prefer-arrow-functions": "^3.2.4", "eslint-plugin-storybook": "^10.3.6", "git-cliff": "^2.12.0", - "jsondiffpatch-react": "^1.0.8", "mocha": "^10.3.0", "mockdate": "^3.0.5", "msw": "^2.12.10", @@ -2990,6 +2990,119 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@pierre/diffs": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@pierre/diffs/-/diffs-1.2.4.tgz", + "integrity": "sha512-SEuYxGpSCHVvfoLly/Q/OYpJSBLWaVLV3M3wI/VBW7aZmzYenNe4aXjOf5sIKJMWW5gbZe9WdLvtKUt6cQ1k1A==", + "license": "apache-2.0", + "dependencies": { + "@pierre/theme": "1.0.3", + "@shikijs/transformers": "^3.0.0", + "diff": "8.0.3", + "hast-util-to-html": "9.0.5", + "lru_map": "0.4.1", + "shiki": "^3.0.0" + }, + "peerDependencies": { + "react": "^18.3.1 || ^19.0.0", + "react-dom": "^18.3.1 || ^19.0.0" + } + }, + "node_modules/@pierre/diffs/node_modules/@shikijs/core": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.23.0.tgz", + "integrity": "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.5" + } + }, + "node_modules/@pierre/diffs/node_modules/@shikijs/engine-javascript": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.23.0.tgz", + "integrity": "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.4" + } + }, + "node_modules/@pierre/diffs/node_modules/@shikijs/engine-oniguruma": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.23.0.tgz", + "integrity": "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@pierre/diffs/node_modules/@shikijs/langs": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.23.0.tgz", + "integrity": "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@pierre/diffs/node_modules/@shikijs/themes": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.23.0.tgz", + "integrity": "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@pierre/diffs/node_modules/@shikijs/types": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.23.0.tgz", + "integrity": "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@pierre/diffs/node_modules/diff": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", + "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/@pierre/diffs/node_modules/shiki": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.23.0.tgz", + "integrity": "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "3.23.0", + "@shikijs/engine-javascript": "3.23.0", + "@shikijs/engine-oniguruma": "3.23.0", + "@shikijs/langs": "3.23.0", + "@shikijs/themes": "3.23.0", + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@pierre/theme": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@pierre/theme/-/theme-1.0.3.tgz", + "integrity": "sha512-sWHv11TMoqKxKDgTIk5VbhQjdPhs8DCcBxbjh3mRlS3YOM/OcrWoGX6MM8eBGn9cUu3M46Py0JnxsG2nJaFTuA==", + "license": "MIT", + "engines": { + "vscode": "^1.0.0" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -3528,6 +3641,38 @@ "node": ">=20" } }, + "node_modules/@shikijs/transformers": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-3.23.0.tgz", + "integrity": "sha512-F9msZVxdF+krQNSdQ4V+Ja5QemeAoTQ2jxt7nJCwhDsdF1JWS3KxIQXA3lQbyKwS3J61oHRUSv4jYWv3CkaKTQ==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "3.23.0", + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@shikijs/transformers/node_modules/@shikijs/core": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.23.0.tgz", + "integrity": "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.5" + } + }, + "node_modules/@shikijs/transformers/node_modules/@shikijs/types": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.23.0.tgz", + "integrity": "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, "node_modules/@shikijs/types": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.0.2.tgz", @@ -3546,7 +3691,6 @@ "version": "10.0.2", "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", - "dev": true, "license": "MIT" }, "node_modules/@sindresorhus/is": { @@ -4685,7 +4829,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "*" @@ -4761,7 +4904,6 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "*" @@ -4974,7 +5116,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true, "license": "MIT" }, "node_modules/@types/use-sync-external-store": { @@ -5302,7 +5443,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true, "license": "ISC" }, "node_modules/@vitejs/plugin-react": { @@ -7325,7 +7465,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -7403,7 +7542,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -7414,7 +7552,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -7668,7 +7805,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -8079,7 +8215,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -8113,7 +8248,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dev": true, "license": "MIT", "dependencies": { "dequal": "^2.0.0" @@ -8159,13 +8293,6 @@ "node": ">=0.3.1" } }, - "node_modules/diff-match-patch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", - "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/diff-sequences": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", @@ -10627,7 +10754,6 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -10651,7 +10777,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0" @@ -10727,7 +10852,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -11548,116 +11672,6 @@ "node": "^18.0.0 || >=20.0.0" } }, - "node_modules/jsondiffpatch-react": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/jsondiffpatch-react/-/jsondiffpatch-react-1.0.8.tgz", - "integrity": "sha512-dbipCQLrCsIN3w1+F+AtIaU9CmcTzfeHQ74QqUW0qZHITpi6F2P5580TB2u1A943Wyod8+09NSxxDjy5gFnXzw==", - "dev": true, - "license": "MIT", - "dependencies": { - "jsondiffpatch": "^0.4.1", - "yarn.lock": "^0.0.1-security" - }, - "peerDependencies": { - "react": "^16.8 || ^17 || ^18", - "react-dom": "^16.8 || ^17 || ^18" - } - }, - "node_modules/jsondiffpatch-react/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jsondiffpatch-react/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jsondiffpatch-react/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/jsondiffpatch-react/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/jsondiffpatch-react/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/jsondiffpatch-react/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/jsondiffpatch-react/node_modules/jsondiffpatch": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.4.1.tgz", - "integrity": "sha512-t0etAxTUk1w5MYdNOkZBZ8rvYYN5iL+2dHCCx/DpkFm/bW28M6y5nUS83D4XdZiHy35Fpaw6LBb+F88fHZnVCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^2.3.0", - "diff-match-patch": "^1.0.0" - }, - "bin": { - "jsondiffpatch": "bin/jsondiffpatch" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/jsondiffpatch-react/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -12188,6 +12202,12 @@ "node": ">=8" } }, + "node_modules/lru_map": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.4.1.tgz", + "integrity": "sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg==", + "license": "MIT" + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -12238,7 +12258,6 @@ "version": "13.2.1", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -12305,7 +12324,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -12326,7 +12344,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -12343,7 +12360,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -12365,7 +12381,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -12382,7 +12397,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -13251,14 +13265,12 @@ "version": "0.12.1", "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", - "dev": true, "license": "MIT" }, "node_modules/oniguruma-to-es": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.5.tgz", "integrity": "sha512-Zjygswjpsewa0NLTsiizVuMQZbp0MDyM6lIt66OxsF21npUDlzpHi1Mgb/qhQdkb+dWFTzJmFbEWdvZgRho8eQ==", - "dev": true, "license": "MIT", "dependencies": { "oniguruma-parser": "^0.12.1", @@ -14001,7 +14013,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -14177,7 +14188,6 @@ "version": "19.2.6", "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -14232,7 +14242,6 @@ "version": "19.2.6", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", - "dev": true, "license": "MIT", "dependencies": { "scheduler": "^0.27.0" @@ -14496,7 +14505,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", - "dev": true, "license": "MIT", "dependencies": { "regex-utilities": "^2.3.0" @@ -14506,7 +14514,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", - "dev": true, "license": "MIT", "dependencies": { "regex-utilities": "^2.3.0" @@ -14516,7 +14523,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", - "dev": true, "license": "MIT" }, "node_modules/require-directory": { @@ -14833,7 +14839,6 @@ "version": "0.27.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "dev": true, "license": "MIT" }, "node_modules/secure-json-parse": { @@ -15248,7 +15253,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -15538,7 +15542,6 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", - "dev": true, "license": "MIT", "dependencies": { "character-entities-html4": "^2.0.0", @@ -15943,7 +15946,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -16441,7 +16443,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -16455,7 +16456,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -16469,7 +16469,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -16483,7 +16482,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -16499,7 +16497,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -16683,7 +16680,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -16698,7 +16694,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -17205,12 +17200,6 @@ "node": ">=8" } }, - "node_modules/yarn.lock": { - "version": "0.0.1-security", - "resolved": "https://registry.npmjs.org/yarn.lock/-/yarn.lock-0.0.1-security.tgz", - "integrity": "sha512-ZRX6v5zGCJMI1T2aO+BQxJggy1vvorXEwonQhWXIC+brO7lkDB3zWelVNAti183ddH6FmJP8z4UDCJnJlioK4Q==", - "dev": true - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -17298,7 +17287,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "dev": true, "license": "MIT", "funding": { "type": "github", diff --git a/package.json b/package.json index db92caf9..0ff146a4 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "@kenyip/backoff-strategies": "^1.0.4", "@keyv/valkey": "^1.0.8", "@lukehagar/plexjs": "^0.39.0", + "@pierre/diffs": "^1.2.4", "@supercharge/promise-pool": "^3.0.0", "@svrooij/sonos": "^2.5.0", "@xhayper/discord-rpc": "^1.3.0", @@ -190,7 +191,6 @@ "eslint-plugin-prefer-arrow-functions": "^3.2.4", "eslint-plugin-storybook": "^10.3.6", "git-cliff": "^2.12.0", - "jsondiffpatch-react": "^1.0.8", "mocha": "^10.3.0", "mockdate": "^3.0.5", "msw": "^2.12.10", @@ -234,10 +234,6 @@ }, "musicbrainz-api": { "rate-limit-threshold": "0.2.1" - }, - "jsondiffpatch-react": { - "react": "$react", - "react-dom": "$react-dom" } } } diff --git a/src/client/components/JsonDiff.css b/src/client/components/JsonDiff.css deleted file mode 100644 index 8f8ac6e4..00000000 --- a/src/client/components/JsonDiff.css +++ /dev/null @@ -1,17 +0,0 @@ -.jsondiffpatch-added .jsondiffpatch-property-name, -.jsondiffpatch-added .jsondiffpatch-value pre, -.jsondiffpatch-modified .jsondiffpatch-right-value pre, -.jsondiffpatch-textdiff-added { - background: #0e2e1b; -} - -.jsondiffpatch-deleted .jsondiffpatch-property-name, -.jsondiffpatch-deleted pre, -.jsondiffpatch-modified .jsondiffpatch-left-value pre, -.jsondiffpatch-textdiff-deleted { - background: #371516 ; -} - -/* .jsondiffpatch-delta, .jsondiffpatch-delta ul { - padding: 0 0 0 0; -} */ \ No newline at end of file diff --git a/src/client/components/JsonDiff.tsx b/src/client/components/JsonDiff.tsx deleted file mode 100644 index def8f98c..00000000 --- a/src/client/components/JsonDiff.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import React, { ComponentProps } from 'react'; -import JsonDiffReact from 'jsondiffpatch-react'; -import { MSErrorBoundary } from './ErrorBoundary'; -import { MarkOptional } from 'ts-essentials'; -import { patchObject } from '../../core/DataUtils'; -import './JsonDiff.css'; -import { Changeset } from 'json-diff-ts'; - -type DiffableVal = [] | object | string; - -export interface JsonDiffReactProps { - right: DiffableVal, - left: DiffableVal - show?: boolean, - annotated?: boolean, - tips?: any, - objectHash?: CallableFunction, -} - -export type JsonDiffPatchProps = MarkOptional & { - diff?: Changeset -} - -export const JsonDiffPatch = (props: JsonDiffPatchProps) => { - const { - right, - left, - diff, - ...rest - } = props; - const detachedLeft = JSON.parse(JSON.stringify(left)); - let realRight: DiffableVal; - if (right !== undefined) { - realRight = structuredClone(right); - } else if (diff !== undefined) { - realRight = patchObject(left, diff); - } else { - throw new Error(`must provide either 'right' or 'diff'`); - } - return - - -}; \ No newline at end of file diff --git a/src/client/components/MSCollapsible.tsx b/src/client/components/MSCollapsible.tsx index 4a10870a..143381c3 100644 --- a/src/client/components/MSCollapsible.tsx +++ b/src/client/components/MSCollapsible.tsx @@ -1,5 +1,4 @@ import { Collapsible, Stack, Box, useBreakpointValue } from "@chakra-ui/react" -import { diff } from "jsondiffpatch"; import { ComponentProps, PropsWithChildren, useState, useEffect, useMemo } from "react"; import { LuChevronRight } from "react-icons/lu" diff --git a/src/client/components/ScrobbleActionResult.tsx b/src/client/components/ScrobbleActionResult.tsx index b1b0a59c..c08883f7 100644 --- a/src/client/components/ScrobbleActionResult.tsx +++ b/src/client/components/ScrobbleActionResult.tsx @@ -8,7 +8,6 @@ import { IoMusicalNoteOutline } from "react-icons/io5"; import { HiOutlineCloudUpload, HiOutlineCloudDownload } from "react-icons/hi"; import { LuCheck, LuCircleX, LuX } from "react-icons/lu"; import { ChakraCodeBlockShort, ChakraPlainBlock, ChakraPlainBlockShort } from "./CodeBlock"; -import { JsonDiffPatch } from "./JsonDiff"; import { formatNumber, jdiff } from "../../core/DataUtils"; import { capitalize } from "../../core/StringUtils"; import { MSCollapsible, MSCollapsibleExternalProps } from "./MSCollapsible"; diff --git a/src/client/components/ScrobbleMatchResult.tsx b/src/client/components/ScrobbleMatchResult.tsx index 0abce0d3..e455df46 100644 --- a/src/client/components/ScrobbleMatchResult.tsx +++ b/src/client/components/ScrobbleMatchResult.tsx @@ -7,7 +7,6 @@ import { BiWrench } from "react-icons/bi"; import { IoMusicalNoteOutline } from "react-icons/io5"; import { LuCheck, LuCircleX, LuX } from "react-icons/lu"; import { ChakraCodeBlockShort, ChakraPlainBlock, ChakraPlainBlockShort } from "./CodeBlock"; -import { JsonDiffPatch } from "./JsonDiff"; import { formatNumber, jdiff } from "../../core/DataUtils"; export interface ScrobbleMatchResultProps { diff --git a/src/client/components/TransformSteps.tsx b/src/client/components/TransformSteps.tsx index fe244fe3..5e81aabd 100644 --- a/src/client/components/TransformSteps.tsx +++ b/src/client/components/TransformSteps.tsx @@ -8,10 +8,10 @@ import { BsStoplights } from "react-icons/bs"; import { BsExclamationTriangle, BsExclamationOctagon } from "react-icons/bs"; import { MdMusicNote } from "react-icons/md"; import { ChakraCodeBlockShort, ChakraPlainBlockShort } from "./CodeBlock"; -import { JsonDiffPatch } from "./JsonDiff"; -import { jdiff, patchObject } from "../../core/DataUtils"; +import { patchObject } from "../../core/DataUtils"; import { MSCollapsible, MSCollapsibleExternalProps } from "./MSCollapsible"; import { Muted } from "./Typography"; +import { JsonDiffPatch } from "./diffs/JsonDiff"; export interface LifeycleStepsTimelineProps extends MSCollapsibleExternalProps { steps: LifecycleStep[] @@ -63,9 +63,7 @@ const diffElements = (original: JsonPlayObject, steps: LifecycleStep[]): [React. try { currentPlay.data = patchObject(currentPlay.data, patch)// jdiff.patch(currentPlay, patch) as JsonPlayObject; diffElements.push( - - - + ) } catch (e) { diffElements.push(); diff --git a/src/client/components/diffs/JsonDiff.tsx b/src/client/components/diffs/JsonDiff.tsx new file mode 100644 index 00000000..be727bd5 --- /dev/null +++ b/src/client/components/diffs/JsonDiff.tsx @@ -0,0 +1,80 @@ +import React, { ComponentProps } from 'react'; +import { + parseDiffFromFile, + type FileContents +} from '@pierre/diffs'; +import { + type FileDiffMetadata, + type FileDiffProps, + FileDiff, +} from '@pierre/diffs/react'; +import { MarkRequired } from 'ts-essentials'; +import { Changeset } from 'json-diff-ts'; +import { MSErrorBoundary } from '../ErrorBoundary'; +import { patchObject } from "../../../core/DataUtils"; + +type DiffableVal = [] | object | string; + +interface JsonDiffOptionalProps { + right?: DiffableVal, + left: DiffableVal + diff?: Changeset + diffOpts?: FileDiffProps +} + +export type JsonDiffProps = MarkRequired | MarkRequired + +const JsonDiffPatchComponent = (props: JsonDiffProps) => { + const { + right: rightVal, + left, + diff, + diffOpts = {}, + } = props; + + if(rightVal === undefined && diff === undefined) { + throw new Error(`Must provide either 'right' or 'diff' props`); + } + + let right = rightVal; + if(right === undefined) { + right = patchObject(structuredClone(left), diff); + } + + const fileDiff: FileDiffMetadata = parseDiffFromFile(valToFileContents(left), valToFileContents(right)); + return +} + +export const JsonDiffPatch = (props: JsonDiffProps) => + +const valToFileContents = (val: DiffableVal, fileContentOpts: Partial = {}): FileContents => { + let strContent: string; + const { + name = 'Content' + } = fileContentOpts; + let fileName: string = name; + let lang: FileContents['lang']; + if(typeof val === 'string') { + strContent = val; + } else { + strContent = JSON.stringify(val, undefined, 2); + lang = 'json'; + } + return { + name: fileName, + lang, + contents: strContent + }; +} \ No newline at end of file diff --git a/src/client/components/diffs/PlayDiff.tsx b/src/client/components/diffs/PlayDiff.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/client/recent/RecentPage.tsx b/src/client/recent/RecentPage.tsx index 27cf0e72..f0c39590 100644 --- a/src/client/recent/RecentPage.tsx +++ b/src/client/recent/RecentPage.tsx @@ -8,7 +8,6 @@ import { faQuestionCircle, faBug } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useCopyToClipboard } from '../components/copyToClipboardHook'; import clsx from "clsx"; -import {patch} from 'jsondiffpatch'; const displayOpts = { include: recentIncludes, diff --git a/src/core/Atomic.ts b/src/core/Atomic.ts index 41f3296d..22c8f5ea 100644 --- a/src/core/Atomic.ts +++ b/src/core/Atomic.ts @@ -2,7 +2,6 @@ import { LogDataPretty, LogLevel } from "@foxxmd/logging"; import { Dayjs } from "dayjs"; import { ListenProgress } from "../backend/sources/PlayerState/ListenProgress.js"; import { AdditionalTrackInfoResponse } from "../backend/common/vendor/listenbrainz/interfaces.js"; -import { Delta } from 'jsondiffpatch'; import { MarkOptional } from "ts-essentials"; import { ErrorObject } from "serialize-error"; import { PlayPlatformIdStr } from "../backend/common/infrastructure/Atomic.js";