Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c57d313b6d | ||
|
|
c504b0c8c6 | ||
|
|
dc3bb5d2ab | ||
|
|
4c810901c3 | ||
|
|
25e1b20d9c | ||
|
|
52b7d1962d | ||
|
|
d4c03f38d2 | ||
|
|
e37607b377 | ||
|
|
abd804ca4e | ||
|
|
ac31a5a1cf | ||
|
|
a53506564d | ||
|
|
2cb9bcd991 | ||
|
|
d7225b201f | ||
|
|
0358dbd5e2 | ||
|
|
bc5e5561c7 | ||
|
|
6df767080a | ||
|
|
2fb902ee01 | ||
|
|
fa7010da0b | ||
|
|
1b42269739 | ||
|
|
c9d309c16d | ||
|
|
3acf393009 | ||
|
|
7508a96d3f | ||
|
|
49e0c57a33 | ||
|
|
d898d820bb | ||
|
|
a4b7a38e67 | ||
|
|
d722b915a9 | ||
|
|
b3515bfff0 | ||
|
|
d4c23be1b6 | ||
|
|
35082d9c43 | ||
|
|
48ac6bcdf7 | ||
|
|
7e46e60d21 | ||
|
|
927cc26669 | ||
|
|
401205b57f | ||
|
|
a08fe62e78 | ||
|
|
fdd972b973 | ||
|
|
d793753a0a | ||
|
|
6f548261a1 | ||
|
|
635a97b133 | ||
|
|
3b0a5b80e7 | ||
|
|
cabd9e3379 | ||
|
|
436f01e459 |
|
Before Width: | Height: | Size: 620 KiB After Width: | Height: | Size: 620 KiB |
|
Before Width: | Height: | Size: 279 B After Width: | Height: | Size: 279 B |
|
Before Width: | Height: | Size: 336 B After Width: | Height: | Size: 336 B |
|
Before Width: | Height: | Size: 486 B After Width: | Height: | Size: 486 B |
@@ -6,6 +6,7 @@ import {
|
|||||||
ViewUpdate,
|
ViewUpdate,
|
||||||
} from "@uiw/react-codemirror";
|
} from "@uiw/react-codemirror";
|
||||||
import { useRef, useEffect } from "react";
|
import { useRef, useEffect } from "react";
|
||||||
|
import { useJsonDoc } from "~/hooks/useJsonDoc";
|
||||||
import { getEditorSetup } from "~/utilities/codeMirrorSetup";
|
import { getEditorSetup } from "~/utilities/codeMirrorSetup";
|
||||||
import { darkTheme, lightTheme } from "~/utilities/codeMirrorTheme";
|
import { darkTheme, lightTheme } from "~/utilities/codeMirrorTheme";
|
||||||
import { useTheme } from "./ThemeProvider";
|
import { useTheme } from "./ThemeProvider";
|
||||||
@@ -92,10 +93,14 @@ export function CodeEditor(opts: CodeEditorProps) {
|
|||||||
}
|
}
|
||||||
}, [selection, view, setSelectionRef.current]);
|
}, [selection, view, setSelectionRef.current]);
|
||||||
|
|
||||||
|
const { minimal } = useJsonDoc();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
className="h-jsonViewerHeight overflow-y-auto no-scrollbar"
|
className={`${
|
||||||
|
minimal ? "h-jsonViewerHeightMinimal" : "h-jsonViewerHeight"
|
||||||
|
} overflow-y-auto no-scrollbar`}
|
||||||
ref={editor}
|
ref={editor}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { colorForItemAtPath } from "~/utilities/colors";
|
|||||||
import { IconComponent } from "~/useColumnView";
|
import { IconComponent } from "~/useColumnView";
|
||||||
import { useJson } from "../hooks/useJson";
|
import { useJson } from "../hooks/useJson";
|
||||||
import { memo, useMemo } from "react";
|
import { memo, useMemo } from "react";
|
||||||
|
import { useJsonDoc } from "~/hooks/useJsonDoc";
|
||||||
|
|
||||||
export type ColumnProps = {
|
export type ColumnProps = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -15,6 +16,7 @@ export type ColumnProps = {
|
|||||||
function ColumnElement(column: ColumnProps) {
|
function ColumnElement(column: ColumnProps) {
|
||||||
const { id, title, children } = column;
|
const { id, title, children } = column;
|
||||||
const [json] = useJson();
|
const [json] = useJson();
|
||||||
|
const { minimal } = useJsonDoc();
|
||||||
const iconColor = useMemo(() => colorForItemAtPath(id, json), [id, json]);
|
const iconColor = useMemo(() => colorForItemAtPath(id, json), [id, json]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -25,9 +27,13 @@ function ColumnElement(column: ColumnProps) {
|
|||||||
>
|
>
|
||||||
<div className="flex items-center text-slate-800 bg-slate-50 mb-[3px] p-2 pb-0 transition dark:bg-slate-900 dark:text-slate-300">
|
<div className="flex items-center text-slate-800 bg-slate-50 mb-[3px] p-2 pb-0 transition dark:bg-slate-900 dark:text-slate-300">
|
||||||
{column.icon && <column.icon className="h-6 w-6 mr-1" />}
|
{column.icon && <column.icon className="h-6 w-6 mr-1" />}
|
||||||
<Title className="">{title}</Title>
|
<Title className="text-ellipsis overflow-hidden">{title}</Title>
|
||||||
</div>
|
</div>
|
||||||
<div className="overflow-y-auto h-viewerHeight no-scrollbar">
|
<div
|
||||||
|
className={`overflow-y-auto ${
|
||||||
|
minimal ? "h-viewerHeightMinimal" : "h-viewerHeight"
|
||||||
|
} no-scrollbar`}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { useHotkeys } from "react-hotkeys-hook";
|
||||||
|
import { useSelectedInfo } from "../hooks/useSelectedInfo";
|
||||||
|
|
||||||
|
export function CopySelectedNodeShortcut() {
|
||||||
|
const selectedInfo = useSelectedInfo();
|
||||||
|
|
||||||
|
useHotkeys(
|
||||||
|
'shift+c,shift+C',
|
||||||
|
(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const selectedJSON = selectedInfo?.name === "string"
|
||||||
|
? selectedInfo?.value
|
||||||
|
: JSON.stringify(selectedInfo?.value, null, 2);
|
||||||
|
navigator.clipboard.writeText(selectedJSON);
|
||||||
|
},
|
||||||
|
[selectedInfo]
|
||||||
|
);
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
@@ -16,52 +16,66 @@ export function DocumentTitle() {
|
|||||||
}
|
}
|
||||||
}, [updateDoc]);
|
}, [updateDoc]);
|
||||||
|
|
||||||
const startEditing = useCallback(() => {
|
if (doc.readOnly) {
|
||||||
ref.current?.select();
|
return (
|
||||||
ref.current?.focus();
|
|
||||||
}, [ref.current]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<updateDoc.Form method="post" action={`/actions/${doc.id}/update`}>
|
|
||||||
<div
|
<div
|
||||||
className="flex justify-center items-center w-full"
|
className="flex justify-center items-center w-full"
|
||||||
title={doc.title}
|
title={doc.title}
|
||||||
>
|
>
|
||||||
<label className="relative block group">
|
<span
|
||||||
<PencilAltIcon className="h-5 w-5 absolute top-1/2 transform -translate-y-1/2 left-3 text-white opacity-0 transition pointer-events-none group-hover:opacity-80 group-focus:opacity-80" />
|
className={
|
||||||
<input
|
"min-w-[15vw] border-none text-ellipsis text-slate-300 px-2 pl-10 py-1 rounded-sm bg-transparent placeholder:text-slate-400 focus:bg-black/30 focus:outline-none focus:border-none hover:cursor-text transition dark:bg-transparent dark:text-slate-200 dark:placeholder:text-slate-400 dark:focus:bg-black dark:focus:bg-opacity-10"
|
||||||
ref={ref}
|
}
|
||||||
className={
|
>
|
||||||
"min-w-[15vw] border-none text-ellipsis text-slate-300 px-2 pl-10 py-1 rounded-sm bg-transparent placeholder:text-slate-400 focus:bg-black/30 focus:outline-none focus:border-none hover:bg-black hover:bg-opacity-30 hover:cursor-text transition dark:bg-transparent dark:text-slate-200 dark:placeholder:text-slate-400 dark:focus:bg-black dark:focus:bg-opacity-10 dark:hover:bg-black dark:hover:bg-opacity-10"
|
{doc.title}
|
||||||
}
|
</span>
|
||||||
type="text"
|
|
||||||
name="title"
|
|
||||||
spellCheck="false"
|
|
||||||
placeholder="Name your JSON file"
|
|
||||||
value={editedTitle}
|
|
||||||
onChange={(e) => setEditedTitle(e.target.value)}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
{match(editedTitle)
|
|
||||||
.with(doc.title, () => <p className="ml-2 text-transparent">Save</p>)
|
|
||||||
.with("", () => (
|
|
||||||
<button
|
|
||||||
className="ml-2 text-lime-500 hover:text-lime-600 transition"
|
|
||||||
onClick={() => setEditedTitle(doc.title)}
|
|
||||||
>
|
|
||||||
Reset
|
|
||||||
</button>
|
|
||||||
))
|
|
||||||
.otherwise(() => (
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="ml-2 text-lime-500 hover:text-lime-600 transition"
|
|
||||||
>
|
|
||||||
Save
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
</updateDoc.Form>
|
);
|
||||||
);
|
} else {
|
||||||
|
return (
|
||||||
|
<updateDoc.Form method="post" action={`/actions/${doc.id}/update`}>
|
||||||
|
<div
|
||||||
|
className="flex justify-center items-center w-full"
|
||||||
|
title={doc.title}
|
||||||
|
>
|
||||||
|
<label className="relative block group">
|
||||||
|
<PencilAltIcon className="h-5 w-5 absolute top-1/2 transform -translate-y-1/2 left-3 text-white opacity-0 transition pointer-events-none group-hover:opacity-80 group-focus:opacity-80" />
|
||||||
|
<input
|
||||||
|
ref={ref}
|
||||||
|
className={
|
||||||
|
"min-w-[15vw] border-none text-ellipsis text-slate-300 px-2 pl-10 py-1 rounded-sm bg-transparent placeholder:text-slate-400 focus:bg-black/30 focus:outline-none focus:border-none hover:bg-black hover:bg-opacity-30 hover:cursor-text transition dark:bg-transparent dark:text-slate-200 dark:placeholder:text-slate-400 dark:focus:bg-black dark:focus:bg-opacity-10 dark:hover:bg-black dark:hover:bg-opacity-10"
|
||||||
|
}
|
||||||
|
type="text"
|
||||||
|
name="title"
|
||||||
|
spellCheck="false"
|
||||||
|
placeholder="Name your JSON file"
|
||||||
|
value={editedTitle}
|
||||||
|
onChange={(e) => setEditedTitle(e.target.value)}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
{match(editedTitle)
|
||||||
|
.with(doc.title, () => (
|
||||||
|
<p className="ml-2 text-transparent">Save</p>
|
||||||
|
))
|
||||||
|
.with("", () => (
|
||||||
|
<button
|
||||||
|
className="ml-2 text-lime-500 hover:text-lime-600 transition"
|
||||||
|
onClick={() => setEditedTitle(doc.title)}
|
||||||
|
>
|
||||||
|
Reset
|
||||||
|
</button>
|
||||||
|
))
|
||||||
|
.otherwise(() => (
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="ml-2 text-lime-500 hover:text-lime-600 transition"
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</updateDoc.Form>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { Link } from "remix";
|
||||||
|
|
||||||
|
export function ExampleDoc({
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
path,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
path?: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
to={`/j/${id}${path ? `?path=${path}` : ""}`}
|
||||||
|
className="bg-slate-900 px-4 py-2 rounded-md whitespace-nowrap text-lime-300 transition hover:text-lime-500"
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
|
import { useJsonDoc } from "~/hooks/useJsonDoc";
|
||||||
import { ArrowKeysIcon } from "./Icons/ArrowKeysIcon";
|
import { ArrowKeysIcon } from "./Icons/ArrowKeysIcon";
|
||||||
|
import { CopyShortcutIcon } from "./Icons/CopyShortcutIcon";
|
||||||
import { EscapeKeyIcon } from "./Icons/EscapeKeyIcon";
|
import { EscapeKeyIcon } from "./Icons/EscapeKeyIcon";
|
||||||
import { SquareBracketsIcon } from "./Icons/SquareBracketsIcon";
|
import { SquareBracketsIcon } from "./Icons/SquareBracketsIcon";
|
||||||
import { Body } from "./Primitives/Body";
|
import { Body } from "./Primitives/Body";
|
||||||
import { ThemeModeToggler } from "./ThemeModeToggle";
|
import { ThemeModeToggler } from "./ThemeModeToggle";
|
||||||
|
import { GithubStarSmall } from "./UI/GithubStarSmall";
|
||||||
|
|
||||||
export function Footer() {
|
export function Footer() {
|
||||||
|
const { minimal } = useJsonDoc();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="flex items-center justify-between w-screen h-[30px] bg-slate-200 dark:bg-slate-800 border-t-[1px] border-slate-400 transition dark:border-slate-600">
|
<footer className="flex items-center justify-between w-screen h-[30px] bg-slate-200 dark:bg-slate-800 border-t-[1px] border-slate-400 transition dark:border-slate-600">
|
||||||
<ol className="flex pl-3">
|
<ol className="flex pl-3">
|
||||||
@@ -26,8 +31,23 @@ export function Footer() {
|
|||||||
Reset path
|
Reset path
|
||||||
</Body>
|
</Body>
|
||||||
</li>
|
</li>
|
||||||
|
<li className="flex items-center">
|
||||||
|
<CopyShortcutIcon className="transition text-slate-300 dark:text-slate-500" />
|
||||||
|
<Body className="pl-2 pr-4 text-slate-800 transition dark:text-white">
|
||||||
|
Copy selected node
|
||||||
|
</Body>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<ol className="flex items-center">
|
||||||
|
{minimal && (
|
||||||
|
<li>
|
||||||
|
<GithubStarSmall />
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
<li>
|
||||||
|
<ThemeModeToggler />
|
||||||
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
<ThemeModeToggler />
|
|
||||||
</footer>
|
</footer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import { ExtraLargeTitle } from "../Primitives/ExtraLargeTitle";
|
|||||||
import { SmallSubtitle } from "../Primitives/SmallSubtitle";
|
import { SmallSubtitle } from "../Primitives/SmallSubtitle";
|
||||||
import { HomeSection } from "./HomeSection";
|
import { HomeSection } from "./HomeSection";
|
||||||
|
|
||||||
|
import shareVideo from "~/assets/home/JsonHeroShare.mp4";
|
||||||
|
|
||||||
export function HomeCollaborateSection() {
|
export function HomeCollaborateSection() {
|
||||||
return (
|
return (
|
||||||
<HomeSection
|
<HomeSection
|
||||||
@@ -20,7 +22,7 @@ export function HomeCollaborateSection() {
|
|||||||
</SmallSubtitle>
|
</SmallSubtitle>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full md:w-1/2">
|
<div className="w-full md:w-1/2">
|
||||||
<AutoplayVideo src="/home/JsonHeroShare.mp4" />
|
<AutoplayVideo src={shareVideo} />
|
||||||
</div>
|
</div>
|
||||||
</HomeSection>
|
</HomeSection>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import { ExtraLargeTitle } from "../Primitives/ExtraLargeTitle";
|
|||||||
import { SmallSubtitle } from "../Primitives/SmallSubtitle";
|
import { SmallSubtitle } from "../Primitives/SmallSubtitle";
|
||||||
import { HomeSection } from "./HomeSection";
|
import { HomeSection } from "./HomeSection";
|
||||||
|
|
||||||
|
import edgeCasesVideo from "~/assets/home/UncoverEdgeCases.mp4";
|
||||||
|
|
||||||
export function HomeEdgeCasesSection() {
|
export function HomeEdgeCasesSection() {
|
||||||
return (
|
return (
|
||||||
<HomeSection
|
<HomeSection
|
||||||
@@ -21,7 +23,7 @@ export function HomeEdgeCasesSection() {
|
|||||||
</SmallSubtitle>
|
</SmallSubtitle>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full md:w-1/2">
|
<div className="w-full md:w-1/2">
|
||||||
<AutoplayVideo src="/home/UncoverEdgeCases.mp4" />
|
<AutoplayVideo src={edgeCasesVideo} />
|
||||||
</div>
|
</div>
|
||||||
</HomeSection>
|
</HomeSection>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
import { Link } from "remix";
|
||||||
import { DiscordIcon } from "../Icons/DiscordIcon";
|
import { DiscordIcon } from "../Icons/DiscordIcon";
|
||||||
import { EmailIcon } from "../Icons/EmailIcon";
|
import { EmailIcon } from "../Icons/EmailIcon";
|
||||||
import { GithubIcon } from "../Icons/GithubIcon";
|
import { GithubIcon } from "../Icons/GithubIcon";
|
||||||
import { Logo } from "../Icons/Logo";
|
import { Logo } from "../Icons/Logo";
|
||||||
|
import { TwitterIcon } from "../Icons/TwitterIcon";
|
||||||
|
|
||||||
export type HomeFooterProps = {
|
export type HomeFooterProps = {
|
||||||
maxWidth?: string;
|
maxWidth?: string;
|
||||||
@@ -36,6 +38,15 @@ export function HomeFooter({ maxWidth = "1150px" }: HomeFooterProps) {
|
|||||||
<DiscordIcon />
|
<DiscordIcon />
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li className="ml-2 hover:cursor-pointer">
|
||||||
|
<a href="https://twitter.com/json_hero" target="_blank">
|
||||||
|
<TwitterIcon />
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li className="ml-2 hover:cursor-pointer text-indigo-700">
|
||||||
|
<Link to="/privacy">Privacy Policy</Link>
|
||||||
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { DiscordIconTransparent } from "../Icons/DiscordIconTransparent";
|
import { DiscordIconTransparent } from "../Icons/DiscordIconTransparent";
|
||||||
import { EmailIconTransparent } from "../Icons/EmailIconTransparent";
|
import { EmailIconTransparent } from "../Icons/EmailIconTransparent";
|
||||||
|
import { TwitterIcon } from "../Icons/TwitterIcon";
|
||||||
import { Logo } from "../Icons/Logo";
|
import { Logo } from "../Icons/Logo";
|
||||||
import { NewDocument } from "../NewDocument";
|
import { NewDocument } from "../NewDocument";
|
||||||
import { GithubStar } from "../UI/GithubStar";
|
import { GithubStar } from "../UI/GithubStar";
|
||||||
@@ -10,10 +11,14 @@ import {
|
|||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "../UI/Popover";
|
} from "../UI/Popover";
|
||||||
|
|
||||||
export function HomeHeader() {
|
export function HomeHeader({ fixed }: { fixed?: boolean }) {
|
||||||
return (
|
return (
|
||||||
<header className="fixed z-20 flex items-center justify-between w-screen h-[82px] px-4 bg-indigo-700">
|
<header
|
||||||
<div className="flex w-44 mr-3">
|
className={`${
|
||||||
|
fixed ? "fixed" : ""
|
||||||
|
} z-20 flex items-center justify-between w-screen h-[82px] px-4 bg-indigo-700`}
|
||||||
|
>
|
||||||
|
<div className="flex w-36 sm:w-44 mr-3">
|
||||||
<Logo />
|
<Logo />
|
||||||
</div>
|
</div>
|
||||||
<ol className="flex items-center gap-2">
|
<ol className="flex items-center gap-2">
|
||||||
@@ -45,6 +50,11 @@ export function HomeHeader() {
|
|||||||
<DiscordIconTransparent />
|
<DiscordIconTransparent />
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li className="hover:cursor-pointer opacity-90 hover:opacity-100 transition">
|
||||||
|
<a href="https://twitter.com/json_hero" target="_blank">
|
||||||
|
<TwitterIcon />
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import { AutoplayVideo } from "../AutoplayVideo";
|
|||||||
import { NewFile } from "../NewFile";
|
import { NewFile } from "../NewFile";
|
||||||
import { ExtraLargeTitle } from "../Primitives/ExtraLargeTitle";
|
import { ExtraLargeTitle } from "../Primitives/ExtraLargeTitle";
|
||||||
import { SmallSubtitle } from "../Primitives/SmallSubtitle";
|
import { SmallSubtitle } from "../Primitives/SmallSubtitle";
|
||||||
import { HomeSection } from "./HomeSection";
|
|
||||||
|
import heroVideo from "~/assets/home/JsonHero2.mp4";
|
||||||
|
|
||||||
const jsonHeroTitle = "JSON sucks.";
|
const jsonHeroTitle = "JSON sucks.";
|
||||||
const jsonHeroSlogan = "But we're making it better.";
|
const jsonHeroSlogan = "But we're making it better.";
|
||||||
@@ -14,7 +15,7 @@ export function HomeHeroSection() {
|
|||||||
>
|
>
|
||||||
<div className="self-center md:w-1/2 md:pr-10 flex justify-end">
|
<div className="self-center md:w-1/2 md:pr-10 flex justify-end">
|
||||||
<div className=" max-w-3xl">
|
<div className=" max-w-3xl">
|
||||||
<AutoplayVideo src="/home/JsonHero2.mp4" />
|
<AutoplayVideo src={heroVideo} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="self-center flex align-center md:w-1/2 px-6 pb-8 mt-8 lg:mt-0">
|
<div className="self-center flex align-center md:w-1/2 px-6 pb-8 mt-8 lg:mt-0">
|
||||||
|
|||||||
@@ -142,7 +142,13 @@ function SampleJSONPreview({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<JsonDocProvider
|
<JsonDocProvider
|
||||||
doc={{ id: "sample", title: "Sample", type: "raw", contents: "" }}
|
doc={{
|
||||||
|
id: "sample",
|
||||||
|
title: "Sample",
|
||||||
|
type: "raw",
|
||||||
|
readOnly: false,
|
||||||
|
contents: "",
|
||||||
|
}}
|
||||||
path={initialSelection}
|
path={initialSelection}
|
||||||
>
|
>
|
||||||
<JsonProvider initialJson={json}>
|
<JsonProvider initialJson={json}>
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import { ExtraLargeTitle } from "../Primitives/ExtraLargeTitle";
|
|||||||
import { SmallSubtitle } from "../Primitives/SmallSubtitle";
|
import { SmallSubtitle } from "../Primitives/SmallSubtitle";
|
||||||
import { HomeSection } from "./HomeSection";
|
import { HomeSection } from "./HomeSection";
|
||||||
|
|
||||||
|
import searchVideo from "~/assets/home/JsonHeroSearch.mp4";
|
||||||
|
|
||||||
export function HomeSearchSection() {
|
export function HomeSearchSection() {
|
||||||
return (
|
return (
|
||||||
<HomeSection containerClassName="py-10 px-6 bg-black md:py-36 lg:py-20">
|
<HomeSection containerClassName="py-10 px-6 bg-black md:py-36 lg:py-20">
|
||||||
@@ -17,7 +19,7 @@ export function HomeSearchSection() {
|
|||||||
</SmallSubtitle>
|
</SmallSubtitle>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full md:w-1/2">
|
<div className="w-full md:w-1/2">
|
||||||
<AutoplayVideo src="/home/JsonHeroSearch.mp4" />
|
<AutoplayVideo src={searchVideo} />
|
||||||
</div>
|
</div>
|
||||||
</HomeSection>
|
</HomeSection>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
export function CopyShortcutIcon(props: React.SVGProps<SVGSVGElement>) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
className={props.className}
|
||||||
|
width="30"
|
||||||
|
height="14"
|
||||||
|
viewBox="0 0 30 14"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<rect width="14" height="14" rx="1.53846" fill="currentColor" />
|
||||||
|
<rect x="16" width="14" height="14" rx="1.53846" fill="currentColor" />
|
||||||
|
<path
|
||||||
|
d="M5.64,10.22H8.25V7a.39.39,0,0,1,.38-.39H10l-3-3L4,6.65H5.26A.39.39,0,0,1,5.64,7v3.18Zm3,.78H5.26a.38.38,0,0,1-.39-.39V7.43H3.11a.39.39,0,0,1-.28-.66L6.72,2.86a.39.39,0,0,1,.55,0l3.88,3.91a.38.38,0,0,1-.27.66H9v3.18a.38.38,0,0,1-.39.39Z"
|
||||||
|
stroke="#0f172a" strokeWidth="0.35px" fill="#0f172a"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M23.81,9.52a1.66,1.66,0,0,0,.53-.27,1.57,1.57,0,0,0,.35-.42,1.07,1.07,0,0,0,.13-.53h1.6a2.26,2.26,0,0,1-.25,1,2.87,2.87,0,0,1-.7.85,3.35,3.35,0,0,1-1,.58,3.56,3.56,0,0,1-1.22.21,3.73,3.73,0,0,1-1.55-.31,3.2,3.2,0,0,1-1.11-.84,3.61,3.61,0,0,1-.67-1.22,4.91,4.91,0,0,1-.23-1.5V6.88a4.91,4.91,0,0,1,.23-1.5,3.54,3.54,0,0,1,.67-1.22,3.33,3.33,0,0,1,1.11-.84,3.94,3.94,0,0,1,2.83-.09,3,3,0,0,1,1,.59,2.66,2.66,0,0,1,.67.92,2.94,2.94,0,0,1,.23,1.17h-1.6a1.48,1.48,0,0,0-.45-1.07,1.65,1.65,0,0,0-.52-.33,1.75,1.75,0,0,0-.65-.12,1.59,1.59,0,0,0-1.44.78,2.27,2.27,0,0,0-.31.8,4.53,4.53,0,0,0-.09.91v.24a4.63,4.63,0,0,0,.09.92,2.46,2.46,0,0,0,.3.8,1.67,1.67,0,0,0,.56.56,1.63,1.63,0,0,0,.89.22A2.05,2.05,0,0,0,23.81,9.52Z"
|
||||||
|
fill="#0f172a"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,11 +1,15 @@
|
|||||||
export function GithubIconSimple(props: React.SVGProps<SVGSVGElement>) {
|
export type IconProps = {
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function GithubIconSimple({ className }: IconProps) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={props.className}
|
className={className}
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="none"
|
fill="currentColor"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<g clipPath="url(#clip0_571_3822)">
|
<g clipPath="url(#clip0_571_3822)">
|
||||||
@@ -13,7 +17,7 @@ export function GithubIconSimple(props: React.SVGProps<SVGSVGElement>) {
|
|||||||
fillRule="evenodd"
|
fillRule="evenodd"
|
||||||
clipRule="evenodd"
|
clipRule="evenodd"
|
||||||
d="M12 0C5.37017 0 0 5.50708 0 12.306C0 17.745 3.44015 22.3532 8.20626 23.9849C8.80295 24.0982 9.02394 23.7205 9.02394 23.3881C9.02394 23.0935 9.01657 22.3229 9.00921 21.2956C5.67219 22.0359 4.96501 19.6487 4.96501 19.6487C4.41989 18.2285 3.63168 17.8508 3.63168 17.8508C2.54144 17.0878 3.71271 17.1029 3.71271 17.1029C4.91344 17.1936 5.55433 18.372 5.55433 18.372C6.62247 20.2531 8.36096 19.7092 9.04604 19.3919C9.15654 18.5987 9.46593 18.0548 9.80479 17.745C7.13812 17.4353 4.33886 16.3777 4.33886 11.6638C4.33886 10.3192 4.80295 9.2238 5.57643 8.36261C5.4512 8.05288 5.03867 6.79887 5.69429 5.1067C5.69429 5.1067 6.7035 4.77432 8.99447 6.36827C9.95212 6.09632 10.9761 5.96034 12 5.95279C13.0166 5.95279 14.0479 6.09632 15.0055 6.36827C17.2965 4.77432 18.3057 5.1067 18.3057 5.1067C18.9613 6.79887 18.5488 8.05288 18.4236 8.36261C19.1897 9.2238 19.6538 10.3192 19.6538 11.6638C19.6538 16.3928 16.8471 17.4278 14.1731 17.7375C14.6004 18.1152 14.9908 18.8706 14.9908 20.0189C14.9908 21.6657 14.9761 22.9877 14.9761 23.3957C14.9761 23.728 15.1897 24.1058 15.8011 23.9849C20.5672 22.3532 24 17.745 24 12.3135C24 5.50708 18.6298 0 12 0Z"
|
d="M12 0C5.37017 0 0 5.50708 0 12.306C0 17.745 3.44015 22.3532 8.20626 23.9849C8.80295 24.0982 9.02394 23.7205 9.02394 23.3881C9.02394 23.0935 9.01657 22.3229 9.00921 21.2956C5.67219 22.0359 4.96501 19.6487 4.96501 19.6487C4.41989 18.2285 3.63168 17.8508 3.63168 17.8508C2.54144 17.0878 3.71271 17.1029 3.71271 17.1029C4.91344 17.1936 5.55433 18.372 5.55433 18.372C6.62247 20.2531 8.36096 19.7092 9.04604 19.3919C9.15654 18.5987 9.46593 18.0548 9.80479 17.745C7.13812 17.4353 4.33886 16.3777 4.33886 11.6638C4.33886 10.3192 4.80295 9.2238 5.57643 8.36261C5.4512 8.05288 5.03867 6.79887 5.69429 5.1067C5.69429 5.1067 6.7035 4.77432 8.99447 6.36827C9.95212 6.09632 10.9761 5.96034 12 5.95279C13.0166 5.95279 14.0479 6.09632 15.0055 6.36827C17.2965 4.77432 18.3057 5.1067 18.3057 5.1067C18.9613 6.79887 18.5488 8.05288 18.4236 8.36261C19.1897 9.2238 19.6538 10.3192 19.6538 11.6638C19.6538 16.3928 16.8471 17.4278 14.1731 17.7375C14.6004 18.1152 14.9908 18.8706 14.9908 20.0189C14.9908 21.6657 14.9761 22.9877 14.9761 23.3957C14.9761 23.728 15.1897 24.1058 15.8011 23.9849C20.5672 22.3532 24 17.745 24 12.3135C24 5.50708 18.6298 0 12 0Z"
|
||||||
fill="#231E1B"
|
fill="currentColor"
|
||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
<defs>
|
<defs>
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import { useJsonColumnViewState } from "~/hooks/useJsonColumnView";
|
|||||||
import { concatenated, getHierarchicalTypes } from "~/utilities/dataType";
|
import { concatenated, getHierarchicalTypes } from "~/utilities/dataType";
|
||||||
import { formatRawValue } from "~/utilities/formatter";
|
import { formatRawValue } from "~/utilities/formatter";
|
||||||
import { isNullable } from "~/utilities/nullable";
|
import { isNullable } from "~/utilities/nullable";
|
||||||
|
import { CopyTextButton } from "./CopyTextButton";
|
||||||
import { Body } from "./Primitives/Body";
|
import { Body } from "./Primitives/Body";
|
||||||
import { LargeMono } from "./Primitives/LargeMono";
|
import { LargeMono } from "./Primitives/LargeMono";
|
||||||
import { Title } from "./Primitives/Title";
|
import { Title } from "./Primitives/Title";
|
||||||
import { ValueIcon, ValueIconSize } from "./ValueIcon";
|
import { ValueIcon, ValueIconSize } from "./ValueIcon";
|
||||||
import { CopyTextButton } from "./CopyTextButton";
|
|
||||||
|
|
||||||
export type InfoHeaderProps = {
|
export type InfoHeaderProps = {
|
||||||
relatedPaths: string[];
|
relatedPaths: string[];
|
||||||
@@ -41,12 +41,13 @@ export function InfoHeader({ relatedPaths }: InfoHeaderProps) {
|
|||||||
}, [relatedPaths, json]);
|
}, [relatedPaths, json]);
|
||||||
|
|
||||||
const [hovering, setHovering] = useState(false);
|
const [hovering, setHovering] = useState(false);
|
||||||
|
console.warn(selectedInfo);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-4 pb-4">
|
<div className="mb-4 pb-4">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<Title className="flex-1 mr-2 text-slate-700 transition dark:text-slate-200">
|
<Title className="flex-1 mr-2 overflow-hidden overflow-ellipsis break-words text-slate-700 transition dark:text-slate-200">
|
||||||
{selectedName ?? "nothing"}
|
{ selectedName ?? "nothing" }
|
||||||
</Title>
|
</Title>
|
||||||
<div>
|
<div>
|
||||||
<ValueIcon
|
<ValueIcon
|
||||||
|
|||||||
@@ -4,27 +4,25 @@ import { PropertiesValue } from "./Properties/PropertiesValue";
|
|||||||
import { InfoHeader } from "./InfoHeader";
|
import { InfoHeader } from "./InfoHeader";
|
||||||
import { ContainerInfo } from "./ContainerInfo";
|
import { ContainerInfo } from "./ContainerInfo";
|
||||||
import { useSelectedInfo } from "~/hooks/useSelectedInfo";
|
import { useSelectedInfo } from "~/hooks/useSelectedInfo";
|
||||||
import { useMemo } from "react";
|
|
||||||
import { useJson } from "~/hooks/useJson";
|
|
||||||
import { getRelatedPathsAtPath } from "~/utilities/relatedValues";
|
|
||||||
import { useJsonColumnViewState } from "~/hooks/useJsonColumnView";
|
|
||||||
import { useRelatedPaths } from "~/hooks/useRelatedPaths";
|
import { useRelatedPaths } from "~/hooks/useRelatedPaths";
|
||||||
|
import { useJsonDoc } from "~/hooks/useJsonDoc";
|
||||||
|
|
||||||
export function InfoPanel() {
|
export function InfoPanel() {
|
||||||
|
const { minimal } = useJsonDoc();
|
||||||
const selectedInfo = useSelectedInfo();
|
const selectedInfo = useSelectedInfo();
|
||||||
const { selectedNodeId } = useJsonColumnViewState();
|
|
||||||
const relatedPaths = useRelatedPaths();
|
const relatedPaths = useRelatedPaths();
|
||||||
|
|
||||||
if (!selectedInfo) {
|
if (!selectedInfo) {
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSelectedLeafNode =
|
|
||||||
selectedInfo.name !== "object" && selectedInfo.name !== "array";
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="h-inspectorHeight p-4 bg-white border-l-[1px] border-slate-300 overflow-y-auto no-scrollbar transition dark:bg-slate-800 dark:border-slate-600">
|
<div
|
||||||
|
className={`${
|
||||||
|
minimal ? "h-inspectorHeightMinimal" : "h-inspectorHeight"
|
||||||
|
} p-4 bg-white border-l-[1px] border-slate-300 overflow-y-auto no-scrollbar transition dark:bg-slate-800 dark:border-slate-600`}
|
||||||
|
>
|
||||||
<InfoHeader relatedPaths={relatedPaths} />
|
<InfoHeader relatedPaths={relatedPaths} />
|
||||||
|
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
@@ -34,7 +32,7 @@ export function InfoPanel() {
|
|||||||
|
|
||||||
<ContainerInfo />
|
<ContainerInfo />
|
||||||
|
|
||||||
{isSelectedLeafNode && <RelatedValues relatedPaths={relatedPaths} />}
|
<RelatedValues relatedPaths={relatedPaths} />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
} from "../hooks/useJsonColumnView";
|
} from "../hooks/useJsonColumnView";
|
||||||
import { useHotkeys } from "react-hotkeys-hook";
|
import { useHotkeys } from "react-hotkeys-hook";
|
||||||
import { Columns } from "./Columns";
|
import { Columns } from "./Columns";
|
||||||
|
import { CopySelectedNodeShortcut } from "./CopySelectedNode";
|
||||||
|
|
||||||
export function JsonColumnView() {
|
export function JsonColumnView() {
|
||||||
const { getColumnViewProps, columns } = useJsonColumnViewState();
|
const { getColumnViewProps, columns } = useJsonColumnViewState();
|
||||||
@@ -67,5 +68,7 @@ function KeyboardShortcuts() {
|
|||||||
[api]
|
[api]
|
||||||
);
|
);
|
||||||
|
|
||||||
return <></>;
|
return <>
|
||||||
|
<CopySelectedNodeShortcut />
|
||||||
|
</>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ export function JsonEditor() {
|
|||||||
<CodeEditor
|
<CodeEditor
|
||||||
language="json"
|
language="json"
|
||||||
content={jsonMapped.json}
|
content={jsonMapped.json}
|
||||||
readOnly={false}
|
readOnly={true}
|
||||||
onUpdate={onUpdate}
|
onUpdate={onUpdate}
|
||||||
selection={selection}
|
selection={selection}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import {
|
|||||||
useJsonColumnViewAPI,
|
useJsonColumnViewAPI,
|
||||||
useJsonColumnViewState,
|
useJsonColumnViewState,
|
||||||
} from "~/hooks/useJsonColumnView";
|
} from "~/hooks/useJsonColumnView";
|
||||||
|
import { useJsonDoc } from "~/hooks/useJsonDoc";
|
||||||
import { JsonTreeViewNode, useJsonTreeViewContext } from "~/hooks/useJsonTree";
|
import { JsonTreeViewNode, useJsonTreeViewContext } from "~/hooks/useJsonTree";
|
||||||
import { VirtualNode } from "~/hooks/useVirtualTree";
|
import { VirtualNode } from "~/hooks/useVirtualTree";
|
||||||
|
import { CopySelectedNodeShortcut } from "./CopySelectedNode";
|
||||||
import { Body } from "./Primitives/Body";
|
import { Body } from "./Primitives/Body";
|
||||||
import { Mono } from "./Primitives/Mono";
|
import { Mono } from "./Primitives/Mono";
|
||||||
|
|
||||||
@@ -77,32 +79,37 @@ export function JsonTreeView() {
|
|||||||
}
|
}
|
||||||
}, [treeRef.current]);
|
}, [treeRef.current]);
|
||||||
|
|
||||||
|
const { minimal } = useJsonDoc();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<>
|
||||||
className="text-white w-full"
|
<CopySelectedNodeShortcut />
|
||||||
ref={parentRef}
|
|
||||||
style={{
|
|
||||||
height: `calc(100vh - 106px)`,
|
|
||||||
overflowY: "auto",
|
|
||||||
overflowX: "hidden",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="relative w-full outline-none"
|
className="text-white w-full"
|
||||||
style={{ height: `${tree.totalSize}px` }}
|
ref={parentRef}
|
||||||
{...tree.getTreeProps()}
|
style={{
|
||||||
ref={treeRef}
|
height: `calc(100vh - ${minimal ? "66px" : "106px"})`,
|
||||||
|
overflowY: "auto",
|
||||||
|
overflowX: "hidden",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{tree.nodes.map((virtualNode) => (
|
<div
|
||||||
<TreeViewNode
|
className="relative w-full outline-none"
|
||||||
virtualNode={virtualNode}
|
style={{ height: `${tree.totalSize}px` }}
|
||||||
key={virtualNode.node.id}
|
{...tree.getTreeProps()}
|
||||||
onToggle={(node, e) => tree.toggleNode(node.id, e)}
|
ref={treeRef}
|
||||||
selectedNodeId={selectedNodeId}
|
>
|
||||||
/>
|
{tree.nodes.map((virtualNode) => (
|
||||||
))}
|
<TreeViewNode
|
||||||
|
virtualNode={virtualNode}
|
||||||
|
key={virtualNode.node.id}
|
||||||
|
onToggle={(node, e) => tree.toggleNode(node.id, e)}
|
||||||
|
selectedNodeId={selectedNodeId}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { useJsonColumnViewAPI } from "~/hooks/useJsonColumnView";
|
|||||||
import { ColumnViewNode, IconComponent } from "~/useColumnView";
|
import { ColumnViewNode, IconComponent } from "~/useColumnView";
|
||||||
import { Body } from "./Primitives/Body";
|
import { Body } from "./Primitives/Body";
|
||||||
|
|
||||||
|
import eyeIcon from "~/assets/svgs/EyeIcon.svg";
|
||||||
|
|
||||||
export type PathPreviewProps = {
|
export type PathPreviewProps = {
|
||||||
nodes: ColumnViewNode[];
|
nodes: ColumnViewNode[];
|
||||||
maxComponents?: number;
|
maxComponents?: number;
|
||||||
@@ -77,7 +79,7 @@ export function PathPreview({
|
|||||||
<div
|
<div
|
||||||
className={`flex select-none pl-7 ${
|
className={`flex select-none pl-7 ${
|
||||||
isEnabled
|
isEnabled
|
||||||
? "relative transition hover:bg-slate-200 hover:cursor-pointer dark:hover:bg-slate-600 after:transition after:absolute after:h-3 after:w-3 after:opacity-0 hover:after:opacity-100 after:top-1 after:left-1 after:content-[''] after:bg-[url('/svgs/EyeIcon.svg')] after:bg-no-repeat"
|
? `relative transition hover:bg-slate-200 hover:cursor-pointer dark:hover:bg-slate-600 after:transition after:absolute after:h-3 after:w-3 after:opacity-0 hover:after:opacity-100 after:top-1 after:left-1 after:content-[''] after:bg-[url('${eyeIcon}')] after:bg-no-repeat`
|
||||||
: "disabled"
|
: "disabled"
|
||||||
}`}
|
}`}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { useRef } from "react";
|
||||||
|
import { useHotkeys } from "react-hotkeys-hook";
|
||||||
|
import { Body } from "~/components/Primitives/Body";
|
||||||
|
import { PreviewBox } from "../PreviewBox";
|
||||||
|
|
||||||
|
export function PreviewAudioUri({
|
||||||
|
src,
|
||||||
|
contentType,
|
||||||
|
}: {
|
||||||
|
src: string;
|
||||||
|
contentType: string;
|
||||||
|
}) {
|
||||||
|
const mediaRef = useRef<HTMLMediaElement>(null);
|
||||||
|
|
||||||
|
useHotkeys(
|
||||||
|
"space",
|
||||||
|
(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (mediaRef.current) {
|
||||||
|
if (mediaRef.current.paused) {
|
||||||
|
mediaRef.current.play();
|
||||||
|
} else {
|
||||||
|
mediaRef.current.pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[mediaRef]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<PreviewBox>
|
||||||
|
<Body>
|
||||||
|
<audio controls src={src} ref={mediaRef}>
|
||||||
|
Sorry, your browser doesn't support embedded audio.
|
||||||
|
</audio>
|
||||||
|
</Body>
|
||||||
|
</PreviewBox>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { PreviewImageUri } from "./PreviewImageUri";
|
||||||
|
|
||||||
|
export function PreviewIPFSImage({ src }: { src: URL }) {
|
||||||
|
const newSrc = createPreviewIPFSImageURL(src);
|
||||||
|
|
||||||
|
return <PreviewImageUri src={newSrc} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const createPreviewIPFSImageURL = (src: URL): string => {
|
||||||
|
const url = new URL(src.href);
|
||||||
|
|
||||||
|
url.protocol = "https:";
|
||||||
|
url.pathname = `/ipfs/${src.pathname.substring(1)}`;
|
||||||
|
url.hostname = "ipfs.io";
|
||||||
|
// Remove the leading slash
|
||||||
|
|
||||||
|
return url.href;
|
||||||
|
};
|
||||||
@@ -6,11 +6,11 @@ export function PreviewImageUri({
|
|||||||
contentType,
|
contentType,
|
||||||
}: {
|
}: {
|
||||||
src: string;
|
src: string;
|
||||||
contentType: string;
|
contentType?: string;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<PreviewBox>
|
<PreviewBox link={src}>
|
||||||
<Body>
|
<Body>
|
||||||
<img src={src} />
|
<img src={src} />
|
||||||
</Body>
|
</Body>
|
||||||
|
|||||||
@@ -6,9 +6,12 @@ import {
|
|||||||
import Color from "color";
|
import Color from "color";
|
||||||
import { CodeViewer } from "~/components/CodeViewer";
|
import { CodeViewer } from "~/components/CodeViewer";
|
||||||
import { PreviewBox } from "../PreviewBox";
|
import { PreviewBox } from "../PreviewBox";
|
||||||
|
import { PreviewAudioUri } from "./PreviewAudioUri";
|
||||||
import { PreviewDate } from "./PreviewDate";
|
import { PreviewDate } from "./PreviewDate";
|
||||||
import { PreviewImageUri } from "./PreviewImageUri";
|
import { PreviewImageUri } from "./PreviewImageUri";
|
||||||
|
import { PreviewIPFSImage } from "./PreviewIPFSImage";
|
||||||
import { PreviewUri } from "./PreviewUri";
|
import { PreviewUri } from "./PreviewUri";
|
||||||
|
import { PreviewVideoUri } from "./PreviewVideoUri";
|
||||||
|
|
||||||
export function PreviewString({ info }: { info: JSONStringType }) {
|
export function PreviewString({ info }: { info: JSONStringType }) {
|
||||||
if (info.format == null) {
|
if (info.format == null) {
|
||||||
@@ -23,9 +26,37 @@ export function PreviewString({ info }: { info: JSONStringType }) {
|
|||||||
info.format.contentType === "image/gif" ||
|
info.format.contentType === "image/gif" ||
|
||||||
info.format.contentType === "image/svg+xml" ||
|
info.format.contentType === "image/svg+xml" ||
|
||||||
info.format.contentType === "image/webp"
|
info.format.contentType === "image/webp"
|
||||||
|
) {
|
||||||
|
const url = new URL(info.value);
|
||||||
|
|
||||||
|
if (url.protocol === "ipfs:") {
|
||||||
|
return <PreviewIPFSImage src={url} />;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<PreviewImageUri
|
||||||
|
src={info.value}
|
||||||
|
contentType={info.format.contentType}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
info.format.contentType === "video/mp4" ||
|
||||||
|
info.format.contentType === "video/webm" ||
|
||||||
|
info.format.contentType === "video/ogg"
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<PreviewImageUri
|
<PreviewVideoUri
|
||||||
|
src={info.value}
|
||||||
|
contentType={info.format.contentType}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else if (
|
||||||
|
info.format.contentType === "audio/mpeg" ||
|
||||||
|
info.format.contentType === "audio/ogg" ||
|
||||||
|
info.format.contentType === "audio/wav"
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<PreviewAudioUri
|
||||||
src={info.value}
|
src={info.value}
|
||||||
contentType={info.format.contentType}
|
contentType={info.format.contentType}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -23,7 +23,15 @@ export function PreviewUri(props: PreviewUriProps) {
|
|||||||
<div>
|
<div>
|
||||||
{previewFetcher.type === "done" ? (
|
{previewFetcher.type === "done" ? (
|
||||||
<>
|
<>
|
||||||
{"error" in previewFetcher.data ? (
|
{typeof previewFetcher.data == "string" ? (
|
||||||
|
<PreviewBox>
|
||||||
|
<Body>
|
||||||
|
<span
|
||||||
|
dangerouslySetInnerHTML={{ __html: previewFetcher.data }}
|
||||||
|
></span>
|
||||||
|
</Body>
|
||||||
|
</PreviewBox>
|
||||||
|
) : "error" in previewFetcher.data ? (
|
||||||
<PreviewBox>
|
<PreviewBox>
|
||||||
<Body>{previewFetcher.data.error}</Body>
|
<Body>{previewFetcher.data.error}</Body>
|
||||||
</PreviewBox>
|
</PreviewBox>
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { useRef } from "react";
|
||||||
|
import { useHotkeys } from "react-hotkeys-hook";
|
||||||
|
import { Body } from "~/components/Primitives/Body";
|
||||||
|
import { PreviewBox } from "../PreviewBox";
|
||||||
|
|
||||||
|
export function PreviewVideoUri({
|
||||||
|
src,
|
||||||
|
contentType,
|
||||||
|
}: {
|
||||||
|
src: string;
|
||||||
|
contentType: string;
|
||||||
|
}) {
|
||||||
|
const videoRef = useRef<HTMLVideoElement>(null);
|
||||||
|
|
||||||
|
useHotkeys(
|
||||||
|
"space",
|
||||||
|
(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (videoRef.current) {
|
||||||
|
if (videoRef.current.paused) {
|
||||||
|
videoRef.current.play();
|
||||||
|
} else {
|
||||||
|
videoRef.current.pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[videoRef]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<PreviewBox>
|
||||||
|
<Body>
|
||||||
|
<video key={src} controls ref={videoRef}>
|
||||||
|
<source src={src} type={contentType} />
|
||||||
|
Sorry, your browser doesn't support embedded videos.
|
||||||
|
</video>
|
||||||
|
</Body>
|
||||||
|
</PreviewBox>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,31 +1,28 @@
|
|||||||
|
import { ExampleDoc } from "./ExampleDoc";
|
||||||
import { ExampleUrl } from "./ExampleUrl";
|
import { ExampleUrl } from "./ExampleUrl";
|
||||||
|
|
||||||
export function SampleUrls() {
|
export function SampleUrls() {
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-start flex-wrap gap-2">
|
<div className="flex justify-start flex-wrap gap-2">
|
||||||
<ExampleUrl
|
<ExampleDoc
|
||||||
url="https://gist.githubusercontent.com/ericallam/332aca65c34dbc0fdb1b3cffbdf3f7a4/raw/4c6e264c3afd3432b608bad628290a7d71035253/unsplash.json"
|
id="xW6aDgcbKgwC"
|
||||||
title="Unsplash API Example"
|
title="Unsplash API"
|
||||||
displayTitle="Unsplash API"
|
path="4.urls.regular"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ExampleUrl
|
<ExampleDoc
|
||||||
url="https://gist.githubusercontent.com/ericallam/77e37e93e370b32387ce8d598dd06fc8/raw/9306a2c039fc27ab42bdadb80cbd6dbca49d27ec/tweet.json"
|
id="d9udW60cLOok"
|
||||||
title="Tweet API Example"
|
title="Tweet JSON"
|
||||||
displayTitle="Tweet JSON"
|
path="data.0.entities.urls.0.expanded_url"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ExampleUrl
|
<ExampleDoc
|
||||||
url="https://gist.githubusercontent.com/ericallam/f11f4981adf72b0427427c349afb3a09/raw/37eee4234b628f3278c9d4f644fee4a1c4987593/Airtable.json"
|
id="JZw4Wx9Mgj6r"
|
||||||
title="Airtable Product Catalog"
|
title="Airtable API"
|
||||||
displayTitle="Airtable API"
|
path="records.3.createdTime"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ExampleUrl
|
<ExampleDoc id="PjHo1o5MVeH4" title="Github API" />
|
||||||
url="https://gist.githubusercontent.com/ericallam/51b77c0051c21a34ea33d601bb0b1bef/raw/0b099f7d3bb5fe47f1fd55007d6a5fe9c5fd046b/GitHub.json"
|
|
||||||
title="List of Github Repos"
|
|
||||||
displayTitle="Github API"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useJsonDoc } from "~/hooks/useJsonDoc";
|
|||||||
import { ToolTip } from "./ToolTip";
|
import { ToolTip } from "./ToolTip";
|
||||||
import { Body } from "./Primitives/Body";
|
import { Body } from "./Primitives/Body";
|
||||||
import { ShortcutIcon } from "./Icons/ShortcutIcon";
|
import { ShortcutIcon } from "./Icons/ShortcutIcon";
|
||||||
|
import { useTheme } from "./ThemeProvider";
|
||||||
|
|
||||||
export function SideBar() {
|
export function SideBar() {
|
||||||
const { doc } = useJsonDoc();
|
const { doc } = useJsonDoc();
|
||||||
@@ -81,6 +82,23 @@ function SidebarLink({
|
|||||||
|
|
||||||
const isActive = location.pathname === to;
|
const isActive = location.pathname === to;
|
||||||
|
|
||||||
|
const { minimal } = useJsonDoc();
|
||||||
|
const [theme] = useTheme();
|
||||||
|
|
||||||
|
const queryParams = new URLSearchParams();
|
||||||
|
|
||||||
|
if (typeof minimal === "boolean") {
|
||||||
|
queryParams.set("minimal", String(minimal));
|
||||||
|
|
||||||
|
if (theme) {
|
||||||
|
queryParams.set("theme", theme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const href = `${to}${
|
||||||
|
queryParams.toString().length > 0 ? `?${queryParams.toString()}` : ""
|
||||||
|
}`;
|
||||||
|
|
||||||
if (hotKey) {
|
if (hotKey) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
@@ -88,7 +106,7 @@ function SidebarLink({
|
|||||||
(e) => {
|
(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!isActive && to) {
|
if (!isActive && to) {
|
||||||
navigate(to);
|
navigate(href);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[navigate, isActive, to]
|
[navigate, isActive, to]
|
||||||
@@ -100,7 +118,7 @@ function SidebarLink({
|
|||||||
: "relative w-10 h-10 mb-1 text-slate-700 hover:bg-slate-300 rounded-sm cursor:pointer transition dark:text-white dark:hover:bg-slate-700";
|
: "relative w-10 h-10 mb-1 text-slate-700 hover:bg-slate-300 rounded-sm cursor:pointer transition dark:text-white dark:hover:bg-slate-700";
|
||||||
|
|
||||||
return !!to ? (
|
return !!to ? (
|
||||||
<Link to={to} prefetch={isActive ? "none" : "render"}>
|
<Link to={href} prefetch={isActive ? "none" : "render"}>
|
||||||
<li className={classes}>{children}</li>
|
<li className={classes}>{children}</li>
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -15,8 +15,10 @@ export function ThemeModeToggler() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={`flex text-xl items-center pr-2 ${
|
className={`flex text-xl items-center px-2 py-1.5 transition ${
|
||||||
theme === "light" ? "text-slate-800" : "text-white"
|
theme === "light"
|
||||||
|
? "text-slate-800 hover:bg-slate-300"
|
||||||
|
: "text-white hover:bg-slate-700"
|
||||||
}`}
|
}`}
|
||||||
onClick={toggleTheme}
|
onClick={toggleTheme}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { formatStarCount } from "~/utilities/formatStarCount";
|
||||||
|
import { GithubIconSimple } from "../Icons/GithubIconSimple";
|
||||||
|
import { Body } from "../Primitives/Body";
|
||||||
|
import { useStarCount } from "../StarCountProvider";
|
||||||
|
|
||||||
|
export type GithubStarSmallProps = {
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function GithubStarSmall({ className }: GithubStarSmallProps) {
|
||||||
|
const starCount = useStarCount();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href="https://github.com/jsonhero-io/jsonhero-web"
|
||||||
|
target="_blank"
|
||||||
|
className="flex p-1 text-slate-700 dark:text-slate-300 hover:bg-slate-300 dark:hover:bg-slate-700 transition hover:cursor-pointer"
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-1.5 pl-1 rounded-l-sm">
|
||||||
|
<GithubIconSimple className="w-4 h-4 ml-1 text-slate-700 dark:text-white transition"></GithubIconSimple>
|
||||||
|
<Body className="font-semibold text-slate-800 dark:text-slate-100">
|
||||||
|
Star
|
||||||
|
</Body>
|
||||||
|
</div>
|
||||||
|
{starCount && (
|
||||||
|
<div className="pr-2 pl-1">
|
||||||
|
<Body className="font-bold dark:text-slate-100">
|
||||||
|
{formatStarCount(starCount)}
|
||||||
|
</Body>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import { JSONDocument } from "~/jsonDoc.server";
|
|||||||
type JsonDocType = {
|
type JsonDocType = {
|
||||||
doc: JSONDocument;
|
doc: JSONDocument;
|
||||||
path?: string;
|
path?: string;
|
||||||
|
minimal?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const JsonDocContext = createContext<JsonDocType | undefined>(undefined);
|
const JsonDocContext = createContext<JsonDocType | undefined>(undefined);
|
||||||
@@ -13,13 +14,15 @@ export function JsonDocProvider({
|
|||||||
children,
|
children,
|
||||||
doc,
|
doc,
|
||||||
path,
|
path,
|
||||||
|
minimal,
|
||||||
}: {
|
}: {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
doc: JSONDocument;
|
doc: JSONDocument;
|
||||||
path?: string;
|
path?: string;
|
||||||
|
minimal?: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<JsonDocContext.Provider value={{ doc, path }}>
|
<JsonDocContext.Provider value={{ doc, path, minimal }}>
|
||||||
{children}
|
{children}
|
||||||
</JsonDocContext.Provider>
|
</JsonDocContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { customRandom } from "nanoid";
|
import { customRandom } from "nanoid";
|
||||||
|
import safeFetch from "./utilities/safeFetch";
|
||||||
|
|
||||||
type BaseJsonDocument = {
|
type BaseJsonDocument = {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
readOnly: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RawJsonDocument = BaseJsonDocument & {
|
export type RawJsonDocument = BaseJsonDocument & {
|
||||||
@@ -17,6 +19,8 @@ export type UrlJsonDocument = BaseJsonDocument & {
|
|||||||
|
|
||||||
export type CreateJsonOptions = {
|
export type CreateJsonOptions = {
|
||||||
ttl?: number;
|
ttl?: number;
|
||||||
|
readOnly?: boolean;
|
||||||
|
injest?: boolean;
|
||||||
metadata?: any;
|
metadata?: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -37,17 +41,33 @@ export async function createFromUrlOrRawJson(
|
|||||||
|
|
||||||
export async function createFromUrl(
|
export async function createFromUrl(
|
||||||
url: URL,
|
url: URL,
|
||||||
title?: string
|
title?: string,
|
||||||
|
options?: CreateJsonOptions
|
||||||
): Promise<JSONDocument> {
|
): Promise<JSONDocument> {
|
||||||
|
if (options?.injest) {
|
||||||
|
const response = await safeFetch(url.href);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Failed to injest ${url.href}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return createFromRawJson(title || url.href, await response.text(), options);
|
||||||
|
}
|
||||||
|
|
||||||
const docId = createId();
|
const docId = createId();
|
||||||
const doc = {
|
|
||||||
|
const doc: JSONDocument = {
|
||||||
id: docId,
|
id: docId,
|
||||||
type: <const>"url",
|
type: <const>"url",
|
||||||
url: url.href,
|
url: url.href,
|
||||||
title: title ?? url.hostname,
|
title: title ?? url.hostname,
|
||||||
|
readOnly: options?.readOnly ?? false,
|
||||||
};
|
};
|
||||||
|
|
||||||
await DOCUMENTS.put(docId, JSON.stringify(doc));
|
await DOCUMENTS.put(docId, JSON.stringify(doc), {
|
||||||
|
expirationTtl: options?.ttl ?? undefined,
|
||||||
|
metadata: options?.metadata ?? undefined,
|
||||||
|
});
|
||||||
|
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
@@ -58,7 +78,13 @@ export async function createFromRawJson(
|
|||||||
options?: CreateJsonOptions
|
options?: CreateJsonOptions
|
||||||
): Promise<JSONDocument> {
|
): Promise<JSONDocument> {
|
||||||
const docId = createId();
|
const docId = createId();
|
||||||
const doc = { id: docId, type: <const>"raw", contents, title: filename };
|
const doc: JSONDocument = {
|
||||||
|
id: docId,
|
||||||
|
type: <const>"raw",
|
||||||
|
contents,
|
||||||
|
title: filename,
|
||||||
|
readOnly: options?.readOnly ?? false,
|
||||||
|
};
|
||||||
|
|
||||||
await DOCUMENTS.put(docId, JSON.stringify(doc), {
|
await DOCUMENTS.put(docId, JSON.stringify(doc), {
|
||||||
expirationTtl: options?.ttl ?? undefined,
|
expirationTtl: options?.ttl ?? undefined,
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ import {
|
|||||||
useTheme,
|
useTheme,
|
||||||
} from "~/components/ThemeProvider";
|
} from "~/components/ThemeProvider";
|
||||||
|
|
||||||
|
import openGraphImage from "~/assets/images/opengraph.png";
|
||||||
|
|
||||||
export const meta: MetaFunction = ({ location }) => {
|
export const meta: MetaFunction = ({ location }) => {
|
||||||
const description =
|
const description =
|
||||||
"JSON Hero makes reading and understand JSON files easy by giving you a clean and beautiful UI packed with extra features.";
|
"JSON Hero makes reading and understand JSON files easy by giving you a clean and beautiful UI packed with extra features.";
|
||||||
@@ -25,11 +27,11 @@ export const meta: MetaFunction = ({ location }) => {
|
|||||||
title: "JSON Viewer - JSON Hero",
|
title: "JSON Viewer - JSON Hero",
|
||||||
viewport: "width=device-width,initial-scale=1",
|
viewport: "width=device-width,initial-scale=1",
|
||||||
description,
|
description,
|
||||||
"og:image": `https://jsonhero.io/images/opengraph.png`,
|
"og:image": `https://jsonhero.io${openGraphImage}`,
|
||||||
"og:url": `https://jsonhero.io${location.pathname}`,
|
"og:url": `https://jsonhero.io${location.pathname}`,
|
||||||
"og:title": "JSON Hero - A beautiful JSON viewer",
|
"og:title": "JSON Hero - A beautiful JSON viewer",
|
||||||
"og:description": description,
|
"og:description": description,
|
||||||
"twitter:image": "https://jsonhero.io/images/opengraph.png",
|
"twitter:image": `https://jsonhero.io${openGraphImage}`,
|
||||||
"twitter:card": "summary_large_image",
|
"twitter:card": "summary_large_image",
|
||||||
"twitter:creator": "@json_hero",
|
"twitter:creator": "@json_hero",
|
||||||
"twitter:site": "@json_hero",
|
"twitter:site": "@json_hero",
|
||||||
@@ -50,20 +52,32 @@ export function links() {
|
|||||||
export type LoaderData = {
|
export type LoaderData = {
|
||||||
theme?: Theme;
|
theme?: Theme;
|
||||||
starCount?: number;
|
starCount?: number;
|
||||||
|
themeOverride?: Theme;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const loader: LoaderFunction = async ({ request }) => {
|
export const loader: LoaderFunction = async ({ request }) => {
|
||||||
const themeSession = await getThemeSession(request);
|
const themeSession = await getThemeSession(request);
|
||||||
const starCount = await getStarCount();
|
const starCount = await getStarCount();
|
||||||
|
const themeOverride = getThemeFromRequest(request);
|
||||||
|
|
||||||
const data: LoaderData = {
|
const data: LoaderData = {
|
||||||
theme: themeSession.getTheme(),
|
theme: themeSession.getTheme(),
|
||||||
starCount,
|
starCount,
|
||||||
|
themeOverride,
|
||||||
};
|
};
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getThemeFromRequest(request: Request): Theme | undefined {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
const theme = url.searchParams.get("theme");
|
||||||
|
if (theme) {
|
||||||
|
return theme as Theme;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [theme] = useTheme();
|
const [theme] = useTheme();
|
||||||
|
|
||||||
@@ -86,7 +100,7 @@ function App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function AppWithProviders() {
|
export default function AppWithProviders() {
|
||||||
const { theme, starCount } = useLoaderData<LoaderData>();
|
const { theme, starCount, themeOverride } = useLoaderData<LoaderData>();
|
||||||
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
@@ -96,7 +110,7 @@ export default function AppWithProviders() {
|
|||||||
return (
|
return (
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
specifiedTheme={theme}
|
specifiedTheme={theme}
|
||||||
themeOverride={forceDarkMode ? "dark" : undefined}
|
themeOverride={forceDarkMode ? "dark" : themeOverride}
|
||||||
>
|
>
|
||||||
<StarCountProvider starCount={starCount}>
|
<StarCountProvider starCount={starCount}>
|
||||||
<App />
|
<App />
|
||||||
|
|||||||
@@ -1,8 +1,22 @@
|
|||||||
import { ActionFunction, json } from "remix";
|
import { ActionFunction, json, LoaderFunction } from "remix";
|
||||||
import invariant from "tiny-invariant";
|
import invariant from "tiny-invariant";
|
||||||
import { sendEvent } from "~/graphJSON.server";
|
import { sendEvent } from "~/graphJSON.server";
|
||||||
import { createFromRawJson, CreateJsonOptions } from "~/jsonDoc.server";
|
import { createFromRawJson, CreateJsonOptions } from "~/jsonDoc.server";
|
||||||
|
|
||||||
|
export const loader: LoaderFunction = async ({ request }) => {
|
||||||
|
if (request.method === "OPTIONS") {
|
||||||
|
return new Response(null, {
|
||||||
|
status: 204,
|
||||||
|
headers: {
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
"Access-Control-Allow-Methods": "POST",
|
||||||
|
"Access-Control-Allow-Headers": "Content-Type",
|
||||||
|
"Access-Control-Max-Age": "86400",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const action: ActionFunction = async ({ request, context }) => {
|
export const action: ActionFunction = async ({ request, context }) => {
|
||||||
const url = new URL(request.url);
|
const url = new URL(request.url);
|
||||||
|
|
||||||
@@ -42,5 +56,12 @@ export const action: ActionFunction = async ({ request, context }) => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
return json({ id: doc.id, title, location: url.toString() });
|
return json(
|
||||||
|
{ id: doc.id, title, location: url.toString() },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { GithubBanner } from "~/components/Home/HomeGithubBanner";
|
|||||||
export default function Index() {
|
export default function Index() {
|
||||||
return (
|
return (
|
||||||
<div className="overflow-x-hidden">
|
<div className="overflow-x-hidden">
|
||||||
<HomeHeader />
|
<HomeHeader fixed={true} />
|
||||||
<HomeHeroSection />
|
<HomeHeroSection />
|
||||||
<GithubBanner />
|
<GithubBanner />
|
||||||
<HomeInfoBoxSection />
|
<HomeInfoBoxSection />
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export const loader: LoaderFunction = async ({ params, request }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const path = getPathFromRequest(request);
|
const path = getPathFromRequest(request);
|
||||||
|
const minimal = getMinimalFromRequest(request);
|
||||||
|
|
||||||
if (doc.type == "url") {
|
if (doc.type == "url") {
|
||||||
console.log(`Fetching ${doc.url}...`);
|
console.log(`Fetching ${doc.url}...`);
|
||||||
@@ -48,6 +49,10 @@ export const loader: LoaderFunction = async ({ params, request }) => {
|
|||||||
const jsonResponse = await safeFetch(doc.url);
|
const jsonResponse = await safeFetch(doc.url);
|
||||||
|
|
||||||
if (!jsonResponse.ok) {
|
if (!jsonResponse.ok) {
|
||||||
|
console.log(
|
||||||
|
`Failed to fetch ${doc.url}: ${jsonResponse.status} (${jsonResponse.statusText})`
|
||||||
|
);
|
||||||
|
|
||||||
throw new Response(jsonResponse.statusText, {
|
throw new Response(jsonResponse.statusText, {
|
||||||
status: jsonResponse.status,
|
status: jsonResponse.status,
|
||||||
});
|
});
|
||||||
@@ -55,16 +60,20 @@ export const loader: LoaderFunction = async ({ params, request }) => {
|
|||||||
|
|
||||||
const json = await jsonResponse.json();
|
const json = await jsonResponse.json();
|
||||||
|
|
||||||
|
console.log(`Fetched ${doc.url} with json, returning...`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
doc,
|
doc,
|
||||||
json,
|
json,
|
||||||
path,
|
path,
|
||||||
|
minimal,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
doc,
|
doc,
|
||||||
json: JSON.parse(doc.contents),
|
json: JSON.parse(doc.contents),
|
||||||
path,
|
path,
|
||||||
|
minimal,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -85,7 +94,24 @@ function getPathFromRequest(request: Request): string | null {
|
|||||||
return `$.${path}`;
|
return `$.${path}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
type LoaderData = { doc: JSONDocument; json: unknown; path?: string };
|
function getMinimalFromRequest(request: Request): boolean | undefined {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
|
||||||
|
const minimal = url.searchParams.get("minimal");
|
||||||
|
|
||||||
|
if (!minimal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return minimal === "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoaderData = {
|
||||||
|
doc: JSONDocument;
|
||||||
|
json: unknown;
|
||||||
|
path?: string;
|
||||||
|
minimal?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export const meta: MetaFunction = ({
|
export const meta: MetaFunction = ({
|
||||||
data,
|
data,
|
||||||
@@ -118,6 +144,7 @@ export default function JsonDocumentRoute() {
|
|||||||
doc={loaderData.doc}
|
doc={loaderData.doc}
|
||||||
path={loaderData.path}
|
path={loaderData.path}
|
||||||
key={loaderData.doc.id}
|
key={loaderData.doc.id}
|
||||||
|
minimal={loaderData.minimal}
|
||||||
>
|
>
|
||||||
<JsonProvider initialJson={loaderData.json}>
|
<JsonProvider initialJson={loaderData.json}>
|
||||||
<JsonSchemaProvider>
|
<JsonSchemaProvider>
|
||||||
@@ -125,7 +152,7 @@ export default function JsonDocumentRoute() {
|
|||||||
<JsonSearchProvider>
|
<JsonSearchProvider>
|
||||||
<JsonTreeViewProvider overscan={25}>
|
<JsonTreeViewProvider overscan={25}>
|
||||||
<div>
|
<div>
|
||||||
<div className="block sm:hidden fixed bg-black/80 h-screen w-screen z-50 text-white">
|
<div className="block md:hidden fixed bg-black/80 h-screen w-screen z-50 text-white">
|
||||||
<div className="flex flex-col items-center justify-center h-full text-center">
|
<div className="flex flex-col items-center justify-center h-full text-center">
|
||||||
<LargeTitle>JSON Hero only works on desktop</LargeTitle>
|
<LargeTitle>JSON Hero only works on desktop</LargeTitle>
|
||||||
<LargeTitle>👇</LargeTitle>
|
<LargeTitle>👇</LargeTitle>
|
||||||
@@ -139,7 +166,7 @@ export default function JsonDocumentRoute() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-screen flex flex-col sm:overflow-hidden">
|
<div className="h-screen flex flex-col sm:overflow-hidden">
|
||||||
<Header />
|
{!loaderData.minimal && <Header />}
|
||||||
<div className="bg-slate-50 flex-grow transition dark:bg-slate-900">
|
<div className="bg-slate-50 flex-grow transition dark:bg-slate-900">
|
||||||
<div className="main-container flex justify-items-stretch h-full">
|
<div className="main-container flex justify-items-stretch h-full">
|
||||||
<SideBar />
|
<SideBar />
|
||||||
|
|||||||
@@ -1,23 +1,49 @@
|
|||||||
import { LoaderFunction, redirect } from "remix";
|
import { json, LoaderFunction, redirect } from "remix";
|
||||||
import invariant from "tiny-invariant";
|
import invariant from "tiny-invariant";
|
||||||
import { sendEvent } from "~/graphJSON.server";
|
import { sendEvent } from "~/graphJSON.server";
|
||||||
import { createFromRawJson, createFromUrl } from "~/jsonDoc.server";
|
import {
|
||||||
|
createFromRawJson,
|
||||||
|
createFromUrl,
|
||||||
|
CreateJsonOptions,
|
||||||
|
} from "~/jsonDoc.server";
|
||||||
|
|
||||||
export let loader: LoaderFunction = async ({ request, context }) => {
|
export let loader: LoaderFunction = async ({ request, context }) => {
|
||||||
const url = new URL(request.url);
|
const url = new URL(request.url);
|
||||||
const jsonUrl = url.searchParams.get("url");
|
const jsonUrl = url.searchParams.get("url");
|
||||||
const base64EncodedJson = url.searchParams.get("j");
|
const base64EncodedJson = url.searchParams.get("j");
|
||||||
|
const ttl = url.searchParams.get("ttl");
|
||||||
|
const readOnly = url.searchParams.get("readonly");
|
||||||
|
const title = url.searchParams.get("title");
|
||||||
|
const injest = url.searchParams.get("injest");
|
||||||
|
|
||||||
if (!jsonUrl && !base64EncodedJson) {
|
if (!jsonUrl && !base64EncodedJson) {
|
||||||
return redirect("/");
|
return redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const options: CreateJsonOptions = {};
|
||||||
|
|
||||||
|
if (typeof ttl === "string") {
|
||||||
|
invariant(ttl.match(/^\d+$/), "ttl must be a number");
|
||||||
|
|
||||||
|
options.ttl = parseInt(ttl, 10);
|
||||||
|
|
||||||
|
invariant(options.ttl >= 60, "ttl must be at least 60 seconds");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof readOnly === "string") {
|
||||||
|
options.readOnly = readOnly === "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof injest === "string") {
|
||||||
|
options.injest = injest === "true";
|
||||||
|
}
|
||||||
|
|
||||||
if (jsonUrl) {
|
if (jsonUrl) {
|
||||||
const jsonURL = new URL(jsonUrl);
|
const jsonURL = new URL(jsonUrl);
|
||||||
|
|
||||||
invariant(jsonURL, "url must be a valid URL");
|
invariant(jsonURL, "url must be a valid URL");
|
||||||
|
|
||||||
const doc = await createFromUrl(jsonURL, jsonURL.href);
|
const doc = await createFromUrl(jsonURL, title ?? jsonURL.href, options);
|
||||||
|
|
||||||
context.waitUntil(
|
context.waitUntil(
|
||||||
sendEvent({
|
sendEvent({
|
||||||
@@ -33,7 +59,11 @@ export let loader: LoaderFunction = async ({ request, context }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (base64EncodedJson) {
|
if (base64EncodedJson) {
|
||||||
const doc = await createFromRawJson("Untitled", atob(base64EncodedJson));
|
const doc = await createFromRawJson(
|
||||||
|
title ?? "Untitled",
|
||||||
|
atob(base64EncodedJson),
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
context.waitUntil(
|
context.waitUntil(
|
||||||
sendEvent({
|
sendEvent({
|
||||||
|
|||||||
@@ -0,0 +1,310 @@
|
|||||||
|
---
|
||||||
|
meta:
|
||||||
|
title: JSON Hero - Privacy
|
||||||
|
---
|
||||||
|
|
||||||
|
import { HomeHeader } from "~/components/Home/HomeHeader";
|
||||||
|
|
||||||
|
<HomeHeader />
|
||||||
|
|
||||||
|
<div style={{width: "800px", marginLeft: "12px", marginTop: "12px", marginBottom: "12px"}}>
|
||||||
|
**PRIVACY NOTICE**
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### Last updated June 01, 2022
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
This privacy notice for Stack Hero Limited ("Company," "we," "us," or "our"), describes how and why we might collect, store, use, and/or share ("process") your information when you use our services ("Services"), such as when you:
|
||||||
|
Visit our website at https://jsonhero.io, or any website of ours that links to this privacy notice
|
||||||
|
Engage with us in other related ways, including any sales, marketing, or events
|
||||||
|
Questions or concerns? Reading this privacy notice will help you understand your privacy rights and choices. If you do not agree with our policies and practices, please do not use our Services. If you still have any questions or concerns, please contact us at hello@jsonhero.io.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
**SUMMARY OF KEY POINTS**
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
This summary provides key points from our privacy notice, but you can find out more details about any of these topics by clicking the link following each key point or by using our table of contents below to find the section you are looking for. You can also click here to go directly to our table of contents.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
What personal information do we process? When you visit, use, or navigate our Services, we may process personal information depending on how you interact with Stack Hero Limited and the Services, the choices you make, and the products and features you use. Click here to learn more.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Do we process any sensitive personal information? We may process sensitive personal information when necessary with your consent or as otherwise permitted by applicable law. Click here to learn more.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Do we receive any information from third parties? We do not receive any information from third parties.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
How do we process your information? We process your information to provide, improve, and administer our Services, communicate with you, for security and fraud prevention, and to comply with law. We may also process your information for other purposes with your consent. We process your information only when we have a valid legal reason to do so. Click here to learn more.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
In what situations and with which parties do we share personal information? We may share information in specific situations and with specific third parties. Click here to learn more.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
How do we keep your information safe? We have organizational and technical processes and procedures in place to protect your personal information. However, no electronic transmission over the internet or information storage technology can be guaranteed to be 100% secure, so we cannot promise or guarantee that hackers, cybercriminals, or other unauthorized third parties will not be able to defeat our security and improperly collect, access, steal, or modify your information. Click here to learn more.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
What are your rights? Depending on where you are located geographically, the applicable privacy law may mean you have certain rights regarding your personal information. Click here to learn more.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
How do I exercise my rights? The easiest way to exercise your rights is by filling out our data subject request form available here: hello@jsonhero.io, or by contacting us. We will consider and act upon any request in accordance with applicable data protection laws.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Want to learn more about what Stack Hero Limited does with any information we collect? Click here to review the notice in full.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
**1. WHAT INFORMATION DO WE COLLECT?**
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
In Short: We collect personal information that you provide to us.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
We collect personal information that you voluntarily provide to us when you express an interest in obtaining information about us or our products and Services, when you participate in activities on the Services, or otherwise when you contact us.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Sensitive Information. When necessary, with your consent or as otherwise permitted by applicable law, we process the following categories of sensitive information:
|
||||||
|
All personal information that you provide to us must be true, complete, and accurate, and you must notify us of any changes to such personal information.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Information automatically collected
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
In Short: Some information — such as your Internet Protocol (IP) address and/or browser and device characteristics — is collected automatically when you visit our Services.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
We automatically collect certain information when you visit, use, or navigate the Services. This information does not reveal your specific identity (like your name or contact information) but may include device and usage information, such as your IP address, browser and device characteristics, operating system, language preferences, referring URLs, device name, country, location, information about how and when you use our Services, and other technical information. This information is primarily needed to maintain the security and operation of our Services, and for our internal analytics and reporting purposes.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Like many businesses, we also collect information through cookies and similar technologies.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
The information we collect includes:
|
||||||
|
Log and Usage Data. Log and usage data is service-related, diagnostic, usage, and performance information our servers automatically collect when you access or use our Services and which we record in log files. Depending on how you interact with us, this log data may include your IP address, device information, browser type, and settings and information about your activity in the Services (such as the date/time stamps associated with your usage, pages and files viewed, searches, and other actions you take such as which features you use), device event information (such as system activity, error reports (sometimes called "crash dumps"), and hardware settings).
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
**2. HOW DO WE PROCESS YOUR INFORMATION?**
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
In Short: We process your information to provide, improve, and administer our Services, communicate with you, for security and fraud prevention, and to comply with law. We may also process your information for other purposes with your consent.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
We process your personal information for a variety of reasons, depending on how you interact with our Services, including:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
To save or protect an individual's vital interest. We may process your information when necessary to save or protect an individual’s vital interest, such as to prevent harm.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
**3. WHAT LEGAL BASES DO WE RELY ON TO PROCESS YOUR INFORMATION?**
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
In Short: We only process your personal information when we believe it is necessary and we have a valid legal reason (i.e., legal basis) to do so under applicable law, like with your consent, to comply with laws, to provide you with services to enter into or fulfill our contractual obligations, to protect your rights, or to fulfill our legitimate business interests.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you are located in the EU or UK, this section applies to you.
|
||||||
|
|
||||||
|
The General Data Protection Regulation (GDPR) and UK GDPR require us to explain the valid legal bases we rely on in order to process your personal information. As such, we may rely on the following legal bases to process your personal information:
|
||||||
|
Consent. We may process your information if you have given us permission (i.e., consent) to use your personal information for a specific purpose. You can withdraw your consent at any time. Click here to learn more.
|
||||||
|
Legal Obligations. We may process your information where we believe it is necessary for compliance with our legal obligations, such as to cooperate with a law enforcement body or regulatory agency, exercise or defend our legal rights, or disclose your information as evidence in litigation in which we are involved.
|
||||||
|
Vital Interests. We may process your information where we believe it is necessary to protect your vital interests or the vital interests of a third party, such as situations involving potential threats to the safety of any person.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you are located in Canada, this section applies to you.
|
||||||
|
|
||||||
|
We may process your information if you have given us specific permission (i.e., express consent) to use your personal information for a specific purpose, or in situations where your permission can be inferred (i.e., implied consent). You can withdraw your consent at any time. Click here to learn more.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
In some exceptional cases, we may be legally permitted under applicable law to process your information without your consent, including, for example:
|
||||||
|
If collection is clearly in the interests of an individual and consent cannot be obtained in a timely way
|
||||||
|
For investigations and fraud detection and prevention
|
||||||
|
For business transactions provided certain conditions are met
|
||||||
|
If it is contained in a witness statement and the collection is necessary to assess, process, or settle an insurance claim
|
||||||
|
For identifying injured, ill, or deceased persons and communicating with next of kin
|
||||||
|
If we have reasonable grounds to believe an individual has been, is, or may be victim of financial abuse
|
||||||
|
If it is reasonable to expect collection and use with consent would compromise the availability or the accuracy of the information and the collection is reasonable for purposes related to investigating a breach of an agreement or a contravention of the laws of Canada or a province
|
||||||
|
If disclosure is required to comply with a subpoena, warrant, court order, or rules of the court relating to the production of records
|
||||||
|
If it was produced by an individual in the course of their employment, business, or profession and the collection is consistent with the purposes for which the information was produced
|
||||||
|
If the collection is solely for journalistic, artistic, or literary purposes
|
||||||
|
If the information is publicly available and is specified by the regulations
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
**4. WHEN AND WITH WHOM DO WE SHARE YOUR PERSONAL INFORMATION?**
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
In Short: We may share information in specific situations described in this section and/or with the following third parties.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
We may need to share your personal information in the following situations:
|
||||||
|
Business Transfers. We may share or transfer your information in connection with, or during negotiations of, any merger, sale of company assets, financing, or acquisition of all or a portion of our business to another company.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
**5. DO WE USE COOKIES AND OTHER TRACKING TECHNOLOGIES?**
|
||||||
|
|
||||||
|
In Short: We may use cookies and other tracking technologies to collect and store your information.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
We may use cookies and similar tracking technologies (like web beacons and pixels) to access or store information. Specific information about how we use such technologies and how you can refuse certain cookies is set out in our Cookie Notice.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
**6. HOW LONG DO WE KEEP YOUR INFORMATION?**
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
In Short: We keep your information for as long as necessary to fulfill the purposes outlined in this privacy notice unless otherwise required by law.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
We will only keep your personal information for as long as it is necessary for the purposes set out in this privacy notice, unless a longer retention period is required or permitted by law (such as tax, accounting, or other legal requirements). No purpose in this notice will require us keeping your personal information for longer than 2 years.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
When we have no ongoing legitimate business need to process your personal information, we will either delete or anonymize such information, or, if this is not possible (for example, because your personal information has been stored in backup archives), then we will securely store your personal information and isolate it from any further processing until deletion is possible.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
**7. HOW DO WE KEEP YOUR INFORMATION SAFE?**
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
In Short: We aim to protect your personal information through a system of organizational and technical security measures.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
We have implemented appropriate and reasonable technical and organizational security measures designed to protect the security of any personal information we process. However, despite our safeguards and efforts to secure your information, no electronic transmission over the Internet or information storage technology can be guaranteed to be 100% secure, so we cannot promise or guarantee that hackers, cybercriminals, or other unauthorized third parties will not be able to defeat our security and improperly collect, access, steal, or modify your information. Although we will do our best to protect your personal information, transmission of personal information to and from our Services is at your own risk. You should only access the Services within a secure environment.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
**8. WHAT ARE YOUR PRIVACY RIGHTS?**
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
In Short: In some regions, such as the European Economic Area (EEA), United Kingdom (UK), and Canada, you have rights that allow you greater access to and control over your personal information. You may review, change, or terminate your account at any time.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
In some regions (like the EEA, UK, and Canada), you have certain rights under applicable data protection laws. These may include the right (i) to request access and obtain a copy of your personal information, (ii) to request rectification or erasure; (iii) to restrict the processing of your personal information; and (iv) if applicable, to data portability. In certain circumstances, you may also have the right to object to the processing of your personal information. You can make such a request by contacting us by using the contact details provided in the section "HOW CAN YOU CONTACT US ABOUT THIS NOTICE?" below.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
We will consider and act upon any request in accordance with applicable data protection laws.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you are located in the EEA or UK and you believe we are unlawfully processing your personal information, you also have the right to complain to your local data protection supervisory authority. You can find their contact details here: https://ec.europa.eu/justice/data-protection/bodies/authorities/index_en.htm.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you are located in Switzerland, the contact details for the data protection authorities are available here: https://www.edoeb.admin.ch/edoeb/en/home.html.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Withdrawing your consent: If we are relying on your consent to process your personal information, which may be express and/or implied consent depending on the applicable law, you have the right to withdraw your consent at any time. You can withdraw your consent at any time by contacting us by using the contact details provided in the section "HOW CAN YOU CONTACT US ABOUT THIS NOTICE?" below.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
However, please note that this will not affect the lawfulness of the processing before its withdrawal, nor when applicable law allows, will it affect the processing of your personal information conducted in reliance on lawful processing grounds other than consent.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Cookies and similar technologies: Most Web browsers are set to accept cookies by default. If you prefer, you can usually choose to set your browser to remove cookies and to reject cookies. If you choose to remove cookies or reject cookies, this could affect certain features or services of our Services. To opt out of interest-based advertising by advertisers on our Services visit http://www.aboutads.info/choices/.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you have questions or comments about your privacy rights, you may email us at hello@jsonhero.io.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
**9. CONTROLS FOR DO-NOT-TRACK FEATURES**
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Most web browsers and some mobile operating systems and mobile applications include a Do-Not-Track ("DNT") feature or setting you can activate to signal your privacy preference not to have data about your online browsing activities monitored and collected. At this stage no uniform technology standard for recognizing and implementing DNT signals has been finalized. As such, we do not currently respond to DNT browser signals or any other mechanism that automatically communicates your choice not to be tracked online. If a standard for online tracking is adopted that we must follow in the future, we will inform you about that practice in a revised version of this privacy notice.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
**10. DO CALIFORNIA RESIDENTS HAVE SPECIFIC PRIVACY RIGHTS?**
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
In Short: Yes, if you are a resident of California, you are granted specific rights regarding access to your personal information.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
California Civil Code Section 1798.83, also known as the "Shine The Light" law, permits our users who are California residents to request and obtain from us, once a year and free of charge, information about categories of personal information (if any) we disclosed to third parties for direct marketing purposes and the names and addresses of all third parties with which we shared personal information in the immediately preceding calendar year. If you are a California resident and would like to make such a request, please submit your request in writing to us using the contact information provided below.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you are under 18 years of age, reside in California, and have a registered account with Services, you have the right to request removal of unwanted data that you publicly post on the Services. To request removal of such data, please contact us using the contact information provided below and include the email address associated with your account and a statement that you reside in California. We will make sure the data is not publicly displayed on the Services, but please be aware that the data may not be completely or comprehensively removed from all our systems (e.g., backups, etc.).
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
**11. DO WE MAKE UPDATES TO THIS NOTICE?**
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
In Short: Yes, we will update this notice as necessary to stay compliant with relevant laws.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
We may update this privacy notice from time to time. The updated version will be indicated by an updated "Revised" date and the updated version will be effective as soon as it is accessible. If we make material changes to this privacy notice, we may notify you either by prominently posting a notice of such changes or by directly sending you a notification. We encourage you to review this privacy notice frequently to be informed of how we are protecting your information.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
**12. HOW CAN YOU CONTACT US ABOUT THIS NOTICE?**
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you have questions or comments about this notice, you may email us at hello@jsonhero.io or by post to:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Stack Hero Limited
|
||||||
|
68 Hanbury St
|
||||||
|
London, England E1 5JL
|
||||||
|
United Kingdom
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
**13. HOW CAN YOU REVIEW, UPDATE, OR DELETE THE DATA WE COLLECT FROM YOU?**
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Based on the applicable laws of your country, you may have the right to request access to the personal information we collect from you, change that information, or delete it in some circumstances. To request to review, update, or delete your personal information, please visit: hello@jsonhero.io.
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -37,7 +37,11 @@ async function getPeekalink(link: string): Promise<PreviewResult> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getUriPreview(uri: string): Promise<PreviewResult> {
|
export async function getUriPreview(uri: string): Promise<PreviewResult> {
|
||||||
const head = await headUri(uri);
|
console.log(`[getPreview][getUriPreview] ${uri}`);
|
||||||
|
|
||||||
|
const url = rewriteUrl(uri);
|
||||||
|
|
||||||
|
const head = await headUri(url.href);
|
||||||
|
|
||||||
// If the url is an image content type, return a preview image
|
// If the url is an image content type, return a preview image
|
||||||
if (
|
if (
|
||||||
@@ -46,14 +50,14 @@ export async function getUriPreview(uri: string): Promise<PreviewResult> {
|
|||||||
contentType.includes(head.contentType)
|
contentType.includes(head.contentType)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
const previewImage = createPreviewImage(uri, head);
|
const previewImage = createPreviewImage(url.href, head);
|
||||||
|
|
||||||
return previewImage;
|
return previewImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the url is a json content type, attempt to request the json and return a preview json
|
// If the url is a json content type, attempt to request the json and return a preview json
|
||||||
if (head?.contentType.includes("application/json")) {
|
if (head?.contentType.includes("application/json")) {
|
||||||
const response = await safeFetch(uri, {
|
const response = await safeFetch(url.href, {
|
||||||
headers: {
|
headers: {
|
||||||
accept: "application/json",
|
accept: "application/json",
|
||||||
},
|
},
|
||||||
@@ -65,10 +69,10 @@ export async function getUriPreview(uri: string): Promise<PreviewResult> {
|
|||||||
|
|
||||||
const jsonBody = await response.json();
|
const jsonBody = await response.json();
|
||||||
|
|
||||||
return createPreviewJson(uri, jsonBody);
|
return createPreviewJson(url.href, jsonBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
const peekalinkResult = await getPeekalink(uri);
|
const peekalinkResult = await getPeekalink(url.href);
|
||||||
|
|
||||||
return peekalinkResult;
|
return peekalinkResult;
|
||||||
}
|
}
|
||||||
@@ -149,3 +153,33 @@ function createPreviewImage(uri: string, head: HeadInfo): PreviewImage {
|
|||||||
size: head.contentLength,
|
size: head.contentLength,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rewrites the URL to convert an ipfs: url to use https://ipfs.io/ipfs/
|
||||||
|
function rewriteUrl(url: string): URL {
|
||||||
|
const unmodifiedUrl = new URL(url);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`[getPreview][rewriteUrl] ${unmodifiedUrl.href}, protocol: ${unmodifiedUrl.protocol}, hostname: ${unmodifiedUrl.hostname}, pathname: ${unmodifiedUrl.pathname}, search: ${unmodifiedUrl.search}, hash: ${unmodifiedUrl.hash}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// Rewrite the URL if it is a relative URL
|
||||||
|
if (unmodifiedUrl.protocol === "ipfs:") {
|
||||||
|
if (unmodifiedUrl.hostname === "") {
|
||||||
|
return new URL(
|
||||||
|
`https://ipfs.io/ipfs/${unmodifiedUrl.pathname.substring(2)}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Parse out the "hostname" from the raw url because hostnames are case-insensitive and automatically lowercased
|
||||||
|
const urlMatches = url.match(/^ipfs:\/\/([A-Za-z0-9]+)(\/.*)?/i);
|
||||||
|
const hostname = urlMatches?.[1];
|
||||||
|
|
||||||
|
return new URL(
|
||||||
|
`https://ipfs.io/ipfs/${hostname ?? unmodifiedUrl.hostname}${
|
||||||
|
unmodifiedUrl.pathname.length > 0 ? `/${unmodifiedUrl.pathname}` : ""
|
||||||
|
}${unmodifiedUrl.search}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unmodifiedUrl;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,17 +1,6 @@
|
|||||||
// Should truncate the number to not show the exact number of stars
|
// Should truncate the number to not show the exact number of stars
|
||||||
// If over 1000, show 1k
|
// If over 1000, show 1k
|
||||||
// If between 1100 and 1199, show 1.1k
|
// Round up to the nearest hundred, so for example, 1150 becomes 1.2k, 1101 becomes 1.1k, etc.
|
||||||
// If between 1200 and 1299, show 1.2k
|
|
||||||
// If between 1300 and 1399, show 1.3k
|
|
||||||
// If over 10000, show 10k
|
|
||||||
// if between 10100 and 10199, show 10.1k
|
|
||||||
// if between 10200 and 10299, show 10.2k
|
|
||||||
// if between 10300 and 10399, show 10.3k
|
|
||||||
// if between 11000 and 11099, show 11k
|
|
||||||
// if between 11100 and 11199, show 11.1k
|
|
||||||
// if over 100000, show 100k
|
|
||||||
// if between 100100 and 100199, show 100.1k
|
|
||||||
// if between 100200 and 100299, show 100.2k
|
|
||||||
export function formatStarCount(count: number | undefined): string {
|
export function formatStarCount(count: number | undefined): string {
|
||||||
if (count === undefined) {
|
if (count === undefined) {
|
||||||
return "⭐️";
|
return "⭐️";
|
||||||
@@ -20,14 +9,11 @@ export function formatStarCount(count: number | undefined): string {
|
|||||||
if (count < 1000) {
|
if (count < 1000) {
|
||||||
return count.toString();
|
return count.toString();
|
||||||
}
|
}
|
||||||
if (count < 10000) {
|
|
||||||
return `${Math.floor(count / 100) / 10}k`;
|
return `${roundWithPrecision(count / 1000, 1)}k`;
|
||||||
}
|
}
|
||||||
if (count < 100000) {
|
|
||||||
return `${Math.floor(count / 100) / 10}k`;
|
function roundWithPrecision(value: number, precision: number): number {
|
||||||
}
|
const multiplier = Math.pow(10, precision);
|
||||||
if (count < 1000000) {
|
return Math.round(value * multiplier) / multiplier;
|
||||||
return `${Math.floor(count / 100) / 10}k`;
|
|
||||||
}
|
|
||||||
return `${Math.floor(count / 100000)}k`;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ export function groupRelatedValues(
|
|||||||
return "undefined";
|
return "undefined";
|
||||||
} else if (value == null) {
|
} else if (value == null) {
|
||||||
return "null";
|
return "null";
|
||||||
|
} else if (Array.isArray(value)) {
|
||||||
|
return "[...]";
|
||||||
|
} else if (typeof value === "object") {
|
||||||
|
return "{...}";
|
||||||
} else {
|
} else {
|
||||||
return value.toString();
|
return value.toString();
|
||||||
}
|
}
|
||||||
@@ -71,6 +75,8 @@ export function getRelatedPathsAtPath(
|
|||||||
|
|
||||||
if (inferredType.name !== "array") continue;
|
if (inferredType.name !== "array") continue;
|
||||||
|
|
||||||
|
if (index + 1 === pathDepth) continue;
|
||||||
|
|
||||||
for (
|
for (
|
||||||
let childIndex = 0;
|
let childIndex = 0;
|
||||||
childIndex < inferredType.value.length;
|
childIndex < inferredType.value.length;
|
||||||
|
|||||||
@@ -0,0 +1,402 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"movie": "Cars 3",
|
||||||
|
"year": 2017,
|
||||||
|
"release_date": "2017-05-23",
|
||||||
|
"director": "Brian Fee",
|
||||||
|
"character": "Lighting McQueen",
|
||||||
|
"movie_duration": "01:42:25",
|
||||||
|
"timestamp": "00:25:10",
|
||||||
|
"full_line": "Oh, hey, Mr. Sterling. Wow.",
|
||||||
|
"current_wow_in_movie": 3,
|
||||||
|
"total_wows_in_movie": 10,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/43fOBsgY8iOJL0dijvFnfl/ea361efc5131a859c173ab5dd3fdfe1e/Cars_3_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/MwAHRe21gYt7qgtQqQSgi/20188401d4ae548db5c4f861fad96f49/Cars_3_Wow_3_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/7dL6LdSOmZ2mbXgdi4KeZl/6fe6efef423d28e5704637658a3650ec/Cars_3_Wow_3_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/7uciNXhLeVXBByZu8ipAr4/5bcae43dde19fa0bb249e9318953ba09/Cars_3_Wow_3_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/KL91bYDqfWVeK6NdaXh1O/f1baca7b2988a2e5853256be5f9e2c89/Cars_3_Wow_3_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/6PlYbs7cO3iXEEM1szcfHZ/bf10fba861c8e0d2c20ac4714974bde1/Cars_3_Wow_3.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "The Internship",
|
||||||
|
"year": 2013,
|
||||||
|
"release_date": "2013-05-29",
|
||||||
|
"director": "Shawn Levy",
|
||||||
|
"character": "Nick Campbell",
|
||||||
|
"movie_duration": "02:05:02",
|
||||||
|
"timestamp": "00:38:59",
|
||||||
|
"full_line": "Wow! Seven projects.",
|
||||||
|
"current_wow_in_movie": 1,
|
||||||
|
"total_wows_in_movie": 5,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/6XhmTpc1PoiTf0q1nDYMyv/594947f72b4dba7f3c24938a680dd603/The_Internship_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/11VKtDgrvqvU4atLRF9QV9/f1f1ae91486a001e41fb3f66821f1e62/The_Internship_Wow_1_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/6uDteZpujqfebwhVAXoFkm/768bbb0a63dcef265b0040b54e417483/The_Internship_Wow_1_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/4JTqjEo1kTWtALpSdE9pVs/f9242e24e89c9bd32aa3f5212eca08e9/The_Internship_Wow_1_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/5VGJ7XEkBhxEbLMuDR4AIC/e5b80d57316dbb910cd72685f72b8f2b/The_Internship_Wow_1_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/2vwdiSubw2iEcsl1yCUk0A/3cb1ba763c12fd7711823619b4c3d904/The_Internship_Wow_1.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "Cars 3",
|
||||||
|
"year": 2017,
|
||||||
|
"release_date": "2017-05-23",
|
||||||
|
"director": "Brian Fee",
|
||||||
|
"character": "Lighting McQueen",
|
||||||
|
"movie_duration": "01:42:25",
|
||||||
|
"timestamp": "01:03:08",
|
||||||
|
"full_line": "Wow. You don't mince words around here, do you?",
|
||||||
|
"current_wow_in_movie": 10,
|
||||||
|
"total_wows_in_movie": 10,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/43fOBsgY8iOJL0dijvFnfl/ea361efc5131a859c173ab5dd3fdfe1e/Cars_3_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/3KJZ435sr6Y5k00AnZdOJ2/2aadc7fbc687b38c3f1536a9efc16cdb/Cars_3_Wow_10_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/5vQtn6ny9J79PNG16jsJMR/1b4804366cfb9206d70472ab9b7f37e6/Cars_3_Wow_10_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/6kIDoftFyBJOgvCBe5Jr5k/51be6dcd0a40aff052a4215258f6f2cb/Cars_3_Wow_10_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/923BnYGWVuiPpWeM7e6wv/db39600a6bd7c6a807e95d397d129dd4/Cars_3_Wow_10_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/3iZaUMMLnxCH1fIqcXpYZ0/78e6ee967cae46e64a6f65c6f451115a/Cars_3_Wow_10.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "Night at the Museum: Secret of the Tomb",
|
||||||
|
"year": 2014,
|
||||||
|
"release_date": "2014-12-11",
|
||||||
|
"director": "Shawn Levy",
|
||||||
|
"character": "Jedediah Smith",
|
||||||
|
"movie_duration": "01:37:48",
|
||||||
|
"timestamp": "00:39:36",
|
||||||
|
"full_line": "Wow. We're a long way from home, boy.",
|
||||||
|
"current_wow_in_movie": 1,
|
||||||
|
"total_wows_in_movie": 1,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/4cwNnRAOKM1HuAtlH6dscl/52762736d4815c2390619a4009d66d93/Night_at_the_Museum_Secret_of_the_Tomb_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/uHF5B0MFoK8H0S40Sqld9/fa9aca4d8c52ebff4ab4f390196ab0f1/Night_at_the_Museum_Secret_of_the_Tomb_Wow_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/47qSLctyurmw22A3z7X1YG/8651f02d7e58ebb1eb312a26f732515b/Night_at_the_Museum_Secret_of_the_Tomb_Wow_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/3ZLiolsGZkiTp3p8aLJb3d/e330311fcaed4716f7a603d058ee8767/Night_at_the_Museum_Secret_of_the_Tomb_Wow_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/1ZwmDYe0zdKzsy1MJrANSE/e5e0f5ea1c745baf61b205b6e6574605/Night_at_the_Museum_Secret_of_the_Tomb_Wow_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/5o3CSC67KEoIojYH0UMghP/fbf9dea48ac1914eb7f7bffca802b012/Night_at_the_Museum_Secret_of_the_Tomb_Wow.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "The Internship",
|
||||||
|
"year": 2013,
|
||||||
|
"release_date": "2013-05-29",
|
||||||
|
"director": "Shawn Levy",
|
||||||
|
"character": "Nick Campbell",
|
||||||
|
"movie_duration": "02:05:02",
|
||||||
|
"timestamp": "01:26:54",
|
||||||
|
"full_line": "You're so cute. It's beautiful. Wow.",
|
||||||
|
"current_wow_in_movie": 4,
|
||||||
|
"total_wows_in_movie": 5,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/6XhmTpc1PoiTf0q1nDYMyv/594947f72b4dba7f3c24938a680dd603/The_Internship_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/61gtrYzY8qsD3Onc4hUNdx/e1685933255e13fce8578594dbfc30aa/The_Internship_Wow_4_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/3CQQDswj7JP1UU95KdHZ2x/af3e2709d1b8c730a177a56e0395bce3/The_Internship_Wow_4_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/67gEv3fXOzKu5IsscIYAxw/bf8e18b6543eec4ac1952d6c6845cb8f/The_Internship_Wow_4_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/1ZrN3pCfLhimJ2fxxf86n3/43116038f56d789a1514778081c7dcc2/The_Internship_Wow_4_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/5Jphk5c8qFsc7ZiWNeJOKQ/80f43d3758ee8730987c6a859ffec667/The_Internship_Wow_4.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "Cars 3",
|
||||||
|
"year": 2017,
|
||||||
|
"release_date": "2017-05-23",
|
||||||
|
"director": "Brian Fee",
|
||||||
|
"character": "Lighting McQueen",
|
||||||
|
"movie_duration": "01:42:25",
|
||||||
|
"timestamp": "00:22:42",
|
||||||
|
"full_line": "Wow!",
|
||||||
|
"current_wow_in_movie": 2,
|
||||||
|
"total_wows_in_movie": 10,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/43fOBsgY8iOJL0dijvFnfl/ea361efc5131a859c173ab5dd3fdfe1e/Cars_3_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/1xpGU65BqXMplnWjcs0HG7/19ad3a66f22c976b7a345ba7a2d931ce/Cars_3_Wow_2_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/NXF2Haueh2DGbaHOpLDuV/21d43d80d211f6f93062b4f35c6d68ba/Cars_3_Wow_2_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/6mN4TgA3TUcgqUEec3qCOV/c30c18bc851f43db95b3cab17aea0fb0/Cars_3_Wow_2_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/316quJhdUfAkcmKkzPjww0/1780af73d03a7a631c71429d59a064e9/Cars_3_Wow_2_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/7rkrQVW7vsUj6amBflfTQ9/fe38afabd1eeaed70d14a8bbcf68d417/Cars_3_Wow_2.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "Hall Pass",
|
||||||
|
"year": 2011,
|
||||||
|
"release_date": "2011-02-25",
|
||||||
|
"director": "Peter Farrelly and Bobby Farrelly",
|
||||||
|
"character": "Rick Mills",
|
||||||
|
"movie_duration": "01:51:35",
|
||||||
|
"timestamp": "01:26:28",
|
||||||
|
"full_line": "Wow.",
|
||||||
|
"current_wow_in_movie": 6,
|
||||||
|
"total_wows_in_movie": 6,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/6jFEUPmYiKifaTuC2cugm8/22087834d091445fc9393cdd9163a901/Hall_Pass_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/V9JGQ3qgfufm4vUkzyJYI/6182dce642b9f31ab698d7ab448688bd/Hall_Pass_Wow_6_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/3RkKyI4NFfakkYzUEO83hG/21d29c6b7695d1b072084a92e05b6283/Hall_Pass_Wow_6_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/54Zd2b5BQrQi4hvZ8IAg8j/9a719307cdf6525257e0dba0afa9ceee/Hall_Pass_Wow_6_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/7Jo3JA6zl3vzAiIkriLLOR/5f488e12cdc1c7792484f098732b790d/Hall_Pass_Wow_6_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/7mZxDvl1IsR95NAg8mKj0t/43a0b44fd325c1de3f86cf6cec3a80d5/Hall_Pass_Wow_6.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "Cars",
|
||||||
|
"year": 2006,
|
||||||
|
"release_date": "2006-06-09",
|
||||||
|
"director": "John Lasseter",
|
||||||
|
"character": "Lightning McQueen",
|
||||||
|
"movie_duration": "01:56:36",
|
||||||
|
"timestamp": "01:23:13",
|
||||||
|
"full_line": "Wow, you were right!",
|
||||||
|
"current_wow_in_movie": 4,
|
||||||
|
"total_wows_in_movie": 5,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/6dsHUil72TJLYqbwYMEjH4/387a2d9994a2f1fb069d970a0f30ba32/Cars_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/5WH68GXLSVdosuz0ouwFDF/0b55b456669a8bf8a13e6aecd46cae89/Cars_Wow_4_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/7KSwlI2izHJDNtiGAH32SU/7d7698ac27be72753ddc1e2291399b46/Cars_Wow_4_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/6OExsgI6VJHXcjNZtlqBkx/3152bd6700486416ec0b818829de9374/Cars_Wow_4_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/2ibZvAYOWwmoqQtANL3d8o/9c09f29a7f42ecd996ac991b52b2cc65/Cars_Wow_4_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/iJ5LIuyc3pmvEAaiSVSLS/85e36dc0324b28549ea56a6882a03062/Cars_Wow_4.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "The Big Bounce",
|
||||||
|
"year": 2004,
|
||||||
|
"release_date": "2004-01-30",
|
||||||
|
"director": "George Armitage",
|
||||||
|
"character": "Jack Ryan",
|
||||||
|
"movie_duration": "01:28:10",
|
||||||
|
"timestamp": "00:58:00",
|
||||||
|
"full_line": "What is it about the produce section? Wow.",
|
||||||
|
"current_wow_in_movie": 2,
|
||||||
|
"total_wows_in_movie": 2,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/4hPpMWXhuXQ8HzLusmcaS5/4c46fa4fa8bce13b06d8b4444f6150ef/The_Big_Bounce_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/6TPALdqhVTMztHMSw2qOOj/81d512b2ee8b7c05e7e851eae7790d0e/The_Big_Bounce_Wow_2_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/dEuiSxnBLWP26YHaWiHbz/599ac6fb7a6aead87e8e6efdab759f74/The_Big_Bounce_Wow_2_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/7tA15W0lgJr7CpJNCf1m4Z/86a953df81d88f5fa79e35aa1e4e4dc1/The_Big_Bounce_Wow_2_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/1iKZTtL0qQRDek4y4SduD5/bbd83798b30435b43a2df4c360130d72/The_Big_Bounce_Wow_2_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/6pjOYj0xK38VAkPAl1QK7R/a5f083c60ce9e9c4fa93a8be70817d22/The_Big_Bounce_Wow_2.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "The Big Year",
|
||||||
|
"year": 2011,
|
||||||
|
"release_date": "2011-10-14",
|
||||||
|
"director": "David Frankel",
|
||||||
|
"character": "Kenny Bostick",
|
||||||
|
"movie_duration": "01:43:09",
|
||||||
|
"timestamp": "01:08:23",
|
||||||
|
"full_line": "Wow, and here I thought I was the bomb at 728.",
|
||||||
|
"current_wow_in_movie": 3,
|
||||||
|
"total_wows_in_movie": 3,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/pCjGOhbTCQVjLRN9zTwIi/ce7cdf4b40f3549326d881697aa468a1/The_Big_Year_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/uOdKu6VANHZjtwZXeBU8M/bf1f0f44c7bc01faa648a1b97b1205d3/The_Big_Year_Wow_3_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/y9wR96fHZaNnZr367mjyI/1262c2af0400cb1dc8528c3c8e6a83a4/The_Big_Year_Wow_3_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/55z94kbUxNFIL0rYb1i2mH/ca0505ca5e2017b663f18cca8af571b2/The_Big_Year_Wow_3_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/6moRL0SzmkTGzgEuZeVByI/c63fa33d0992c0594ecbaed4fcd7e891/The_Big_Year_Wow_3_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/1dXEYZQP1Fl6CX1roy7ZAH/f31b90a6f961dcc16c16b294f4faf664/The_Big_Year_Wow_3.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "Hall Pass",
|
||||||
|
"year": 2011,
|
||||||
|
"release_date": "2011-02-25",
|
||||||
|
"director": "Peter Farrelly and Bobby Farrelly",
|
||||||
|
"character": "Rick Mills",
|
||||||
|
"movie_duration": "01:51:35",
|
||||||
|
"timestamp": "00:46:55",
|
||||||
|
"full_line": "Wow. This is awkward. I feel like I'm at my first junior high mixer. You know? When you don't know what to say.",
|
||||||
|
"current_wow_in_movie": 3,
|
||||||
|
"total_wows_in_movie": 6,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/6jFEUPmYiKifaTuC2cugm8/22087834d091445fc9393cdd9163a901/Hall_Pass_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/4QcL02MHJ8ApVkbfN8cP6E/264c28c1e9195d87f0206e143c5ca54a/Hall_Pass_Wow_3_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/15h0sMoIhdeaPDB8qSsUN9/36245f66352b595dc40bc4d9903fa5b3/Hall_Pass_Wow_3_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/74fQiVcwuT7ePQemGC7ih4/b102922c97c9ff38f47268d648628a22/Hall_Pass_Wow_3_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/7mSGl1rSVtGdfSacwnKVsu/e7ac36e5684f6b64978987d2f68c43db/Hall_Pass_Wow_3_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/2NBIVPDF4o7cy0epTvPOwR/406cd5c17e9b01511f1e350bb96df352/Hall_Pass_Wow_3.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "No Escape",
|
||||||
|
"year": 2015,
|
||||||
|
"release_date": "2015-08-26",
|
||||||
|
"director": "John Erick Dowdle",
|
||||||
|
"character": "Jack Dwyer",
|
||||||
|
"movie_duration": "01:43:06",
|
||||||
|
"timestamp": "00:08:11",
|
||||||
|
"full_line": "Wow.",
|
||||||
|
"current_wow_in_movie": 1,
|
||||||
|
"total_wows_in_movie": 2,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/R3PGhNHo0k5uhnPM7bqIp/5e2b3723c69f7c70313be19417c6fdba/No_Escape_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/3WxIt1hZQtpqnveyAb4xw3/54773cfd70ab4380c47048324f216fc4/No_Escape_Wow_1_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/2JcYMonzmocD3qABm1dpNg/019b752a33b2517033d75ea5bfd20b59/No_Escape_Wow_1_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/5QMtRpqqyfg9irqjPPx5JO/5a24212c22dc20944b5831e5b81efe4d/No_Escape_Wow_1_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/6aou6AH16gfvXSccxgcZFf/347d5ff951c851d5fe9928323e6067eb/No_Escape_Wow_1_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/24lDtvWBG8mDqaqBM8Qsr0/4c08f87367dd3399efb6a5554f6f4858/No_Escape_Wow_1.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "Midnight in Paris",
|
||||||
|
"year": 2011,
|
||||||
|
"release_date": "2011-05-20",
|
||||||
|
"director": "Woody Allen",
|
||||||
|
"character": "Gil Pender",
|
||||||
|
"movie_duration": "01:33:57",
|
||||||
|
"timestamp": "00:58:22",
|
||||||
|
"full_line": "Wow.",
|
||||||
|
"current_wow_in_movie": 5,
|
||||||
|
"total_wows_in_movie": 10,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/2ZcfSCe2dlfoVzYMr4b9nK/d566e5ad044dee56645f3bffc7200d64/Midnight_in_Paris_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/1DSaYjQ8SnL1Imeuxe0eXE/100d3106c8a0bf5e80372e2187daf325/Midnight_in_Paris_Wow_5_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/eFI1n7voe4CsxkWEWv2q0/36781ed8f50e508e8e1f79c8e65e601a/Midnight_in_Paris_Wow_5_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/6oSaIzfy7k3DJMvvy3j1kN/d77192d7decb3ba9d06a5210a58df1fa/Midnight_in_Paris_Wow_5_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/4LQ4lkhx41XDC6UcMlmjbA/dfd5e3604c85c9fb9d38ea2dfdd02a2f/Midnight_in_Paris_Wow_5_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/2A5G34x8JCQBuYwU4D2l9S/27cc467b3ff5796ff1bbe113a06a6e64/Midnight_in_Paris_Wow_5.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "The Haunting",
|
||||||
|
"year": 1999,
|
||||||
|
"release_date": "1999-07-23",
|
||||||
|
"director": "Jan de Bont",
|
||||||
|
"character": "Luke Sanderson",
|
||||||
|
"movie_duration": "01:52:37",
|
||||||
|
"timestamp": "00:41:34",
|
||||||
|
"full_line": "Wow, I sorta got screwed on the ol' bedroom selection.",
|
||||||
|
"current_wow_in_movie": 4,
|
||||||
|
"total_wows_in_movie": 5,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/6Zu7ux0JYrUWk0UC8vxPtj/d0da8bfbad670655779a9921ac514759/The_Haunting_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/01C128tlGJ79vtlFEPc7V9/184759a9ca6fb1ab57114977afccb2ff/The_Haunting_Wow_4_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/3fR8AigFIp2I1vkSLRhzur/afb0c226daf7806bc9bd9c5e7b008fb4/The_Haunting_Wow_4_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/1OCimrvhXGGfffHqBKaqz7/52d16b12a2d1a8a264b09364afc4c87c/The_Haunting_Wow_4_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/6bwt57tdhBCbhsXZ4i0pce/7f6debc7e52f80c78a618f19c8087985/The_Haunting_Wow_4_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/3yvd3DvmY0XUyqWPLUYLqp/1aabc0f7a6b58003ccdaa61469b8d5ee/The_Haunting_Wow_4.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "Cars 3",
|
||||||
|
"year": 2017,
|
||||||
|
"release_date": "2017-05-23",
|
||||||
|
"director": "Brian Fee",
|
||||||
|
"character": "Lighting McQueen",
|
||||||
|
"movie_duration": "01:42:25",
|
||||||
|
"timestamp": "00:26:23",
|
||||||
|
"full_line": "Wow.",
|
||||||
|
"current_wow_in_movie": 5,
|
||||||
|
"total_wows_in_movie": 10,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/43fOBsgY8iOJL0dijvFnfl/ea361efc5131a859c173ab5dd3fdfe1e/Cars_3_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/4Vp8pVwekVrXfmHT3xYCBm/5775501444824d3ee90acda0698e3472/Cars_3_Wow_5_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/6IoA0jwJiPwyXcSbDCrbJ5/5e65c8caa57c62ce9fc862aaeb327255/Cars_3_Wow_5_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/JrOrzMzr2aHCVPkRJUCae/06c5cb7543e95211a6f99ed89e6ea498/Cars_3_Wow_5_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/6uufhJa3yX9e0Ib0xsOb46/16f9e55246ad32a33a34d58e621b8942/Cars_3_Wow_5_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/4aUtZzrqLHol2Hhb52zgHQ/ed5c4ef03ebba9ae34659e9058e58461/Cars_3_Wow_5.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "Cars 3",
|
||||||
|
"year": 2017,
|
||||||
|
"release_date": "2017-05-23",
|
||||||
|
"director": "Brian Fee",
|
||||||
|
"character": "Lighting McQueen",
|
||||||
|
"movie_duration": "01:42:25",
|
||||||
|
"timestamp": "00:26:11",
|
||||||
|
"full_line": "Wow.",
|
||||||
|
"current_wow_in_movie": 4,
|
||||||
|
"total_wows_in_movie": 10,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/43fOBsgY8iOJL0dijvFnfl/ea361efc5131a859c173ab5dd3fdfe1e/Cars_3_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/7G6jLS5xfYBOepUxkW7R3c/c78d22f63ba51f371a1550834888b9ca/Cars_3_Wow_4_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/lIhPcmNS5L4DnpY41EpUA/96b0c5b44acf3fe16e68d1e67156d41c/Cars_3_Wow_4_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/1h3am3BfJYUm0VXV4uKF9P/e75775ec0621889efd40ce1bc372735a/Cars_3_Wow_4_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/6eO8c3ojQA4rWMlE1hMMOa/c3a9ce4c01b2d342b33144c9f90b9e3e/Cars_3_Wow_4_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/6aJuGg3bTjqd20j59vP1Wv/6cb60311194d3a9aa040882911a5f516/Cars_3_Wow_4.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "Midnight in Paris",
|
||||||
|
"year": 2011,
|
||||||
|
"release_date": "2011-05-20",
|
||||||
|
"director": "Woody Allen",
|
||||||
|
"character": "Gil Pender",
|
||||||
|
"movie_duration": "01:33:57",
|
||||||
|
"timestamp": "01:19:23",
|
||||||
|
"full_line": "Wow. Yes. Yes. Yes.",
|
||||||
|
"current_wow_in_movie": 7,
|
||||||
|
"total_wows_in_movie": 10,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/2ZcfSCe2dlfoVzYMr4b9nK/d566e5ad044dee56645f3bffc7200d64/Midnight_in_Paris_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/7N21xMDnGKfrmBO42xvoc9/c8e05e53e5841c6ba8a659aaf4f6736a/Midnight_in_Paris_Wow_7_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/6CF2q8U9OYgt3yFA7JUBkr/d6ddbf8d57b1cf9d38127735a6266431/Midnight_in_Paris_Wow_7_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/4IoMNf4pF7L3wDZ72Ad31d/efd2e6859fecf3a82a7ecdaf43175826/Midnight_in_Paris_Wow_7_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/5yF8k9rwFj99H69WASEZWU/f9741ed0771da2afd9a26454863137bb/Midnight_in_Paris_Wow_7_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/UmpPa6skALBubhqeKQFpn/2a64c51d16877b8c0bf8c23a74749f7e/Midnight_in_Paris_Wow_7.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "Midnight in Paris",
|
||||||
|
"year": 2011,
|
||||||
|
"release_date": "2011-05-20",
|
||||||
|
"director": "Woody Allen",
|
||||||
|
"character": "Gil Pender",
|
||||||
|
"movie_duration": "01:33:57",
|
||||||
|
"timestamp": "00:48:45",
|
||||||
|
"full_line": "Wow.",
|
||||||
|
"current_wow_in_movie": 3,
|
||||||
|
"total_wows_in_movie": 10,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/2ZcfSCe2dlfoVzYMr4b9nK/d566e5ad044dee56645f3bffc7200d64/Midnight_in_Paris_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/7BBJiej0qdBbuB3Xvimrae/932bc77c9e9a9918949709f846035541/Midnight_in_Paris_Wow_3_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/5tBiVUM6ef2mARH3OXzP92/8ad999e82b7bff5ac4a07d1b4dcb45f3/Midnight_in_Paris_Wow_3_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/39zl8hKK4QP1kASldccYyN/7fc8a7c86872abb9fd527a350365beea/Midnight_in_Paris_Wow_3_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/6rl512MqIH6r04L4O9jHU2/2d843c19937d770860f17719960d8352/Midnight_in_Paris_Wow_3_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/7BDkqWADSOxxYOSQGqNRcr/6fc4696de0d8bcafa487ddea97bb6d3b/Midnight_in_Paris_Wow_3.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "The Internship",
|
||||||
|
"year": 2013,
|
||||||
|
"release_date": "2013-05-29",
|
||||||
|
"director": "Shawn Levy",
|
||||||
|
"character": "Nick Campbell",
|
||||||
|
"movie_duration": "02:05:02",
|
||||||
|
"timestamp": "01:27:38",
|
||||||
|
"full_line": "Wow, a little heart and everything.",
|
||||||
|
"current_wow_in_movie": 5,
|
||||||
|
"total_wows_in_movie": 5,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/6XhmTpc1PoiTf0q1nDYMyv/594947f72b4dba7f3c24938a680dd603/The_Internship_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/1tZ97B7BWV7WhuYJSRL0aQ/c86ca6ce4c67a0f1f5343e68a7b1f428/The_Internship_Wow_5_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/2QlKc3s0Nf10vMLaKGFhVf/a76e1c99d80b13687ae593ad95837706/The_Internship_Wow_5_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/2t0rkVxOB7MVJVzUtVobAV/c396fd523e190052d4b009081b22423f/The_Internship_Wow_5_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/1W9V229ebo4J74HLZGO7pF/f4379d501080fc77221ca8df020a7cd6/The_Internship_Wow_5_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/30nYCeovpGBN5dwVmnTxrf/62c07aaab901bb488bc53ed61d2edffc/The_Internship_Wow_5.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"movie": "The Big Year",
|
||||||
|
"year": 2011,
|
||||||
|
"release_date": "2011-10-14",
|
||||||
|
"director": "David Frankel",
|
||||||
|
"character": "Kenny Bostick",
|
||||||
|
"movie_duration": "01:43:09",
|
||||||
|
"timestamp": "00:44:48",
|
||||||
|
"full_line": "Wow!",
|
||||||
|
"current_wow_in_movie": 1,
|
||||||
|
"total_wows_in_movie": 3,
|
||||||
|
"poster": "https://images.ctfassets.net/bs8ntwkklfua/pCjGOhbTCQVjLRN9zTwIi/ce7cdf4b40f3549326d881697aa468a1/The_Big_Year_Poster.jpg",
|
||||||
|
"video": {
|
||||||
|
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/2IZMW5Aeytz5rtu5MzcFk8/f675c3f6ef153c5df0c81679c80677d4/The_Big_Year_Wow_1_1080p.mp4",
|
||||||
|
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/2K0XjRiHYd8zbdYcmiTMH4/b2e4a9b02db184a4d4bd71fe15ab37a9/The_Big_Year_Wow_1_720p.mp4",
|
||||||
|
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/6QMkzBk6HrfuVxVT97mQg/5877904b163d7ccdc4baa92d449858d8/The_Big_Year_Wow_1_480p.mp4",
|
||||||
|
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/5SFeCoTmyTUEJYtK0kOO92/462afffbd6315182db59271f99a5a829/The_Big_Year_Wow_1_360p.mp4"
|
||||||
|
},
|
||||||
|
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/45tt9xH4Uf3Rgt0EJtykZZ/b5cef0c5d09d368359f4a9c0e66a6663/The_Big_Year_Wow_1.mp3"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,936 @@
|
|||||||
|
{
|
||||||
|
"abilities": [
|
||||||
|
{
|
||||||
|
"ability": {
|
||||||
|
"name": "limber",
|
||||||
|
"url": "https://pokeapi.co/api/v2/ability/7/"
|
||||||
|
},
|
||||||
|
"is_hidden": false,
|
||||||
|
"slot": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ability": {
|
||||||
|
"name": "imposter",
|
||||||
|
"url": "https://pokeapi.co/api/v2/ability/150/"
|
||||||
|
},
|
||||||
|
"is_hidden": true,
|
||||||
|
"slot": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"base_experience": 101,
|
||||||
|
"forms": [
|
||||||
|
{
|
||||||
|
"name": "ditto",
|
||||||
|
"url": "https://pokeapi.co/api/v2/pokemon-form/132/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"game_indices": [
|
||||||
|
{
|
||||||
|
"game_index": 76,
|
||||||
|
"version": {
|
||||||
|
"name": "red",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/1/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 76,
|
||||||
|
"version": {
|
||||||
|
"name": "blue",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/2/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 76,
|
||||||
|
"version": {
|
||||||
|
"name": "yellow",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/3/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "gold",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/4/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "silver",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/5/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "crystal",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/6/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "ruby",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/7/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "sapphire",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/8/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "emerald",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/9/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "firered",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/10/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "leafgreen",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/11/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "diamond",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/12/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "pearl",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/13/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "platinum",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/14/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "heartgold",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/15/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "soulsilver",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/16/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "black",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/17/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "white",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/18/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "black-2",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/21/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"game_index": 132,
|
||||||
|
"version": {
|
||||||
|
"name": "white-2",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/22/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"height": 3,
|
||||||
|
"held_items": [
|
||||||
|
{
|
||||||
|
"item": {
|
||||||
|
"name": "metal-powder",
|
||||||
|
"url": "https://pokeapi.co/api/v2/item/234/"
|
||||||
|
},
|
||||||
|
"version_details": [
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "ruby",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/7/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "sapphire",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/8/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "emerald",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/9/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "firered",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/10/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "leafgreen",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/11/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "diamond",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/12/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "pearl",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/13/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "platinum",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/14/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "heartgold",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/15/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "soulsilver",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/16/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "black",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/17/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "white",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/18/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "black-2",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/21/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "white-2",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/22/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "x",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/23/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "y",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/24/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "omega-ruby",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/25/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "alpha-sapphire",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/26/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "sun",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/27/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "moon",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/28/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "ultra-sun",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/29/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 5,
|
||||||
|
"version": {
|
||||||
|
"name": "ultra-moon",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/30/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"item": {
|
||||||
|
"name": "quick-powder",
|
||||||
|
"url": "https://pokeapi.co/api/v2/item/251/"
|
||||||
|
},
|
||||||
|
"version_details": [
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "diamond",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/12/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "pearl",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/13/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "platinum",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/14/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "heartgold",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/15/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "soulsilver",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/16/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "black",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/17/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "white",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/18/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "black-2",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/21/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "white-2",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/22/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "x",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/23/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "y",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/24/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "omega-ruby",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/25/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "alpha-sapphire",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/26/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "sun",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/27/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "moon",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/28/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "ultra-sun",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/29/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rarity": 50,
|
||||||
|
"version": {
|
||||||
|
"name": "ultra-moon",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version/30/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 132,
|
||||||
|
"is_default": true,
|
||||||
|
"location_area_encounters": "https://pokeapi.co/api/v2/pokemon/132/encounters",
|
||||||
|
"moves": [
|
||||||
|
{
|
||||||
|
"move": {
|
||||||
|
"name": "transform",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move/144/"
|
||||||
|
},
|
||||||
|
"version_group_details": [
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "red-blue",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/1/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "yellow",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/2/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "gold-silver",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/3/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "crystal",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/4/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "ruby-sapphire",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/5/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "emerald",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/6/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "firered-leafgreen",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/7/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "diamond-pearl",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/8/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "platinum",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/9/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "heartgold-soulsilver",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/10/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "black-white",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/11/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "colosseum",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/12/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "xd",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/13/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "black-2-white-2",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/14/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "x-y",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/15/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "omega-ruby-alpha-sapphire",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/16/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "sun-moon",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/17/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "ultra-sun-ultra-moon",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/18/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "lets-go-pikachu-lets-go-eevee",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/19/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_learned_at": 1,
|
||||||
|
"move_learn_method": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
|
||||||
|
},
|
||||||
|
"version_group": {
|
||||||
|
"name": "sword-shield",
|
||||||
|
"url": "https://pokeapi.co/api/v2/version-group/20/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "ditto",
|
||||||
|
"order": 214,
|
||||||
|
"past_types": [],
|
||||||
|
"species": {
|
||||||
|
"name": "ditto",
|
||||||
|
"url": "https://pokeapi.co/api/v2/pokemon-species/132/"
|
||||||
|
},
|
||||||
|
"sprites": {
|
||||||
|
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/back/132.png",
|
||||||
|
"back_female": null,
|
||||||
|
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/back/shiny/132.png",
|
||||||
|
"back_shiny_female": null,
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/132.png",
|
||||||
|
"front_female": null,
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/132.png",
|
||||||
|
"front_shiny_female": null,
|
||||||
|
"other": {
|
||||||
|
"dream_world": {
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/dream-world/132.svg",
|
||||||
|
"front_female": null
|
||||||
|
},
|
||||||
|
"home": {
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/home/132.png",
|
||||||
|
"front_female": null,
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/home/shiny/132.png",
|
||||||
|
"front_shiny_female": null
|
||||||
|
},
|
||||||
|
"official-artwork": {
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/132.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"versions": {
|
||||||
|
"generation-i": {
|
||||||
|
"red-blue": {
|
||||||
|
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/red-blue/back/132.png",
|
||||||
|
"back_gray": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/red-blue/back/gray/132.png",
|
||||||
|
"back_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/red-blue/transparent/back/132.png",
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/red-blue/132.png",
|
||||||
|
"front_gray": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/red-blue/gray/132.png",
|
||||||
|
"front_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/red-blue/transparent/132.png"
|
||||||
|
},
|
||||||
|
"yellow": {
|
||||||
|
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/yellow/back/132.png",
|
||||||
|
"back_gray": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/yellow/back/gray/132.png",
|
||||||
|
"back_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/yellow/transparent/back/132.png",
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/yellow/132.png",
|
||||||
|
"front_gray": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/yellow/gray/132.png",
|
||||||
|
"front_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/yellow/transparent/132.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"generation-ii": {
|
||||||
|
"crystal": {
|
||||||
|
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/back/132.png",
|
||||||
|
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/back/shiny/132.png",
|
||||||
|
"back_shiny_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/transparent/back/shiny/132.png",
|
||||||
|
"back_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/transparent/back/132.png",
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/132.png",
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/shiny/132.png",
|
||||||
|
"front_shiny_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/transparent/shiny/132.png",
|
||||||
|
"front_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/transparent/132.png"
|
||||||
|
},
|
||||||
|
"gold": {
|
||||||
|
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/gold/back/132.png",
|
||||||
|
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/gold/back/shiny/132.png",
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/gold/132.png",
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/gold/shiny/132.png",
|
||||||
|
"front_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/gold/transparent/132.png"
|
||||||
|
},
|
||||||
|
"silver": {
|
||||||
|
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/silver/back/132.png",
|
||||||
|
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/silver/back/shiny/132.png",
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/silver/132.png",
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/silver/shiny/132.png",
|
||||||
|
"front_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/silver/transparent/132.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"generation-iii": {
|
||||||
|
"emerald": {
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/emerald/132.png",
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/emerald/shiny/132.png"
|
||||||
|
},
|
||||||
|
"firered-leafgreen": {
|
||||||
|
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/firered-leafgreen/back/132.png",
|
||||||
|
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/firered-leafgreen/back/shiny/132.png",
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/firered-leafgreen/132.png",
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/firered-leafgreen/shiny/132.png"
|
||||||
|
},
|
||||||
|
"ruby-sapphire": {
|
||||||
|
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/ruby-sapphire/back/132.png",
|
||||||
|
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/ruby-sapphire/back/shiny/132.png",
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/ruby-sapphire/132.png",
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/ruby-sapphire/shiny/132.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"generation-iv": {
|
||||||
|
"diamond-pearl": {
|
||||||
|
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/diamond-pearl/back/132.png",
|
||||||
|
"back_female": null,
|
||||||
|
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/diamond-pearl/back/shiny/132.png",
|
||||||
|
"back_shiny_female": null,
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/diamond-pearl/132.png",
|
||||||
|
"front_female": null,
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/diamond-pearl/shiny/132.png",
|
||||||
|
"front_shiny_female": null
|
||||||
|
},
|
||||||
|
"heartgold-soulsilver": {
|
||||||
|
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/heartgold-soulsilver/back/132.png",
|
||||||
|
"back_female": null,
|
||||||
|
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/heartgold-soulsilver/back/shiny/132.png",
|
||||||
|
"back_shiny_female": null,
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/heartgold-soulsilver/132.png",
|
||||||
|
"front_female": null,
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/heartgold-soulsilver/shiny/132.png",
|
||||||
|
"front_shiny_female": null
|
||||||
|
},
|
||||||
|
"platinum": {
|
||||||
|
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/platinum/back/132.png",
|
||||||
|
"back_female": null,
|
||||||
|
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/platinum/back/shiny/132.png",
|
||||||
|
"back_shiny_female": null,
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/platinum/132.png",
|
||||||
|
"front_female": null,
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/platinum/shiny/132.png",
|
||||||
|
"front_shiny_female": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"generation-v": {
|
||||||
|
"black-white": {
|
||||||
|
"animated": {
|
||||||
|
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/animated/back/132.gif",
|
||||||
|
"back_female": null,
|
||||||
|
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/animated/back/shiny/132.gif",
|
||||||
|
"back_shiny_female": null,
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/animated/132.gif",
|
||||||
|
"front_female": null,
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/animated/shiny/132.gif",
|
||||||
|
"front_shiny_female": null
|
||||||
|
},
|
||||||
|
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/back/132.png",
|
||||||
|
"back_female": null,
|
||||||
|
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/back/shiny/132.png",
|
||||||
|
"back_shiny_female": null,
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/132.png",
|
||||||
|
"front_female": null,
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/shiny/132.png",
|
||||||
|
"front_shiny_female": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"generation-vi": {
|
||||||
|
"omegaruby-alphasapphire": {
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vi/omegaruby-alphasapphire/132.png",
|
||||||
|
"front_female": null,
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vi/omegaruby-alphasapphire/shiny/132.png",
|
||||||
|
"front_shiny_female": null
|
||||||
|
},
|
||||||
|
"x-y": {
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vi/x-y/132.png",
|
||||||
|
"front_female": null,
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vi/x-y/shiny/132.png",
|
||||||
|
"front_shiny_female": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"generation-vii": {
|
||||||
|
"icons": {
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vii/icons/132.png",
|
||||||
|
"front_female": null
|
||||||
|
},
|
||||||
|
"ultra-sun-ultra-moon": {
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vii/ultra-sun-ultra-moon/132.png",
|
||||||
|
"front_female": null,
|
||||||
|
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vii/ultra-sun-ultra-moon/shiny/132.png",
|
||||||
|
"front_shiny_female": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"generation-viii": {
|
||||||
|
"icons": {
|
||||||
|
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-viii/icons/132.png",
|
||||||
|
"front_female": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"stats": [
|
||||||
|
{
|
||||||
|
"base_stat": 48,
|
||||||
|
"effort": 1,
|
||||||
|
"stat": {
|
||||||
|
"name": "hp",
|
||||||
|
"url": "https://pokeapi.co/api/v2/stat/1/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"base_stat": 48,
|
||||||
|
"effort": 0,
|
||||||
|
"stat": {
|
||||||
|
"name": "attack",
|
||||||
|
"url": "https://pokeapi.co/api/v2/stat/2/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"base_stat": 48,
|
||||||
|
"effort": 0,
|
||||||
|
"stat": {
|
||||||
|
"name": "defense",
|
||||||
|
"url": "https://pokeapi.co/api/v2/stat/3/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"base_stat": 48,
|
||||||
|
"effort": 0,
|
||||||
|
"stat": {
|
||||||
|
"name": "special-attack",
|
||||||
|
"url": "https://pokeapi.co/api/v2/stat/4/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"base_stat": 48,
|
||||||
|
"effort": 0,
|
||||||
|
"stat": {
|
||||||
|
"name": "special-defense",
|
||||||
|
"url": "https://pokeapi.co/api/v2/stat/5/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"base_stat": 48,
|
||||||
|
"effort": 0,
|
||||||
|
"stat": {
|
||||||
|
"name": "speed",
|
||||||
|
"url": "https://pokeapi.co/api/v2/stat/6/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"slot": 1,
|
||||||
|
"type": {
|
||||||
|
"name": "normal",
|
||||||
|
"url": "https://pokeapi.co/api/v2/type/1/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"weight": 40
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
[
|
||||||
|
"There has never been a sadness that can’t been cured by breakfast food.",
|
||||||
|
"Dear frozen yogurt, you are the celery of desserts. Be ice cream or be nothing. Zero stars.",
|
||||||
|
"Shorts over six inches are capri pants, shorts under six inches are European.",
|
||||||
|
"Sting like a bee. Do not float like a butterfly. That’s ridiculous.",
|
||||||
|
"Well, I am not usually one for speeches. So, goodbye.",
|
||||||
|
"I change my locks every 16 days.",
|
||||||
|
"Are you going to tell a man that he can't fart in his own car?",
|
||||||
|
"I love nothing.",
|
||||||
|
"Fishing relaxes me. It's like yoga, except I still get to kill something.",
|
||||||
|
"My son is several weeks old. He is very familiar with the sound of power tools.",
|
||||||
|
"Do you have any history of mental illness in your family? I have an uncle who does yoga.",
|
||||||
|
"If there were more food and fewer people, this would be a perfect party.",
|
||||||
|
"The three most useless jobs in the world in order are: lawyer, congressman, and doctor.",
|
||||||
|
"One rage every three months is permitted. Try not to hurt anyone who doesn't deserve it.",
|
||||||
|
"I hate everything.",
|
||||||
|
"I’ve had the same haircut since 1978 and I’ve driven the same car since 1991. I’ve used the same wooden comb for three decades. I have one bowl. I still get my milk delivered by horse.",
|
||||||
|
"Tom put all my records into this rectangle!",
|
||||||
|
"It’s pointless for a human to paint scenes of nature when they can go outside and stand in it.",
|
||||||
|
"My first ex-wife’s name is Tammy. My second ex-wife’s name is Tammy. My Mom’s name is Tamara…she goes by Tammy.",
|
||||||
|
"Live your life how you want, but don’t confuse drama with happiness."
|
||||||
|
]
|
||||||
@@ -53,10 +53,11 @@
|
|||||||
"@types/lodash-es": "^4.17.6",
|
"@types/lodash-es": "^4.17.6",
|
||||||
"@types/react": "^17.0.24",
|
"@types/react": "^17.0.24",
|
||||||
"@types/react-dom": "^17.0.9",
|
"@types/react-dom": "^17.0.9",
|
||||||
|
"@types/ua-parser-js": "^0.7.36",
|
||||||
"concurrently": "^7.0.0",
|
"concurrently": "^7.0.0",
|
||||||
"esbuild-visualizer": "^0.3.1",
|
"esbuild-visualizer": "^0.3.1",
|
||||||
"jest": "^27.4.7",
|
"jest": "^27.4.7",
|
||||||
"miniflare": "^2.1.0",
|
"miniflare": "^2.4.0",
|
||||||
"patch-package": "^6.4.7",
|
"patch-package": "^6.4.7",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"tailwindcss": "^3.0.22",
|
"tailwindcss": "^3.0.22",
|
||||||
@@ -1724,9 +1725,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jsonhero/json-infer-types": {
|
"node_modules/@jsonhero/json-infer-types": {
|
||||||
"version": "1.2.9",
|
"version": "1.2.10",
|
||||||
"resolved": "https://registry.npmjs.org/@jsonhero/json-infer-types/-/json-infer-types-1.2.9.tgz",
|
"resolved": "https://registry.npmjs.org/@jsonhero/json-infer-types/-/json-infer-types-1.2.10.tgz",
|
||||||
"integrity": "sha512-QuIOEy7M57bB4fhwadtDUQv5HjrUFD9SXjvQfWUMSQ6zOL8l9S9SV/wRQCn0y0dal+xZPBoMoDqTMJyEBIHnQQ==",
|
"integrity": "sha512-D91mdtH59U76CRflPZrRfkPMuUPQjBaCqDpH18WnSC0tTqLKymF11XAGcY0KLeXoFd2EqJu9Q8HwxsFOTQQa8A==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ip-address": "^8.1.0",
|
"ip-address": "^8.1.0",
|
||||||
"json5": "^2.2.0",
|
"json5": "^2.2.0",
|
||||||
@@ -1793,13 +1794,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/cache": {
|
"node_modules/@miniflare/cache": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.4.0.tgz",
|
||||||
"integrity": "sha512-lOf3WVtrs0ac7KOtsQ+JOGHWR90zsqqJbolE+Wt4hIZuvM2U3t1RD2Ms7U20J301msVIsBAd02IL57H95LXQtQ==",
|
"integrity": "sha512-tMDXlUVlThgFubJmlxZoKmLK8kBxDmuMbVMt7csHpXegzkuo2TmIsDqBE/C3CRiJ5xeCQgpD6iZtKBu5Zn5fRA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@miniflare/core": "2.3.0",
|
"@miniflare/core": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"http-cache-semantics": "^4.1.0",
|
"http-cache-semantics": "^4.1.0",
|
||||||
"undici": "4.13.0"
|
"undici": "4.13.0"
|
||||||
},
|
},
|
||||||
@@ -1808,12 +1809,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/cli-parser": {
|
"node_modules/@miniflare/cli-parser": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.4.0.tgz",
|
||||||
"integrity": "sha512-yQzU+OBBvWshr9qVxAe6bWXJLNfpmLYrfkfR3u+rPOo2LYnccWg0f/8jtxrXM1TIyu+tCOJGqCODpO//XtrwWw==",
|
"integrity": "sha512-Xr5lO8f+oIr9r/b2dfo0on1p0MNN+pkwRHWoY5ACSnp9FaGnwm/g71DM7AajIQPIk0TpRsSVNDx8Ygj1LPT+sQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"kleur": "^4.1.4"
|
"kleur": "^4.1.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1821,14 +1822,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/core": {
|
"node_modules/@miniflare/core": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.4.0.tgz",
|
||||||
"integrity": "sha512-Dltb3p+Uq5Lx53DuInckHYaDoMrBq49HE/p/oUDXmzHmQy7EAM6v+nJGKmiM9Uen4OqyqsmlmPWqntSMjaX7Jg==",
|
"integrity": "sha512-vYl8xaWTFzxtkbzx3IkT4Py0OAFdfmFnVo627O1HKHWVGlkjVr8UKtxBpIR+f5pq/HCMzzqA1HM9FXO0dQfy3A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"@miniflare/watcher": "2.3.0",
|
"@miniflare/watcher": "2.4.0",
|
||||||
"busboy": "^0.3.1",
|
"busboy": "^0.3.1",
|
||||||
"dotenv": "^10.0.0",
|
"dotenv": "^10.0.0",
|
||||||
"kleur": "^4.1.4",
|
"kleur": "^4.1.4",
|
||||||
@@ -1840,14 +1841,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/durable-objects": {
|
"node_modules/@miniflare/durable-objects": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.4.0.tgz",
|
||||||
"integrity": "sha512-YuzxBBu9xBU3xxD4TzGdeVVMXrE76AWJE4MIqkJR5UmASqayyv//cApGw3+C01NHe07cpbrTM1QTgFo2eBncwQ==",
|
"integrity": "sha512-VVLaUXXcAQcYE/3YmDLTacZf5OzR8bib6q1T9NqVb0uK5sLMQqyHvQdsG5rMqs7iyxfJxyZ0bL2OW9XGALOkoQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@miniflare/core": "2.3.0",
|
"@miniflare/core": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"@miniflare/storage-memory": "2.3.0",
|
"@miniflare/storage-memory": "2.4.0",
|
||||||
"undici": "4.13.0"
|
"undici": "4.13.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1855,13 +1856,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/html-rewriter": {
|
"node_modules/@miniflare/html-rewriter": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.4.0.tgz",
|
||||||
"integrity": "sha512-cyWhmQgzhtRlBeg0mxP5FmAq/75ChuLwWQlhokx88XkGnteuh0/DOk3OxIMaveF2oDHKmIlLFgSlzv4NbT1Mng==",
|
"integrity": "sha512-ZG8819N7LelDD+8+Ss5FZpVyQQq/V2igod0qE68JK4he/w4/yn57Rk6Efb49y15HoHAXl2RpCCsnCyIow/Xjug==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@miniflare/core": "2.3.0",
|
"@miniflare/core": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"html-rewriter-wasm": "^0.4.1",
|
"html-rewriter-wasm": "^0.4.1",
|
||||||
"undici": "4.13.0"
|
"undici": "4.13.0"
|
||||||
},
|
},
|
||||||
@@ -1870,14 +1871,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/http-server": {
|
"node_modules/@miniflare/http-server": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.4.0.tgz",
|
||||||
"integrity": "sha512-jTzsRuro3yWVb4T85znBGw1w+ydimgi2PJvHrTuGFKDjFam+R037fGH+HZCAjAgPiBHTroXfkeSXypJLXbQBEg==",
|
"integrity": "sha512-r6Z/nqxE0oa1z63L95yvnG0PUeLRxZOeGS7ADxZMFKan4WD5lvYtSKDuDEm0lkbQshCOHQ3uXFr0cotOm8JoMQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@miniflare/core": "2.3.0",
|
"@miniflare/core": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"@miniflare/web-sockets": "2.3.0",
|
"@miniflare/web-sockets": "2.4.0",
|
||||||
"kleur": "^4.1.4",
|
"kleur": "^4.1.4",
|
||||||
"selfsigned": "^2.0.0",
|
"selfsigned": "^2.0.0",
|
||||||
"undici": "4.13.0",
|
"undici": "4.13.0",
|
||||||
@@ -1889,9 +1890,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/http-server/node_modules/ws": {
|
"node_modules/@miniflare/http-server/node_modules/ws": {
|
||||||
"version": "8.5.0",
|
"version": "8.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz",
|
||||||
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
|
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
@@ -1910,37 +1911,37 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/kv": {
|
"node_modules/@miniflare/kv": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.4.0.tgz",
|
||||||
"integrity": "sha512-m0zu5sRoaFDm+WVTnLRrz8+77b6eVxQN7cLN6ZQiKP3Nd8cAggPdaIIef8dVksWbPvOW9DztoUVZTB1v9EOaLA==",
|
"integrity": "sha512-1UW7f1386xR6EDEXNZOR1TpFwQfRRSxUPqD6m/U0WprlsbM0cIYGz+AUeaVbkFf8lfE2MeXCUrjbWsLOvsnw3g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@miniflare/shared": "2.3.0"
|
"@miniflare/shared": "2.4.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.7"
|
"node": ">=16.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/runner-vm": {
|
"node_modules/@miniflare/runner-vm": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.4.0.tgz",
|
||||||
"integrity": "sha512-/aB997YodNcRFxtlnvEn4BJSIqKXRw29FexOqCWwWv+b7XQkTTxd4IfSocIFi6du3265gp85icqP/hxsLAQBVg==",
|
"integrity": "sha512-7sdwBYzXQTwYeR3tTvQ+vJfzc7BXwqR8AUPK9l5gvCtg+Geq9sMslr5SikIJpgcvbYqKDjvC9DQEPJ3sqr9cSQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@miniflare/shared": "2.3.0"
|
"@miniflare/shared": "2.4.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.7"
|
"node": ">=16.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/scheduler": {
|
"node_modules/@miniflare/scheduler": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.4.0.tgz",
|
||||||
"integrity": "sha512-Er80srMNXbxqGbYXtiZkD8UlveHsw4cpwcytQgsEJCHG7/48vC/rpmtN0zKOWFEHifaOUvHhURZRJu+S2E4Stg==",
|
"integrity": "sha512-dfMCXoAS8Y+3xABNxYju62I2xIBS54Op7ohCHoatvAM5RvualJUPICEMPZzX6/z29q5xPIeSLhLDhl/asAQ19w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@miniflare/core": "2.3.0",
|
"@miniflare/core": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"cron-schedule": "^3.0.4"
|
"cron-schedule": "^3.0.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1948,9 +1949,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/shared": {
|
"node_modules/@miniflare/shared": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.4.0.tgz",
|
||||||
"integrity": "sha512-TvCSUe1op5AKINx3zHSSdfAbdoV3eSF3MzeVQA4+1NmtuefY8cjujQCdILeAxg3oPbHXaZkc7j1zZ13rYdvwGQ==",
|
"integrity": "sha512-lPQFzBUVGNQ93gQ/dliToWnO0OqAgsD3/902Pd/IixVSRwRj3BTnYv2dHMUKZcODBPrhnbqZeqcPWdBLzEx8uw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ignore": "^5.1.8",
|
"ignore": "^5.1.8",
|
||||||
@@ -1961,64 +1962,64 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/sites": {
|
"node_modules/@miniflare/sites": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.4.0.tgz",
|
||||||
"integrity": "sha512-WkRBxQbf6k/eS1D/D1mw30Zs253TFeIkWFh8HQ8Z36Kdt79rNVezT9YmRpahUfvYXmubTquV5JftNOAhvbOJXA==",
|
"integrity": "sha512-YZy/TujnR1lkBvCncDDQ8tsWsXRE4JJ4x9a0bKN/XnZh7r6OhDM0sw4BFcBQhT6Ukdtttam1O3FlJxnMitrDGg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@miniflare/kv": "2.3.0",
|
"@miniflare/kv": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"@miniflare/storage-file": "2.3.0"
|
"@miniflare/storage-file": "2.4.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.7"
|
"node": ">=16.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/storage-file": {
|
"node_modules/@miniflare/storage-file": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.4.0.tgz",
|
||||||
"integrity": "sha512-1rda/MC0R8wVC6N7Na2EdSGNAZv6o/yugp7Z+GikJ1vbgi1+9soAczDzFtaq4jrBzAkCFOMT79DgkSKSl59vxg==",
|
"integrity": "sha512-f1AUMz8xps/4VhNJMb8JeCevZFeU4pg2lIWmC11gG4xeq2nibTPBi6Qtx594Le7ZKij/tF6rRsoNfGau2Q5gdw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"@miniflare/storage-memory": "2.3.0"
|
"@miniflare/storage-memory": "2.4.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.7"
|
"node": ">=16.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/storage-memory": {
|
"node_modules/@miniflare/storage-memory": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.4.0.tgz",
|
||||||
"integrity": "sha512-cMqQK9neRySchoNUVhQYOmLFrYkAjT5V113Wfxmsz93dladQ1/mXOsndqPrlb+5hhnwbw4Ns67nyzkHUe9sX/g==",
|
"integrity": "sha512-mhWwgHhDNtEa7y1bYbdVucV0lqUmzagYXUSppAdSGS5JPyJMyw3HseqRNTk6gC/vKlvEYlFf3ugWcREGCedr9A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@miniflare/shared": "2.3.0"
|
"@miniflare/shared": "2.4.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.7"
|
"node": ">=16.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/watcher": {
|
"node_modules/@miniflare/watcher": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.4.0.tgz",
|
||||||
"integrity": "sha512-G0ZE9WHIcdR2TlPXwwQabULDIMZ9LujfC0tn+yXmPXKxgWoJWcWFmUbkhVDcOJzkIz2TAhRlLbW11n8nChUHFQ==",
|
"integrity": "sha512-gDQRUxwOjmctvowyd4Hcdy3fjxz3ERKzirp6TvA3AWUohKZk3IhwGlaA8aCwbdP+ELYQlG5wK44AfLSGi956fg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@miniflare/shared": "2.3.0"
|
"@miniflare/shared": "2.4.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.7"
|
"node": ">=16.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/web-sockets": {
|
"node_modules/@miniflare/web-sockets": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.4.0.tgz",
|
||||||
"integrity": "sha512-3xcPG1vfiMb2obVC4jNtS5VzUxzM1rdUrWPCG86gpZaHky0xC1U7Tp+eFdxQFTty99HPYrrVKXl1ww2h1LGWRA==",
|
"integrity": "sha512-cz/cN0GoQOXRLh80UmlcEJODPIw2ijKBK3PLRzvfTzqQ5avK6wp2M8Fj8C/5JIT6g7siwvBANyKXD3U3RpKGHQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@miniflare/core": "2.3.0",
|
"@miniflare/core": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"undici": "4.13.0",
|
"undici": "4.13.0",
|
||||||
"ws": "^8.2.2"
|
"ws": "^8.2.2"
|
||||||
},
|
},
|
||||||
@@ -2027,9 +2028,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@miniflare/web-sockets/node_modules/ws": {
|
"node_modules/@miniflare/web-sockets/node_modules/ws": {
|
||||||
"version": "8.5.0",
|
"version": "8.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz",
|
||||||
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
|
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
@@ -3050,6 +3051,12 @@
|
|||||||
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
|
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/ua-parser-js": {
|
||||||
|
"version": "0.7.36",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz",
|
||||||
|
"integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/unist": {
|
"node_modules/@types/unist": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
|
||||||
@@ -4396,9 +4403,9 @@
|
|||||||
"integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA=="
|
"integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA=="
|
||||||
},
|
},
|
||||||
"node_modules/cron-schedule": {
|
"node_modules/cron-schedule": {
|
||||||
"version": "3.0.5",
|
"version": "3.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-3.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-3.0.6.tgz",
|
||||||
"integrity": "sha512-YjtB4jy7RJEX8j9GokHp+y8S/ihCHjrD2Z3E13LSGP/+G0Sdv+MEKsZu5wPLLWwW1HQc4HwpGMFU3GUTStZTaA==",
|
"integrity": "sha512-izfGgKyzzIyLaeb1EtZ3KbglkS6AKp9cv7LxmiyoOu+fXfol1tQDC0Cof0enVZGNtudTHW+3lfuW9ZkLQss4Wg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/cross-spawn": {
|
"node_modules/cross-spawn": {
|
||||||
@@ -10236,25 +10243,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/miniflare": {
|
"node_modules/miniflare": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.4.0.tgz",
|
||||||
"integrity": "sha512-0lK4Df+jfqLDSDDgj4AOJffb1G6sN7XvB5QGUaquEakW+qPdurydyNhFKcFKBgpk4ozN6WTmB2x802iPXQcJJQ==",
|
"integrity": "sha512-xOBL/dQsUL95rxIYO+KrrVPPpm2TAf6TKl4AvhcjSfUeVkzDWd/y9f7hXCt8x6srDoK0Z2LpYouatvSfSUzGOw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@miniflare/cache": "2.3.0",
|
"@miniflare/cache": "2.4.0",
|
||||||
"@miniflare/cli-parser": "2.3.0",
|
"@miniflare/cli-parser": "2.4.0",
|
||||||
"@miniflare/core": "2.3.0",
|
"@miniflare/core": "2.4.0",
|
||||||
"@miniflare/durable-objects": "2.3.0",
|
"@miniflare/durable-objects": "2.4.0",
|
||||||
"@miniflare/html-rewriter": "2.3.0",
|
"@miniflare/html-rewriter": "2.4.0",
|
||||||
"@miniflare/http-server": "2.3.0",
|
"@miniflare/http-server": "2.4.0",
|
||||||
"@miniflare/kv": "2.3.0",
|
"@miniflare/kv": "2.4.0",
|
||||||
"@miniflare/runner-vm": "2.3.0",
|
"@miniflare/runner-vm": "2.4.0",
|
||||||
"@miniflare/scheduler": "2.3.0",
|
"@miniflare/scheduler": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"@miniflare/sites": "2.3.0",
|
"@miniflare/sites": "2.4.0",
|
||||||
"@miniflare/storage-file": "2.3.0",
|
"@miniflare/storage-file": "2.4.0",
|
||||||
"@miniflare/storage-memory": "2.3.0",
|
"@miniflare/storage-memory": "2.4.0",
|
||||||
"@miniflare/web-sockets": "2.3.0",
|
"@miniflare/web-sockets": "2.4.0",
|
||||||
"kleur": "^4.1.4",
|
"kleur": "^4.1.4",
|
||||||
"semiver": "^1.1.0",
|
"semiver": "^1.1.0",
|
||||||
"source-map-support": "^0.5.20",
|
"source-map-support": "^0.5.20",
|
||||||
@@ -10267,7 +10274,7 @@
|
|||||||
"node": ">=16.7"
|
"node": ">=16.7"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@miniflare/storage-redis": "2.3.0",
|
"@miniflare/storage-redis": "2.4.0",
|
||||||
"cron-schedule": "^3.0.4",
|
"cron-schedule": "^3.0.4",
|
||||||
"ioredis": "^4.27.9"
|
"ioredis": "^4.27.9"
|
||||||
},
|
},
|
||||||
@@ -10491,9 +10498,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/node-forge": {
|
"node_modules/node-forge": {
|
||||||
"version": "1.2.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
|
||||||
"integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==",
|
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 6.13.0"
|
"node": ">= 6.13.0"
|
||||||
@@ -11919,12 +11926,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/selfsigned": {
|
"node_modules/selfsigned": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.1.tgz",
|
||||||
"integrity": "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==",
|
"integrity": "sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-forge": "^1.2.0"
|
"node-forge": "^1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
@@ -14905,9 +14912,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@jsonhero/json-infer-types": {
|
"@jsonhero/json-infer-types": {
|
||||||
"version": "1.2.9",
|
"version": "1.2.10",
|
||||||
"resolved": "https://registry.npmjs.org/@jsonhero/json-infer-types/-/json-infer-types-1.2.9.tgz",
|
"resolved": "https://registry.npmjs.org/@jsonhero/json-infer-types/-/json-infer-types-1.2.10.tgz",
|
||||||
"integrity": "sha512-QuIOEy7M57bB4fhwadtDUQv5HjrUFD9SXjvQfWUMSQ6zOL8l9S9SV/wRQCn0y0dal+xZPBoMoDqTMJyEBIHnQQ==",
|
"integrity": "sha512-D91mdtH59U76CRflPZrRfkPMuUPQjBaCqDpH18WnSC0tTqLKymF11XAGcY0KLeXoFd2EqJu9Q8HwxsFOTQQa8A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ip-address": "^8.1.0",
|
"ip-address": "^8.1.0",
|
||||||
"json5": "^2.2.0",
|
"json5": "^2.2.0",
|
||||||
@@ -14962,36 +14969,36 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/cache": {
|
"@miniflare/cache": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.4.0.tgz",
|
||||||
"integrity": "sha512-lOf3WVtrs0ac7KOtsQ+JOGHWR90zsqqJbolE+Wt4hIZuvM2U3t1RD2Ms7U20J301msVIsBAd02IL57H95LXQtQ==",
|
"integrity": "sha512-tMDXlUVlThgFubJmlxZoKmLK8kBxDmuMbVMt7csHpXegzkuo2TmIsDqBE/C3CRiJ5xeCQgpD6iZtKBu5Zn5fRA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@miniflare/core": "2.3.0",
|
"@miniflare/core": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"http-cache-semantics": "^4.1.0",
|
"http-cache-semantics": "^4.1.0",
|
||||||
"undici": "4.13.0"
|
"undici": "4.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/cli-parser": {
|
"@miniflare/cli-parser": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.4.0.tgz",
|
||||||
"integrity": "sha512-yQzU+OBBvWshr9qVxAe6bWXJLNfpmLYrfkfR3u+rPOo2LYnccWg0f/8jtxrXM1TIyu+tCOJGqCODpO//XtrwWw==",
|
"integrity": "sha512-Xr5lO8f+oIr9r/b2dfo0on1p0MNN+pkwRHWoY5ACSnp9FaGnwm/g71DM7AajIQPIk0TpRsSVNDx8Ygj1LPT+sQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"kleur": "^4.1.4"
|
"kleur": "^4.1.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/core": {
|
"@miniflare/core": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.4.0.tgz",
|
||||||
"integrity": "sha512-Dltb3p+Uq5Lx53DuInckHYaDoMrBq49HE/p/oUDXmzHmQy7EAM6v+nJGKmiM9Uen4OqyqsmlmPWqntSMjaX7Jg==",
|
"integrity": "sha512-vYl8xaWTFzxtkbzx3IkT4Py0OAFdfmFnVo627O1HKHWVGlkjVr8UKtxBpIR+f5pq/HCMzzqA1HM9FXO0dQfy3A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"@miniflare/watcher": "2.3.0",
|
"@miniflare/watcher": "2.4.0",
|
||||||
"busboy": "^0.3.1",
|
"busboy": "^0.3.1",
|
||||||
"dotenv": "^10.0.0",
|
"dotenv": "^10.0.0",
|
||||||
"kleur": "^4.1.4",
|
"kleur": "^4.1.4",
|
||||||
@@ -15000,38 +15007,38 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/durable-objects": {
|
"@miniflare/durable-objects": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.4.0.tgz",
|
||||||
"integrity": "sha512-YuzxBBu9xBU3xxD4TzGdeVVMXrE76AWJE4MIqkJR5UmASqayyv//cApGw3+C01NHe07cpbrTM1QTgFo2eBncwQ==",
|
"integrity": "sha512-VVLaUXXcAQcYE/3YmDLTacZf5OzR8bib6q1T9NqVb0uK5sLMQqyHvQdsG5rMqs7iyxfJxyZ0bL2OW9XGALOkoQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@miniflare/core": "2.3.0",
|
"@miniflare/core": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"@miniflare/storage-memory": "2.3.0",
|
"@miniflare/storage-memory": "2.4.0",
|
||||||
"undici": "4.13.0"
|
"undici": "4.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/html-rewriter": {
|
"@miniflare/html-rewriter": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.4.0.tgz",
|
||||||
"integrity": "sha512-cyWhmQgzhtRlBeg0mxP5FmAq/75ChuLwWQlhokx88XkGnteuh0/DOk3OxIMaveF2oDHKmIlLFgSlzv4NbT1Mng==",
|
"integrity": "sha512-ZG8819N7LelDD+8+Ss5FZpVyQQq/V2igod0qE68JK4he/w4/yn57Rk6Efb49y15HoHAXl2RpCCsnCyIow/Xjug==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@miniflare/core": "2.3.0",
|
"@miniflare/core": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"html-rewriter-wasm": "^0.4.1",
|
"html-rewriter-wasm": "^0.4.1",
|
||||||
"undici": "4.13.0"
|
"undici": "4.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/http-server": {
|
"@miniflare/http-server": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.4.0.tgz",
|
||||||
"integrity": "sha512-jTzsRuro3yWVb4T85znBGw1w+ydimgi2PJvHrTuGFKDjFam+R037fGH+HZCAjAgPiBHTroXfkeSXypJLXbQBEg==",
|
"integrity": "sha512-r6Z/nqxE0oa1z63L95yvnG0PUeLRxZOeGS7ADxZMFKan4WD5lvYtSKDuDEm0lkbQshCOHQ3uXFr0cotOm8JoMQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@miniflare/core": "2.3.0",
|
"@miniflare/core": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"@miniflare/web-sockets": "2.3.0",
|
"@miniflare/web-sockets": "2.4.0",
|
||||||
"kleur": "^4.1.4",
|
"kleur": "^4.1.4",
|
||||||
"selfsigned": "^2.0.0",
|
"selfsigned": "^2.0.0",
|
||||||
"undici": "4.13.0",
|
"undici": "4.13.0",
|
||||||
@@ -15040,47 +15047,47 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ws": {
|
"ws": {
|
||||||
"version": "8.5.0",
|
"version": "8.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz",
|
||||||
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
|
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {}
|
"requires": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/kv": {
|
"@miniflare/kv": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.4.0.tgz",
|
||||||
"integrity": "sha512-m0zu5sRoaFDm+WVTnLRrz8+77b6eVxQN7cLN6ZQiKP3Nd8cAggPdaIIef8dVksWbPvOW9DztoUVZTB1v9EOaLA==",
|
"integrity": "sha512-1UW7f1386xR6EDEXNZOR1TpFwQfRRSxUPqD6m/U0WprlsbM0cIYGz+AUeaVbkFf8lfE2MeXCUrjbWsLOvsnw3g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@miniflare/shared": "2.3.0"
|
"@miniflare/shared": "2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/runner-vm": {
|
"@miniflare/runner-vm": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.4.0.tgz",
|
||||||
"integrity": "sha512-/aB997YodNcRFxtlnvEn4BJSIqKXRw29FexOqCWwWv+b7XQkTTxd4IfSocIFi6du3265gp85icqP/hxsLAQBVg==",
|
"integrity": "sha512-7sdwBYzXQTwYeR3tTvQ+vJfzc7BXwqR8AUPK9l5gvCtg+Geq9sMslr5SikIJpgcvbYqKDjvC9DQEPJ3sqr9cSQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@miniflare/shared": "2.3.0"
|
"@miniflare/shared": "2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/scheduler": {
|
"@miniflare/scheduler": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.4.0.tgz",
|
||||||
"integrity": "sha512-Er80srMNXbxqGbYXtiZkD8UlveHsw4cpwcytQgsEJCHG7/48vC/rpmtN0zKOWFEHifaOUvHhURZRJu+S2E4Stg==",
|
"integrity": "sha512-dfMCXoAS8Y+3xABNxYju62I2xIBS54Op7ohCHoatvAM5RvualJUPICEMPZzX6/z29q5xPIeSLhLDhl/asAQ19w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@miniflare/core": "2.3.0",
|
"@miniflare/core": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"cron-schedule": "^3.0.4"
|
"cron-schedule": "^3.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/shared": {
|
"@miniflare/shared": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.4.0.tgz",
|
||||||
"integrity": "sha512-TvCSUe1op5AKINx3zHSSdfAbdoV3eSF3MzeVQA4+1NmtuefY8cjujQCdILeAxg3oPbHXaZkc7j1zZ13rYdvwGQ==",
|
"integrity": "sha512-lPQFzBUVGNQ93gQ/dliToWnO0OqAgsD3/902Pd/IixVSRwRj3BTnYv2dHMUKZcODBPrhnbqZeqcPWdBLzEx8uw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ignore": "^5.1.8",
|
"ignore": "^5.1.8",
|
||||||
@@ -15088,60 +15095,60 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/sites": {
|
"@miniflare/sites": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.4.0.tgz",
|
||||||
"integrity": "sha512-WkRBxQbf6k/eS1D/D1mw30Zs253TFeIkWFh8HQ8Z36Kdt79rNVezT9YmRpahUfvYXmubTquV5JftNOAhvbOJXA==",
|
"integrity": "sha512-YZy/TujnR1lkBvCncDDQ8tsWsXRE4JJ4x9a0bKN/XnZh7r6OhDM0sw4BFcBQhT6Ukdtttam1O3FlJxnMitrDGg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@miniflare/kv": "2.3.0",
|
"@miniflare/kv": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"@miniflare/storage-file": "2.3.0"
|
"@miniflare/storage-file": "2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/storage-file": {
|
"@miniflare/storage-file": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.4.0.tgz",
|
||||||
"integrity": "sha512-1rda/MC0R8wVC6N7Na2EdSGNAZv6o/yugp7Z+GikJ1vbgi1+9soAczDzFtaq4jrBzAkCFOMT79DgkSKSl59vxg==",
|
"integrity": "sha512-f1AUMz8xps/4VhNJMb8JeCevZFeU4pg2lIWmC11gG4xeq2nibTPBi6Qtx594Le7ZKij/tF6rRsoNfGau2Q5gdw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"@miniflare/storage-memory": "2.3.0"
|
"@miniflare/storage-memory": "2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/storage-memory": {
|
"@miniflare/storage-memory": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.4.0.tgz",
|
||||||
"integrity": "sha512-cMqQK9neRySchoNUVhQYOmLFrYkAjT5V113Wfxmsz93dladQ1/mXOsndqPrlb+5hhnwbw4Ns67nyzkHUe9sX/g==",
|
"integrity": "sha512-mhWwgHhDNtEa7y1bYbdVucV0lqUmzagYXUSppAdSGS5JPyJMyw3HseqRNTk6gC/vKlvEYlFf3ugWcREGCedr9A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@miniflare/shared": "2.3.0"
|
"@miniflare/shared": "2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/watcher": {
|
"@miniflare/watcher": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.4.0.tgz",
|
||||||
"integrity": "sha512-G0ZE9WHIcdR2TlPXwwQabULDIMZ9LujfC0tn+yXmPXKxgWoJWcWFmUbkhVDcOJzkIz2TAhRlLbW11n8nChUHFQ==",
|
"integrity": "sha512-gDQRUxwOjmctvowyd4Hcdy3fjxz3ERKzirp6TvA3AWUohKZk3IhwGlaA8aCwbdP+ELYQlG5wK44AfLSGi956fg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@miniflare/shared": "2.3.0"
|
"@miniflare/shared": "2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@miniflare/web-sockets": {
|
"@miniflare/web-sockets": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.4.0.tgz",
|
||||||
"integrity": "sha512-3xcPG1vfiMb2obVC4jNtS5VzUxzM1rdUrWPCG86gpZaHky0xC1U7Tp+eFdxQFTty99HPYrrVKXl1ww2h1LGWRA==",
|
"integrity": "sha512-cz/cN0GoQOXRLh80UmlcEJODPIw2ijKBK3PLRzvfTzqQ5avK6wp2M8Fj8C/5JIT6g7siwvBANyKXD3U3RpKGHQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@miniflare/core": "2.3.0",
|
"@miniflare/core": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"undici": "4.13.0",
|
"undici": "4.13.0",
|
||||||
"ws": "^8.2.2"
|
"ws": "^8.2.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ws": {
|
"ws": {
|
||||||
"version": "8.5.0",
|
"version": "8.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz",
|
||||||
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
|
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {}
|
"requires": {}
|
||||||
}
|
}
|
||||||
@@ -16018,6 +16025,12 @@
|
|||||||
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
|
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/ua-parser-js": {
|
||||||
|
"version": "0.7.36",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz",
|
||||||
|
"integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/unist": {
|
"@types/unist": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
|
||||||
@@ -17037,9 +17050,9 @@
|
|||||||
"integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA=="
|
"integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA=="
|
||||||
},
|
},
|
||||||
"cron-schedule": {
|
"cron-schedule": {
|
||||||
"version": "3.0.5",
|
"version": "3.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-3.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-3.0.6.tgz",
|
||||||
"integrity": "sha512-YjtB4jy7RJEX8j9GokHp+y8S/ihCHjrD2Z3E13LSGP/+G0Sdv+MEKsZu5wPLLWwW1HQc4HwpGMFU3GUTStZTaA==",
|
"integrity": "sha512-izfGgKyzzIyLaeb1EtZ3KbglkS6AKp9cv7LxmiyoOu+fXfol1tQDC0Cof0enVZGNtudTHW+3lfuW9ZkLQss4Wg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"cross-spawn": {
|
"cross-spawn": {
|
||||||
@@ -21188,25 +21201,25 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"miniflare": {
|
"miniflare": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.4.0.tgz",
|
||||||
"integrity": "sha512-0lK4Df+jfqLDSDDgj4AOJffb1G6sN7XvB5QGUaquEakW+qPdurydyNhFKcFKBgpk4ozN6WTmB2x802iPXQcJJQ==",
|
"integrity": "sha512-xOBL/dQsUL95rxIYO+KrrVPPpm2TAf6TKl4AvhcjSfUeVkzDWd/y9f7hXCt8x6srDoK0Z2LpYouatvSfSUzGOw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@miniflare/cache": "2.3.0",
|
"@miniflare/cache": "2.4.0",
|
||||||
"@miniflare/cli-parser": "2.3.0",
|
"@miniflare/cli-parser": "2.4.0",
|
||||||
"@miniflare/core": "2.3.0",
|
"@miniflare/core": "2.4.0",
|
||||||
"@miniflare/durable-objects": "2.3.0",
|
"@miniflare/durable-objects": "2.4.0",
|
||||||
"@miniflare/html-rewriter": "2.3.0",
|
"@miniflare/html-rewriter": "2.4.0",
|
||||||
"@miniflare/http-server": "2.3.0",
|
"@miniflare/http-server": "2.4.0",
|
||||||
"@miniflare/kv": "2.3.0",
|
"@miniflare/kv": "2.4.0",
|
||||||
"@miniflare/runner-vm": "2.3.0",
|
"@miniflare/runner-vm": "2.4.0",
|
||||||
"@miniflare/scheduler": "2.3.0",
|
"@miniflare/scheduler": "2.4.0",
|
||||||
"@miniflare/shared": "2.3.0",
|
"@miniflare/shared": "2.4.0",
|
||||||
"@miniflare/sites": "2.3.0",
|
"@miniflare/sites": "2.4.0",
|
||||||
"@miniflare/storage-file": "2.3.0",
|
"@miniflare/storage-file": "2.4.0",
|
||||||
"@miniflare/storage-memory": "2.3.0",
|
"@miniflare/storage-memory": "2.4.0",
|
||||||
"@miniflare/web-sockets": "2.3.0",
|
"@miniflare/web-sockets": "2.4.0",
|
||||||
"kleur": "^4.1.4",
|
"kleur": "^4.1.4",
|
||||||
"semiver": "^1.1.0",
|
"semiver": "^1.1.0",
|
||||||
"source-map-support": "^0.5.20",
|
"source-map-support": "^0.5.20",
|
||||||
@@ -21364,9 +21377,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node-forge": {
|
"node-forge": {
|
||||||
"version": "1.2.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
|
||||||
"integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==",
|
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node-int64": {
|
"node-int64": {
|
||||||
@@ -22398,12 +22411,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"selfsigned": {
|
"selfsigned": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.1.tgz",
|
||||||
"integrity": "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==",
|
"integrity": "sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"node-forge": "^1.2.0"
|
"node-forge": "^1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"semiver": {
|
"semiver": {
|
||||||
|
|||||||
@@ -73,10 +73,11 @@
|
|||||||
"@types/lodash-es": "^4.17.6",
|
"@types/lodash-es": "^4.17.6",
|
||||||
"@types/react": "^17.0.24",
|
"@types/react": "^17.0.24",
|
||||||
"@types/react-dom": "^17.0.9",
|
"@types/react-dom": "^17.0.9",
|
||||||
|
"@types/ua-parser-js": "^0.7.36",
|
||||||
"concurrently": "^7.0.0",
|
"concurrently": "^7.0.0",
|
||||||
"esbuild-visualizer": "^0.3.1",
|
"esbuild-visualizer": "^0.3.1",
|
||||||
"jest": "^27.4.7",
|
"jest": "^27.4.7",
|
||||||
"miniflare": "^2.1.0",
|
"miniflare": "^2.4.0",
|
||||||
"patch-package": "^6.4.7",
|
"patch-package": "^6.4.7",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"tailwindcss": "^3.0.22",
|
"tailwindcss": "^3.0.22",
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
@import url("https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;700;900&display=swap");
|
@import url("https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;700;900&family=Roboto+Mono&display=swap");
|
||||||
@font-face {
|
|
||||||
font-family: "MonoLisa";
|
|
||||||
src: url("/fonts/MonoLisa/woff2/MonoLisa-Regular.woff2") format("woff2"),
|
|
||||||
url("/fonts/MonoLisa/woff/MonoLisa-Regular.woff") format("woff");
|
|
||||||
}
|
|
||||||
|
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
|
|||||||
@@ -16,17 +16,19 @@ module.exports = {
|
|||||||
"6xl": ["2.625rem", "3rem"], // 42px
|
"6xl": ["2.625rem", "3rem"], // 42px
|
||||||
"7xl": "4rem", // 64px
|
"7xl": "4rem", // 64px
|
||||||
"8xl": "8rem", // 128px
|
"8xl": "8rem", // 128px
|
||||||
|
|
||||||
},
|
},
|
||||||
extend: {
|
extend: {
|
||||||
height: {
|
height: {
|
||||||
viewerHeight: "calc(100vh - 146px)",
|
viewerHeight: "calc(100vh - 146px)",
|
||||||
inspectorHeight: "calc(100vh - 70px)",
|
inspectorHeight: "calc(100vh - 70px)",
|
||||||
jsonViewerHeight: "calc(100vh - 106px)",
|
jsonViewerHeight: "calc(100vh - 106px)",
|
||||||
|
viewerHeightMinimal: "calc(100vh - 106px)",
|
||||||
|
inspectorHeightMinimal: "calc(100vh - 30px)",
|
||||||
|
jsonViewerHeightMinimal: "calc(100vh - 66px)",
|
||||||
},
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
sans: ["Source Sans Pro", "sans-serif"],
|
sans: ["Source Sans Pro", "sans-serif"],
|
||||||
mono: ["MonoLisa", "monospace"],
|
mono: ["Roboto Mono", "monospace"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,16 +6,18 @@ describe("formatStarCount", () => {
|
|||||||
expect(formatStarCount(0)).toBe("0");
|
expect(formatStarCount(0)).toBe("0");
|
||||||
expect(formatStarCount(999)).toBe("999");
|
expect(formatStarCount(999)).toBe("999");
|
||||||
expect(formatStarCount(1000)).toBe("1k");
|
expect(formatStarCount(1000)).toBe("1k");
|
||||||
|
expect(formatStarCount(1050)).toBe("1.1k");
|
||||||
expect(formatStarCount(1100)).toBe("1.1k");
|
expect(formatStarCount(1100)).toBe("1.1k");
|
||||||
expect(formatStarCount(1200)).toBe("1.2k");
|
expect(formatStarCount(1200)).toBe("1.2k");
|
||||||
expect(formatStarCount(1300)).toBe("1.3k");
|
expect(formatStarCount(1300)).toBe("1.3k");
|
||||||
expect(formatStarCount(10000)).toBe("10k");
|
expect(formatStarCount(10000)).toBe("10k");
|
||||||
|
expect(formatStarCount(10050)).toBe("10.1k");
|
||||||
expect(formatStarCount(10100)).toBe("10.1k");
|
expect(formatStarCount(10100)).toBe("10.1k");
|
||||||
expect(formatStarCount(10101)).toBe("10.1k");
|
expect(formatStarCount(10101)).toBe("10.1k");
|
||||||
expect(formatStarCount(10199)).toBe("10.1k");
|
expect(formatStarCount(10199)).toBe("10.2k");
|
||||||
expect(formatStarCount(10200)).toBe("10.2k");
|
expect(formatStarCount(10200)).toBe("10.2k");
|
||||||
expect(formatStarCount(52678)).toBe("52.6k");
|
expect(formatStarCount(52678)).toBe("52.7k");
|
||||||
expect(formatStarCount(99999)).toBe("99.9k");
|
expect(formatStarCount(99949)).toBe("99.9k");
|
||||||
expect(formatStarCount(100000)).toBe("100k");
|
expect(formatStarCount(100000)).toBe("100k");
|
||||||
expect(formatStarCount(100100)).toBe("100.1k");
|
expect(formatStarCount(100100)).toBe("100.1k");
|
||||||
expect(formatStarCount(101100)).toBe("101.1k");
|
expect(formatStarCount(101100)).toBe("101.1k");
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ const json = {
|
|||||||
},
|
},
|
||||||
id: "B65hEUWW01ErVKDDGImKcBquYhwEAkjW6Ic3lPY0299Cc",
|
id: "B65hEUWW01ErVKDDGImKcBquYhwEAkjW6Ic3lPY0299Cc",
|
||||||
created_at: "1607587513",
|
created_at: "1607587513",
|
||||||
|
another_field: {
|
||||||
|
nested: "value",
|
||||||
|
},
|
||||||
modifiedAt: null,
|
modifiedAt: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -75,11 +78,62 @@ const json = {
|
|||||||
},
|
},
|
||||||
id: "B65hEUWW01ErVKDDGImKcBquYhwEAkjW6Ic3lPY0299Cc",
|
id: "B65hEUWW01ErVKDDGImKcBquYhwEAkjW6Ic3lPY0299Cc",
|
||||||
created_at: "1607587513",
|
created_at: "1607587513",
|
||||||
|
another_field: {
|
||||||
|
nested: "value",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
describe("calculateRelatedValuesGroups", () => {
|
describe("calculateRelatedValuesGroups", () => {
|
||||||
|
test("it should return the correct values when path is an object", () => {
|
||||||
|
const path = "$.data.1.another_field";
|
||||||
|
|
||||||
|
const result = calculateRelatedValuesGroups(path, json);
|
||||||
|
|
||||||
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"paths": Array [
|
||||||
|
"$.data.1.another_field",
|
||||||
|
"$.data.2.another_field",
|
||||||
|
],
|
||||||
|
"value": "{...}",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"paths": Array [
|
||||||
|
"$.data.0.another_field",
|
||||||
|
],
|
||||||
|
"value": "undefined",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("it should return the correct values when path is an array", () => {
|
||||||
|
const path = "$.data.1.recent_asset_ids";
|
||||||
|
|
||||||
|
const result = calculateRelatedValuesGroups(path, json);
|
||||||
|
|
||||||
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"paths": Array [
|
||||||
|
"$.data.1.recent_asset_ids",
|
||||||
|
"$.data.2.recent_asset_ids",
|
||||||
|
],
|
||||||
|
"value": "[...]",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"paths": Array [
|
||||||
|
"$.data.0.recent_asset_ids",
|
||||||
|
],
|
||||||
|
"value": "undefined",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
test("it should return the correct related values grouped by value", () => {
|
test("it should return the correct related values grouped by value", () => {
|
||||||
const path = "$.data.1.playback_ids.0.policy";
|
const path = "$.data.1.playback_ids.0.policy";
|
||||||
|
|
||||||
@@ -106,7 +160,7 @@ describe("calculateRelatedValuesGroups", () => {
|
|||||||
paths: ["$.data.2.playback_ids.1.policy"],
|
paths: ["$.data.2.playback_ids.1.policy"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "[object Object]",
|
value: "{...}",
|
||||||
paths: ["$.data.2.playback_ids.2.policy"],
|
paths: ["$.data.2.playback_ids.2.policy"],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||