From 4289a9887ebea5879531fe1817a3b5e0aec1018c Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Wed, 12 Jan 2022 19:53:49 +0100 Subject: [PATCH 01/20] Fix bug in ci/cd --- .drone.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.drone.yml b/.drone.yml index 1c55862..e24d0c3 100644 --- a/.drone.yml +++ b/.drone.yml @@ -71,6 +71,7 @@ steps: #- docker login -u $${DOCKER_USER} -p $${DOCKER_PASS} - docker-compose -p website-dev -f docker-compose.dev.yml rm -s -v -f - docker rmi $${REGISTRY_HOST}/$${IMAGE} || true + - docker rmi localhost:5000/$${IMAGE} || true - docker pull $${REGISTRY_HOST}/$${IMAGE} - docker-compose -p website-dev -f docker-compose.dev.yml up --no-build -d - name: deploy-stable @@ -89,5 +90,6 @@ steps: #- docker login -u $${DOCKER_USER} -p $${DOCKER_PASS} - docker-compose -p website -f docker-compose.stable.yml rm -s -v -f - docker rmi $${REGISTRY_HOST}/$${IMAGE} || true + - docker rmi localhost:5000/$${IMAGE} || true - docker pull $${REGISTRY_HOST}/$${IMAGE} - docker-compose -p website -f docker-compose.stable.yml up --no-build -d \ No newline at end of file From c137ed08f5815edc1a182ab6cd04a10b6054ea68 Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Wed, 12 Jan 2022 19:54:29 +0100 Subject: [PATCH 02/20] One useful api --- pages/api/hello.ts | 13 ------------- pages/api/ping.ts | 7 +++++++ 2 files changed, 7 insertions(+), 13 deletions(-) delete mode 100644 pages/api/hello.ts create mode 100644 pages/api/ping.ts diff --git a/pages/api/hello.ts b/pages/api/hello.ts deleted file mode 100644 index 941d4fa..0000000 --- a/pages/api/hello.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Next.js API route support: https://nextjs.org/docs/api-routes/introduction -import type { NextApiRequest, NextApiResponse } from "next"; - -type Data = { - name: string -} - -export default function handler( - req: NextApiRequest, - res: NextApiResponse -) { - res.status(200).json({ name: "John Doe" }); -} diff --git a/pages/api/ping.ts b/pages/api/ping.ts new file mode 100644 index 0000000..cfdba75 --- /dev/null +++ b/pages/api/ping.ts @@ -0,0 +1,7 @@ +// Next.js API route support: https://nextjs.org/docs/api-routes/introduction +import type { NextApiRequest, NextApiResponse } from "next"; + +export default function handler(_req: NextApiRequest, res: NextApiResponse) { + res.status(200).send("Pong!"); + res.end(); +} From ee8e4b9fb9e4f1633756ca7ce4fdfc4581ba1d60 Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Thu, 13 Jan 2022 18:15:32 +0100 Subject: [PATCH 03/20] Add project api route --- pages/api/get_project.ts | 33 +++++++++++++++++++++++++++++++++ public/projects/.gitkeep | 0 2 files changed, 33 insertions(+) create mode 100644 pages/api/get_project.ts create mode 100644 public/projects/.gitkeep diff --git a/pages/api/get_project.ts b/pages/api/get_project.ts new file mode 100644 index 0000000..0e33ad7 --- /dev/null +++ b/pages/api/get_project.ts @@ -0,0 +1,33 @@ +import { readFileSync } from "fs"; +import { resolve } from "path"; +import type { NextApiRequest, NextApiResponse } from "next"; + +interface IFileError { + message: string; + name: string; + stack?: string; + code: string; + errno: number; + syscall: string; + path: string; +} + +export default function handler(req: NextApiRequest, res: NextApiResponse) { + if (req.method !== "GET") return res.status(405).end(); + if (!req.query.projectName) return res.status(400).end(); + + const project = req.query.projectName; + + try { + const path = resolve("./public", "projects", `${project}.md`) + const data = readFileSync(path).toString(); + console.debug(`[API/get_project]\tRequest for ${project}`); + res.status(200).send(data); + } catch (err) { + console.error(`[API/get_project]\tError in request for ${project}! Code: ${(err as IFileError).code}`); + if ((err as IFileError).code === "ENOENT") res.status(404); + else res.status(500); + } finally { + res.end(); + } +} diff --git a/public/projects/.gitkeep b/public/projects/.gitkeep new file mode 100644 index 0000000..e69de29 From a2f035ce1a86ad114da0bf3b6bd2bd0a2d136437 Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Fri, 14 Jan 2022 14:27:19 +0100 Subject: [PATCH 04/20] Add Modal --- components/ProjectModal.tsx | 63 +++++ components/REPL/REPLInput.tsx | 15 +- components/REPL/index.tsx | 12 +- lib/commands/definitions.ts | 6 +- lib/commands/index.ts | 53 ++-- lib/commands/types.tsx | 4 +- package-lock.json | 439 ++++++++++++++++++++++++++++++--- package.json | 1 + pages/api/get_project.ts | 2 +- pages/index.tsx | 77 +++--- public/projects/homepage.adoc | 1 + styles/ProjectModal.module.css | 19 ++ testfile | 1 + 13 files changed, 592 insertions(+), 101 deletions(-) create mode 100644 components/ProjectModal.tsx create mode 100644 public/projects/homepage.adoc create mode 100644 styles/ProjectModal.module.css create mode 100644 testfile diff --git a/components/ProjectModal.tsx b/components/ProjectModal.tsx new file mode 100644 index 0000000..02520ca --- /dev/null +++ b/components/ProjectModal.tsx @@ -0,0 +1,63 @@ +import type { NextPage } from "next"; +import { useEffect, useRef, useState } from "react"; +import asciidoctor from "asciidoctor"; +import styles from "../styles/ProjectModal.module.css"; + +interface ModalInput { + project: string; + visible: boolean; + setVisible: CallableFunction; +} + +const ad = asciidoctor(); + +const ProjectModal: NextPage = ({ project, visible, setVisible }) => { + const projectEmpty = "
Kein Projekt ausgewählt.
"; + const [projectData, setProjectData] = useState(projectEmpty); + const containerRef = useRef(null); + + const projectNotFoundHtml = `
Sorry! There is no data for this project. Please check back later to see if that changed!
`; + const projectServerErrorHtml = `
Sorry! A server error happend when the project data was fetched!
`; + + useEffect(() => { + if (project && project !== "") { + // TODO + // set Spinner + fetch(`/api/get_project?projectName=${project}`).then((res) => { + if (res.status === 404) setProjectData(projectNotFoundHtml); + if (res.status !== 200) setProjectData(projectServerErrorHtml); + res.text().then(data => { + try { + setProjectData(ad.convert(data).toString()); + } catch { + setProjectData(projectServerErrorHtml); + } + }); + }); + } else if (project === "") setProjectData(projectEmpty) + }, [project]) + + useEffect(() => { + if (projectData && containerRef.current && projectData !== "") { + containerRef.current.innerHTML = projectData; + } + + }, [projectData, visible]) + + const onEscClose = (e: React.KeyboardEvent) => { + if (e.key === "Escape") { + e.preventDefault(); + setVisible(false); + } + } + + if (!visible) return <> + + return
+
+
+
+} + + +export default ProjectModal; \ No newline at end of file diff --git a/components/REPL/REPLInput.tsx b/components/REPL/REPLInput.tsx index 37c6fb3..cf71421 100644 --- a/components/REPL/REPLInput.tsx +++ b/components/REPL/REPLInput.tsx @@ -1,19 +1,24 @@ import type { NextPage } from "next"; import React, { MutableRefObject } from "react"; -import { commandCompletion, executeCommand } from "../../lib/commands"; +import { CommandInterface } from "../../lib/commands"; import styles from "../../styles/REPL/REPLInput.module.css"; interface REPLInputParams { historyCallback: CallableFunction; historyClear: CallableFunction; inputRef: MutableRefObject; + modalManipulation: { + setModalVisible: CallableFunction; + setModalProject: CallableFunction; + } } -const REPLInput: NextPage = ({historyCallback, historyClear, inputRef}) => { +const REPLInput: NextPage = ({historyCallback, historyClear, inputRef, modalManipulation}) => { const typed = React.createRef(); const completion = React.createRef(); const [currentCmd, setCurrentCmd] = React.useState([]); const [justTabbed, setJustTabbed] = React.useState(0); + const cmdIf = new CommandInterface(modalManipulation); const clearInput = (inputRef: HTMLInputElement) => { inputRef.value = ""; @@ -37,7 +42,7 @@ const REPLInput: NextPage = ({historyCallback, historyClear, in } else { input.maxLength = 20; // Get completion hint - const suggest = commandCompletion(currentInput); + const suggest = CommandInterface.commandCompletion(currentInput); setCurrentCmd(suggest); if (suggest.length === 0) suggest.push(""); if (typed.current) typed.current.innerHTML = currentInput; @@ -64,7 +69,7 @@ const REPLInput: NextPage = ({historyCallback, historyClear, in historyClear(); return false; } - const result = executeCommand(command); + const result = cmdIf.executeCommand(command); clearInput(input); historyCallback(result); return false; @@ -72,7 +77,7 @@ const REPLInput: NextPage = ({historyCallback, historyClear, in if (e.key === "d" && e.ctrlKey) { e.preventDefault(); - const result = executeCommand("exit"); + const result = cmdIf.executeCommand("exit"); clearInput(input); historyCallback(result); return false; diff --git a/components/REPL/index.tsx b/components/REPL/index.tsx index cf03d88..73e4731 100644 --- a/components/REPL/index.tsx +++ b/components/REPL/index.tsx @@ -4,7 +4,15 @@ import REPLHistory from "./REPLHistory"; import styles from "../../styles/REPL/REPLComplete.module.css"; import type { NextPage } from "next"; -const REPL: NextPage<{inputRef: MutableRefObject}> = ({ inputRef }) => { +interface IREPLProps { + inputRef: MutableRefObject; + modalManipulation: { + setModalVisible: CallableFunction; + setModalProject: CallableFunction; + } +} + +const REPL: NextPage = ({ inputRef, modalManipulation }) => { const [history, manipulateHistory] = useState([]); const onCommandExecuted = (result: string[]) => manipulateHistory(result.reverse().concat(history).slice(0, 1000)); const onClearHistory = () => manipulateHistory([]); @@ -15,7 +23,7 @@ const REPL: NextPage<{inputRef: MutableRefObject}> = return (
- +
); }; diff --git a/lib/commands/definitions.ts b/lib/commands/definitions.ts index 2408d86..a76d6f6 100644 --- a/lib/commands/definitions.ts +++ b/lib/commands/definitions.ts @@ -145,7 +145,7 @@ const project: Command = { list: {short: "l", long: "list", desc: "Show list of projects."} }, subcommands: {name: {name: "name", desc: "Name of the project."}}, - execute: (flags, args) => { + execute: (flags, args, _raw, cmdIf) => { if (project.flags && checkFlagInclude(flags, project.flags.list)) { const result = ["Found the following projects:"]; projectList.forEach(project => result.push(`\t${project.name}\t${project.short}`)); @@ -172,8 +172,8 @@ const project: Command = { } if (project.flags && checkFlagInclude(flags, project.flags.minimal)) return pjt.desc; - // TODO - // Open project page here. + cmdIf.callbacks.setModalProject(args[0]); + cmdIf.callbacks.setModalVisible(true); return []; } }; diff --git a/lib/commands/index.ts b/lib/commands/index.ts index a0c1be7..a2cb9b0 100644 --- a/lib/commands/index.ts +++ b/lib/commands/index.ts @@ -1,29 +1,42 @@ import { printSyntax, commandList } from "./definitions"; -export function commandCompletion(input: string): string[] { - if (input === "") return []; - const candidates = commandList.filter(cmd => cmd.name.substring(0, input.length) === input).map(cmd => cmd.name); - return candidates; +interface CommandInterfaceCallbacks { + setModalVisible: CallableFunction, + setModalProject: CallableFunction } -export function executeCommand(command: string): string[] { - if (!command) return [`$ ${command}`].concat(illegalCommand(command)); - const args = command.split(" "); - const cmd = commandList.find(cmd => cmd.name === args[0]); - if (!cmd) return [`$ ${command}`].concat(illegalCommand(command)); +export class CommandInterface { + callbacks: CommandInterfaceCallbacks; - const parsed = seperateFlags(args.splice(1)); - const result = parsed.flags.includes("--help") ? printSyntax(cmd) : cmd.execute(parsed.flags, parsed.subcmds, command); + constructor(callbacks: CommandInterfaceCallbacks) { + this.callbacks = callbacks; + } - return [`$ ${command}`].concat(result); -} + static commandCompletion(input: string): string[] { + if (input === "") return []; + const candidates = commandList.filter(cmd => cmd.name.substring(0, input.length) === input).map(cmd => cmd.name); + return candidates; + } -function seperateFlags(args: string[]): {flags: string[], subcmds: string[]} { - const flags = args.filter(arg => arg.substring(0,1) === "-"); - const subcmds = args.filter(arg => arg.substring(0,1) !== "-"); - return {flags, subcmds}; -} + executeCommand(command: string): string[] { + if (!command) return [`$ ${command}`].concat(this.illegalCommand(command)); + const args = command.split(" "); + const cmd = commandList.find(cmd => cmd.name === args[0]); + if (!cmd) return [`$ ${command}`].concat(this.illegalCommand(command)); + + const parsed = this.seperateFlags(args.splice(1)); + const result = parsed.flags.includes("--help") ? printSyntax(cmd) : cmd.execute(parsed.flags, parsed.subcmds, command, this); + + return [`$ ${command}`].concat(result); + } -function illegalCommand(command: string): string[] { - return [`Command '${command}' not found.`, "Type 'help' for help."]; + private seperateFlags(args: string[]): {flags: string[], subcmds: string[]} { + const flags = args.filter(arg => arg.substring(0,1) === "-"); + const subcmds = args.filter(arg => arg.substring(0,1) !== "-"); + return {flags, subcmds}; + } + + private illegalCommand(command: string): string[] { + return [`Command '${command}' not found.`, "Type 'help' for help."]; + } } \ No newline at end of file diff --git a/lib/commands/types.tsx b/lib/commands/types.tsx index f072ab7..c4b6bbd 100644 --- a/lib/commands/types.tsx +++ b/lib/commands/types.tsx @@ -1,3 +1,5 @@ +import type { CommandInterface } from "."; + export interface Flag { short: string; long: string; @@ -15,5 +17,5 @@ export interface Command { desc: string; flags?: Record; subcommands?: Record; - execute: (flags: string[], args: string[], raw: string, extra?: any) => string[]; + execute: (flags: string[], args: string[], raw: string, cmdIf: CommandInterface) => string[]; } diff --git a/package-lock.json b/package-lock.json index 22df8c4..e1e1e02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,6 +6,7 @@ "": { "name": "my_website", "dependencies": { + "asciidoctor": "^2.2.5", "next": "12.0.7", "phosphor-react": "^1.3.1", "react": "17.0.2", @@ -19,6 +20,39 @@ "typescript": "4.5.2" } }, + "node_modules/@asciidoctor/cli": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@asciidoctor/cli/-/cli-3.4.0.tgz", + "integrity": "sha512-jOtxA0I6zB+6z+GGwm9+xhlmGTqCTkFPE902L6fauFlE6v7LxjhLYNxvjDVyn0zMrFLybvoSRcAnM3DcticNoQ==", + "dependencies": { + "yargs": "15.3.1" + }, + "bin": { + "asciidoctor": "bin/asciidoctor", + "asciidoctorjs": "bin/asciidoctor" + }, + "engines": { + "node": ">=8.11", + "npm": ">=5.0.0" + }, + "peerDependencies": { + "@asciidoctor/core": "^2.0.0-rc.1" + } + }, + "node_modules/@asciidoctor/core": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-2.2.5.tgz", + "integrity": "sha512-jtQPQ5EivgFbwvSyGKas4ANnMGGHPbmu791H9xrZKooA65JNI30jM2em5MvUXTTetSPgb6saUf+PJibEuSB6uw==", + "dependencies": { + "asciidoctor-opal-runtime": "0.3.3", + "unxhr": "1.0.1" + }, + "engines": { + "node": ">=8.11", + "npm": ">=5.0.0", + "yarn": ">=1.1.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", @@ -1534,6 +1568,52 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asciidoctor": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/asciidoctor/-/asciidoctor-2.2.5.tgz", + "integrity": "sha512-rrmCK34faw+w+xGFQggjwPB0/pcISnwOXaulfJvn7j4Nm0bFwz+x4tG3ZANIA9+9i6Csex/PO0fSLBO8CSdzVA==", + "dependencies": { + "@asciidoctor/cli": "3.4.0", + "@asciidoctor/core": "2.2.5" + }, + "bin": { + "asciidoctor": "bin/asciidoctor", + "asciidoctorjs": "bin/asciidoctor" + }, + "engines": { + "node": ">=8.11", + "npm": ">=5.0.0", + "yarn": ">=1.1.0" + } + }, + "node_modules/asciidoctor-opal-runtime": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/asciidoctor-opal-runtime/-/asciidoctor-opal-runtime-0.3.3.tgz", + "integrity": "sha512-/CEVNiOia8E5BMO9FLooo+Kv18K4+4JBFRJp8vUy/N5dMRAg+fRNV4HA+o6aoSC79jVU/aT5XvUpxSxSsTS8FQ==", + "dependencies": { + "glob": "7.1.3", + "unxhr": "1.0.1" + }, + "engines": { + "node": ">=8.11" + } + }, + "node_modules/asciidoctor-opal-runtime/node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -1605,8 +1685,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base64-js": { "version": "1.5.1", @@ -1652,7 +1731,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1811,6 +1889,14 @@ "node": ">=6" } }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001283", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001283.tgz", @@ -1867,6 +1953,16 @@ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -1893,8 +1989,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "node_modules/constants-browserify": { "version": "1.0.0", @@ -2059,6 +2154,14 @@ "ms": "2.0.0" } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -3111,8 +3214,7 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "node_modules/fsevents": { "version": "2.3.2", @@ -3147,6 +3249,14 @@ "node": ">=6.9.0" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -3456,7 +3566,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -3581,7 +3690,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -4035,7 +4143,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4313,7 +4420,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "dependencies": { "wrappy": "1" } @@ -4433,7 +4539,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4788,6 +4893,14 @@ "url": "https://github.com/sponsors/mysticatea" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -4797,6 +4910,11 @@ "node": ">=0.10.0" } }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, "node_modules/resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -4917,6 +5035,11 @@ "semver": "bin/semver.js" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -5118,7 +5241,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -5131,8 +5253,7 @@ "node_modules/string-width/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/string.prototype.matchall": { "version": "4.0.6", @@ -5462,6 +5583,14 @@ "node": ">= 0.8" } }, + "node_modules/unxhr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unxhr/-/unxhr-1.0.1.tgz", + "integrity": "sha512-MAhukhVHyaLGDjyDYhy8gVjWJyhTECCdNsLwlMoGFoNJ3o79fpQhtQuzmAE4IxCMDwraF4cW8ZjpAV0m9CRQbg==", + "engines": { + "node": ">=8.11" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -5568,6 +5697,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, "node_modules/which-typed-array": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", @@ -5596,11 +5730,53 @@ "node": ">=0.10.0" } }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/xtend": { "version": "4.0.2", @@ -5610,12 +5786,50 @@ "node": ">=0.4" } }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/yargs": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", + "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -5629,6 +5843,23 @@ } }, "dependencies": { + "@asciidoctor/cli": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@asciidoctor/cli/-/cli-3.4.0.tgz", + "integrity": "sha512-jOtxA0I6zB+6z+GGwm9+xhlmGTqCTkFPE902L6fauFlE6v7LxjhLYNxvjDVyn0zMrFLybvoSRcAnM3DcticNoQ==", + "requires": { + "yargs": "15.3.1" + } + }, + "@asciidoctor/core": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-2.2.5.tgz", + "integrity": "sha512-jtQPQ5EivgFbwvSyGKas4ANnMGGHPbmu791H9xrZKooA65JNI30jM2em5MvUXTTetSPgb6saUf+PJibEuSB6uw==", + "requires": { + "asciidoctor-opal-runtime": "0.3.3", + "unxhr": "1.0.1" + } + }, "@babel/code-frame": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", @@ -6710,6 +6941,39 @@ "es-abstract": "^1.19.0" } }, + "asciidoctor": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/asciidoctor/-/asciidoctor-2.2.5.tgz", + "integrity": "sha512-rrmCK34faw+w+xGFQggjwPB0/pcISnwOXaulfJvn7j4Nm0bFwz+x4tG3ZANIA9+9i6Csex/PO0fSLBO8CSdzVA==", + "requires": { + "@asciidoctor/cli": "3.4.0", + "@asciidoctor/core": "2.2.5" + } + }, + "asciidoctor-opal-runtime": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/asciidoctor-opal-runtime/-/asciidoctor-opal-runtime-0.3.3.tgz", + "integrity": "sha512-/CEVNiOia8E5BMO9FLooo+Kv18K4+4JBFRJp8vUy/N5dMRAg+fRNV4HA+o6aoSC79jVU/aT5XvUpxSxSsTS8FQ==", + "requires": { + "glob": "7.1.3", + "unxhr": "1.0.1" + }, + "dependencies": { + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, "asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -6771,8 +7035,7 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base64-js": { "version": "1.5.1", @@ -6798,7 +7061,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6935,6 +7197,11 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, "caniuse-lite": { "version": "1.0.30001283", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001283.tgz", @@ -6979,6 +7246,16 @@ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -7005,8 +7282,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "constants-browserify": { "version": "1.0.0", @@ -7150,6 +7426,11 @@ "ms": "2.0.0" } }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -7962,8 +8243,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.3.2", @@ -7988,6 +8268,11 @@ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "peer": true }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, "get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -8204,7 +8489,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -8289,8 +8573,7 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-generator-function": { "version": "1.0.10", @@ -8624,7 +8907,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -8822,7 +9104,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -8916,8 +9197,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { "version": "3.1.1", @@ -9182,12 +9462,22 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, "require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -9261,6 +9551,11 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -9425,7 +9720,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -9435,8 +9729,7 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" } } }, @@ -9687,6 +9980,11 @@ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, + "unxhr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unxhr/-/unxhr-1.0.1.tgz", + "integrity": "sha512-MAhukhVHyaLGDjyDYhy8gVjWJyhTECCdNsLwlMoGFoNJ3o79fpQhtQuzmAE4IxCMDwraF4cW8ZjpAV0m9CRQbg==" + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -9778,6 +10076,11 @@ "is-symbol": "^1.0.3" } }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, "which-typed-array": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", @@ -9797,23 +10100,87 @@ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "yargs": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", + "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.1" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 2f38902..bb97384 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "lint": "npx next lint" }, "dependencies": { + "asciidoctor": "^2.2.5", "next": "12.0.7", "phosphor-react": "^1.3.1", "react": "17.0.2", diff --git a/pages/api/get_project.ts b/pages/api/get_project.ts index 0e33ad7..9f3e46a 100644 --- a/pages/api/get_project.ts +++ b/pages/api/get_project.ts @@ -19,7 +19,7 @@ export default function handler(req: NextApiRequest, res: NextApiResponse { - const inputRef = useRef(); + const inputRef = useRef(); + const [modalVisible, setModalVisible] = useState(false); + const [modalProject, setModalProject] = useState(""); - const focusInput = () => {if (inputRef.current) inputRef.current.focus();}; - - return (<> - - c0ntroller.de - -
-
-   - Source - | - Bug? - | - - | - - | - - | - - - - - C0ntroller_Z#3883 - - -   -
- -
- ); + const focusInput = () => { if (inputRef.current) inputRef.current.focus(); }; + + const hideModalOnEsc = (e: React.KeyboardEvent) => { + if (e.key === "Escape") { + e.preventDefault(); + setModalVisible(false); + } + } + + return (
+ + c0ntroller.de + + +
+
+   + Source + | + Bug? + | + + | + + | + + | + + + + + C0ntroller_Z#3883 + + +   +
+ +
+
); }; export default Home; diff --git a/public/projects/homepage.adoc b/public/projects/homepage.adoc new file mode 100644 index 0000000..64034f6 --- /dev/null +++ b/public/projects/homepage.adoc @@ -0,0 +1 @@ +Hey. This is a test. \ No newline at end of file diff --git a/styles/ProjectModal.module.css b/styles/ProjectModal.module.css new file mode 100644 index 0000000..f9b5910 --- /dev/null +++ b/styles/ProjectModal.module.css @@ -0,0 +1,19 @@ +.modal { + z-index: 99; + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + padding: 5%; + background: transparent; +} + +.modalContainer { + background: #333; + color: #ccc; + width: 100%; + height: 100%; + padding: 20px; + border-radius: 20px; +} \ No newline at end of file diff --git a/testfile b/testfile new file mode 100644 index 0000000..45ea532 --- /dev/null +++ b/testfile @@ -0,0 +1 @@ +Miau From 04c0882c067c65c1307cd9ddc2021d68d580fdb8 Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Fri, 14 Jan 2022 15:26:13 +0100 Subject: [PATCH 05/20] Test volume mount --- docker-compose.dev.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index f78ae47..8724551 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -4,6 +4,8 @@ services: server: image: localhost:5000/c0ntroller.de:dev restart: always + volumes: + - ./website_projects:/app/public/projects networks: - traefik labels: From 727bb0d0cf191ab17dfc412f73c9b42aaacf94e5 Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Fri, 14 Jan 2022 15:39:08 +0100 Subject: [PATCH 06/20] Fix path for projects --- docker-compose.dev.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 8724551..5ac7df9 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -5,7 +5,8 @@ services: image: localhost:5000/c0ntroller.de:dev restart: always volumes: - - ./website_projects:/app/public/projects + # Relative paths are located in the tmp folder where the projet is clones + - /srv/website/projects:/app/public/projects:ro networks: - traefik labels: From d40eb433c776e0c21a417b20e6fdb27945feef0f Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Fri, 14 Jan 2022 16:28:38 +0100 Subject: [PATCH 07/20] Remove test project file --- public/projects/homepage.adoc | 1 - 1 file changed, 1 deletion(-) delete mode 100644 public/projects/homepage.adoc diff --git a/public/projects/homepage.adoc b/public/projects/homepage.adoc deleted file mode 100644 index 64034f6..0000000 --- a/public/projects/homepage.adoc +++ /dev/null @@ -1 +0,0 @@ -Hey. This is a test. \ No newline at end of file From 7ac2a6a66382730f44b54de4a7145e75dc429fbe Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Fri, 14 Jan 2022 16:32:23 +0100 Subject: [PATCH 08/20] Mask git folder --- docker-compose.dev.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 5ac7df9..4e5dfb3 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -7,6 +7,7 @@ services: volumes: # Relative paths are located in the tmp folder where the projet is clones - /srv/website/projects:/app/public/projects:ro + - git_mask:/app/public/projects/.git networks: - traefik labels: @@ -25,4 +26,6 @@ services: networks: traefik: - external: true \ No newline at end of file + external: true +volumes: + git_mask: \ No newline at end of file From 36b0b16059c8d28eb5726e5c69c9e9052aefc4ef Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Fri, 14 Jan 2022 17:17:55 +0100 Subject: [PATCH 09/20] Lint --- .eslintrc.json | 2 +- components/ProjectModal.tsx | 14 +++++++------- pages/api/get_project.ts | 2 +- pages/index.tsx | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 242520f..cfca33b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,7 +1,7 @@ { "extends": "next/core-web-vitals", "rules": { - "semi": ["warn", "always"], + "semi": ["warn", "always", { "omitLastInOneLineBlock": true }], "quotes": ["warn", "double"], "eqeqeq": "error" } diff --git a/components/ProjectModal.tsx b/components/ProjectModal.tsx index 02520ca..c27bfdc 100644 --- a/components/ProjectModal.tsx +++ b/components/ProjectModal.tsx @@ -34,30 +34,30 @@ const ProjectModal: NextPage = ({ project, visible, setVisible }) => } }); }); - } else if (project === "") setProjectData(projectEmpty) - }, [project]) + } else if (project === "") setProjectData(projectEmpty); + }, [project, projectEmpty, projectNotFoundHtml, projectServerErrorHtml]); useEffect(() => { if (projectData && containerRef.current && projectData !== "") { containerRef.current.innerHTML = projectData; } - }, [projectData, visible]) + }, [projectData, visible]); const onEscClose = (e: React.KeyboardEvent) => { if (e.key === "Escape") { e.preventDefault(); setVisible(false); } - } + }; - if (!visible) return <> + if (!visible) return <>; return
-
-} + ; +}; export default ProjectModal; \ No newline at end of file diff --git a/pages/api/get_project.ts b/pages/api/get_project.ts index 9f3e46a..0cef4ac 100644 --- a/pages/api/get_project.ts +++ b/pages/api/get_project.ts @@ -19,7 +19,7 @@ export default function handler(req: NextApiRequest, res: NextApiResponse { e.preventDefault(); setModalVisible(false); } - } + }; return (
From 5846e5241d616841cc489e31462ad2f5925debe3 Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Fri, 14 Jan 2022 17:44:52 +0100 Subject: [PATCH 10/20] Add arrow history (fix #2) --- components/REPL/REPLInput.tsx | 48 +++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/components/REPL/REPLInput.tsx b/components/REPL/REPLInput.tsx index cf71421..dbdb0e9 100644 --- a/components/REPL/REPLInput.tsx +++ b/components/REPL/REPLInput.tsx @@ -1,5 +1,5 @@ import type { NextPage } from "next"; -import React, { MutableRefObject } from "react"; +import { MutableRefObject, useState, createRef } from "react"; import { CommandInterface } from "../../lib/commands"; import styles from "../../styles/REPL/REPLInput.module.css"; @@ -14,10 +14,12 @@ interface REPLInputParams { } const REPLInput: NextPage = ({historyCallback, historyClear, inputRef, modalManipulation}) => { - const typed = React.createRef(); - const completion = React.createRef(); - const [currentCmd, setCurrentCmd] = React.useState([]); - const [justTabbed, setJustTabbed] = React.useState(0); + const typed = createRef(); + const completion = createRef(); + const [currentCmd, setCurrentCmd] = useState([]); + const [justTabbed, setJustTabbed] = useState(0); + const [inCmdHistory, setInCmdHistory] = useState(-1); + const [cmdHistory, setCmdHistory] = useState([]); const cmdIf = new CommandInterface(modalManipulation); const clearInput = (inputRef: HTMLInputElement) => { @@ -52,8 +54,10 @@ const REPLInput: NextPage = ({historyCallback, historyClear, in const keyEvent = (e: React.KeyboardEvent) => { const input = (e.target as HTMLInputElement); - if (e.key === "Tab" && currentCmd.length !== 0) { + if (e.key === "Tab") { e.preventDefault(); + } + if (e.key === "Tab" && currentCmd.length !== 0) { input.value = currentCmd[justTabbed % currentCmd.length]; if(typed.current) typed.current.innerHTML = currentCmd[justTabbed % currentCmd.length]; if(completion.current) completion.current.innerHTML = ""; @@ -64,13 +68,15 @@ const REPLInput: NextPage = ({historyCallback, historyClear, in if (e.key === "Enter") { e.preventDefault(); const command = (e.target as HTMLInputElement).value; + setCmdHistory(cmdHistory.concat([command]).splice(0, 100)); + clearInput(input); + setInCmdHistory(-1); + setCurrentCmd([]); if (command === "clear") { - clearInput(input); historyClear(); return false; } const result = cmdIf.executeCommand(command); - clearInput(input); historyCallback(result); return false; } @@ -96,6 +102,32 @@ const REPLInput: NextPage = ({historyCallback, historyClear, in return false; } + if (e.key === "ArrowUp") { + e.preventDefault(); + const idx = inCmdHistory + 1; + if (idx < cmdHistory.length) { + const cmd = cmdHistory[cmdHistory.length - idx - 1]; + input.value = cmd; + if(typed.current) typed.current.innerHTML = cmd; + if(completion.current) completion.current.innerHTML = ""; + setInCmdHistory(idx); + } + } + + if (e.key === "ArrowDown") { + e.preventDefault(); + const idx = inCmdHistory - 1; + if (0 <= idx) { + const cmd = cmdHistory[cmdHistory.length - idx - 1]; + input.value = cmd; + if(typed.current) typed.current.innerHTML = cmd; + if(completion.current) completion.current.innerHTML = ""; + setInCmdHistory(idx); + } else { + clearInput(input); + } + } + }; return
From 0539bceeaac18b50a864101322624d3d5aebff28 Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Sun, 16 Jan 2022 14:58:48 +0100 Subject: [PATCH 11/20] New routes for projects --- pages/api/projects.ts | 29 +++++++++++++++++++++++++++++ pages/api/projects/[name].ts | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 pages/api/projects.ts create mode 100644 pages/api/projects/[name].ts diff --git a/pages/api/projects.ts b/pages/api/projects.ts new file mode 100644 index 0000000..3037fa6 --- /dev/null +++ b/pages/api/projects.ts @@ -0,0 +1,29 @@ +import { readFileSync } from "fs"; +import { resolve } from "path"; +import type { NextApiRequest, NextApiResponse } from "next"; + +interface IFileError { + message: string; + name: string; + stack?: string; + code: string; + errno: number; + syscall: string; + path: string; +} + +export default function handler(req: NextApiRequest, res: NextApiResponse) { + if (req.method !== "GET") return res.status(405).end(); + + try { + const path = resolve("./public", "projects", "list.json"); + const data = readFileSync(path).toString(); + console.debug("[API/get_project]\tRequest for project list"); + res.status(200).send(data); + } catch (err) { + console.error(`[API/get_project]\tError in request for project list! Code: ${(err as IFileError).code}`); + res.status(500); + } finally { + res.end(); + } +} diff --git a/pages/api/projects/[name].ts b/pages/api/projects/[name].ts new file mode 100644 index 0000000..027319f --- /dev/null +++ b/pages/api/projects/[name].ts @@ -0,0 +1,33 @@ +import { readFileSync } from "fs"; +import { resolve } from "path"; +import type { NextApiRequest, NextApiResponse } from "next"; + +interface IFileError { + message: string; + name: string; + stack?: string; + code: string; + errno: number; + syscall: string; + path: string; +} + +export default function handler(req: NextApiRequest, res: NextApiResponse) { + if (req.method !== "GET") return res.status(405).end(); + if (!req.query.name) return res.status(400).end(); + + const project = req.query.name; + + try { + const path = resolve("./public", "projects", `${project}.adoc`); + const data = readFileSync(path).toString(); + console.debug(`[API/get_project]\tRequest for ${project}`); + res.status(200).send(data); + } catch (err) { + console.error(`[API/get_project]\tError in request for ${project}! Code: ${(err as IFileError).code}`); + if ((err as IFileError).code === "ENOENT") res.status(404); + else res.status(500); + } finally { + res.end(); + } +} From 3efbcae886d49f5940c17ced4ef34cebadc56312 Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Sun, 16 Jan 2022 15:15:48 +0100 Subject: [PATCH 12/20] Update CommandInterface for dynamic project lists --- components/REPL/REPLInput.tsx | 18 +++++++++++++++--- lib/commands/definitions.ts | 6 ++---- lib/commands/index.ts | 5 ++++- package-lock.json | 17 ++++++++++++++++- package.json | 3 ++- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/components/REPL/REPLInput.tsx b/components/REPL/REPLInput.tsx index dbdb0e9..2d42af1 100644 --- a/components/REPL/REPLInput.tsx +++ b/components/REPL/REPLInput.tsx @@ -1,7 +1,9 @@ import type { NextPage } from "next"; -import { MutableRefObject, useState, createRef } from "react"; +import useSWR from "swr"; +import { MutableRefObject, useState, createRef, useEffect } from "react"; import { CommandInterface } from "../../lib/commands"; import styles from "../../styles/REPL/REPLInput.module.css"; +import { Project } from "../../lib/projects/types"; interface REPLInputParams { historyCallback: CallableFunction; @@ -13,6 +15,11 @@ interface REPLInputParams { } } +async function fetchProjects(endpoint: string): Promise { + const res = await fetch(endpoint); + return res.json(); +} + const REPLInput: NextPage = ({historyCallback, historyClear, inputRef, modalManipulation}) => { const typed = createRef(); const completion = createRef(); @@ -20,7 +27,8 @@ const REPLInput: NextPage = ({historyCallback, historyClear, in const [justTabbed, setJustTabbed] = useState(0); const [inCmdHistory, setInCmdHistory] = useState(-1); const [cmdHistory, setCmdHistory] = useState([]); - const cmdIf = new CommandInterface(modalManipulation); + const [cmdIf, setCmdIf] = useState(new CommandInterface(modalManipulation, [])); + const { data: projects, error: projectsError } = useSWR("/api/projects", fetchProjects); const clearInput = (inputRef: HTMLInputElement) => { inputRef.value = ""; @@ -127,9 +135,13 @@ const REPLInput: NextPage = ({historyCallback, historyClear, in clearInput(input); } } - }; + useEffect(() => { + if (!projectsError && projects) setCmdIf(new CommandInterface(modalManipulation, projects)); + // In any other case we just don't create another interface. + }, [projects, projectsError, modalManipulation]); + return
diff --git a/lib/commands/definitions.ts b/lib/commands/definitions.ts index a76d6f6..f328641 100644 --- a/lib/commands/definitions.ts +++ b/lib/commands/definitions.ts @@ -1,6 +1,4 @@ import type { Command, Flag } from "./types"; -import type { Project } from "../projects/types"; -import projectList from "../projects"; function getCommandByName(name: string): Command|undefined { return commandList.find(cmd => cmd.name === name); @@ -148,7 +146,7 @@ const project: Command = { execute: (flags, args, _raw, cmdIf) => { if (project.flags && checkFlagInclude(flags, project.flags.list)) { const result = ["Found the following projects:"]; - projectList.forEach(project => result.push(`\t${project.name}\t${project.short}`)); + cmdIf.projects.forEach(project => result.push(`\t${project.name}\t${project.short}`)); return result; } @@ -156,7 +154,7 @@ const project: Command = { if (args[0] === "this") args[0] = "homepage"; - const pjt = projectList.find(p => p.name === args[0]); + const pjt = cmdIf.projects.find(p => p.name === args[0]); if (!pjt) return [ `Cannot find project ${args[0]}!`, "You can see available projects using 'project -l'." diff --git a/lib/commands/index.ts b/lib/commands/index.ts index a2cb9b0..1c6b3a2 100644 --- a/lib/commands/index.ts +++ b/lib/commands/index.ts @@ -1,3 +1,4 @@ +import { Project } from "../projects/types"; import { printSyntax, commandList } from "./definitions"; interface CommandInterfaceCallbacks { @@ -7,9 +8,11 @@ interface CommandInterfaceCallbacks { export class CommandInterface { callbacks: CommandInterfaceCallbacks; + projects: Project[]; - constructor(callbacks: CommandInterfaceCallbacks) { + constructor(callbacks: CommandInterfaceCallbacks, projects: Project[]) { this.callbacks = callbacks; + this.projects = projects; } static commandCompletion(input: string): string[] { diff --git a/package-lock.json b/package-lock.json index e1e1e02..7258d60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,8 @@ "next": "12.0.7", "phosphor-react": "^1.3.1", "react": "17.0.2", - "react-dom": "17.0.2" + "react-dom": "17.0.2", + "swr": "^1.1.2" }, "devDependencies": { "@types/node": "16.11.11", @@ -5388,6 +5389,14 @@ "node": ">=4" } }, + "node_modules/swr": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/swr/-/swr-1.1.2.tgz", + "integrity": "sha512-UsM0eo5T+kRPyWFZtWRx2XR5qzohs/LS4lDC0GCyLpCYFmsfTk28UCVDbOE9+KtoXY4FnwHYiF+ZYEU3hnJ1lQ==", + "peerDependencies": { + "react": "^16.11.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/table": { "version": "6.7.3", "resolved": "https://registry.npmjs.org/table/-/table-6.7.3.tgz", @@ -9828,6 +9837,12 @@ "has-flag": "^3.0.0" } }, + "swr": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/swr/-/swr-1.1.2.tgz", + "integrity": "sha512-UsM0eo5T+kRPyWFZtWRx2XR5qzohs/LS4lDC0GCyLpCYFmsfTk28UCVDbOE9+KtoXY4FnwHYiF+ZYEU3hnJ1lQ==", + "requires": {} + }, "table": { "version": "6.7.3", "resolved": "https://registry.npmjs.org/table/-/table-6.7.3.tgz", diff --git a/package.json b/package.json index bb97384..3a52e8f 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "next": "12.0.7", "phosphor-react": "^1.3.1", "react": "17.0.2", - "react-dom": "17.0.2" + "react-dom": "17.0.2", + "swr": "^1.1.2" }, "devDependencies": { "@types/node": "16.11.11", From 74adb7c19f39bc0f8315f7bfae6361d1b6e26861 Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Sun, 16 Jan 2022 15:16:24 +0100 Subject: [PATCH 13/20] Use new API route (fix #10) --- components/ProjectModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/ProjectModal.tsx b/components/ProjectModal.tsx index c27bfdc..f8ca0c5 100644 --- a/components/ProjectModal.tsx +++ b/components/ProjectModal.tsx @@ -23,7 +23,7 @@ const ProjectModal: NextPage = ({ project, visible, setVisible }) => if (project && project !== "") { // TODO // set Spinner - fetch(`/api/get_project?projectName=${project}`).then((res) => { + fetch(`/api/projects/${project}`).then((res) => { if (res.status === 404) setProjectData(projectNotFoundHtml); if (res.status !== 200) setProjectData(projectServerErrorHtml); res.text().then(data => { From 5da799009f1e835e773fa82da79166e33ae7584c Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Sun, 16 Jan 2022 15:17:39 +0100 Subject: [PATCH 14/20] Remove old projects directory --- public/projects/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 public/projects/.gitkeep diff --git a/public/projects/.gitkeep b/public/projects/.gitkeep deleted file mode 100644 index e69de29..0000000 From f0a4f89d51de1d5ca4653f70bfe7ff96e112b4d8 Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Sun, 16 Jan 2022 15:18:36 +0100 Subject: [PATCH 15/20] Use submodule It will not need to be cloned on build as it's volume mounted --- .gitmodules | 3 +++ public/projects | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 public/projects diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5dd7b45 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "public/projects"] + path = public/projects + url = git@git.c0ntroller.de:c0ntroller/frontpage-projects.git diff --git a/public/projects b/public/projects new file mode 160000 index 0000000..54fe11a --- /dev/null +++ b/public/projects @@ -0,0 +1 @@ +Subproject commit 54fe11a492812ae92f9020aac1dc701b48e9b170 From 0085f16a1232ba18bafddab892cf934cef88eb27 Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Sun, 16 Jan 2022 15:22:16 +0100 Subject: [PATCH 16/20] Use new submodule commits --- public/projects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/projects b/public/projects index 54fe11a..0496a88 160000 --- a/public/projects +++ b/public/projects @@ -1 +1 @@ -Subproject commit 54fe11a492812ae92f9020aac1dc701b48e9b170 +Subproject commit 0496a88b3610ce432d678bf6d2e418f72e537758 From 4b67191aab50414a2ecab2ddb0f1ca2d923a697a Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Sun, 16 Jan 2022 15:24:28 +0100 Subject: [PATCH 17/20] Update debug messages --- pages/api/projects.ts | 4 ++-- pages/api/projects/[name].ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pages/api/projects.ts b/pages/api/projects.ts index 3037fa6..a27f351 100644 --- a/pages/api/projects.ts +++ b/pages/api/projects.ts @@ -18,10 +18,10 @@ export default function handler(req: NextApiRequest, res: NextApiResponse Date: Sun, 16 Jan 2022 15:39:19 +0100 Subject: [PATCH 18/20] Remove old project files --- lib/projects/index.ts | 21 --------------------- pages/api/get_project.ts | 33 --------------------------------- 2 files changed, 54 deletions(-) delete mode 100644 lib/projects/index.ts delete mode 100644 pages/api/get_project.ts diff --git a/lib/projects/index.ts b/lib/projects/index.ts deleted file mode 100644 index 1cf942d..0000000 --- a/lib/projects/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { Project } from "./types"; - -const projectList: Project[] = [ - { - name: "homepage", - short: "This website.", - desc: [ - "This is my homepage.", - "What you see here should resemble an CLI. If you ever used Linux this should be pretty easy for you.", - "Everyone else: Have no fear. It is pretty simple. You just type in commands and the output is shown here or it does something on the webite.", - "To find out, which commands are available, you can type just 'help'.", - "", - "Currently everything is still in development. So if you come back in a few days/weeks/months/years something could have been changed!", - "", - "Have fun!" - ], - repo: "https://git.c0ntroller.de/c0ntroller/frontpage" - } -]; - -export default projectList; \ No newline at end of file diff --git a/pages/api/get_project.ts b/pages/api/get_project.ts deleted file mode 100644 index 0cef4ac..0000000 --- a/pages/api/get_project.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { readFileSync } from "fs"; -import { resolve } from "path"; -import type { NextApiRequest, NextApiResponse } from "next"; - -interface IFileError { - message: string; - name: string; - stack?: string; - code: string; - errno: number; - syscall: string; - path: string; -} - -export default function handler(req: NextApiRequest, res: NextApiResponse) { - if (req.method !== "GET") return res.status(405).end(); - if (!req.query.projectName) return res.status(400).end(); - - const project = req.query.projectName; - - try { - const path = resolve("./public", "projects", `${project}.adoc`); - const data = readFileSync(path).toString(); - console.debug(`[API/get_project]\tRequest for ${project}`); - res.status(200).send(data); - } catch (err) { - console.error(`[API/get_project]\tError in request for ${project}! Code: ${(err as IFileError).code}`); - if ((err as IFileError).code === "ENOENT") res.status(404); - else res.status(500); - } finally { - res.end(); - } -} From 858cffb58782bf4ccc48c116722271b7bd8de667 Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Sun, 16 Jan 2022 16:11:48 +0100 Subject: [PATCH 19/20] Fix #9 --- components/REPL/REPLInput.tsx | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/components/REPL/REPLInput.tsx b/components/REPL/REPLInput.tsx index 2d42af1..6cdf714 100644 --- a/components/REPL/REPLInput.tsx +++ b/components/REPL/REPLInput.tsx @@ -27,13 +27,22 @@ const REPLInput: NextPage = ({historyCallback, historyClear, in const [justTabbed, setJustTabbed] = useState(0); const [inCmdHistory, setInCmdHistory] = useState(-1); const [cmdHistory, setCmdHistory] = useState([]); + const [usrInputTmp, setUsrInputTmp] = useState(""); const [cmdIf, setCmdIf] = useState(new CommandInterface(modalManipulation, [])); const { data: projects, error: projectsError } = useSWR("/api/projects", fetchProjects); + const setInput = (inputRef: HTMLInputElement, input: string) => { + const nativeSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set; + if (!nativeSetter) return; + nativeSetter.call(inputRef, input); + //if(typed.current) typed.current.innerHTML = input; + //if(completion.current) completion.current.innerHTML = ""; + const event = new Event("input", { bubbles: true }); + inputRef.dispatchEvent(event); + }; + const clearInput = (inputRef: HTMLInputElement) => { - inputRef.value = ""; - if(typed.current) typed.current.innerHTML = ""; - if(completion.current) completion.current.innerHTML = ""; + setInput(inputRef, ""); }; const replinOnChange = (e: React.FormEvent) => { @@ -66,9 +75,7 @@ const REPLInput: NextPage = ({historyCallback, historyClear, in e.preventDefault(); } if (e.key === "Tab" && currentCmd.length !== 0) { - input.value = currentCmd[justTabbed % currentCmd.length]; - if(typed.current) typed.current.innerHTML = currentCmd[justTabbed % currentCmd.length]; - if(completion.current) completion.current.innerHTML = ""; + setInput(input, currentCmd[justTabbed % currentCmd.length]); setJustTabbed(justTabbed + 1); return false; } else setJustTabbed(0); @@ -114,10 +121,10 @@ const REPLInput: NextPage = ({historyCallback, historyClear, in e.preventDefault(); const idx = inCmdHistory + 1; if (idx < cmdHistory.length) { + if (inCmdHistory === -1) setUsrInputTmp(input.value); + const cmd = cmdHistory[cmdHistory.length - idx - 1]; - input.value = cmd; - if(typed.current) typed.current.innerHTML = cmd; - if(completion.current) completion.current.innerHTML = ""; + setInput(input, cmd); setInCmdHistory(idx); } } @@ -127,12 +134,11 @@ const REPLInput: NextPage = ({historyCallback, historyClear, in const idx = inCmdHistory - 1; if (0 <= idx) { const cmd = cmdHistory[cmdHistory.length - idx - 1]; - input.value = cmd; - if(typed.current) typed.current.innerHTML = cmd; - if(completion.current) completion.current.innerHTML = ""; + setInput(input, cmd); setInCmdHistory(idx); - } else { - clearInput(input); + } else if (idx === -1) { + setInput(input, usrInputTmp); + setInCmdHistory(-1); } } }; From caa9442575beb9edbf7235c7a8d23cb08bed5fb9 Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Sun, 16 Jan 2022 16:13:38 +0100 Subject: [PATCH 20/20] Fix #8 --- components/REPL/REPLInput.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/REPL/REPLInput.tsx b/components/REPL/REPLInput.tsx index 6cdf714..4e7c74c 100644 --- a/components/REPL/REPLInput.tsx +++ b/components/REPL/REPLInput.tsx @@ -75,7 +75,8 @@ const REPLInput: NextPage = ({historyCallback, historyClear, in e.preventDefault(); } if (e.key === "Tab" && currentCmd.length !== 0) { - setInput(input, currentCmd[justTabbed % currentCmd.length]); + const cmd = `${currentCmd[justTabbed % currentCmd.length]}${currentCmd.length === 1 ? " " : ""}`; + setInput(input, cmd); setJustTabbed(justTabbed + 1); return false; } else setJustTabbed(0);