diff --git a/build.js b/build.js
deleted file mode 100644
index c7f229e..0000000
--- a/build.js
+++ /dev/null
@@ -1,100 +0,0 @@
-const { promises: fs } = require("fs");
-const path = require("path");
-const { html: beautifyHtml } = require('js-beautify');
-
-const buildConfig = require("./buildconfig");
-
-// source: https://stackoverflow.com/a/41407246
-const escapeCodes = {
- reset: "\x1b[0m",
- bright: "\x1b[1m",
- dim: "\x1b[2m",
- underscore: "\x1b[4m",
- blink: "\x1b[5m",
- reverse: "\x1b[7m",
- hidden: "\x1b[8m",
-
- fgBlack: "\x1b[30m",
- fgRed: "\x1b[31m",
- fgGreen: "\x1b[32m",
- fgYellow: "\x1b[33m",
- fgBlue: "\x1b[34m",
- fgMagenta: "\x1b[35m",
- fgCyan: "\x1b[36m",
- fgWhite: "\x1b[37m",
-
- bgBlack: "\x1b[40m",
- bgRed: "\x1b[41m",
- bgGreen: "\x1b[42m",
- bgYellow: "\x1b[43m",
- bgBlue: "\x1b[44m",
- bgMagenta: "\x1b[45m",
- bgCyan: "\x1b[46m",
- bgWhite: "\x1b[47m",
-};
-
-if (!buildConfig.allowSpecialCharacters) {
- for (i in escapeCodes) {
- escapeCodes[i] = "";
- }
-}
-
-const specialCharacter = (c) => {
- if (buildConfig.allowSpecialCharacters) {
- return c;
- }
- return "";
-}
-
-const processPageOutput = async (out) => {
- if (typeof out === "function")
- out = await out();
- if (typeof out !== "string")
- throw new Error("got non-string page output (maybe one of the pages isn't exporting a string?)");
-
- if (buildConfig.postProcessing.trimOutput) {
- out = out.trim();
- }
-
- if (buildConfig.postProcessing.beautifyOutput) {
- out = beautifyHtml(out, buildConfig.postProcessing.beautifyOutputOptions);
- }
-
- return out;
-};
-
-const findAllPages = async (directory) =>
- (await fs.readdir(directory))
- .filter(
- f => f.endsWith(buildConfig.pageExtension)
- )
- .map(f => directory + "/" + f); // TODO: hack
-
-const buildPage = async (pagePath) => {
- const processed = await processPageOutput(require(pagePath));
- console.log(`${escapeCodes.fgGreen}${specialCharacter("→")}${escapeCodes.reset} Built ${escapeCodes.fgBlue}${path.parse(path.basename(pagePath, buildConfig.pageExtension)).name}${escapeCodes.reset}`);
- return processed
-};
-
-const buildAllPages = async (directory) =>
- await Promise.all((await findAllPages(directory))
- .map(
- async p => [p, (await buildPage(p))]
- ));
-
-const exportAllPages = async (sourcePath, outputPath) => {
- const pages = await buildAllPages(sourcePath);
- for (const [pagePath, pageContent] of pages) {
- const pageName = path.parse(path.basename(pagePath, buildConfig.pageExtension)).name;
- await fs.writeFile(path.join(outputPath, pageName + ".html"), pageContent);
- }
- return pages.length;
-};
-
-const main = async () => {
- const startTime = new Date();
- const builtPages = await exportAllPages(buildConfig.sourceDirectory, buildConfig.outputDirectory);
- console.log(`${escapeCodes.fgGreen}${specialCharacter("✓")} Done! ${escapeCodes.fgBlue}Built ${builtPages} pages in ${((new Date()) - startTime)}ms.${escapeCodes.reset}`);
-};
-
-main();
\ No newline at end of file
diff --git a/buildconfig.js b/buildconfig.js
deleted file mode 100644
index 4cd394f..0000000
--- a/buildconfig.js
+++ /dev/null
@@ -1,14 +0,0 @@
-module.exports = {
- sourceDirectory: "./src",
- outputDirectory: "./out",
- pageExtension: ".page.js",
- postProcessing: {
- trimOutput: false,
- beautifyOutput: true,
- beautifyOutputOptions: {
- indent_size: 2,
- preserve_newlines: false
- }
- },
- allowSpecialCharacters: true
-};
\ No newline at end of file
diff --git a/out/_/jd3ymgfg3gk6vrlaxhbn/GatewayClient.js b/out/_/jd3ymgfg3gk6vrlaxhbn/GatewayClient.js
deleted file mode 100644
index 8c594a0..0000000
--- a/out/_/jd3ymgfg3gk6vrlaxhbn/GatewayClient.js
+++ /dev/null
@@ -1,105 +0,0 @@
-window.modules.register("GatewayClient", () => {
- const messageSchema = { t: "number", d: "object" };
- const messageTypes = {
- HELLO: 0,
- YOO: 1,
- READY: 2,
- EVENT: 3
- };
-
- class GatewayClient {
- constructor(gatewayPath) {
- this.gatewayPath = gatewayPath;
- this.ws = null;
- this.token = null;
- this.user = null;
- this.onEvent = (e) => {};
- this.onConnected = () => {};
- this.onDisconnected = () => {};
- }
-
- connect(token) {
- if (!token)
- token = this.token;
-
- console.log("gateway: connecting");
-
- this.ws = new WebSocket(this.gatewayPath);
-
- this.ws.addEventListener("message", ({ data }) => {
- if (typeof data !== "string") {
- console.warn("gateway: got non-string data from server, ignoring...");
- return;
- }
-
- let message;
- try {
- message = JSON.parse(data);
- } catch(e) {
- console.warn("gateway: got invalid JSON from server (failed to parse), ignoring...");
- return;
- }
-
- if (!this._checkMessageSchema(message)) {
- console.warn("gateway: got invalid JSON from server (does not match schema), ignoring...");
- return;
- }
-
- switch (message.t) {
- case messageTypes.HELLO: {
- console.log("gateway: HELLO");
- this.ws.send(JSON.stringify({
- t: messageTypes.YOO,
- d: {
- token
- }
- }));
- break;
- }
- case messageTypes.READY: {
- console.log("gateway: READY");
- this.user = message.d.user;
- this.onConnected();
- break;
- }
- case messageTypes.EVENT: {
- this.onEvent(message.d);
- break;
- }
- default: {
- console.warn("gateway: got invalid JSON from server (invalid type), ignoring...");
- return;
- }
- }
- });
- this.ws.addEventListener("open", () => {
- console.log("gateway: open");
- });
- this.ws.addEventListener("close", ({ code }) => {
- console.log("gateway: closed");
- this.onDisconnected(code);
- if (code === 4001) {
- console.log(`gateway: disconnect code is ${code} (bad auth), will not attempt reconnect`);
- return;
- }
- setTimeout(() => {
- console.log("gateway: reconnecting");
- this.connect(token);
- }, 4000);
- });
- }
-
- _checkMessageSchema(message) {
- for (const [key, value] of Object.entries(message)) {
- if (!messageSchema[key])
- return false;
-
- if (typeof value !== messageSchema[key])
- return false;
- }
- return true;
- }
- }
-
- return GatewayClient;
-});
diff --git a/out/_/jd3ymgfg3gk6vrlaxhbn/app.js b/out/_/jd3ymgfg3gk6vrlaxhbn/app.js
deleted file mode 100644
index 83d72df..0000000
--- a/out/_/jd3ymgfg3gk6vrlaxhbn/app.js
+++ /dev/null
@@ -1,21 +0,0 @@
-window.modules.register("$app", () => {
- const App = window.modules.require("App");
-
- if (!window._APP_ENV)
- throw new Error("$app: could not find window._APP_ENV");
- if (!App)
- throw new Error("$app: require('App') returned undefined");
-
- const initialLoading = document.getElementById("initial-loading");
- if (initialLoading) {
- initialLoading.parentElement.removeChild(initialLoading);
- }
-
- const appMountElement = document.createElement("div");
- document.body.appendChild(appMountElement);
-
- const app = new App(appMountElement);
- app.mount();
-
- return app;
-});
diff --git a/out/_/jd3ymgfg3gk6vrlaxhbn/components.js b/out/_/jd3ymgfg3gk6vrlaxhbn/components.js
deleted file mode 100644
index db9f1bb..0000000
--- a/out/_/jd3ymgfg3gk6vrlaxhbn/components.js
+++ /dev/null
@@ -1,185 +0,0 @@
-window.modules.register("AuthPromptRoute", () => {
- class AuthPromptRoute {
- constructor() {
- this.element = null;
- }
-
- mountOn(target) {
- if (this.element)
- return; // Already mounted
-
- this.element = document.createRange().createContextualFragment(`
-
-
-
-
- `).children[0];
-
- this.element.querySelector("#continue-button").addEventListener("click", () => {
- if (this.onPasswordSubmitted)
- this.onPasswordSubmitted(this.element.querySelector("#code-input").value);
- });
-
- target.appendChild(this.element);
- }
-
- unmount() {
- if (!this.element)
- return; // Already unmounted
- this.element.parentElement.removeChild(this.element);
- this.element = null;
- }
- }
-
- return AuthPromptRoute;
-});
-
-window.modules.register("MainChatView", () => {
- class MainChatView {
- constructor() {
- this.element = null;
- }
-
- mountOn(target) {
- if (this.element)
- return; // Already mounted
-
- this.element = document.createRange().createContextualFragment(`
-
- `).children[0];
-
- const textInput = this.element.querySelector("#message-input");
- this.element.querySelector("#message-submit").addEventListener("click", () => {
- const message = textInput.value;
- if (this.onSendMessage)
- this.onSendMessage(message);
-
- textInput.value = "";
- });
-
- target.appendChild(this.element);
- }
-
- appendMessage(messageObject) {
- const { author, content } = messageObject;
- if (!this.element)
- return;
-
- const usernameLetters = author.username
- .split("");
- let authorUsernameNumber = 150;
- usernameLetters.forEach(l => {
- authorUsernameNumber += l.charCodeAt(0);
- });
-
- const messageElement = document.createRange().createContextualFragment(`
-
- [author could not be loaded]
- [content could not be loaded]
-
- `).children[0];
-
- messageElement.querySelector("b").innerText = `User ${authorUsernameNumber} `;
- messageElement.querySelector("span").innerText = content;
-
- const container = this.element.querySelector("#messages-container");
- container.appendChild(messageElement);
- container.scrollTop = container.scrollHeight;
- }
-
- unmount() {
- if (!this.element)
- return; // Already unmounted
- this.element.parentElement.removeChild(this.element);
- this.element = null;
- }
- }
-
- return MainChatView;
-});
-
-
-window.modules.register("App", () => {
- const AuthPromptRoute = window.modules.require("AuthPromptRoute");
- const MainChatView = window.modules.require("MainChatView");
- const GatewayClient = window.modules.require("GatewayClient");
-
-
- class App {
- constructor(mountElement) {
- this.mountElement = mountElement;
- this.currentMountedElement = null;
-
- this.authPromptRoute = new AuthPromptRoute();
- this.mainChatView = new MainChatView();
- this.gatewayClient = new GatewayClient(window._APP_ENV.gatewayBase);
- }
-
- _mountElement(element) {
- if (this.currentMountedElement) {
- this.currentMountedElement.unmount();
- }
- this.currentMountedElement = element;
- this.currentMountedElement.mountOn(this.mountElement);
- }
-
- _unmountAll() {
- if (this.currentMountedElement) {
- this.currentMountedElement.unmount();
- }
- }
-
- mount() {
- let serverId;
- let channelId;
- let token;
-
- this._mountElement(this.authPromptRoute);
-
- this.gatewayClient.onEvent = (e) => {
- if (e.eventType === "MESSAGE_CREATE" && e.message && e.message.guild_id === serverId && e.message.channel_id === channelId) {
- this.mainChatView.appendMessage(e.message);
- }
- };
- this.gatewayClient.onConnected = () => {
- this._mountElement(this.mainChatView);
- };
- this.gatewayClient.onDisconnected = () => {
- this._mountElement(this.authPromptRoute);
- };
- this.authPromptRoute.onPasswordSubmitted = (auth) => {
- const parts = auth.split(",,");
- if (parts.length !== 3)
- return;
-
- const [userToken, userServerId, userChannelId] = parts;
- serverId = userServerId;
- channelId = userChannelId;
- token = userToken
- this.gatewayClient.connect(token);
- };
- this.mainChatView.onSendMessage = async (message) => {
- if (typeof message === "string" && message.trim() === "")
- return;
-
- await fetch(`${window._APP_ENV.apiBase}/guilds/${serverId}/channels/${channelId}/messages/create`, {
- method: "POST",
- body: JSON.stringify({
- content: message
- }),
- headers: {
- "content-type": "application/json",
- "authorization": token
- }
- });
- };
- }
- }
-
- return App;
-});
diff --git a/out/_/jd3ymgfg3gk6vrlaxhbn/index.html b/out/_/jd3ymgfg3gk6vrlaxhbn/index.html
deleted file mode 100644
index eeedea7..0000000
--- a/out/_/jd3ymgfg3gk6vrlaxhbn/index.html
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
- .
-
-
-
- loading
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/out/_/jd3ymgfg3gk6vrlaxhbn/moduleruntime.js b/out/_/jd3ymgfg3gk6vrlaxhbn/moduleruntime.js
deleted file mode 100644
index ebb5905..0000000
--- a/out/_/jd3ymgfg3gk6vrlaxhbn/moduleruntime.js
+++ /dev/null
@@ -1,26 +0,0 @@
-const modules = {
- _cache: {},
- _registry: {},
- require(moduleName) {
- if (this._cache[moduleName]) {
- return this._cache[moduleName];
- }
-
- if (this._registry[moduleName]) {
- const loaderFunction = this._registry[moduleName];
- this._cache[moduleName] = loaderFunction(1);
- return this._cache[moduleName];
- }
-
- return null;
- },
- register(moduleName, loaderFunction) {
- this._registry[moduleName] = loaderFunction;
- this._cache[moduleName] = loaderFunction(0);
- },
- registerLazy(moduleName, loaderFunction) {
- this._registry[moduleName] = loaderFunction;
- }
-};
-
-window.modules = modules;
diff --git a/out/res/fastnav.js b/out/res/fastnav.js
new file mode 100644
index 0000000..3fdd4f1
--- /dev/null
+++ b/out/res/fastnav.js
@@ -0,0 +1,26 @@
+const map = {"projects.html":"Mysterious! This project has no description.
a react frontend for waffle (brainlet)
Simple experimental low-level UI library written in C++.
bridge bot api for discord servers
my personal forks of various software and my dotfiles
Mysterious! This project has no description.
🎤🐢 An open source, self-hosted alternative to Discord
simple and fast remote touchpad
Mysterious! This project has no description.
A simple websocket abstraction.
a command-line minecraft launcher written in rust
Helper program for deploying protocol associations needed for running Roblox on Linux
Mysterious! This project has no description.
Mysterious! This project has no description.
turn pages into pure html
","index.html":"hippoz's website
i think
"};
+const content = document.getElementById("content");
+
+const load = (page) => content.innerHTML = map[page.substring(1, page.length) || "_notfound"];
+const navigate = (page) => {
+ history.pushState(null, "", page);
+ load(page);
+};
+
+const populate = () => {
+ const elements = document.querySelectorAll("[href]");
+ elements.forEach(element => {
+ const existingLink = element.getAttribute("href");
+ if (map[existingLink]) {
+ element.setAttribute("href", "#");
+ element.onclick = () => navigate(existingLink);
+ }
+ });
+};
+
+const main = () => {
+ populate();
+ window.onpopstate = () => {load(location.pathname); console.log("a");};
+};
+
+main();
diff --git a/src/assets/fastnav.js b/src/assets/fastnav.js
new file mode 100644
index 0000000..97a5a08
--- /dev/null
+++ b/src/assets/fastnav.js
@@ -0,0 +1,29 @@
+const map = "{{NAV_DATA}}";
+const content = document.getElementById("content");
+
+const load = (page) => {
+ content.innerHTML = map[page.substring(1, page.length) || "_notfound"];
+ console.log("a");
+};
+const navigate = (page) => {
+ history.pushState(null, "", page);
+ load(page);
+};
+
+const populate = () => {
+ const elements = document.querySelectorAll("[href]");
+ elements.forEach(element => {
+ const existingLink = element.getAttribute("href");
+ if (map[existingLink]) {
+ element.setAttribute("href", "");
+ element.onclick = () => navigate(existingLink);
+ }
+ });
+};
+
+const main = () => {
+ populate();
+ window.onpopstate = () => load(location.pathname);
+};
+
+main();
diff --git a/src/blog.page.js b/src/blog.page.js
deleted file mode 100644
index 09b961b..0000000
--- a/src/blog.page.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const Page = require("./components/Page.component");
-
-module.exports = Page({
- title: "hippoz blog",
- description: "hippoz blog",
- name: "blog",
-})(`
- hippoz's blog
- i think
-
-
- no articles yet
-`);
diff --git a/src/components/LinkButton.component.js b/src/components/LinkButton.component.js
deleted file mode 100644
index bc5c801..0000000
--- a/src/components/LinkButton.component.js
+++ /dev/null
@@ -1,2 +0,0 @@
-module.exports = ({ link, text, selected=false }) =>
- `${text}`;
\ No newline at end of file
diff --git a/src/components/Navigation.component.js b/src/components/Navigation.component.js
deleted file mode 100644
index 6cf105a..0000000
--- a/src/components/Navigation.component.js
+++ /dev/null
@@ -1,21 +0,0 @@
-const { navigationLinks, navigationBrandingText } = require("../env");
-const LinkButtonComponent = require("./LinkButton.component");
-
-module.exports = ({ pageName }) => `
-
-
- ${navigationBrandingText}
-
-
- ${
- navigationLinks.map(
- ({link, text, name}) =>
- LinkButtonComponent({
- link,
- text,
- selected: name === pageName
- })
- ).join("")
- }
-
-
`;
\ No newline at end of file
diff --git a/src/components/Page.component.js b/src/components/Page.component.js
deleted file mode 100644
index 3d732c7..0000000
--- a/src/components/Page.component.js
+++ /dev/null
@@ -1,21 +0,0 @@
-const NavigationComponent = require("./Navigation.component");
-
-module.exports = ({ title="page", description="a page", name="page" }) => (content) =>
-`
-
-
-
-
-
- ${title}
-
-
-
- ${NavigationComponent({
- pageName: name
- })}
-
- ${content}
-
-
-`;
diff --git a/src/env/index.js b/src/env/index.js
deleted file mode 100644
index f8962a2..0000000
--- a/src/env/index.js
+++ /dev/null
@@ -1,25 +0,0 @@
-const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
-
-module.exports = {
- navigationLinks: [
- {link: "index.html", text: "home", name: "home"},
- {link: "blog.html", text: "blog", name: "blog"},
- {link: "projects.html", text: "projects", name: "projects"},
- {link: "https://git.hippoz.xyz", text: "git", name: "__ext_git"},
- ],
- repositoryList: {
- gitTargetUsername: "hippoz",
- repositoryFetchUrl: `https://git.hippoz.xyz/api/v1/users/hippoz/repos?page=1&limit=100`,
- _cache: null,
- fetchProjects: async function() {
- if (this._cache) return this._cache;
-
- const response = await fetch(this.repositoryFetchUrl);
- const json = await response.json();
- this._cache = json;
-
- return json;
- }
- },
- navigationBrandingText: "hippoz."
-}
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..74d2ab3
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,162 @@
+const fs = require("node:fs/promises");
+const path = require("node:path");
+const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
+const { html: beautifyHtml } = require('js-beautify');
+
+const data = {
+ outputDirectory: "./out",
+ navigationLinks: [
+ {link: "index.html", text: "home", name: "home"},
+ {link: "projects.html", text: "projects", name: "projects"},
+ {link: "https://git.hippoz.xyz", text: "git", name: "__ext_git"},
+ ],
+ postProcessing: {
+ beautifyOutput: true,
+ beautifyOutputOptions: {
+ indent_size: 2,
+ preserve_newlines: false
+ },
+ minifyOutputOptions: {
+ indent_size: 0,
+ preserve_newlines: false,
+ end_with_newline: false,
+ eol: ""
+ }
+ },
+ repositoryList: {
+ gitTargetUsername: "hippoz",
+ repositoryFetchUrl: `https://git.hippoz.xyz/api/v1/users/hippoz/repos?page=1&limit=100`,
+ _cache: null,
+ fetchProjects: async function() {
+ if (this._cache) return this._cache;
+
+ const response = await fetch(this.repositoryFetchUrl);
+ const json = await response.json();
+ this._cache = json;
+
+ return json;
+ }
+ },
+ navigationBrandingText: "hippoz."
+};
+
+const linkButton = ({ link, text, selected=false }) => `
+ ${text}
+`;
+
+const navigation = ({currentName}) => `
+
+
+ ${data.navigationBrandingText}
+
+
+ ${data.navigationLinks.map(e => linkButton({ ...e, selected: currentName === e.name })).join("")}
+
+
+`;
+
+const makePage = ({ name, description, title }) => content => [`
+
+
+
+
+
+
+ ${title}
+
+
+
+ ${navigation({currentName: name})}
+
+
+
+
+
+`, content];
+
+const indexPage = () => makePage({
+ title: "hippoz",
+ description: "hippoz website homepage",
+ name: "home",
+})(`
+ hippoz's website
+ i think
+`);
+
+const projectsPage = async () => makePage({
+ title: "hippoz",
+ description: "hippoz projects",
+ name: "projects",
+})(`
+ ${
+ (await data.repositoryList.fetchProjects())
+ .sort((a, b) => b.size - a.size) // biggest projects first
+ .filter(a => !a.archived)
+ .map(
+ repo =>`
+
+
+
${repo.fork ? "🍴" : "📘"} ${repo.name}
+
view >>
+
+ ${repo.description ? `
${repo.description}
` : `
Mysterious! This project has no description.
`}
+
`
+ )
+ .join("\n")
+ }
+`);
+
+const pages = {
+ "projects.html": projectsPage,
+ "index.html": indexPage
+};
+let renderedPageCache = null;
+
+const renderPages = async () => {
+ if (renderedPageCache) return renderedPageCache;
+
+ renderedPageCache = {};
+ for (const [pageName, builder] of Object.entries(pages)) {
+ renderedPageCache[pageName] = await builder();
+ }
+ return renderedPageCache;
+};
+
+const deployNavScript = async () => {
+ let script = await fs.readFile("./src/assets/fastnav.js");
+ if (script) script = script.toString();
+
+ const renderedPages = await renderPages();
+ let navMap = {};
+ for (let [pageName, content] of Object.entries(renderedPages)) {
+ if (data.postProcessing.beautifyOutput) {
+ content = beautifyHtml(content[1], data.postProcessing.minifyOutputOptions);
+ }
+
+ navMap[pageName] = content;
+ }
+
+ const content = script.replace(`"{{NAV_DATA}}"`, JSON.stringify(navMap));
+
+ await fs.writeFile("./out/res/fastnav.js", content);
+};
+
+const deployPages = async () => {
+ const renderedPages = await renderPages();
+ for (let [pageName, content] of Object.entries(renderedPages)) {
+ if (data.postProcessing.beautifyOutput) {
+ content = beautifyHtml(content[0], data.postProcessing.beautifyOutputOptions);
+ }
+
+ await fs.writeFile(path.join(data.outputDirectory, pageName), content);
+ }
+};
+
+const deployAll = async () => {
+ await deployNavScript();
+ await deployPages();
+};
+
+deployAll();
diff --git a/src/index.page.js b/src/index.page.js
deleted file mode 100644
index 0042aaa..0000000
--- a/src/index.page.js
+++ /dev/null
@@ -1,10 +0,0 @@
-const Page = require("./components/Page.component");
-
-module.exports = Page({
- title: "hippoz",
- description: "hippoz website homepage",
- name: "home",
-})(`
- hippoz's website
- i think
-`);
diff --git a/src/projects.page.js b/src/projects.page.js
deleted file mode 100644
index dc9d3a4..0000000
--- a/src/projects.page.js
+++ /dev/null
@@ -1,25 +0,0 @@
-const { repositoryList } = require("./env");
-const Page = require("./components/Page.component");
-
-module.exports = async () => Page({
- title: "hippoz",
- description: "hippoz website homepage",
- name: "projects",
-})(`
- ${
- (await repositoryList.fetchProjects())
- .sort((a, b) => b.size - a.size) // biggest projects first
- .filter(a => !a.archived)
- .map(
- repo =>`
-
-
-
${repo.fork ? "🍴" : "📘"} ${repo.name}
-
view >>
-
- ${repo.description ? `
${repo.description}
` : `
Mysterious! This project has no description.
`}
-
`
- )
- .join("\n")
- }
-`);
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 0000000..d1e0bd1
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,197 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+abbrev@1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
+ integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
+
+balanced-match@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+commander@^2.19.0:
+ version "2.20.3"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
+
+config-chain@^1.1.13:
+ version "1.1.13"
+ resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4"
+ integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==
+ dependencies:
+ ini "^1.3.4"
+ proto-list "~1.2.1"
+
+data-uri-to-buffer@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b"
+ integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==
+
+editorconfig@^0.15.3:
+ version "0.15.3"
+ resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5"
+ integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==
+ dependencies:
+ commander "^2.19.0"
+ lru-cache "^4.1.5"
+ semver "^5.6.0"
+ sigmund "^1.0.1"
+
+fetch-blob@^3.1.2, fetch-blob@^3.1.4:
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.1.5.tgz#0077bf5f3fcdbd9d75a0b5362f77dbb743489863"
+ integrity sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==
+ dependencies:
+ node-domexception "^1.0.0"
+ web-streams-polyfill "^3.0.3"
+
+formdata-polyfill@^4.0.10:
+ version "4.0.10"
+ resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
+ integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==
+ dependencies:
+ fetch-blob "^3.1.2"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
+
+glob@^7.1.3:
+ version "7.2.2"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.2.tgz#29deb38e1ef90f132d5958abe9c3ee8e87f3c318"
+ integrity sha512-NzDgHDiJwKYByLrL5lONmQFpK/2G78SMMfo+E9CuGlX4IkvfKDsiQSNPwAYxEy+e6p7ZQ3uslSLlwlJcqezBmQ==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.1.1"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+ini@^1.3.4:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
+ integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
+
+js-beautify@^1.14.0:
+ version "1.14.3"
+ resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.14.3.tgz#3dd11c949178de7f3bdf3f6f752778d3bed95150"
+ integrity sha512-f1ra8PHtOEu/70EBnmiUlV8nJePS58y9qKjl4JHfYWlFH6bo7ogZBz//FAZp7jDuXtYnGYKymZPlrg2I/9Zo4g==
+ dependencies:
+ config-chain "^1.1.13"
+ editorconfig "^0.15.3"
+ glob "^7.1.3"
+ nopt "^5.0.0"
+
+lru-cache@^4.1.5:
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
+ integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
+ dependencies:
+ pseudomap "^1.0.2"
+ yallist "^2.1.2"
+
+minimatch@^3.1.1:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
+ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+node-domexception@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
+ integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
+
+node-fetch@^3.0.0:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.4.tgz#3fbca2d8838111048232de54cb532bd3cf134947"
+ integrity sha512-WvYJRN7mMyOLurFR2YpysQGuwYrJN+qrrpHjJDuKMcSPdfFccRUla/kng2mz6HWSBxJcqPbvatS6Gb4RhOzCJw==
+ dependencies:
+ data-uri-to-buffer "^4.0.0"
+ fetch-blob "^3.1.4"
+ formdata-polyfill "^4.0.10"
+
+nopt@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
+ integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==
+ dependencies:
+ abbrev "1"
+
+once@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
+ dependencies:
+ wrappy "1"
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
+
+proto-list@~1.2.1:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
+ integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
+
+pseudomap@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
+ integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
+
+semver@^5.6.0:
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
+ integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+
+sigmund@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
+ integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=
+
+web-streams-polyfill@^3.0.3:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"
+ integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
+
+yallist@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
+ integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=