Compare commits

..

3 commits

9 changed files with 65 additions and 27 deletions

View file

@ -4,8 +4,10 @@
"": { "": {
"name": "bun-ssh-portfolio", "name": "bun-ssh-portfolio",
"dependencies": { "dependencies": {
"@types/qrcode-terminal": "^0.12.2",
"@types/ssh2": "^1.15.4", "@types/ssh2": "^1.15.4",
"ansi-escapes": "^7.0.0", "ansi-escapes": "^7.0.0",
"qrcode-terminal": "^0.12.0",
"ssh2": "^1.16.0", "ssh2": "^1.16.0",
}, },
"devDependencies": { "devDependencies": {
@ -21,6 +23,8 @@
"@types/node": ["@types/node@18.19.80", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-kEWeMwMeIvxYkeg1gTc01awpwLbfMRZXdIhwRcakd/KlK53jmRC26LqcbIt7fnAQTu5GzlnWmzA3H6+l1u6xxQ=="], "@types/node": ["@types/node@18.19.80", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-kEWeMwMeIvxYkeg1gTc01awpwLbfMRZXdIhwRcakd/KlK53jmRC26LqcbIt7fnAQTu5GzlnWmzA3H6+l1u6xxQ=="],
"@types/qrcode-terminal": ["@types/qrcode-terminal@0.12.2", "", {}, "sha512-v+RcIEJ+Uhd6ygSQ0u5YYY7ZM+la7GgPbs0V/7l/kFs2uO4S8BcIUEMoP7za4DNIqNnUD5npf0A/7kBhrCKG5Q=="],
"@types/ssh2": ["@types/ssh2@1.15.4", "", { "dependencies": { "@types/node": "^18.11.18" } }, "sha512-9JTQgVBWSgq6mAen6PVnrAmty1lqgCMvpfN+1Ck5WRUsyMYPa6qd50/vMJ0y1zkGpOEgLzm8m8Dx/Y5vRouLaA=="], "@types/ssh2": ["@types/ssh2@1.15.4", "", { "dependencies": { "@types/node": "^18.11.18" } }, "sha512-9JTQgVBWSgq6mAen6PVnrAmty1lqgCMvpfN+1Ck5WRUsyMYPa6qd50/vMJ0y1zkGpOEgLzm8m8Dx/Y5vRouLaA=="],
"@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="],
@ -41,6 +45,8 @@
"nan": ["nan@2.22.2", "", {}, "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ=="], "nan": ["nan@2.22.2", "", {}, "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ=="],
"qrcode-terminal": ["qrcode-terminal@0.12.0", "", { "bin": { "qrcode-terminal": "./bin/qrcode-terminal.js" } }, "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ=="],
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
"ssh2": ["ssh2@1.16.0", "", { "dependencies": { "asn1": "^0.2.6", "bcrypt-pbkdf": "^1.0.2" }, "optionalDependencies": { "cpu-features": "~0.0.10", "nan": "^2.20.0" } }, "sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg=="], "ssh2": ["ssh2@1.16.0", "", { "dependencies": { "asn1": "^0.2.6", "bcrypt-pbkdf": "^1.0.2" }, "optionalDependencies": { "cpu-features": "~0.0.10", "nan": "^2.20.0" } }, "sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg=="],

View file

@ -8,6 +8,8 @@ interface ContactProps {
const Contact = ({ width, height }: ContactProps) => { const Contact = ({ width, height }: ContactProps) => {
return ( return (
`${newLine}` +
` Use ⌘/ctrl+click to open the links below!${newLine}` +
`${newLine}` + `${newLine}` +
` Email: ${link("contact@jokinsuares.fr", "mailto:contact@jokinsuares.fr")}${newLine}` + ` Email: ${link("contact@jokinsuares.fr", "mailto:contact@jokinsuares.fr")}${newLine}` +
` Phone: ${link("+33 6 02 26 22 00", "tel:+33602262200")}${newLine}` + ` Phone: ${link("+33 6 02 26 22 00", "tel:+33602262200")}${newLine}` +

View file

@ -1,5 +1,6 @@
import { link } from "ansi-escapes"; import { link } from "ansi-escapes";
import { newLine } from ".."; import { newLine } from "..";
import generateQRCode from "../../wrapers/qr-code-wraper";
interface ProjectProps { interface ProjectProps {
title: string; title: string;
@ -8,7 +9,7 @@ interface ProjectProps {
learnMoreLink: string; learnMoreLink: string;
} }
const Project = ({ title, description, technologies, learnMoreLink }: ProjectProps) => { const Project = async ({ title, description, technologies, learnMoreLink }: ProjectProps) => {
return ( return (
` ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓${newLine}` + ` ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓${newLine}` +
`\x1b[33m${title.padEnd(80 - 4)}\x1b[0m ┃${newLine}` + `\x1b[33m${title.padEnd(80 - 4)}\x1b[0m ┃${newLine}` +
@ -24,6 +25,10 @@ const Project = ({ title, description, technologies, learnMoreLink }: ProjectPro
" \x1b[32mLearn more\x1b[0m ", " \x1b[32mLearn more\x1b[0m ",
learnMoreLink learnMoreLink
)}${newLine}` + )}${newLine}` +
(await generateQRCode(learnMoreLink))
.split(newLine)
.map((line) => `${line.padEnd(57 - 4).padStart(80 - 4)}${newLine}`)
.join("") +
` ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛${newLine}` ` ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛${newLine}`
); );
}; };

View file

@ -9,7 +9,7 @@ interface ProjectsProps {
scrollPosition: number; scrollPosition: number;
} }
const Projects = ({ width, height, scrollPosition }: ProjectsProps) => { const Projects = async ({ width, height, scrollPosition }: ProjectsProps) => {
const projects: ProjectProps[] = [ const projects: ProjectProps[] = [
{ {
title: "Algoforge", title: "Algoforge",
@ -52,13 +52,18 @@ const Projects = ({ width, height, scrollPosition }: ProjectsProps) => {
learnMoreLink: "https://github.com/Feror-BotMaker/sh-chat", learnMoreLink: "https://github.com/Feror-BotMaker/sh-chat",
}, },
]; ];
const projectsComponents = await Promise.all(projects.map(async (project) => await Project(project)));
return ScrollComponent({ return ScrollComponent({
width, width,
height, height,
scrollPosition, scrollPosition,
text: ` Use the arrows keys to navigate up and down.${newLine}${newLine}${projects text:
.map((project) => Project(project)) ` Use the arrows keys to navigate up and down.${newLine}` +
.join(newLine)}`, ` You can either ⌘/ctrl click a link to open it, or scan the QR code below it.${newLine}` +
`${newLine}` +
`${projectsComponents.join(newLine)}`,
}); });
}; };
export default Projects; export default Projects;

View file

@ -9,12 +9,12 @@ interface TabRouterProps {
scrollPosition: number; scrollPosition: number;
} }
const TabRouter = ({ width, height, selectedTab, scrollPosition }: TabRouterProps) => { const TabRouter = async ({ width, height, selectedTab, scrollPosition }: TabRouterProps) => {
switch (selectedTab) { switch (selectedTab) {
case "About": case "About":
return About({ width, height, scrollPosition }); return About({ width, height, scrollPosition });
case "Projects": case "Projects":
return Projects({ width, height, scrollPosition }); return await Projects({ width, height, scrollPosition });
case "Contact": case "Contact":
return Contact({ width, height }); return Contact({ width, height });
} }

View file

@ -22,14 +22,14 @@ const terminalTooSmall = (width: number, height: number) => {
); );
}; };
const Front = ({ columns, rows, selectedTab, scrollPosition }: FrontProps) => { const Front = async ({ columns, rows, selectedTab, scrollPosition }: FrontProps) => {
if (columns < minimumWidth || rows < minimumHeight) { if (columns < minimumWidth || rows < minimumHeight) {
return terminalTooSmall(columns, rows); return terminalTooSmall(columns, rows);
} }
return ( return (
`${Header({ width: columns, height: 3 })}${newLine}` + `${Header({ width: columns, height: 3 })}${newLine}` +
`${Categories({ width: columns, height: 3, selectedTab })}${newLine}` + `${Categories({ width: columns, height: 3, selectedTab })}${newLine}` +
`${TabRouter({ width: columns, height: rows - 6, selectedTab, scrollPosition })}` `${await TabRouter({ width: columns, height: rows - 6, selectedTab, scrollPosition })}`
); );
}; };

View file

@ -82,7 +82,7 @@ const server = new Server(
contactFormSelectedField: "name", contactFormSelectedField: "name",
}; };
const render = () => { const render = async () => {
userWindow.stream?.write(eraseScreen); userWindow.stream?.write(eraseScreen);
userWindow.stream?.write(cursorTo(0, 0)); userWindow.stream?.write(cursorTo(0, 0));
userWindow.stream?.write(cursorHide); userWindow.stream?.write(cursorHide);
@ -90,7 +90,7 @@ const server = new Server(
userWindow.stream?.write(ContactForm(userWindow)); userWindow.stream?.write(ContactForm(userWindow));
return; return;
} }
userWindow.stream?.write(Front(userWindow)); userWindow.stream?.write(await Front(userWindow));
}; };
session.on("pty", (accept, reject, info) => { session.on("pty", (accept, reject, info) => {

View file

@ -1,17 +1,23 @@
{ {
"name": "bun-ssh-portfolio", "name": "bun-ssh-portfolio",
"module": "index.ts", "module": "index.ts",
"type": "module", "type": "module",
"private": true, "private": true,
"devDependencies": { "scripts": {
"@types/bun": "latest" "start": "bun index.ts",
}, "dev": "bun --watch ."
"peerDependencies": { },
"typescript": "^5" "devDependencies": {
}, "@types/bun": "latest"
"dependencies": { },
"@types/ssh2": "^1.15.4", "peerDependencies": {
"ansi-escapes": "^7.0.0", "typescript": "^5"
"ssh2": "^1.16.0" },
} "dependencies": {
} "@types/qrcode-terminal": "^0.12.2",
"@types/ssh2": "^1.15.4",
"ansi-escapes": "^7.0.0",
"qrcode-terminal": "^0.12.0",
"ssh2": "^1.16.0"
}
}

14
wrapers/qr-code-wraper.ts Normal file
View file

@ -0,0 +1,14 @@
import qrcode from "qrcode-terminal";
import { newLine } from "../front";
const generateQRCode = (text: string): Promise<string> => {
return new Promise((resolve, reject) => {
qrcode.generate(text, { small: true }, (qrCode) => {
// On va enlever les \n et les remplacer par des newLine
qrCode = qrCode.replace(/\n/g, newLine);
resolve(qrCode);
});
});
};
export default generateQRCode;