Author SHA1 Message Date
Matt Aitken 6e41828512 ColumnItems are now virtualized 2022-05-02 17:41:20 +01:00
31 changed files with 198 additions and 1865 deletions
-9
View File
@@ -1,9 +0,0 @@
import { Body } from "./Primitives/Body";
export function Banner() {
return (
<div className="flex justify-center items-center w-screen bg-yellow-300 min-h-[30px]">
<Body>Test Banner</Body>
</div>
);
}
+4 -1
View File
@@ -94,7 +94,10 @@ export function CodeEditor(opts: CodeEditorProps) {
return (
<div>
<div className="h-full overflow-y-auto no-scrollbar" ref={editor} />
<div
className="h-jsonViewerHeight overflow-y-auto no-scrollbar"
ref={editor}
/>
</div>
);
}
+59 -6
View File
@@ -1,33 +1,86 @@
import { Title } from "./Primitives/Title";
import { colorForItemAtPath } from "~/utilities/colors";
import { IconComponent } from "~/useColumnView";
import { ColumnViewNode, IconComponent } from "~/useColumnView";
import { useJson } from "../hooks/useJson";
import { memo, useMemo } from "react";
import { memo, useCallback, useMemo, useRef } from "react";
import { ColumnItem } from "./ColumnItem";
import { useJsonColumnViewAPI } from "~/hooks/useJsonColumnView";
import { useVirtual } from "react-virtual";
export type ColumnProps = {
id: string;
title: string;
icon?: IconComponent;
hasHighlightedElement: boolean;
children: React.ReactNode;
items: ColumnViewNode[];
selectedPath: string[];
highlightedPath: string[];
};
function ColumnElement(column: ColumnProps) {
const { id, title, children } = column;
const { id, title, items, selectedPath, highlightedPath } = column;
const [json] = useJson();
const iconColor = useMemo(() => colorForItemAtPath(id, json), [id, json]);
const { goToNodeId } = useJsonColumnViewAPI();
const containerRef = useRef<HTMLDivElement>(null);
const rowVirtualizer = useVirtual({
size: items.length,
parentRef: containerRef,
estimateSize: useCallback(() => 36, []),
overscan: 5,
});
return (
<div
className={
"column flex-none overflow-x-auto no-scrollbar border-r-[1px] border-slate-300 w-80 transition dark:border-slate-600"
"column flex-none border-r-[1px] border-slate-300 w-80 transition dark:border-slate-600"
}
>
<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" />}
<Title className="">{title}</Title>
</div>
<div className="h-full">{children}</div>
<div
className="overflow-y-auto h-viewerHeight no-scrollbar"
ref={containerRef}
>
<div
style={{
height: `${rowVirtualizer.totalSize}px`,
width: "100%",
position: "relative",
}}
>
{rowVirtualizer.virtualItems.map((virtualRow) => {
const item = items[virtualRow.index];
return (
<div
key={virtualRow.index}
style={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: `${virtualRow.size}px`,
transform: `translateY(${virtualRow.start}px)`,
}}
>
<ColumnItem
item={item}
json={json}
isSelected={selectedPath.includes(item.id)}
isHighlighted={
highlightedPath[highlightedPath.length - 1] === item.id
}
onClick={(id) => goToNodeId(id, "columnView")}
/>
</div>
);
})}
</div>
</div>
</div>
);
}
+6 -26
View File
@@ -10,17 +10,10 @@ import { BlankColumn } from "./BlankColumn";
import { Column } from "./Column";
import { ColumnItem } from "./ColumnItem";
function ColumnsElement({
columns,
props,
}: {
columns: ColumnDefinition[];
props?: any;
}) {
function ColumnsElement({ columns }: { columns: ColumnDefinition[] }) {
const [json] = useJson();
const { selectedPath, highlightedPath, highlightedNodeId } =
useJsonColumnViewState();
const { goToNodeId } = useJsonColumnViewAPI();
const highlightedItemIsValue = useMemo<boolean>(() => {
if (highlightedNodeId == null) {
return false;
@@ -33,10 +26,7 @@ function ColumnsElement({
}, [highlightedPath, json]);
return (
<div
className="all-columns flex h-full overflow-hidden focus:outline-none"
{...props}
>
<div className="columns flex flex-grow overflow-x-auto no-scrollbar focus:outline-none">
{columns.map((column) => {
return (
<Column
@@ -47,20 +37,10 @@ function ColumnsElement({
hasHighlightedElement={
highlightedPath[highlightedPath.length - 2] === column.id
}
>
{column.items.map((item) => (
<ColumnItem
key={item.id}
item={item}
json={json}
isSelected={selectedPath.includes(item.id)}
isHighlighted={
highlightedPath[highlightedPath.length - 1] === item.id
}
onClick={(id) => goToNodeId(id, "columnView")}
/>
))}
</Column>
selectedPath={selectedPath}
highlightedPath={highlightedPath}
items={column.items}
/>
);
})}
{highlightedItemIsValue ? <BlankColumn /> : null}
-20
View File
@@ -1,20 +0,0 @@
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 <></>;
}
+43 -57
View File
@@ -16,66 +16,52 @@ export function DocumentTitle() {
}
}, [updateDoc]);
if (doc.readOnly) {
return (
const startEditing = useCallback(() => {
ref.current?.select();
ref.current?.focus();
}, [ref.current]);
return (
<updateDoc.Form method="post" action={`/actions/${doc.id}/update`}>
<div
className="flex justify-center items-center w-full"
title={doc.title}
>
<span
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:cursor-text transition dark:bg-transparent dark:text-slate-200 dark:placeholder:text-slate-400 dark:focus:bg-black dark:focus:bg-opacity-10"
}
>
{doc.title}
</span>
</div>
);
} 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>
<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>
);
}
{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>
);
}
-20
View File
@@ -1,20 +0,0 @@
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 -8
View File
@@ -1,5 +1,4 @@
import { ArrowKeysIcon } from "./Icons/ArrowKeysIcon";
import { CopyShortcutIcon } from "./Icons/CopyShortcutIcon";
import { EscapeKeyIcon } from "./Icons/EscapeKeyIcon";
import { SquareBracketsIcon } from "./Icons/SquareBracketsIcon";
import { Body } from "./Primitives/Body";
@@ -7,7 +6,7 @@ import { ThemeModeToggler } from "./ThemeModeToggle";
export function Footer() {
return (
<footer className="flex items-center justify-between w-screen min-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">
<li className="flex items-center">
<ArrowKeysIcon className="transition text-slate-300 dark:text-slate-500" />
@@ -27,12 +26,6 @@ export function Footer() {
Reset path
</Body>
</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>
<ThemeModeToggler />
</footer>
-6
View File
@@ -2,7 +2,6 @@ import { DiscordIcon } from "../Icons/DiscordIcon";
import { EmailIcon } from "../Icons/EmailIcon";
import { GithubIcon } from "../Icons/GithubIcon";
import { Logo } from "../Icons/Logo";
import { TwitterIcon } from "../Icons/TwitterIcon";
export type HomeFooterProps = {
maxWidth?: string;
@@ -37,11 +36,6 @@ export function HomeFooter({ maxWidth = "1150px" }: HomeFooterProps) {
<DiscordIcon />
</a>
</li>
<li className="ml-2 hover:cursor-pointer">
<a href="https://twitter.com/json_hero" target="_blank">
<TwitterIcon />
</a>
</li>
</ol>
</div>
</footer>
+1 -7
View File
@@ -1,6 +1,5 @@
import { DiscordIconTransparent } from "../Icons/DiscordIconTransparent";
import { EmailIconTransparent } from "../Icons/EmailIconTransparent";
import { TwitterIcon } from "../Icons/TwitterIcon";
import { Logo } from "../Icons/Logo";
import { NewDocument } from "../NewDocument";
import { GithubStar } from "../UI/GithubStar";
@@ -14,7 +13,7 @@ import {
export function HomeHeader() {
return (
<header className="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">
<div className="flex w-44 mr-3">
<Logo />
</div>
<ol className="flex items-center gap-2">
@@ -46,11 +45,6 @@ export function HomeHeader() {
<DiscordIconTransparent />
</a>
</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>
</header>
);
+1 -7
View File
@@ -142,13 +142,7 @@ function SampleJSONPreview({
}) {
return (
<JsonDocProvider
doc={{
id: "sample",
title: "Sample",
type: "raw",
readOnly: false,
contents: "",
}}
doc={{ id: "sample", title: "Sample", type: "raw", contents: "" }}
path={initialSelection}
>
<JsonProvider initialJson={json}>
-23
View File
@@ -1,23 +0,0 @@
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 -1
View File
@@ -24,7 +24,7 @@ export function InfoPanel() {
return (
<>
<div className="h-full 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="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} />
<div className="mb-4">
+4 -7
View File
@@ -4,7 +4,6 @@ import {
} from "../hooks/useJsonColumnView";
import { useHotkeys } from "react-hotkeys-hook";
import { Columns } from "./Columns";
import { CopySelectedNodeShortcut } from "./CopySelectedNode";
export function JsonColumnView() {
const { getColumnViewProps, columns } = useJsonColumnViewState();
@@ -12,7 +11,9 @@ export function JsonColumnView() {
return (
<>
<KeyboardShortcuts />
<Columns columns={columns} props={getColumnViewProps()} />
<div {...getColumnViewProps()}>
<Columns columns={columns} />
</div>
</>
);
}
@@ -66,9 +67,5 @@ function KeyboardShortcuts() {
[api]
);
return (
<>
<CopySelectedNodeShortcut />
</>
);
return <></>;
}
+1 -1
View File
@@ -81,7 +81,7 @@ export function JsonEditor() {
<CodeEditor
language="json"
content={jsonMapped.json}
readOnly={true}
readOnly={false}
onUpdate={onUpdate}
selection={selection}
/>
+22 -26
View File
@@ -6,7 +6,6 @@ import {
} from "~/hooks/useJsonColumnView";
import { JsonTreeViewNode, useJsonTreeViewContext } from "~/hooks/useJsonTree";
import { VirtualNode } from "~/hooks/useVirtualTree";
import { CopySelectedNodeShortcut } from "./CopySelectedNode";
import { Body } from "./Primitives/Body";
import { Mono } from "./Primitives/Mono";
@@ -79,34 +78,31 @@ export function JsonTreeView() {
}, [treeRef.current]);
return (
<>
<CopySelectedNodeShortcut />
<div
className="text-white w-full"
ref={parentRef}
style={{
height: `calc(100vh - 106px)`,
overflowY: "auto",
overflowX: "hidden",
}}
>
<div
className="text-white w-full"
ref={parentRef}
style={{
height: `calc(100vh - 106px)`,
overflowY: "auto",
overflowX: "hidden",
}}
className="relative w-full outline-none"
style={{ height: `${tree.totalSize}px` }}
{...tree.getTreeProps()}
ref={treeRef}
>
<div
className="relative w-full outline-none"
style={{ height: `${tree.totalSize}px` }}
{...tree.getTreeProps()}
ref={treeRef}
>
{tree.nodes.map((virtualNode) => (
<TreeViewNode
virtualNode={virtualNode}
key={virtualNode.node.id}
onToggle={(node, e) => tree.toggleNode(node.id, e)}
selectedNodeId={selectedNodeId}
/>
))}
</div>
{tree.nodes.map((virtualNode) => (
<TreeViewNode
virtualNode={virtualNode}
key={virtualNode.node.id}
onToggle={(node, e) => tree.toggleNode(node.id, e)}
selectedNodeId={selectedNodeId}
/>
))}
</div>
</>
</div>
);
}
+1 -1
View File
@@ -4,7 +4,7 @@ import { SearchBar } from "./SearchBar";
export function JsonView({ children }: { children: React.ReactNode }) {
return (
<div className="path-bar-and-columns flex flex-col flex-grow overflow-x-hidden border-l-[1px] border-slate-300 transition dark:border-slate-600">
<div className="path-bar-and-column-wrapper flex flex-col flex-grow overflow-x-hidden border-l-[1px] border-slate-300 transition dark:border-slate-600">
<div className="flex justify-between p-1 bg-slate-200 border-slate-300 border-b-[1px] transition dark:bg-slate-900 dark:border-slate-600">
<div className="flex-shrink-0 flex-grow-0">
<PathHistoryControls />
@@ -1,42 +0,0 @@
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>
);
}
@@ -6,11 +6,9 @@ import {
import Color from "color";
import { CodeViewer } from "~/components/CodeViewer";
import { PreviewBox } from "../PreviewBox";
import { PreviewAudioUri } from "./PreviewAudioUri";
import { PreviewDate } from "./PreviewDate";
import { PreviewImageUri } from "./PreviewImageUri";
import { PreviewUri } from "./PreviewUri";
import { PreviewVideoUri } from "./PreviewVideoUri";
export function PreviewString({ info }: { info: JSONStringType }) {
if (info.format == null) {
@@ -32,28 +30,6 @@ export function PreviewString({ info }: { info: JSONStringType }) {
contentType={info.format.contentType}
/>
);
} else if (
info.format.contentType === "video/mp4" ||
info.format.contentType === "video/webm" ||
info.format.contentType === "video/ogg"
) {
return (
<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}
contentType={info.format.contentType}
/>
);
} else {
return <PreviewUri value={info.value} type={info} />;
}
@@ -1,43 +0,0 @@
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>
);
}
+17 -14
View File
@@ -1,28 +1,31 @@
import { ExampleDoc } from "./ExampleDoc";
import { ExampleUrl } from "./ExampleUrl";
export function SampleUrls() {
return (
<div className="flex justify-start flex-wrap gap-2">
<ExampleDoc
id="xW6aDgcbKgwC"
title="Unsplash API"
path="4.urls.regular"
<ExampleUrl
url="https://gist.githubusercontent.com/ericallam/332aca65c34dbc0fdb1b3cffbdf3f7a4/raw/4c6e264c3afd3432b608bad628290a7d71035253/unsplash.json"
title="Unsplash API Example"
displayTitle="Unsplash API"
/>
<ExampleDoc
id="d9udW60cLOok"
title="Tweet JSON"
path="data.0.entities.urls.0.expanded_url"
<ExampleUrl
url="https://gist.githubusercontent.com/ericallam/77e37e93e370b32387ce8d598dd06fc8/raw/9306a2c039fc27ab42bdadb80cbd6dbca49d27ec/tweet.json"
title="Tweet API Example"
displayTitle="Tweet JSON"
/>
<ExampleDoc
id="JZw4Wx9Mgj6r"
title="Airtable API"
path="records.3.createdTime"
<ExampleUrl
url="https://gist.githubusercontent.com/ericallam/f11f4981adf72b0427427c349afb3a09/raw/37eee4234b628f3278c9d4f644fee4a1c4987593/Airtable.json"
title="Airtable Product Catalog"
displayTitle="Airtable API"
/>
<ExampleDoc id="PjHo1o5MVeH4" title="Github API" />
<ExampleUrl
url="https://gist.githubusercontent.com/ericallam/51b77c0051c21a34ea33d601bb0b1bef/raw/0b099f7d3bb5fe47f1fd55007d6a5fe9c5fd046b/GitHub.json"
title="List of Github Repos"
displayTitle="Github API"
/>
</div>
);
}
+4 -30
View File
@@ -1,10 +1,8 @@
import { customRandom } from "nanoid";
import safeFetch from "./utilities/safeFetch";
type BaseJsonDocument = {
id: string;
title: string;
readOnly: boolean;
};
export type RawJsonDocument = BaseJsonDocument & {
@@ -19,8 +17,6 @@ export type UrlJsonDocument = BaseJsonDocument & {
export type CreateJsonOptions = {
ttl?: number;
readOnly?: boolean;
injest?: boolean;
metadata?: any;
};
@@ -41,33 +37,17 @@ export async function createFromUrlOrRawJson(
export async function createFromUrl(
url: URL,
title?: string,
options?: CreateJsonOptions
title?: string
): 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 doc: JSONDocument = {
const doc = {
id: docId,
type: <const>"url",
url: url.href,
title: title ?? url.hostname,
readOnly: options?.readOnly ?? false,
};
await DOCUMENTS.put(docId, JSON.stringify(doc), {
expirationTtl: options?.ttl ?? undefined,
metadata: options?.metadata ?? undefined,
});
await DOCUMENTS.put(docId, JSON.stringify(doc));
return doc;
}
@@ -78,13 +58,7 @@ export async function createFromRawJson(
options?: CreateJsonOptions
): Promise<JSONDocument> {
const docId = createId();
const doc: JSONDocument = {
id: docId,
type: <const>"raw",
contents,
title: filename,
readOnly: options?.readOnly ?? false,
};
const doc = { id: docId, type: <const>"raw", contents, title: filename };
await DOCUMENTS.put(docId, JSON.stringify(doc), {
expirationTtl: options?.ttl ?? undefined,
-64
View File
@@ -1,64 +0,0 @@
export default function Index() {
return <Flex />;
}
function Grid() {
return (
<div className="grid overflow-hidden grid-cols-1 grid-rows-app gap-0 h-screen">
<div className="bg-yellow-300 border-yellow-500 border-dashed border">
banner
</div>
<div className="bg-green-300 border-green-500 border-dashed border">
header
</div>
<div className="bg-red-300 border-red-500 border-dashed border">
<div className="flex h-full w-24 bg-slate-500"></div>
</div>
<div className="bg-blue-300 border-blue-500 border-dashed border">
footer
</div>
</div>
);
}
function Flex() {
return (
<div className="flex overflow-hidden flex-col gap-0 h-screen">
<div className="bg-yellow-300 border-yellow-500 border-dashed border min-h-8">
banner
</div>
<div className="bg-green-300 border-green-500 border-dashed border min-h-8">
header
</div>
<div className="bg-red-300 border-red-500 overflow-y-auto border-dashed border flex-grow">
<div className="h-full w-48 overflow-y-auto no-scrollbar bg-slate-500">
<div className="">
<TestItem></TestItem>
<TestItem></TestItem>
<TestItem></TestItem>
<TestItem></TestItem>
<TestItem></TestItem>
<TestItem></TestItem>
<TestItem></TestItem>
<TestItem></TestItem>
<TestItem></TestItem>
<TestItem></TestItem>
<TestItem></TestItem>
<TestItem></TestItem>
</div>
</div>
</div>
<div className="bg-blue-300 border-blue-500 border-dashed border min-h-8">
footer
</div>
</div>
);
}
function TestItem() {
return (
<div className="flex items-center justify-center bg-orange-300 border-b-slate-900 border-b">
<p className="text-2xl text-black">Test Item</p>
</div>
);
}
+1 -9
View File
@@ -28,7 +28,6 @@ import { Body } from "~/components/Primitives/Body";
import { PageNotFoundTitle } from "~/components/Primitives/PageNotFoundTitle";
import { SmallSubtitle } from "~/components/Primitives/SmallSubtitle";
import { Logo } from "~/components/Icons/Logo";
import { Banner } from "~/components/Banner";
export const loader: LoaderFunction = async ({ params, request }) => {
invariant(params.id, "expected params.id");
@@ -49,10 +48,6 @@ export const loader: LoaderFunction = async ({ params, request }) => {
const jsonResponse = await safeFetch(doc.url);
if (!jsonResponse.ok) {
console.log(
`Failed to fetch ${doc.url}: ${jsonResponse.status} (${jsonResponse.statusText})`
);
throw new Response(jsonResponse.statusText, {
status: jsonResponse.status,
});
@@ -60,8 +55,6 @@ export const loader: LoaderFunction = async ({ params, request }) => {
const json = await jsonResponse.json();
console.log(`Fetched ${doc.url} with json, returning...`);
return {
doc,
json,
@@ -132,7 +125,7 @@ export default function JsonDocumentRoute() {
<JsonSearchProvider>
<JsonTreeViewProvider overscan={25}>
<div>
<div className="block md:hidden fixed bg-black/80 h-screen w-screen z-50 text-white">
<div className="block sm: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">
<LargeTitle>JSON Hero only works on desktop</LargeTitle>
<LargeTitle>👇</LargeTitle>
@@ -146,7 +139,6 @@ export default function JsonDocumentRoute() {
</div>
</div>
<div className="h-screen flex flex-col sm:overflow-hidden">
<Banner />
<Header />
<div className="bg-slate-50 flex-grow transition dark:bg-slate-900">
<div className="main-container flex justify-items-stretch h-full">
+4 -34
View File
@@ -1,49 +1,23 @@
import { json, LoaderFunction, redirect } from "remix";
import { LoaderFunction, redirect } from "remix";
import invariant from "tiny-invariant";
import { sendEvent } from "~/graphJSON.server";
import {
createFromRawJson,
createFromUrl,
CreateJsonOptions,
} from "~/jsonDoc.server";
import { createFromRawJson, createFromUrl } from "~/jsonDoc.server";
export let loader: LoaderFunction = async ({ request, context }) => {
const url = new URL(request.url);
const jsonUrl = url.searchParams.get("url");
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) {
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) {
const jsonURL = new URL(jsonUrl);
invariant(jsonURL, "url must be a valid URL");
const doc = await createFromUrl(jsonURL, title ?? jsonURL.href, options);
const doc = await createFromUrl(jsonURL, jsonURL.href);
context.waitUntil(
sendEvent({
@@ -59,11 +33,7 @@ export let loader: LoaderFunction = async ({ request, context }) => {
}
if (base64EncodedJson) {
const doc = await createFromRawJson(
title ?? "Untitled",
atob(base64EncodedJson),
options
);
const doc = await createFromRawJson("Untitled", atob(base64EncodedJson));
context.waitUntil(
sendEvent({
+22 -8
View File
@@ -1,6 +1,17 @@
// Should truncate the number to not show the exact number of stars
// If over 1000, show 1k
// Round up to the nearest hundred, so for example, 1150 becomes 1.2k, 1101 becomes 1.1k, etc.
// If between 1100 and 1199, show 1.1k
// 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 {
if (count === undefined) {
return "⭐️";
@@ -9,11 +20,14 @@ export function formatStarCount(count: number | undefined): string {
if (count < 1000) {
return count.toString();
}
return `${roundWithPrecision(count / 1000, 1)}k`;
}
function roundWithPrecision(value: number, precision: number): number {
const multiplier = Math.pow(10, precision);
return Math.round(value * multiplier) / multiplier;
if (count < 10000) {
return `${Math.floor(count / 100) / 10}k`;
}
if (count < 100000) {
return `${Math.floor(count / 100) / 10}k`;
}
if (count < 1000000) {
return `${Math.floor(count / 100) / 10}k`;
}
return `${Math.floor(count / 100000)}k`;
}
-402
View File
@@ -1,402 +0,0 @@
[
{
"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"
}
]
-936
View File
@@ -1,936 +0,0 @@
{
"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
}
-22
View File
@@ -1,22 +0,0 @@
[
"There has never been a sadness that cant 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. Thats 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.",
"Ive had the same haircut since 1978 and Ive driven the same car since 1991. Ive 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!",
"Its pointless for a human to paint scenes of nature when they can go outside and stand in it.",
"My first ex-wifes name is Tammy. My second ex-wifes name is Tammy. My Moms name is Tamara…she goes by Tammy.",
"Live your life how you want, but dont confuse drama with happiness."
]
+3 -6
View File
@@ -20,12 +20,9 @@ module.exports = {
},
extend: {
height: {
// viewerHeight: "calc(100vh - 146px)",
// inspectorHeight: "calc(100vh - 70px)",
// jsonViewerHeight: "calc(100vh - 106px)",
},
gridTemplateColumns: {
'json-column': 'auto',
viewerHeight: "calc(100vh - 146px)",
inspectorHeight: "calc(100vh - 70px)",
jsonViewerHeight: "calc(100vh - 106px)",
},
fontFamily: {
sans: ["Source Sans Pro", "sans-serif"],
+3 -5
View File
@@ -6,18 +6,16 @@ describe("formatStarCount", () => {
expect(formatStarCount(0)).toBe("0");
expect(formatStarCount(999)).toBe("999");
expect(formatStarCount(1000)).toBe("1k");
expect(formatStarCount(1050)).toBe("1.1k");
expect(formatStarCount(1100)).toBe("1.1k");
expect(formatStarCount(1200)).toBe("1.2k");
expect(formatStarCount(1300)).toBe("1.3k");
expect(formatStarCount(10000)).toBe("10k");
expect(formatStarCount(10050)).toBe("10.1k");
expect(formatStarCount(10100)).toBe("10.1k");
expect(formatStarCount(10101)).toBe("10.1k");
expect(formatStarCount(10199)).toBe("10.2k");
expect(formatStarCount(10199)).toBe("10.1k");
expect(formatStarCount(10200)).toBe("10.2k");
expect(formatStarCount(52678)).toBe("52.7k");
expect(formatStarCount(99949)).toBe("99.9k");
expect(formatStarCount(52678)).toBe("52.6k");
expect(formatStarCount(99999)).toBe("99.9k");
expect(formatStarCount(100000)).toBe("100k");
expect(formatStarCount(100100)).toBe("100.1k");
expect(formatStarCount(101100)).toBe("101.1k");