components: add search

This commit is contained in:
Matilde Park 2022-06-23 00:55:08 -07:00
parent a34b556b3c
commit a668e7f69f
20 changed files with 1010 additions and 41 deletions

View File

@ -30,7 +30,7 @@ export default function BasicPage({
<title>{post.title} developers.urbit.org</title>
{Meta(post)}
</Head>
<Header />
<Header search={search} />
<SingleColumn>
<Section narrow={!wide}>
<h1>{post.title}</h1>

View File

@ -21,7 +21,7 @@ function ActiveLink({ children, href, className, currentPath }) {
);
}
export default function Header(props) {
export default function Header({ search }) {
const [isOpen, setTray] = useState(false);
const currentPath = useRouter().asPath;
@ -33,7 +33,7 @@ export default function Header(props) {
return (
<>
{" "}
<IntraNav ourSite="https://developers.urbit.org" search={() => null} />
<IntraNav ourSite="https://developers.urbit.org" search={search} />
<header className="layout max-w-screen-lg px-4 md:px-8 flex justify-between items-center pt-8 md:pt-10 lg:pt-12 pb-10 md:pb-12 lg:pb-24">
<div>
<Link href="/" passHref>
@ -100,7 +100,7 @@ export default function Header(props) {
{
// Small screen header
}
<MenuTray isOpen={isOpen} setTray={setTray} search={() => null}>
<MenuTray isOpen={isOpen} setTray={setTray} search={search}>
<Link href="/" passHref>
<a className="type-ui mb-12">Urbit</a>
</Link>

276
components/Search.js Normal file
View File

@ -0,0 +1,276 @@
import { Component, createRef } from "react";
// import { glossary } from "../lib/glossary";
import { withRouter } from "next/router";
import debounce from "lodash.debounce";
import Downshift from "downshift";
import ob from "urbit-ob";
import Sigil from "./Sigil";
// import levenSort from "leven-sort";
class Search extends Component {
constructor(props) {
super(props);
this.state = {
results: [],
};
this.searchEndpoint = this.searchEndpoint.bind(this);
this.onInputValueChange = this.onInputValueChange.bind(this);
this.onSelect = this.onSelect.bind(this);
// this.glossarySearch = this.glossarySearch.bind(this);
this.patpSearch = this.patpSearch.bind(this);
}
searchEndpoint(query) {
return `/api/search?q=${query}`;
}
// glossarySearch(query) {
// const entries = glossary.filter((entry) => {
// return (
// entry.name.includes(query.toLowerCase()) || entry.symbol.includes(query)
// );
// });
// return levenSort(entries, query, ["symbol"]);
// }
patpSearch(query) {
return (
(ob.isValidPatp(`~${deSig(query.toLowerCase())}`) &&
`~${deSig(query.toLowerCase())}`.length < 15) ||
(!isNaN(query) && query <= 4294967295)
);
}
onSelect(item) {
if (item.slug) {
this.props.router.push(item.slug);
}
this.setState({
query: "",
results: [],
});
this.props.closeSearch();
}
onInputValueChange = debounce((query) => {
if (query.length) {
fetch(this.searchEndpoint(query))
.then((res) => res.json())
.then((res) => {
console.log(res);
// Wrap results in an object which will tell React what component to use to render results.
const results = res.results.map((item) => ({
type: "RESULT",
content: item,
}));
const patp = this.patpSearch(query)
? !isNaN(query)
? ob.patp(query)
: ob.patp(ob.patp2dec(`~${deSig(query)}`))
: null;
const patpResult = this.patpSearch(query)
? [
{
type: "PATP",
content: {
patp: patp,
slug: `https://urbit.org/ids/${patp}`,
},
},
]
: [];
// const glossaryResults = this.glossarySearch(query).map((item) => ({
// type: "GLOSSARY_RESULT",
// content: item,
// }));
// const list = [...glossaryResults, ...patpResult, ...results];
const list = [...patpResult, ...results];
this.setState({ results: list });
});
} else {
this.setState({ results: [] });
}
}, 250);
render() {
const { state, props } = this;
if (props.showSearch) {
return (
<Downshift
onSelect={(selection) => this.onSelect(selection)}
onInputValueChange={(event) => this.onInputValueChange(event)}
itemToString={(item) => (item ? item.slug : "")}
defaultHighlightedIndex={0}
>
{({
getInputProps,
getItemProps,
getLabelProps,
getMenuProps,
isOpen,
inputValue,
highlightedIndex,
selectedItem,
getRootProps,
}) => (
<div className="fixed w-screen h-screen z-50 flex flex-col items-center p-4">
<div
onClick={(event) => props.closeSearch(event)}
className="top-0 left-0 fixed w-screen h-screen bg-washedWall"
/>
<div className="relative flex flex-col max-w-screen-lg md:my-32 w-full md:w-10/12 lg:w-8/12 xl:w-6/12 rounded-xl bg-white min-h-0 overflow-hidden">
<div
style={{ display: "inline-block" }}
{...getRootProps({}, { suppressRefError: true })}
>
<input
autoFocus
className="text-lg md:text-xl lg:text-2xl font-medium text-green-400 bg-transparent py-2 px-4 outline-none relative w-full"
placeholder="Search..."
type="text"
onClick={(e) => e.stopPropagation()}
{...getInputProps({
onKeyDown: (event) => {
if (event.key === "Escape") {
// Prevent Downshift's default 'Escape' behavior.
event.nativeEvent.preventDownshiftDefault = true;
this.props.closeSearch(event);
}
},
})}
/>
</div>
<ul {...getMenuProps()} className="overflow-y-scroll">
{isOpen
? state.results.map((item, index) => {
const selected = highlightedIndex === index;
if (item.type === "PATP") {
return (
<li
className={`cursor-pointer p-2 flex space-x-2 items-center text-left w-full ${
selected ? "bg-green-400" : ""
}`}
{...getItemProps({
key: item.content.slug + "-" + index,
index,
item: item.content,
selected: highlightedIndex === index,
})}
>
<div className="rounded-md overflow-hidden">
<Sigil
patp={item.content.patp}
size={25}
icon
/>
</div>
<p className="font-mono">{item.content.patp}</p>
</li>
);
}
// if (item.type === "GLOSSARY_RESULT") {
// return (
// <li
// className={`cursor-pointer flex text-left w-full ${
// selected ? "bg-green-400" : ""
// }`}
// {...getItemProps({
// key: item.content.slug + "-" + index,
// index,
// item: item.content,
// selected: highlightedIndex === index,
// })}
// >
// <div className="font-semibold p-3">
// <p
// className={`text-base ${
// selected ? "text-white" : "text-wall-600"
// }`}
// >
// {item.content.symbol.length > 0 && (
// <code
// className={`mr-1 rounded px-1 py-0.5 ${
// selected
// ? "bg-washedWhite"
// : "bg-wall-100"
// }`}
// >
// {item.content.symbol}
// </code>
// )}
// {item.content.name}
// </p>
// <p
// className={`font-normal text-base mt-1 ${
// selected ? "text-white" : "text-wall-600"
// }`}
// dangerouslySetInnerHTML={{
// __html: item.content.desc,
// }}
// ></p>
// </div>
// </li>
// );
// }
if (item.type === "RESULT") {
return (
<li
className={`cursor-pointer flex text-left w-full ${
selected ? "bg-green-400" : ""
}`}
{...getItemProps({
key: item.content.link + "-" + index,
index,
item: item.content,
selected,
})}
>
<div className="p-3">
<p
className={`font-medium text-base ${
selected ? "text-white" : "text-wall-600"
}`}
>
{item.content.parent !== "Content"
? `${item.content.parent} /`
: ""}{" "}
{item.content.title}
</p>
<p
className={`text-base font-regular text-small ${
selected ? "text-midWhite" : "text-wall-500"
}`}
>
{item.content.content}
</p>
</div>
</li>
);
}
return null;
})
: null}
</ul>
</div>
</div>
)}
</Downshift>
);
} else {
return null;
}
}
}
function deSig(string) {
return string.startsWith("~") ? string.substring(1) : string;
}
export default withRouter(Search);

36
components/Sigil.js Normal file
View File

@ -0,0 +1,36 @@
import { sigil, reactRenderer } from "@tlon/sigil-js";
export const foregroundFromBackground = (background) => {
const rgb = {
r: parseInt(background.slice(1, 3), 16),
g: parseInt(background.slice(3, 5), 16),
b: parseInt(background.slice(5, 7), 16),
};
const brightness = (299 * rgb.r + 587 * rgb.g + 114 * rgb.b) / 1000;
const whiteBrightness = 255;
return whiteBrightness - brightness < 50 ? "black" : "white";
};
export const Sigil = ({ patp, size, color = "#24201E", icon }) => {
if (patp.length > 14) {
return <div />;
}
const foreground = foregroundFromBackground(color);
return (
<div
className={icon ? "p-1" : ""}
style={{ backgroundColor: icon ? color || "black" : "transparent" }}
>
{sigil({
patp: patp,
renderer: reactRenderer,
size: icon ? size / 2 : size,
colors: [color, foreground],
icon: icon || false,
})}
</div>
);
};
export default Sigil;

75
lib/cache.js Normal file
View File

@ -0,0 +1,75 @@
const fs = require("fs");
const path = require("path");
const matter = require("gray-matter");
const toml = require("@iarna/toml");
const options = {
engines: {
toml: toml.parse.bind(toml),
},
language: "toml",
delimiters: "+++",
};
const index = [];
function buildSearchIndex(dir) {
const dirName = dir.split("/").slice(-1).join("");
let metadata = {
data: {
title: dirName.charAt(0).toUpperCase() + dirName.slice(1),
},
};
try {
metadata = matter(fs.readFileSync(path.join(dir, "_index.md")), options);
} catch (err) {}
const children = fs.readdirSync(dir, { withFileTypes: true });
const pages = children.filter((f) => f.isFile() && f.name !== "_index.md");
const subdirs = children.filter(
(f) => f.isDirectory() && f.name !== "ids" && f.name !== "glossary"
);
index.push(
...pages.map((page) => {
const { data: pageData, content: pageContent } = matter(
fs.readFileSync(path.join(dir, page.name)),
options
);
return {
title: pageData.title,
base: page.name,
slug: path.join(
dir.substr(dir.indexOf("content") + 7),
"/",
page.name.replace(/.md$/, "")
),
content: pageData.description || "",
parent: metadata.data.title,
};
})
);
Object.fromEntries(
subdirs.map((subdir) => [
subdir.name,
buildSearchIndex(path.join(dir, subdir.name)),
])
);
}
buildSearchIndex(path.join(process.cwd(), "content"));
const fileContents = `export const index = ${JSON.stringify(index)}`;
try {
fs.readdirSync("cache");
} catch (err) {
fs.mkdirSync("cache");
}
fs.writeFile("cache/data.js", fileContents, function (err) {
if (err) return console.error(err);
console.log("Site index created.");
});

523
package-lock.json generated
View File

@ -9,17 +9,23 @@
"version": "0.1.0",
"dependencies": {
"@iarna/toml": "^2.2.5",
"@tlon/sigil-js": "^1.4.5",
"browserify-zlib": "^0.2.0",
"classnames": "^2.3.1",
"downshift": "^6.1.7",
"foundation-design-system": "github:urbit/foundation-design-system",
"gray-matter": "^4.0.3",
"leven-sort": "^3.0.0",
"lodash.debounce": "^4.0.8",
"luxon": "^2.4.0",
"next": "12.1.6",
"path-browserify": "^1.0.1",
"react": "^17",
"react-dom": "^17",
"react-hotkeys": "^2.0.0",
"react-swipeable": "^7.0.0",
"stream-browserify": "^3.0.0"
"stream-browserify": "^3.0.0",
"urbit-ob": "^5.0.1"
},
"devDependencies": {
"eslint": "8.18.0",
@ -30,7 +36,6 @@
"version": "7.18.3",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.3.tgz",
"integrity": "sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==",
"dev": true,
"dependencies": {
"regenerator-runtime": "^0.13.4"
},
@ -345,6 +350,19 @@
"tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1"
}
},
"node_modules/@tlon/sigil-js": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/@tlon/sigil-js/-/sigil-js-1.4.5.tgz",
"integrity": "sha512-+Fn0EizPetjePaK+z8njjzE74wxzqIRLVM8W53Dlri6XU87wJ4vk82baVGgZQFAQs96rYM/f4WV7kCzuSxSMAw==",
"dependencies": {
"invariant": "^2.2.4",
"svgson": "^4.0.0",
"transformation-matrix": "2.1.1"
},
"peerDependencies": {
"react": "^16 || ^17"
}
},
"node_modules/@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@ -720,6 +738,11 @@
"node": ">=8"
}
},
"node_modules/bn.js": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -904,6 +927,11 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/compute-scroll-into-view": {
"version": "1.0.17",
"resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz",
"integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg=="
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -985,6 +1013,29 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
"node_modules/deep-rename-keys": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/deep-rename-keys/-/deep-rename-keys-0.2.1.tgz",
"integrity": "sha512-RHd9ABw4Fvk+gYDWqwOftG849x0bYOySl/RgX0tLI9i27ZIeSO91mLZJEp7oPHOMFqHvpgu21YptmDt0FYD/0A==",
"dependencies": {
"kind-of": "^3.0.2",
"rename-keys": "^1.1.2"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/deep-rename-keys/node_modules/kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
"dependencies": {
"is-buffer": "^1.1.5"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/define-properties": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
@ -1119,6 +1170,31 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/downshift": {
"version": "6.1.7",
"resolved": "https://registry.npmjs.org/downshift/-/downshift-6.1.7.tgz",
"integrity": "sha512-cVprZg/9Lvj/uhYRxELzlu1aezRcgPWBjTvspiGTVEU64gF5pRdSRKFVLcxqsZC637cLAGMbL40JavEfWnqgNg==",
"dependencies": {
"@babel/runtime": "^7.14.8",
"compute-scroll-into-view": "^1.0.17",
"prop-types": "^15.7.2",
"react-is": "^17.0.2",
"tslib": "^2.3.0"
},
"peerDependencies": {
"react": ">=16.12.0"
}
},
"node_modules/downshift/node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
"node_modules/downshift/node_modules/tslib": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
},
"node_modules/electron-to-chromium": {
"version": "1.4.166",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.166.tgz",
@ -1661,6 +1737,11 @@
"node": ">=0.10.0"
}
},
"node_modules/eventemitter3": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
"integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg=="
},
"node_modules/extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
@ -1922,6 +2003,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-value": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
"integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/glob": {
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
@ -2094,6 +2183,38 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-value": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
"integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==",
"dependencies": {
"get-value": "^2.0.3",
"has-values": "^0.1.4",
"isobject": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/has-value/node_modules/isobject": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
"integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==",
"dependencies": {
"isarray": "1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/has-values": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
"integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/html-dom-parser": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-1.2.0.tgz",
@ -2202,6 +2323,14 @@
"node": ">= 0.4"
}
},
"node_modules/invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/is-bigint": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
@ -2242,6 +2371,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"node_modules/is-callable": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
@ -2367,6 +2501,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
"dependencies": {
"isobject": "^3.0.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-regex": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
@ -2448,11 +2593,24 @@
"node": ">=8"
}
},
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
"node_modules/isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -2546,6 +2704,22 @@
"language-subtag-registry": "~0.3.2"
}
},
"node_modules/leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
"integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
"engines": {
"node": ">=6"
}
},
"node_modules/leven-sort": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/leven-sort/-/leven-sort-3.0.0.tgz",
"integrity": "sha512-dw+6CDkFAbmXiAv/bU2IQKEJzgdXUYnc2Z4FipY9gOt+tdUUiP1R1Jn8S05aORllj5NLcKyx6zwIz+M3ygCohA==",
"dependencies": {
"leven": "^3.1.0"
}
},
"node_modules/levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@ -2581,6 +2755,21 @@
"node": ">=4"
}
},
"node_modules/lodash.chunk": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
"integrity": "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w=="
},
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
},
"node_modules/lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
},
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@ -2886,6 +3075,18 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/omit-deep": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/omit-deep/-/omit-deep-0.3.0.tgz",
"integrity": "sha512-Lbl/Ma59sss2b15DpnWnGmECBRL8cRl/PjPbPMVW+Y8zIQzRrwMaI65Oy6HvxyhYeILVKBJb2LWeG81bj5zbMg==",
"dependencies": {
"is-plain-object": "^2.0.1",
"unset-value": "^0.1.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@ -3380,7 +3581,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"dev": true,
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
@ -3452,11 +3652,21 @@
"react": "17.0.2"
}
},
"node_modules/react-hotkeys": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-hotkeys/-/react-hotkeys-2.0.0.tgz",
"integrity": "sha512-3n3OU8vLX/pfcJrR3xJ1zlww6KS1kEJt0Whxc4FiGV+MJrQ1mYSYI3qS/11d2MJDFm8IhOXMTFQirfu6AVOF6Q==",
"dependencies": {
"prop-types": "^15.6.1"
},
"peerDependencies": {
"react": ">= 0.14.0"
}
},
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"dev": true
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/react-property": {
"version": "2.0.0",
@ -3508,8 +3718,7 @@
"node_modules/regenerator-runtime": {
"version": "0.13.9",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
"dev": true
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
},
"node_modules/regexp.prototype.flags": {
"version": "1.4.3",
@ -3540,6 +3749,14 @@
"url": "https://github.com/sponsors/mysticatea"
}
},
"node_modules/rename-keys": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/rename-keys/-/rename-keys-1.2.0.tgz",
"integrity": "sha512-U7XpAktpbSgHTRSNRrjKSrjYkZKuhUukfoBlXWXUExCAqhzh1TU3BDRAfJmarcl5voKS+pbKU9MvyLWKZ4UEEg==",
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/resolve": {
"version": "1.22.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
@ -3886,6 +4103,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/svgson": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/svgson/-/svgson-4.1.0.tgz",
"integrity": "sha512-DodISxHtdLKUghDYA+PGK4Qq350+CbBAkdvGLkBFSmWd9WKSg4dijgjB1IiRPTmsUCd+a7KYe+ILHtklYgQyzQ==",
"dependencies": {
"deep-rename-keys": "^0.2.1",
"omit-deep": "0.3.0",
"xml-reader": "2.4.3"
}
},
"node_modules/tailwindcss": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.4.tgz",
@ -3954,6 +4181,11 @@
"node": ">=8.0"
}
},
"node_modules/transformation-matrix": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/transformation-matrix/-/transformation-matrix-2.1.1.tgz",
"integrity": "sha512-74MoNHhwLVuzwaPDcAecFjSkOA9vwWqyOdkeB0Be8Jc/IWSS5SNZKapFllqzkTliqZptkvqX5CZnVeDvfhN8cw=="
},
"node_modules/tsconfig-paths": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
@ -4048,6 +4280,18 @@
"node": ">= 4.0.0"
}
},
"node_modules/unset-value": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-0.1.2.tgz",
"integrity": "sha512-yhv5I4TsldLdE3UcVQn0hD2T5sNCPv4+qm/CTUpRKIpwthYRIipsAPdsrNpOI79hPQa0rTTeW22Fq6JWRcTgNg==",
"dependencies": {
"has-value": "^0.3.1",
"isobject": "^3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/update-browserslist-db": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.3.tgz",
@ -4074,6 +4318,16 @@
"browserslist": ">= 4.21.0"
}
},
"node_modules/urbit-ob": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/urbit-ob/-/urbit-ob-5.0.1.tgz",
"integrity": "sha512-qGNAwu87XNkW3g8ah4fUwmh2EKXtsdhEbyEiE5qX4Op17rhLH3HSkvu8g9z+MhqX51Uz9sf8ktvqJj/IRwETIQ==",
"dependencies": {
"bn.js": "^4.11.8",
"lodash.chunk": "^4.2.0",
"lodash.isequal": "^4.5.0"
}
},
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@ -4139,6 +4393,23 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/xml-lexer": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/xml-lexer/-/xml-lexer-0.2.2.tgz",
"integrity": "sha512-G0i98epIwiUEiKmMcavmVdhtymW+pCAohMRgybyIME9ygfVu8QheIi+YoQh3ngiThsT0SQzJT4R0sKDEv8Ou0w==",
"dependencies": {
"eventemitter3": "^2.0.0"
}
},
"node_modules/xml-reader": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/xml-reader/-/xml-reader-2.4.3.tgz",
"integrity": "sha512-xWldrIxjeAMAu6+HSf9t50ot1uL5M+BtOidRCWHXIeewvSeIpscWCsp4Zxjk8kHHhdqFBrfK8U0EJeCcnyQ/gA==",
"dependencies": {
"eventemitter3": "^2.0.0",
"xml-lexer": "^0.2.2"
}
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@ -4169,7 +4440,6 @@
"version": "7.18.3",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.3.tgz",
"integrity": "sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==",
"dev": true,
"requires": {
"regenerator-runtime": "^0.13.4"
}
@ -4350,6 +4620,16 @@
"peer": true,
"requires": {}
},
"@tlon/sigil-js": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/@tlon/sigil-js/-/sigil-js-1.4.5.tgz",
"integrity": "sha512-+Fn0EizPetjePaK+z8njjzE74wxzqIRLVM8W53Dlri6XU87wJ4vk82baVGgZQFAQs96rYM/f4WV7kCzuSxSMAw==",
"requires": {
"invariant": "^2.2.4",
"svgson": "^4.0.0",
"transformation-matrix": "2.1.1"
}
},
"@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@ -4597,6 +4877,11 @@
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"peer": true
},
"bn.js": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -4722,6 +5007,11 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"compute-scroll-into-view": {
"version": "1.0.17",
"resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz",
"integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg=="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -4776,6 +5066,25 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
"deep-rename-keys": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/deep-rename-keys/-/deep-rename-keys-0.2.1.tgz",
"integrity": "sha512-RHd9ABw4Fvk+gYDWqwOftG849x0bYOySl/RgX0tLI9i27ZIeSO91mLZJEp7oPHOMFqHvpgu21YptmDt0FYD/0A==",
"requires": {
"kind-of": "^3.0.2",
"rename-keys": "^1.1.2"
},
"dependencies": {
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
"requires": {
"is-buffer": "^1.1.5"
}
}
}
},
"define-properties": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
@ -4873,6 +5182,30 @@
"domhandler": "^4.2.0"
}
},
"downshift": {
"version": "6.1.7",
"resolved": "https://registry.npmjs.org/downshift/-/downshift-6.1.7.tgz",
"integrity": "sha512-cVprZg/9Lvj/uhYRxELzlu1aezRcgPWBjTvspiGTVEU64gF5pRdSRKFVLcxqsZC637cLAGMbL40JavEfWnqgNg==",
"requires": {
"@babel/runtime": "^7.14.8",
"compute-scroll-into-view": "^1.0.17",
"prop-types": "^15.7.2",
"react-is": "^17.0.2",
"tslib": "^2.3.0"
},
"dependencies": {
"react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
"tslib": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
}
}
},
"electron-to-chromium": {
"version": "1.4.166",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.166.tgz",
@ -5287,6 +5620,11 @@
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true
},
"eventemitter3": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
"integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg=="
},
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
@ -5483,6 +5821,11 @@
"get-intrinsic": "^1.1.1"
}
},
"get-value": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
"integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA=="
},
"glob": {
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
@ -5606,6 +5949,31 @@
"has-symbols": "^1.0.2"
}
},
"has-value": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
"integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==",
"requires": {
"get-value": "^2.0.3",
"has-values": "^0.1.4",
"isobject": "^2.0.0"
},
"dependencies": {
"isobject": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
"integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==",
"requires": {
"isarray": "1.0.0"
}
}
}
},
"has-values": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
"integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ=="
},
"html-dom-parser": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-1.2.0.tgz",
@ -5689,6 +6057,14 @@
"side-channel": "^1.0.4"
}
},
"invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"requires": {
"loose-envify": "^1.0.0"
}
},
"is-bigint": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
@ -5717,6 +6093,11 @@
"has-tostringtag": "^1.0.0"
}
},
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"is-callable": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
@ -5791,6 +6172,14 @@
"has-tostringtag": "^1.0.0"
}
},
"is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
"requires": {
"isobject": "^3.0.1"
}
},
"is-regex": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
@ -5845,11 +6234,21 @@
"is-docker": "^2.0.0"
}
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -5931,6 +6330,19 @@
"language-subtag-registry": "~0.3.2"
}
},
"leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
"integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="
},
"leven-sort": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/leven-sort/-/leven-sort-3.0.0.tgz",
"integrity": "sha512-dw+6CDkFAbmXiAv/bU2IQKEJzgdXUYnc2Z4FipY9gOt+tdUUiP1R1Jn8S05aORllj5NLcKyx6zwIz+M3ygCohA==",
"requires": {
"leven": "^3.1.0"
}
},
"levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@ -5957,6 +6369,21 @@
"path-exists": "^3.0.0"
}
},
"lodash.chunk": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
"integrity": "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w=="
},
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
},
"lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
},
"lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@ -6165,6 +6592,15 @@
"es-abstract": "^1.19.1"
}
},
"omit-deep": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/omit-deep/-/omit-deep-0.3.0.tgz",
"integrity": "sha512-Lbl/Ma59sss2b15DpnWnGmECBRL8cRl/PjPbPMVW+Y8zIQzRrwMaI65Oy6HvxyhYeILVKBJb2LWeG81bj5zbMg==",
"requires": {
"is-plain-object": "^2.0.1",
"unset-value": "^0.1.1"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@ -6502,7 +6938,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"dev": true,
"requires": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
@ -6545,11 +6980,18 @@
"scheduler": "^0.20.2"
}
},
"react-hotkeys": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-hotkeys/-/react-hotkeys-2.0.0.tgz",
"integrity": "sha512-3n3OU8vLX/pfcJrR3xJ1zlww6KS1kEJt0Whxc4FiGV+MJrQ1mYSYI3qS/11d2MJDFm8IhOXMTFQirfu6AVOF6Q==",
"requires": {
"prop-types": "^15.6.1"
}
},
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"dev": true
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"react-property": {
"version": "2.0.0",
@ -6593,8 +7035,7 @@
"regenerator-runtime": {
"version": "0.13.9",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
"dev": true
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
},
"regexp.prototype.flags": {
"version": "1.4.3",
@ -6613,6 +7054,11 @@
"integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
"dev": true
},
"rename-keys": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/rename-keys/-/rename-keys-1.2.0.tgz",
"integrity": "sha512-U7XpAktpbSgHTRSNRrjKSrjYkZKuhUukfoBlXWXUExCAqhzh1TU3BDRAfJmarcl5voKS+pbKU9MvyLWKZ4UEEg=="
},
"resolve": {
"version": "1.22.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
@ -6842,6 +7288,16 @@
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
},
"svgson": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/svgson/-/svgson-4.1.0.tgz",
"integrity": "sha512-DodISxHtdLKUghDYA+PGK4Qq350+CbBAkdvGLkBFSmWd9WKSg4dijgjB1IiRPTmsUCd+a7KYe+ILHtklYgQyzQ==",
"requires": {
"deep-rename-keys": "^0.2.1",
"omit-deep": "0.3.0",
"xml-reader": "2.4.3"
}
},
"tailwindcss": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.4.tgz",
@ -6894,6 +7350,11 @@
"is-number": "^7.0.0"
}
},
"transformation-matrix": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/transformation-matrix/-/transformation-matrix-2.1.1.tgz",
"integrity": "sha512-74MoNHhwLVuzwaPDcAecFjSkOA9vwWqyOdkeB0Be8Jc/IWSS5SNZKapFllqzkTliqZptkvqX5CZnVeDvfhN8cw=="
},
"tsconfig-paths": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
@ -6960,6 +7421,15 @@
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
},
"unset-value": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-0.1.2.tgz",
"integrity": "sha512-yhv5I4TsldLdE3UcVQn0hD2T5sNCPv4+qm/CTUpRKIpwthYRIipsAPdsrNpOI79hPQa0rTTeW22Fq6JWRcTgNg==",
"requires": {
"has-value": "^0.3.1",
"isobject": "^3.0.0"
}
},
"update-browserslist-db": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.3.tgz",
@ -6970,6 +7440,16 @@
"picocolors": "^1.0.0"
}
},
"urbit-ob": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/urbit-ob/-/urbit-ob-5.0.1.tgz",
"integrity": "sha512-qGNAwu87XNkW3g8ah4fUwmh2EKXtsdhEbyEiE5qX4Op17rhLH3HSkvu8g9z+MhqX51Uz9sf8ktvqJj/IRwETIQ==",
"requires": {
"bn.js": "^4.11.8",
"lodash.chunk": "^4.2.0",
"lodash.isequal": "^4.5.0"
}
},
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@ -7023,6 +7503,23 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"xml-lexer": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/xml-lexer/-/xml-lexer-0.2.2.tgz",
"integrity": "sha512-G0i98epIwiUEiKmMcavmVdhtymW+pCAohMRgybyIME9ygfVu8QheIi+YoQh3ngiThsT0SQzJT4R0sKDEv8Ou0w==",
"requires": {
"eventemitter3": "^2.0.0"
}
},
"xml-reader": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/xml-reader/-/xml-reader-2.4.3.tgz",
"integrity": "sha512-xWldrIxjeAMAu6+HSf9t50ot1uL5M+BtOidRCWHXIeewvSeIpscWCsp4Zxjk8kHHhdqFBrfK8U0EJeCcnyQ/gA==",
"requires": {
"eventemitter3": "^2.0.0",
"xml-lexer": "^0.2.2"
}
},
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",

