From d5f2eb3d3fbcd1ec72e9d0b9a1f65273b3d91c4d Mon Sep 17 00:00:00 2001 From: Danny Wahl Date: Thu, 15 Feb 2024 19:38:09 -0700 Subject: [PATCH] add file explorer --- isp-site/src/routes/markdown.jsx | 22 ++++++++++++ isp-site/src/strings/markdown.js | 12 +++++++ isp-site/src/utils/explorer.js | 58 ++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 isp-site/src/utils/explorer.js diff --git a/isp-site/src/routes/markdown.jsx b/isp-site/src/routes/markdown.jsx index ac680cdb..700b3189 100644 --- a/isp-site/src/routes/markdown.jsx +++ b/isp-site/src/routes/markdown.jsx @@ -1,5 +1,6 @@ // Modules import React, { useState, useEffect } from "react"; +import reactDOM from "react-dom"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import remarkGemoji from "remark-gemoji"; @@ -28,6 +29,7 @@ import mdtoui from "components/mdtoui"; import { useParams } from "react-router-dom"; import strings from "strings/markdown"; import { getStrings, getLang } from "utils/langs"; +import { Explorer } from "utils/explorer"; // Page export default function Markdown({ readme }) { @@ -50,6 +52,26 @@ export default function Markdown({ readme }) { .catch((error) => console.error(error)); }); + useEffect(() => { + const page = document.getElementsByTagName("body")[0].classList[0]; + const branches = document.querySelectorAll(".markdown .contents"); + + for (const branch of branches) { + Explorer(page, branch, l).then((table) => { + reactDOM.render( + , + branch, + ); + }); + } + }); + return ( <> diff --git a/isp-site/src/strings/markdown.js b/isp-site/src/strings/markdown.js index 10e8b5fc..468cccf3 100644 --- a/isp-site/src/strings/markdown.js +++ b/isp-site/src/strings/markdown.js @@ -11,5 +11,17 @@ const strings = { PT_BR: "Não buscou o texto corretamente.", DE: "Text nicht korrekt abgerufen.", }, + download: { + EN: "Download", + ES_LA: "Descargar", + PT_BR: "Baixar", + DE: "Herunterladen", + }, + explore: { + EN: "Explore", + ES_LA: "Explorar", + PT_BR: "Explorar", + DE: "Erkunden", + }, }; export default strings; diff --git a/isp-site/src/utils/explorer.js b/isp-site/src/utils/explorer.js new file mode 100644 index 00000000..34cef2eb --- /dev/null +++ b/isp-site/src/utils/explorer.js @@ -0,0 +1,58 @@ +import strings from "strings/markdown"; +import { getStrings, getLang } from "utils/langs"; + +async function getGithubRepoContents(owner, repo, branch) { + const apiUrl = `https://api.github.com/repos/${owner}/${repo}/git/trees/${branch}?recursive=1`; + + try { + const response = await fetch(apiUrl); + const data = await response.json(); + + return data.tree || []; + } catch (error) { + console.error(`Error: ${error.message}`); + return []; + } +} + +function formatGithubContents(contents, name, language) { + const l = getLang(language); + const s = getStrings(strings, l); + const dlUrl = `https://raw.githubusercontent.com/thedannywahl/instructure-security-package/${name}/`; + const dirs = contents.filter((item) => item.type === "tree"); // TODO: Sort + const files = contents + .filter((item) => item.type === "blob") + .filter((item) => item.path !== ".gitignore"); + + let htmlTable = `
+ 🕵️ ${s.explore}\r\n\r\n`; + + for (const [i, dir] of dirs.entries()) { + htmlTable += `| ${dir.path} | |\r\n| ---------------- | - |`; + + for (const file of files) { + if (file.path.startsWith(dir.path)) { + htmlTable += `\r\n| [${file.path.replace( + `${dir.path}/`, + "", + )}](${encodeURI(dlUrl + file.path)}) | |`; + } + } + if (i < dirs.length - 1) htmlTable += "\r\n\r\n"; + } + + htmlTable += "
"; + + return htmlTable; +} + +export async function Explorer(page, branch, language) { + const owner = "thedannywahl"; + const repo = "instructure-security-package"; + const name = [...branch.classList].filter((c) => ~c.indexOf(page)).toString(); + + const contents = await getGithubRepoContents(owner, repo, name); + + const mdTable = formatGithubContents(contents, name, language); + return mdTable; +}