1
0
This commit is contained in:
Zef Hemel 2022-03-01 16:57:20 +01:00
parent 5cd5feeafa
commit 9b1b950c41
23 changed files with 636 additions and 290 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
pages
logo.pxd
.DS_Store

View File

@ -89,8 +89,8 @@ fsRouter.put("/:page(.*)", async (context) => {
const text = await readAll(result.value);
file.write(text);
file.close();
const stat = await Deno.stat(localPath);
console.log("Wrote to", localPath);
const stat = await Deno.stat(localPath);
context.response.status = existingPage ? 200 : 201;
context.response.headers.set("Last-Modified", "" + stat.mtime?.getTime());
context.response.body = "OK";

View File

@ -13,6 +13,9 @@
"check-watch": "tsc --noEmit --watch"
},
"devDependencies": {
"@parcel/packager-raw-url": "2.3.2",
"@parcel/transformer-sass": "2.3.2",
"@parcel/transformer-webmanifest": "2.3.2",
"@parcel/validator-typescript": "^2.3.2",
"@types/react": "^17.0.39",
"@types/react-dom": "^17.0.11",
@ -29,6 +32,9 @@
"@codemirror/lang-markdown": "^0.19.6",
"@codemirror/state": "^0.19.7",
"@codemirror/view": "^0.19.42",
"@fortawesome/fontawesome-svg-core": "^1.3.0",
"@fortawesome/free-solid-svg-icons": "^6.0.0",
"@fortawesome/react-fontawesome": "^0.1.17",
"@parcel/service-worker": "^2.3.2",
"dexie": "^3.2.1",
"idb": "^7.0.0",

View File

@ -1,6 +1,7 @@
import { AppCommand } from "../types";
import { isMacLike } from "../util";
import { FilterList, Option } from "./filter";
import { faPersonRunning } from "@fortawesome/free-solid-svg-icons";
export function CommandPalette({
commands,
@ -20,9 +21,12 @@ export function CommandPalette({
console.log("Commands", options);
return (
<FilterList
placeholder="Enter command to run"
label="Run"
placeholder="Command"
options={options}
allowNew={false}
icon={faPersonRunning}
helpText="Start typing the command name to filter results, press <code>Return</code> to run."
onSelect={(opt) => {
if (opt) {
onTrigger(commands.get(opt.name));

View File

@ -1,4 +1,6 @@
import React, { useEffect, useRef, useState } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { IconDefinition } from "@fortawesome/free-solid-svg-icons";
export interface Option {
name: string;
@ -16,17 +18,23 @@ function magicSorter(a: Option, b: Option): number {
export function FilterList({
placeholder,
options,
label,
onSelect,
onKeyPress,
allowNew = false,
helpText = "",
icon,
newHint,
}: {
placeholder: string;
options: Option[];
label: string;
onKeyPress?: (key: string, currentText: string) => void;
onSelect: (option: Option | undefined) => void;
allowNew?: boolean;
helpText: string;
newHint?: string;
icon?: IconDefinition;
}) {
const searchBoxRef = useRef<HTMLInputElement>(null);
const [text, setText] = useState("");
@ -81,40 +89,45 @@ export function FilterList({
};
}, []);
const returEl = (
<div className="filter-container">
<input
type="text"
value={text}
placeholder={placeholder}
ref={searchBoxRef}
onChange={filter}
onKeyDown={(e: React.KeyboardEvent) => {
console.log("Key up", e.key);
if (onKeyPress) {
onKeyPress(e.key, text);
}
switch (e.key) {
case "ArrowUp":
setSelectionOption(Math.max(0, selectedOption - 1));
break;
case "ArrowDown":
setSelectionOption(
Math.min(matchingOptions.length - 1, selectedOption + 1)
);
break;
case "Enter":
onSelect(matchingOptions[selectedOption]);
e.preventDefault();
break;
case "Escape":
onSelect(undefined);
break;
}
}}
className="input"
/>
const returnEl = (
<div className="filter-box">
<div className="header">
<label>{label}</label>
<input
type="text"
value={text}
placeholder={placeholder}
ref={searchBoxRef}
onChange={filter}
onKeyDown={(e: React.KeyboardEvent) => {
console.log("Key up", e.key);
if (onKeyPress) {
onKeyPress(e.key, text);
}
switch (e.key) {
case "ArrowUp":
setSelectionOption(Math.max(0, selectedOption - 1));
break;
case "ArrowDown":
setSelectionOption(
Math.min(matchingOptions.length - 1, selectedOption + 1)
);
break;
case "Enter":
onSelect(matchingOptions[selectedOption]);
e.preventDefault();
break;
case "Escape":
onSelect(undefined);
break;
}
}}
/>
</div>
<div
className="help-text"
dangerouslySetInnerHTML={{ __html: helpText }}
></div>
<div className="result-list">
{matchingOptions && matchingOptions.length > 0
? matchingOptions.map((option, idx) => (
@ -132,7 +145,10 @@ export function FilterList({
onSelect(option);
}}
>
<span className="user-name">{option.name}</span>
<span className="icon">
{icon && <FontAwesomeIcon icon={icon} />}
</span>
<span className="name">{option.name}</span>
{option.hint && <span className="hint">{option.hint}</span>}
</div>
))
@ -147,5 +163,5 @@ export function FilterList({
});
});
return returEl;
return returnEl;
}

View File

@ -1,4 +1,6 @@
import { PageMeta } from "../types";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faFileLines } from "@fortawesome/free-solid-svg-icons";
export function NavigationBar({
currentPage,
@ -8,9 +10,12 @@ export function NavigationBar({
onClick: () => void;
}) {
return (
<div id="top">
<div className="current-page" onClick={onClick}>
» {currentPage?.name}
<div id="top" onClick={onClick}>
<div className="inner">
<span className="icon">
<FontAwesomeIcon icon={faFileLines} />
</span>
<span className="current-page">{currentPage?.name}</span>
</div>
</div>
);

View File

@ -1,5 +1,6 @@
import { PageMeta } from "../types";
import { FilterList, Option } from "./filter";
import { faFileLines } from "@fortawesome/free-solid-svg-icons";
export function PageNavigator({
allPages,
@ -28,9 +29,12 @@ export function PageNavigator({
}
return (
<FilterList
placeholder=""
placeholder="Page"
label="Open"
options={options}
icon={faFileLines}
allowNew={true}
helpText="Start typing the page name to filter results, press <code>Return</code> to open."
newHint="Create page"
onSelect={(opt) => {
onNavigate(opt?.name);

View File

@ -57,6 +57,7 @@ import {
import { safeRun } from "./util";
import { Indexer } from "./indexer";
import { IPageNavigator, PathPageNavigator } from "./navigator";
import { smartQuoteKeymap } from "./smart_quotes";
class PageState {
editorState: EditorState;
@ -123,7 +124,7 @@ export class Editor implements AppEventDispatcher {
}
async loadPlugins() {
const system = new BrowserSystem("plugin");
const system = new BrowserSystem("/plugin");
system.registerSyscalls(
dbSyscalls,
editorSyscalls(this),
@ -222,6 +223,7 @@ export class Editor implements AppEventDispatcher {
{ selector: "FencedCode", class: "line-fenced-code" },
]),
keymap.of([
...smartQuoteKeymap,
...closeBracketsKeymap,
...standardKeymap,
...searchKeymap,
@ -248,8 +250,8 @@ export class Editor implements AppEventDispatcher {
},
},
{
key: "Ctrl-e",
mac: "Cmd-e",
key: "Ctrl-k",
mac: "Cmd-k",
run: (target): boolean => {
this.viewDispatch({ type: "start-navigate" });
return true;
@ -302,7 +304,6 @@ export class Editor implements AppEventDispatcher {
ctx: CompletionContext
): Promise<CompletionResult | null> {
let allCompletionResults = await this.dispatchAppEvent("editor:complete");
// console.log("All results", allCompletionResults);
if (allCompletionResults.length === 1) {
return allCompletionResults[0];
} else if (allCompletionResults.length > 1) {
@ -368,13 +369,14 @@ export class Editor implements AppEventDispatcher {
console.log("Page not modified, skipping saving");
return;
}
// Write to file system
let text = editorState.sliceDoc();
let pageMeta = await this.space.writePage(this.currentPage.name, text);
// Write to the space
const pageName = this.currentPage.name;
const text = editorState.sliceDoc();
let pageMeta = await this.space.writePage(pageName, text);
// Update in open page cache
this.openPages.set(
this.currentPage.name,
pageName,
new PageState(editorState, this.editorView!.scrollDOM.scrollTop, pageMeta)
);
@ -422,10 +424,10 @@ export class Editor implements AppEventDispatcher {
console.log("File changed on disk, reloading");
let pageData = await this.space.readPage(currentPageName);
this.openPages.set(
newPageMeta.name,
currentPageName,
new PageState(this.createEditorState(pageData.text), 0, newPageMeta)
);
await this.loadPage(currentPageName);
await this.loadPage(currentPageName, false);
}
}
@ -433,11 +435,11 @@ export class Editor implements AppEventDispatcher {
this.editorView!.focus();
}
async navigate(name: string) {
await this.pageNavigator.navigate(name);
navigate(name: string) {
this.pageNavigator.navigate(name);
}
async loadPage(pageName: string) {
async loadPage(pageName: string, checkNewVersion: boolean = true) {
let pageState = this.openPages.get(pageName);
if (!pageState) {
let pageData = await this.space.readPage(pageName);
@ -447,11 +449,8 @@ export class Editor implements AppEventDispatcher {
pageData.meta
);
this.openPages.set(pageName, pageState!);
} else {
// Loaded page from in-mory cache, let's async see if this page hasn't been updated
this.checkForNewVersion(pageState.meta).catch((e) => {
console.error("Failed to check for new version");
});
// Freshly loaded, no need to check for a new version either way
checkNewVersion = false;
}
this.editorView!.setState(pageState!.editorState);
this.editorView!.scrollDOM.scrollTop = pageState!.scrollTop;
@ -470,6 +469,13 @@ export class Editor implements AppEventDispatcher {
) {
await this.indexPage(pageState.editorState.sliceDoc(), pageState.meta);
}
if (checkNewVersion) {
// Loaded page from in-memory cache, let's async see if this page hasn't been updated
this.checkForNewVersion(pageState.meta).catch((e) => {
console.error("Failed to check for new version");
});
}
}
ViewComponent(): React.ReactElement {

View File

@ -43,8 +43,8 @@ self.addEventListener("message", (event) => {
let data = messageEvent.data;
switch (data.type) {
case "boot":
console.log("Booting", `./${data.prefix}/function/${data.name}`);
importScripts(`./${data.prefix}/function/${data.name}`);
console.log("Booting", `${data.prefix}/function/${data.name}`);
importScripts(`${data.prefix}/function/${data.name}`);
self.postMessage({
type: "inited",
});

BIN
webapp/src/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

View File

@ -3,8 +3,9 @@
<head>
<meta charset="utf-8" />
<title>Page</title>
<link rel="stylesheet" href="styles.css" />
<link rel="stylesheet" href="styles/main.scss" />
<script type="module" src="boot.ts"></script>
<link rel="manifest" href="manifest.json" />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
</head>

17
webapp/src/manifest.json Normal file
View File

@ -0,0 +1,17 @@
{
"short_name": "Nugget",
"name": "Nugget",
"icons": [
{
"src": "./images/logo.png",
"type": "image/png",
"sizes": "1024x1024"
}
],
"capture_links": "new-client",
"start_url": "/start",
"display": "standalone",
"scope": "/",
"theme_color": "#000",
"description": "Note taking for winners"
}

View File

@ -17,7 +17,6 @@ function decodePageUrl(url: string): string {
export class PathPageNavigator implements IPageNavigator {
navigationResolve?: (value: undefined) => void;
async navigate(page: string) {
console.log("Pushing state", page);
window.history.pushState({ page: page }, page, `/${encodePageUrl(page)}`);
window.dispatchEvent(new PopStateEvent("popstate"));
await new Promise<undefined>((resolve) => {
@ -27,7 +26,10 @@ export class PathPageNavigator implements IPageNavigator {
}
subscribe(pageLoadCallback: (pageName: string) => Promise<void>): void {
const cb = () => {
console.log("State popped", this.getCurrentPage());
const gotoPage = this.getCurrentPage();
if (!gotoPage) {
return;
}
safeRun(async () => {
await pageLoadCallback(this.getCurrentPage());
if (this.navigationResolve) {

View File

@ -46,6 +46,7 @@ export class BrowserSystem extends System {
new URL("../plugin_sw.ts", import.meta.url),
{
type: "module",
scope: "/",
}
);

View File

@ -18,7 +18,7 @@ export class FunctionWorker {
// type: "classic",
// });
let worker = window.Worker;
this.worker = new worker("function_worker.js");
this.worker = new worker("/function_worker.js");
// console.log("Starting worker", this.worker);
this.worker.onmessage = this.onmessage.bind(this);

View File

@ -4,7 +4,7 @@ export default function reducer(
state: AppViewState,
action: Action
): AppViewState {
console.log("Got action", action);
// console.log("Got action", action);
switch (action.type) {
case "page-loaded":
return {

View File

@ -0,0 +1,35 @@
import { KeyBinding } from "@codemirror/view";
// TODO: Add support for selection (put quotes around or create blockquote block?)
function keyBindingForQuote(
quote: string,
left: string,
right: string
): KeyBinding {
return {
key: quote,
run: (target): boolean => {
let cursorPos = target.state.selection.main.from;
let chBefore = target.state.sliceDoc(cursorPos - 1, cursorPos);
let quote = right;
if (/\W/.exec(chBefore) && !/[!\?,\.\-=“]/.exec(chBefore)) {
quote = left;
}
target.dispatch({
changes: {
insert: quote,
from: cursorPos,
},
selection: {
anchor: cursorPos + 1,
},
});
return true;
},
};
}
export const smartQuoteKeymap: KeyBinding[] = [
keyBindingForQuote('"', "“", "”"),
keyBindingForQuote("'", "", ""),
];

View File

@ -10,6 +10,7 @@ export interface Space {
export class HttpRemoteSpace implements Space {
url: string;
constructor(url: string) {
this.url = url;
}

View File

@ -1,221 +0,0 @@
:root {
--ident: 18px;
/* --editor-font: "Avenir"; */
--editor-font: "Menlo";
--top-bar-bg: rgb(41, 41, 41);
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
#top {
height: 40px;
background-color: var(--top-bar-bg);
position: absolute;
top: 0;
left: 0;
right: 0;
color: #eee;
}
#bottom {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 25px;
background-color: var(--top-bar-bg);
color: #eee;
margin: 0;
padding: 5px;
font-family: var(--editor-font);
text-align: right;
}
#editor {
position: absolute;
top: 40px;
bottom: 40px;
left: 0;
right: 0;
overflow-y: hidden;
}
.cm-editor {
width: 100%;
height: 100%;
font-size: var(--ident);
}
@media only screen and (max-width: 800px) {
.cm-editor .cm-content {
margin: 0 10px !important;
}
}
.cm-editor .cm-content {
font-family: var(--editor-font);
margin: auto;
max-width: 800px;
}
.cm-editor .cm-selectionBackground {
background-color: #d7e1f6 !important;
}
.cm-editor .h1 {
font-size: 1.5em;
color: #fff;
font-weight: bold;
}
.cm-editor .cm-line.line-h1 {
display: block;
background-color: rgba(0, 15, 52, 0.6);
}
.cm-editor .h1.meta {
color: orange;
}
.cm-editor .h2 {
font-size: 1.2em;
color: #fff;
font-weight: bold;
}
.cm-editor .cm-line.line-h2 {
display: block;
background-color: rgba(0, 15, 52, 0.6);
}
.cm-editor .h2.meta {
color: orange;
}
/* .cm-editor .cm-line {
padding-left: 50px;
max-width: 800px;
} */
.cm-editor .line-code {
background-color: #efefef;
margin-left: 30px;
}
.cm-editor .line-fenced-code {
background-color: #efefef;
}
.cm-editor .meta {
color: #650007;
}
.cm-editor .line-blockquote {
background-color: #eee;
color: #676767;
text-indent: calc(-1 * (var(--ident) + 3px));
padding-left: var(--ident);
}
.cm-editor .emphasis {
font-style: italic;
}
.cm-editor .strong {
font-weight: 900;
}
.cm-editor .link:not(.meta, .url) {
color: #0330cb;
text-decoration: underline;
}
.cm-editor .link.url {
color: #7e7d7d;
}
.cm-editor .url:not(.link) {
color: #0330cb;
text-decoration: underline;
}
.cm-editor .wiki-link-page {
color: #0330cb;
text-decoration: underline;
}
.cm-editor .wiki-link {
color: #808080;
}
.cm-editor .mention {
color: gray;
}
.cm-editor .tag {
color: #8d8d8d;
}
.cm-editor .line-li {
text-indent: calc(-1 * var(--ident) - 3px);
margin-left: var(--ident);
}
.cm-editor .task-marker {
background-color: #ddd;
}
.current-page {
font-family: var(--editor-font);
margin-left: 10px;
margin-top: 10px;
font-weight: bold;
}
.filter-container {
font-family: var(--editor-font);
display: block;
border: #333 1px solid;
z-index: 1000;
position: absolute;
left: 25px;
top: 10px;
right: 10px;
}
.filter-container .result-list {
max-height: 200px;
overflow-y: scroll;
background-color: white;
}
.filter-container input {
font-family: var(--editor-font);
width: 100%;
/* border: 1px #333 solid; */
background-color: var(--top-bar-bg);
color: #eee;
border: 0;
padding: 3px;
outline: 0;
font-weight: bold;
}
.filter-container .option,
.filter-container .selected-option {
padding: 3px 3px 3px 3px;
cursor: pointer;
}
.filter-container .selected-option {
background-color: #b1b1b1;
}
.filter-container .hint {
float: right;
margin-right: 10px;
color: #333;
}

View File

@ -0,0 +1,120 @@
.cm-editor {
width: 100%;
height: 100%;
font-size: var(--ident);
.cm-content {
font-family: var(--editor-font);
margin: auto;
max-width: 800px;
}
.cm-selectionBackground {
background-color: #d7e1f6 !important;
}
.h1 {
font-size: 1.5em;
color: #fff;
font-weight: bold;
}
.cm-line.line-h1 {
display: block;
background-color: rgba(0, 15, 52, 0.6);
}
.h1.meta {
color: orange;
}
.h2 {
font-size: 1.2em;
color: #fff;
font-weight: bold;
}
.cm-line.line-h2 {
display: block;
background-color: rgba(0, 15, 52, 0.6);
}
.h2.meta {
color: orange;
}
/* Color list item this way */
.line-li .meta {
color: rgb(0, 123, 19);
}
/* Then undo other meta */
.line-li .meta ~ .meta {
color: #650007;
}
.line-code {
background-color: #efefef;
margin-left: 30px;
}
.line-fenced-code {
background-color: #efefef;
}
.meta {
color: #650007;
}
.line-blockquote {
background-color: #eee;
color: #676767;
text-indent: calc(-1 * (var(--ident) + 3px));
padding-left: var(--ident);
}
.emphasis {
font-style: italic;
}
.strong {
font-weight: 900;
}
.link:not(.meta, .url) {
color: #0330cb;
text-decoration: underline;
}
.link.url {
color: #7e7d7d;
}
.url:not(.link) {
color: #0330cb;
text-decoration: underline;
}
.wiki-link-page {
color: #0330cb;
text-decoration: underline;
}
.wiki-link {
color: #808080;
}
.mention {
color: gray;
}
.tag {
color: #8d8d8d;
}
.line-li {
text-indent: calc(-1 * var(--ident) - 3px);
margin-left: var(--ident);
}
.task-marker {
background-color: #ddd;
}
}

View File

@ -0,0 +1,87 @@
.filter-box {
position: absolute;
font-family: var(--ui-font);
margin: auto;
width: 500px;
height: 600px;
background-color: #fff;
left: 0;
right: 0;
top: 0;
bottom: 0;
max-height: 290px;
overflow: auto;
z-index: 100;
border: rgb(103, 103, 103) 1px solid;
border-radius: 8px;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
label {
color: var(--highlight-color);
}
.header {
border-bottom: 1px rgb(108, 108, 108) solid;
padding: 13px 10px 10px 10px;
}
.help-text {
background-color: #eee;
border-bottom: 1px rgb(108, 108, 108) solid;
padding: 5px;
color: #555;
}
.result-list {
max-height: 200px;
overflow-y: scroll;
background-color: white;
.icon {
padding: 0 8px 0 5px;
}
.name {
padding-top: -3px;
}
}
input {
font-family: "Arial";
background: transparent;
color: #000;
border: 0;
padding: 3px;
outline: 0;
font-size: 1em;
}
input::placeholder {
color: rgb(199, 199, 199);
font-weight: normal;
}
.option,
.selected-option {
padding: 8px;
cursor: pointer;
}
.selected-option {
background-color: var(--highlight-color);
color: #eee;
}
.option .hint,
.selected-option .hint {
float: right;
margin-right: 0;
margin-top: -4px;
padding-left: 5px;
padding-right: 5px;
padding-top: 3px;
padding-bottom: 3px;
color: #eee;
background-color: #212476;
border-radius: 5px;
}
}

View File

@ -0,0 +1,77 @@
@use "editor.scss";
@use "filter_box.scss";
:root {
--ident: 18px;
/* --editor-font: "Avenir"; */
--editor-font: "Menlo";
--ui-font: "Arial";
--top-bar-bg: rgb(41, 41, 41);
--highlight-color: #464cfc;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
#top {
height: 55px;
position: absolute;
top: 0;
left: 0;
right: 0;
background-color: rgb(213, 213, 213);
border-bottom: rgb(193, 193, 193) 1px solid;
color: rgb(55, 55, 55);
.inner {
padding-top: 12px;
max-width: 800px;
font-size: 28px;
margin: auto;
}
.current-page {
font-family: var(--ui-font);
font-weight: bold;
}
.icon {
padding-left: 5px;
padding-right: 10px;
}
}
#bottom {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 20px;
background-color: rgb(232, 232, 232);
color: rgb(79, 78, 78);
border-top: rgb(186, 186, 186) 1px solid;
margin: 0;
padding: 5px 10px;
font-family: var(--ui-font);
font-size: 0.9em;
text-align: right;
}
#editor {
position: absolute;
top: 60px;
bottom: 30px;
left: 0;
right: 0;
overflow-y: hidden;
}
@media only screen and (max-width: 800px) {
.cm-editor .cm-content {
margin: 0 10px !important;
}
}

View File

@ -280,6 +280,32 @@
style-mod "^4.0.0"
w3c-keyname "^2.2.4"
"@fortawesome/fontawesome-common-types@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.3.0.tgz#949995a05c0d8801be7e0a594f775f1dbaa0d893"
integrity sha512-CA3MAZBTxVsF6SkfkHXDerkhcQs0QPofy43eFdbWJJkZiq3SfiaH1msOkac59rQaqto5EqWnASboY1dBuKen5w==
"@fortawesome/fontawesome-svg-core@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.3.0.tgz#343fac91fa87daa630d26420bfedfba560f85885"
integrity sha512-UIL6crBWhjTNQcONt96ExjUnKt1D68foe3xjEensLDclqQ6YagwCRYVQdrp/hW0ALRp/5Fv/VKw+MqTUWYYvPg==
dependencies:
"@fortawesome/fontawesome-common-types" "^0.3.0"
"@fortawesome/free-solid-svg-icons@^6.0.0":
version "6.0.0"
resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.0.0.tgz#bed4a501b631c6cfa35c09830f7cb63ffca1589d"
integrity sha512-o4FZ1XbndcgeWNb8Wh0y+Hgf73CjmyOQowUSaqQCtgIIdS+XliSBSOwCl330wER+I6CGYE96hT27bHBPmzX2Gg==
dependencies:
"@fortawesome/fontawesome-common-types" "^0.3.0"
"@fortawesome/react-fontawesome@^0.1.17":
version "0.1.17"
resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.17.tgz#06fc06cb1a721e38e5b50b4a1cb851e9b9c77d7a"
integrity sha512-dX43Z5IvMaW7fwzU8farosYjKNGfRb2HB/DgjVBHeJZ/NSnuuaujPPx0YOdcAq+n3mqn70tyCde2HM1mqbhiuw==
dependencies:
prop-types "^15.8.1"
"@lezer/common@^0.15.0", "@lezer/common@^0.15.5", "@lezer/common@git://github.com/zefhemel/common.git#046c880d1fcab713cadad327a5b7d8bb5de6522c":
version "0.15.11"
resolved "git://github.com/zefhemel/common.git#046c880d1fcab713cadad327a5b7d8bb5de6522c"
@ -601,6 +627,14 @@
globals "^13.2.0"
nullthrows "^1.1.1"
"@parcel/packager-raw-url@2.3.2":
version "2.3.2"
resolved "https://registry.yarnpkg.com/@parcel/packager-raw-url/-/packager-raw-url-2.3.2.tgz#9dc8e9a5cb3f12a41ec15603aa81e973e015fcd4"
integrity sha512-xkV/fC5OtMi8xIOO6aRAQcIR2rmRfKvVCME4aXfMj4pKSqvZKyF75/UsIezAt41GTaO0H/hYIUTQUJdzI0wq5g==
dependencies:
"@parcel/plugin" "2.3.2"
"@parcel/utils" "2.3.2"
"@parcel/packager-raw@2.3.2":
version "2.3.2"
resolved "https://registry.yarnpkg.com/@parcel/packager-raw/-/packager-raw-2.3.2.tgz#869cc3e7bee8ff3655891a0af400cf4e7dd4f144"
@ -816,6 +850,15 @@
"@parcel/utils" "2.3.2"
react-refresh "^0.9.0"
"@parcel/transformer-sass@2.3.2":
version "2.3.2"
resolved "https://registry.yarnpkg.com/@parcel/transformer-sass/-/transformer-sass-2.3.2.tgz#ee124d02acb1f44417f0d78d366302dd68aa412b"
integrity sha512-jVDdhyzfCYLY/91gOfMAT0Cj3a3czETD71WpvnXhzfctnhZZ/lhC1aFUJxlhIF1hkVNyZ1b9USCCBAD4fje2Jg==
dependencies:
"@parcel/plugin" "2.3.2"
"@parcel/source-map" "^2.0.0"
sass "^1.38.0"
"@parcel/transformer-svg@2.3.2":
version "2.3.2"
resolved "https://registry.yarnpkg.com/@parcel/transformer-svg/-/transformer-svg-2.3.2.tgz#9a66aef5011c7bbb1fa3ce9bb52ca56d8f0f964d"
@ -830,6 +873,16 @@
posthtml-render "^3.0.0"
semver "^5.7.1"
"@parcel/transformer-webmanifest@2.3.2":
version "2.3.2"
resolved "https://registry.yarnpkg.com/@parcel/transformer-webmanifest/-/transformer-webmanifest-2.3.2.tgz#8796d396049b0db62e87ed5d981a21654ffe1b30"
integrity sha512-aaiDhhfag5ygjoNI1SmE3wVI/C63gABvfzp6BgkXNV/kKsqk/lSftukgcDTekSUtZNOhGJk7LeWkhm8RF38jIw==
dependencies:
"@parcel/diagnostic" "2.3.2"
"@parcel/plugin" "2.3.2"
"@parcel/utils" "2.3.2"
json-source-map "^0.6.1"
"@parcel/ts-utils@2.3.2":
version "2.3.2"
resolved "https://registry.yarnpkg.com/@parcel/ts-utils/-/ts-utils-2.3.2.tgz#d63f7027574f3c1a128e1c865d683d6aacb4476d"
@ -954,6 +1007,14 @@ ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
anymatch@~3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
dependencies:
normalize-path "^3.0.0"
picomatch "^2.0.4"
base-x@^3.0.8:
version "3.0.9"
resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320"
@ -961,11 +1022,23 @@ base-x@^3.0.8:
dependencies:
safe-buffer "^5.0.1"
binary-extensions@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
boolbase@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
braces@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
dependencies:
fill-range "^7.0.1"
browserslist@^4.0.0, browserslist@^4.16.6, browserslist@^4.6.6:
version "4.19.1"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3"
@ -1019,6 +1092,21 @@ chalk@^4.1.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
"chokidar@>=3.0.0 <4.0.0":
version "3.5.3"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
dependencies:
anymatch "~3.1.2"
braces "~3.0.2"
glob-parent "~5.1.2"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.6.0"
optionalDependencies:
fsevents "~2.3.2"
chrome-trace-event@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
@ -1263,11 +1351,30 @@ escape-string-regexp@^1.0.5:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
dependencies:
to-regex-range "^5.0.1"
fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
get-port@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/get-port/-/get-port-4.2.0.tgz#e37368b1e863b7629c43c5a323625f95cf24b119"
integrity sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==
glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
globals@^13.2.0:
version "13.12.1"
resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.1.tgz#ec206be932e6c77236677127577aa8e50bf1c5cb"
@ -1309,6 +1416,11 @@ idb@^7.0.0:
resolved "https://registry.yarnpkg.com/idb/-/idb-7.0.0.tgz#f349b418c128f625961147a7d6b0e4b526fd34ed"
integrity sha512-jSx0WOY9Nj+QzP6wX5e7g64jqh8ExtDs/IAuOrOEZCD/h6+0HqyrKsDMfdJc0hqhSvh0LsrwqrkDn+EtjjzSRA==
immutable@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23"
integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==
import-fresh@^3.2.1:
version "3.3.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
@ -1322,11 +1434,35 @@ is-arrayish@^0.2.1:
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
is-binary-path@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
dependencies:
binary-extensions "^2.0.0"
is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
is-glob@^4.0.1, is-glob@~4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
dependencies:
is-extglob "^2.1.1"
is-json@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-json/-/is-json-2.0.1.tgz#6be166d144828a131d686891b983df62c39491ff"
integrity sha1-a+Fm0USCihMdaGiRuYPfYsOUkf8=
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@ -1380,7 +1516,7 @@ lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
loose-envify@^1.1.0:
loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@ -1437,6 +1573,11 @@ node-releases@^2.0.1:
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01"
integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==
normalize-path@^3.0.0, normalize-path@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
normalize-url@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
@ -1511,6 +1652,11 @@ picocolors@^1.0.0:
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
picomatch@^2.0.4, picomatch@^2.2.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
postcss-calc@^8.2.0:
version "8.2.4"
resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5"
@ -1751,6 +1897,15 @@ posthtml@^0.16.4, posthtml@^0.16.5:
posthtml-parser "^0.10.0"
posthtml-render "^3.0.0"
prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
dependencies:
loose-envify "^1.4.0"
object-assign "^4.1.1"
react-is "^16.13.1"
react-dom@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
@ -1760,6 +1915,11 @@ react-dom@^17.0.2:
object-assign "^4.1.1"
scheduler "^0.20.2"
react-is@^16.13.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-refresh@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.9.0.tgz#71863337adc3e5c2f8a6bfddd12ae3bfe32aafbf"
@ -1773,6 +1933,13 @@ react@^17.0.2:
loose-envify "^1.1.0"
object-assign "^4.1.1"
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
dependencies:
picomatch "^2.2.1"
regenerator-runtime@^0.13.7:
version "0.13.9"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
@ -1788,6 +1955,15 @@ safe-buffer@^5.0.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
sass@^1.38.0:
version "1.49.9"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.49.9.tgz#b15a189ecb0ca9e24634bae5d1ebc191809712f9"
integrity sha512-YlYWkkHP9fbwaFRZQRXgDi3mXZShslVmmo+FVK3kHLUELHHEYrCmL1x6IUjC7wLS6VuJSAFXRQS/DxdsC4xL1A==
dependencies:
chokidar ">=3.0.0 <4.0.0"
immutable "^4.0.0"
source-map-js ">=0.6.2 <2.0.0"
scheduler@^0.20.2:
version "0.20.2"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
@ -1801,7 +1977,7 @@ semver@^5.7.0, semver@^5.7.1:
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
source-map-js@^1.0.2:
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
@ -1883,6 +2059,13 @@ timsort@^0.3.0:
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
dependencies:
is-number "^7.0.0"
type-fest@^0.20.2:
version "0.20.2"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"