View File

@ -3,24 +3,32 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "npm run prebuild && next dev",
"prebuild": "npm run cache-posts",
"cache-posts": "node lib/cache.js",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@iarna/toml": "^2.2.5",
"@tlon/sigil-js": "^1.4.5",
"browserify-zlib": "^0.2.0",
"classnames": "^2.3.1",
"downshift": "^6.1.7",
"foundation-design-system": "github:urbit/foundation-design-system",
"gray-matter": "^4.0.3",
"leven-sort": "^3.0.0",
"lodash.debounce": "^4.0.8",
"luxon": "^2.4.0",
"next": "12.1.6",
"path-browserify": "^1.0.1",
"react": "^17",
"react-dom": "^17",
"react-hotkeys": "^2.0.0",
"react-swipeable": "^7.0.0",
"stream-browserify": "^3.0.0"
"stream-browserify": "^3.0.0",
"urbit-ob": "^5.0.1"
},
"devDependencies": {
"eslint": "8.18.0",

View File

@ -14,7 +14,7 @@ export default function NotFound(props) {
<title>404 developers.urbit.org</title>
{Meta(post)}
</Head>
<Header />
<Header search={props.search} />
<SingleColumn>
<Section className="pt-48">
<h1>404</h1>

View File

@ -1,10 +1,71 @@
import { useState, useEffect } from "react";
import { configure, GlobalHotKeys } from "react-hotkeys";
import Search from "../components/Search";
import "foundation-design-system/styles/globals.css";
import "foundation-design-system/styles/markdown.css";
import "foundation-design-system/styles/prism.css";
import "../styles/developers.css";
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
const [showSearch, setSearch] = useState(false);
const closeSearch = (event) => {
if (event?.preventDefault) {
event.preventDefault();
}
setSearch(false);
};
const openSearch = (event) => {
if (event?.preventDefault) {
event.preventDefault();
}
setSearch(true);
};
const toggleSearch = (event) => {
if (event?.preventDefault) {
event.preventDefault();
}
setSearch((state) => !state);
};
const keyMap = {
closeSearch: ["esc"],
toggleSearch: ["command+k", "ctrl+k"],
};
const handlers = {
closeSearch: (event) => closeSearch(event),
openSearch: (event) => openSearch(event),
toggleSearch: (event) => toggleSearch(event),
};
configure({
// ignoreTags: [],
ignoreTags: ["input", "select", "textarea"],
ignoreEventsCondition: function () {},
});
return (
<>
<GlobalHotKeys keyMap={keyMap} handlers={handlers} />
<Search
showSearch={showSearch}
toggleSearch={toggleSearch}
closeSearch={closeSearch}
openSearch={openSearch}
/>
<Component
{...pageProps}
search={{
toggleSearch: toggleSearch,
closeSearch: closeSearch,
openSearch: openSearch,
}}
/>
</>
);
}
export default MyApp;

View File

@ -1,5 +0,0 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' })
}

15
pages/api/search.js Normal file
View File

@ -0,0 +1,15 @@
import { index } from "../../cache/data";
const levenSort = require("leven-sort");
export default (req, res) => {
const results = index.filter(
(e) =>
e.title?.toLowerCase().includes(req.query.q.toLowerCase()) ||
e?.slug.includes(req.query.q.toLowerCase()) ||
e?.parent.toLowerCase().includes(req.query.q.toLowerCase())
);
const sorted = levenSort(results, req.q, ["title", "slug", "parent"]);
res.statusCode = 200;
res.setHeader("Content-Type", "application/json");
res.end(JSON.stringify({ results: sorted }));
};

View File

@ -11,7 +11,7 @@ import {
import { getAllPosts, formatDate, generateDisplayDate } from "../lib/lib";
import Footer from "../components/Footer";
export default function Blog({ posts }) {
export default function Blog({ posts, search }) {
const post = {
title: "Developer Blog",
description: "Technical-oriented posts by Urbit engineers.",
@ -23,7 +23,7 @@ export default function Blog({ posts }) {
<title>Blog developers.urbit.org</title>
{Meta(post)}
</Head>
<Header />
<Header search={search} />
<SingleColumn>
<Section narrow short>
<h1 className="pb-16">Developer Blog</h1>

View File

@ -22,7 +22,13 @@ import {
TwoUp,
} from "foundation-design-system";
export default function BlogPost({ post, markdown, nextPost, previousPost }) {
export default function BlogPost({
post,
search,
markdown,
nextPost,
previousPost,
}) {
const router = useRouter();
if (!router.isFallback && !post?.slug) {
return <ErrorPage />;
@ -35,7 +41,7 @@ export default function BlogPost({ post, markdown, nextPost, previousPost }) {
<title>{post.title} Blog developers.urbit.org</title>
{Meta(post)}
</Head>
<Header />
<Header search={search} />
<SingleColumn>
<Section short narrow>
<h1>{post.title}</h1>

View File

@ -46,7 +46,7 @@ export default function Event({
<title>{event.title} Events urbit.org</title>
{Meta(event)}
</Head>
<Header />
<Header search={search} />
<SingleColumn>
<Section narrow short>
<h1>{event.title}</h1>

View File

@ -49,7 +49,7 @@ export default function Events({ events, search }) {
<title>Developer Events developer.urbit.org</title>
{Meta(post)}
</Head>
<Header />
<Header search={search} />
<SingleColumn>
<Section short narrow>
<h1 className="pb-16">Developer Events</h1>

View File

@ -11,7 +11,7 @@ import {
import Meta from "../../components/Meta";
import Card from "../../components/Card";
export default function Community() {
export default function Community({ search }) {
const post = {
title: "Community",
description:
@ -23,7 +23,7 @@ export default function Community() {
<title>Blog developers.urbit.org</title>
{Meta(post)}
</Head>
<Header />
<Header search={search} />
<SingleColumn>
<Section>
<h1>Community</h1>

View File

@ -20,7 +20,7 @@ export default function Courses({ search }) {
<title>Courses developers.urbit.org</title>
{Meta(post)}
</Head>
<Header />
<Header search={search} />
<SingleColumn>
<Section>
<h1>Courses</h1>

View File

@ -12,7 +12,7 @@ import {
} from "foundation-design-system";
import { Comms, MintFiller } from "../../components/icons";
export default function GuidePage() {
export default function GuidePage({ search }) {
const post = {
title: "Guides",
description:
@ -24,7 +24,7 @@ export default function GuidePage() {
<title>Guides developers.urbit.org</title>
{Meta(post)}
</Head>
<Header />
<Header search={search} />
<SingleColumn>
<Section>
<h1>Guides</h1>

View File

@ -21,14 +21,14 @@ import {
import Card from "../components/Card";
import TallCard from "../components/TallCard";
export default function Home() {
export default function Home({ search }) {
return (
<div>
<Head>
<title>Urbit Developers</title>
</Head>
<Container>
<Header />
<Header search={search} />
<SingleColumn>
<Section className="pb-72">
{/* Hero statement */}

View File

@ -20,7 +20,7 @@ import {
} from "../components/icons";
import Footer from "../components/Footer";
export default function Overview({ markdown }) {
export default function Overview({ markdown, search }) {
const post = {
title: "Overview",
description: "Urbit's stack in a nutshell.",
@ -31,7 +31,7 @@ export default function Overview({ markdown }) {
<title>Overview developers.urbit.org</title>
{Meta(post)}
</Head>
<Header />
<Header search={search} />
<SingleColumn>
<Section>
<h1>Overview</h1>