From 518bd58c5aba1a6eaa645074f3ae2d780c45f6dc Mon Sep 17 00:00:00 2001 From: HampusM Date: Mon, 24 May 2021 10:49:41 +0200 Subject: Restructured the whole project & added Nodemon and Concurrently --- src/App.vue | 11 -- src/api/git.js | 237 ++++++++++++++++++++++ src/api/sanitization.js | 14 ++ src/api/v1.js | 74 +++++++ src/app.html | 11 -- src/app.js | 101 +++++++++- src/components/BaseBackButton.vue | 25 --- src/components/CommitPatch.vue | 149 -------------- src/components/HomeHeader.vue | 39 ---- src/components/RepositoryHeader.vue | 50 ----- src/components/RepositoryNavbar.vue | 32 --- src/frontend/App.vue | 11 ++ src/frontend/app.html | 11 ++ src/frontend/app.js | 7 + src/frontend/components/BaseBackButton.vue | 25 +++ src/frontend/components/CommitPatch.vue | 149 ++++++++++++++ src/frontend/components/HomeHeader.vue | 39 ++++ src/frontend/components/RepositoryHeader.vue | 50 +++++ src/frontend/components/RepositoryNavbar.vue | 32 +++ src/frontend/router/index.js | 39 ++++ src/frontend/scss/abstracts/_colors.scss | 9 + src/frontend/scss/abstracts/_fonts.scss | 5 + src/frontend/scss/style.scss | 284 +++++++++++++++++++++++++++ src/frontend/util/hljs-languages.js | 45 +++++ src/frontend/views/Home.vue | 62 ++++++ src/frontend/views/Repository.vue | 29 +++ src/frontend/views/RepositoryCommit.vue | 98 +++++++++ src/frontend/views/RepositoryLog.vue | 91 +++++++++ src/router/index.js | 39 ---- src/scss/abstracts/_colors.scss | 9 - src/scss/abstracts/_fonts.scss | 5 - src/scss/style.scss | 284 --------------------------- src/util/hljs-languages.js | 45 ----- src/views/Home.vue | 62 ------ src/views/Repository.vue | 29 --- src/views/RepositoryCommit.vue | 98 --------- src/views/RepositoryLog.vue | 91 --------- 37 files changed, 1406 insertions(+), 985 deletions(-) delete mode 100644 src/App.vue create mode 100644 src/api/git.js create mode 100644 src/api/sanitization.js create mode 100644 src/api/v1.js delete mode 100644 src/app.html delete mode 100644 src/components/BaseBackButton.vue delete mode 100644 src/components/CommitPatch.vue delete mode 100644 src/components/HomeHeader.vue delete mode 100644 src/components/RepositoryHeader.vue delete mode 100644 src/components/RepositoryNavbar.vue create mode 100644 src/frontend/App.vue create mode 100644 src/frontend/app.html create mode 100644 src/frontend/app.js create mode 100644 src/frontend/components/BaseBackButton.vue create mode 100644 src/frontend/components/CommitPatch.vue create mode 100644 src/frontend/components/HomeHeader.vue create mode 100644 src/frontend/components/RepositoryHeader.vue create mode 100644 src/frontend/components/RepositoryNavbar.vue create mode 100644 src/frontend/router/index.js create mode 100644 src/frontend/scss/abstracts/_colors.scss create mode 100644 src/frontend/scss/abstracts/_fonts.scss create mode 100644 src/frontend/scss/style.scss create mode 100644 src/frontend/util/hljs-languages.js create mode 100644 src/frontend/views/Home.vue create mode 100644 src/frontend/views/Repository.vue create mode 100644 src/frontend/views/RepositoryCommit.vue create mode 100644 src/frontend/views/RepositoryLog.vue delete mode 100644 src/router/index.js delete mode 100644 src/scss/abstracts/_colors.scss delete mode 100644 src/scss/abstracts/_fonts.scss delete mode 100644 src/scss/style.scss delete mode 100644 src/util/hljs-languages.js delete mode 100644 src/views/Home.vue delete mode 100644 src/views/Repository.vue delete mode 100644 src/views/RepositoryCommit.vue delete mode 100644 src/views/RepositoryLog.vue (limited to 'src') diff --git a/src/App.vue b/src/App.vue deleted file mode 100644 index cbdce56..0000000 --- a/src/App.vue +++ /dev/null @@ -1,11 +0,0 @@ - - - \ No newline at end of file diff --git a/src/api/git.js b/src/api/git.js new file mode 100644 index 0000000..dad7cc6 --- /dev/null +++ b/src/api/git.js @@ -0,0 +1,237 @@ +const { formatDistance } = require('date-fns'); +const fs = require('fs'); +const git = require("nodegit"); + +function addRepoDirSuffix(repo_name) +{ + if(!repo_name.endsWith(".git")) { + return repo_name + ".git"; + } + return repo_name; +} + +async function getLog(base_dir, repo_name) +{ + const repo = await git.Repository.openBare(`${base_dir}/${repo_name}`) + + const walker = git.Revwalk.create(repo); + walker.pushHead(); + + const raw_commits = await walker.getCommits(); + + const commits = Promise.all(raw_commits.map(async commit => ({ + commit: commit.sha(), + author_full: commit.author().toString(), + author_name: commit.author().name(), + author_email: commit.author().email(), + date: commit.date(), + message: commit.message().replace(/\n/g, ""), + insertions: (await (await commit.getDiff())[0].getStats()).insertions(), + deletions: (await (await commit.getDiff())[0].getStats()).deletions(), + files_changed: (await (await commit.getDiff())[0].getStats()).filesChanged() + }))); + + return await commits; +} + +async function getTimeSinceLatestCommit(base_dir, repo_name) +{ + const repo = await git.Repository.openBare(`${base_dir}/${repo_name}`) + const master_commit = await repo.getMasterCommit(); + + return formatDistance(new Date(), master_commit.date()); +} + +function getRepoFile(base_dir, repo, file) +{ + return new Promise(resolve => + { + fs.readFile(`${base_dir}/${repo}/${file}`, async (err, content) => + { + if(!err) { + resolve(content.toString().replace(/\n/g, "")); + return; + } + resolve(""); + }); + }); +} + +function getRepos(base_dir) +{ + return new Promise((resolve) => + { + fs.readdir(base_dir, (err, dir_content) => + { + if(err) { + resolve({ "error": err }); + return; + } + + dir_content.filter(repo => repo.endsWith(".git")).reduce((acc, repo) => + { + return acc.then((repos) => + { + return getRepoFile(base_dir, repo, "description").then((description) => + { + return getRepoFile(base_dir, repo, "owner").then((owner) => + { + return getTimeSinceLatestCommit(base_dir, repo).then((last_commit_date) => + { + repos[repo.slice(0, -4)] = { "description": description, "owner": owner, "last_updated": last_commit_date }; + return repos; + }); + }); + }); + }); + }, Promise.resolve({})).then((repos) => + { + resolve(repos); + }); + }); + }); +} + +function parseHunkAddDel(hunk) +{ + let new_lines = []; + let deleted_lines = []; + + hunk.forEach((line, index) => + { + if(line.charAt(0) === '+') { + hunk[index] = line.slice(1); + new_lines.push(index); + } + else if(line.charAt(0) === '-') { + hunk[index] = line.slice(1); + deleted_lines.push(index); + } + }); + + return { new: new_lines, deleted: deleted_lines, hunk: hunk.join("\n") }; +} + +async function getCommit(base_dir, repo_name, commit_oid) +{ + repo_name = addRepoDirSuffix(repo_name); + + const repo = await git.Repository.openBare(`${base_dir}/${repo_name}`) + const commit = await repo.getCommit(commit_oid); + const diff = (await commit.getDiff())[0]; + const all_patches = (await diff.toBuf(1)).split('\n'); + + // Get the count of lines for all of patches's headers + const patch_headers = (await diff.toBuf(2)).split('\n'); + const patch_header_data = await patch_headers.reduce((acc, line, index) => + { + return acc.then((arr) => + { + if(/^diff --git/.test(line)) { + arr[0].push(all_patches.indexOf(line)); + + if(arr[2] != undefined) { + arr[1].push(patch_headers.slice(arr[2], index).length); + } + arr[2] = index; + } + else if(index == patch_headers.length - 1 && arr[2] != undefined) { + arr[1].push(patch_headers.slice(arr[2], index).length); + } + return arr; + }); + }, Promise.resolve([ [], [], undefined ])); + + console.log(patch_header_data); + + const patches = await diff.patches(); + const parsed_patches = patches.reduce((acc, patch, patch_index) => + { + return acc.then((arr) => + { + return patch.hunks().then((hunks) => + { + console.log("\n" + patch.newFile().path()); + + const patch_start = patch_header_data[0][patch_index] + patch_header_data[1][patch_index]; + const patch_end = (patch_header_data[0][patch_index + 1] !== undefined) ? patch_header_data[0][patch_index + 1] : all_patches.length - 1; + const patch_content = all_patches.slice(patch_start, patch_end); + + const line_lengths = patch_content.map((line) => line.length).reduce((acc, length) => acc + length); + + if(patch_content.length > 5000 || line_lengths > 5000) { + console.log("Too large!"); + + arr.push({ + from: patch.oldFile().path(), + to: patch.newFile().path(), + additions: patch.lineStats()["total_additions"], + deletions: patch.lineStats()["total_deletions"], + too_large: true, + hunks: null + }); + return arr; + } + + // Go through all of the patch's hunks + // Patches are split into parts of where in the file the change is made. Those parts are called hunks. + return hunks.reduce((acc, hunk, hunk_index) => + { + return acc.then((hunks_data) => + { + const hunk_header = hunk.header(); + const hunk_header_index = patch_content.indexOf(hunk_header.replace(/\n/g, "")); + + if(hunks_data[0] !== undefined) { + const prev_hunk = hunks[hunk_index - 1]; + hunks_data[1].push(Object.assign({ + new_start: prev_hunk.newStart(), + new_lines: prev_hunk.newLines(), + old_start: prev_hunk.oldStart(), + old_lines: prev_hunk.oldLines(), + }, parseHunkAddDel(patch_content.slice(hunks_data[0], hunk_header_index)))); + + hunks_data[2] = hunks_data + patch_content.slice(hunks_data[0], hunk_header_index).length; + } + + hunks_data[0] = hunk_header_index; + return hunks_data; + }); + }, Promise.resolve([ undefined, [], 0 ])).then((hunks_data) => + { + const prev_hunk = hunks[hunks.length - 1]; + hunks_data[1].push(Object.assign({ + new_start: prev_hunk.newStart(), + new_lines: prev_hunk.newLines(), + old_start: prev_hunk.oldStart(), + old_lines: prev_hunk.oldLines(), + }, parseHunkAddDel(patch_content.slice(hunks_data[0], patch_end)))); + + arr.push({ + from: patch.oldFile().path(), + to: patch.isDeleted() ? "/dev/null" : patch.newFile().path(), + additions: patch.lineStats()["total_additions"], + deletions: patch.lineStats()["total_deletions"], + too_large: false, + hunks: hunks_data[1] + }); + + return arr; + }); + }); + }); + }, Promise.resolve([])); + + return { + hash: commit.sha(), + author: commit.author().toString(), + message: commit.message(), + date: commit.date(), + patches: await parsed_patches + }; +} + +module.exports.getLog = getLog; +module.exports.getRepos = getRepos; +module.exports.getRepoFile = getRepoFile; +module.exports.getCommit = getCommit; \ No newline at end of file diff --git a/src/api/sanitization.js b/src/api/sanitization.js new file mode 100644 index 0000000..95c8810 --- /dev/null +++ b/src/api/sanitization.js @@ -0,0 +1,14 @@ +function sanitizeRepoName(dirty) +{ + const valid_repo_name = /^[a-zA-Z0-9\.\-_]+$/; + return valid_repo_name.test(dirty); +} + +function sanitizeCommitID(dirty) +{ + const valid_commit_id = /^[a-fA-F0-9]{40}$/; + return valid_commit_id.test(dirty); +} + +module.exports.sanitizeRepoName = sanitizeRepoName; +module.exports.sanitizeCommitID = sanitizeCommitID; \ No newline at end of file diff --git a/src/api/v1.js b/src/api/v1.js new file mode 100644 index 0000000..7920afc --- /dev/null +++ b/src/api/v1.js @@ -0,0 +1,74 @@ +const express = require("express"); +const git = require("./git"); +const sanitization = require("./sanitization"); + +const router = express.Router(); + +router.get("/info", function(req, res) +{ + res.json({ "data": req.settings }); + return; +}); + +router.get("/repos", async function(req, res) +{ + let repos = await git.getRepos(req.settings["base_dir"]); + + if(repos["error"]) { + res.status(500).send("Internal server error!"); + return; + } + + res.json({ "data": repos }); +}); + +router.use("/repos/:repo", async function(req, res, next) +{ + if(!sanitization.sanitizeRepoName(req.params.repo)) { + res.status(400).json({ "error": "Unacceptable git repository name!" }); + return; + } + next(); +}); + +router.get("/repos/:repo", async function(req, res) +{ + const repo = `${req.params.repo}.git`; + const desc = await git.getRepoFile(req.settings["base_dir"], repo, "description"); + + res.json({ "data": { "name": req.params.repo, "description": desc } }); +}); + +router.get("/repos/:repo/log", async function(req, res) +{ + const repo = `${req.params.repo}.git`; + const log = await git.getLog(req.settings["base_dir"], repo); + + if(log["error"]) { + if(typeof log["error"] === "string") { + res.status(500).json({ "error": log["error"] }); + return; + } + switch(log["error"]) { + case 404: + res.status(404).json({ "error": "Git repository doesn't exist!" }); + return; + } + return; + } + res.json({ data: log }); +}); + +router.get("/repos/:repo/log/:commit", async function(req, res) +{ + if(!sanitization.sanitizeCommitID(req.params.commit)) { + res.status(400).json({ "error": "Unacceptable commit id!" }); + return; + } + + const commit = await git.getCommit(req.settings["base_dir"], req.params.repo, req.params.commit); + + res.json({ data: commit }); +}); + +module.exports = router; \ No newline at end of file diff --git a/src/app.html b/src/app.html deleted file mode 100644 index 348ca45..0000000 --- a/src/app.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - -
- - - \ No newline at end of file diff --git a/src/app.js b/src/app.js index 1b43bbe..3c5ecd9 100644 --- a/src/app.js +++ b/src/app.js @@ -1,7 +1,96 @@ -import { createApp } from "vue/dist/vue.esm-bundler"; -import App from "./App.vue"; -import router from "./router"; +const express = require("express"); +const api = require("./api/v1"); +const yaml = require('js-yaml'); +const fs = require('fs'); +const { exit } = require("process"); -createApp(App) - .use(router) - .mount("#app"); \ No newline at end of file +const settings = yaml.load(fs.readFileSync(__dirname + "/../settings.yml", 'utf8')); +const settings_keys = Object.keys(settings); + +const mandatory_settings = [ "host", "port", "title", "about", "base_dir" ]; + +const mandatory_not_included = settings_keys.filter(x => !mandatory_settings.includes(x)); +const settings_not_included = mandatory_settings.filter(x => !settings_keys.includes(x)); + +if(settings_not_included.length !== 0) { + console.log(`Error: settings.yml is missing ${(mandatory_not_included.length > 1) ? "keys" : "key"}:`); + console.log(settings_not_included.join(", ")); + exit(1); +} +if(mandatory_not_included.length !== 0) { + console.log(`Error: settings.yml includes ${(mandatory_not_included.length > 1) ? "pointless keys" : "a pointless key"}:`); + console.log(mandatory_not_included.join(", ")); + exit(1); +} + +const dist_dir = __dirname + "/../dist"; + +const app = express(); + +app.get(/.*\.(css|js|ico)$/, (req, res, next) => +{ + fs.access(`${dist_dir}${req.path}`, err => + { + if(err) { + next(); + return; + } + res.sendFile(`${req.path}`, { root: dist_dir }); + }); +}); + +app.use("/api/v1", (req, res, next) => +{ + req.settings = settings; + next(); +}, api); + +app.get("/", (req, res) => +{ + res.sendFile(`app.html`, { root: dist_dir }); +}); + +const repo_router = express.Router(); + +app.use("/:repo([a-zA-Z0-9-_]+)", (req, res, next) => +{ + console.log("AAAA"); + fs.readdir(settings["base_dir"], (err, dir_content) => + { + if(err) { + res.status(404).send("404: Not found"); + return; + } + + dir_content = dir_content.filter(repo => repo.endsWith(".git")); + if(!dir_content.includes(req.params.repo + ".git")) { + res.status(404).send("404: Not found"); + return; + } + else { + next(); + } + }); +}, repo_router); + +repo_router.get(/$|log$|refs$|tree$/, (req, res) => +{ + res.sendFile(`app.html`, { root: dist_dir }); +}); + +repo_router.get(/\/log\/[a-fA-F0-9]{40}$/, (req, res) => +{ + res.sendFile(`app.html`, { root: dist_dir }); +}) + +repo_router.use((req, res) => +{ + res.status(404).send("404: Not found eeee"); +}); + +app.use((req, res) => +{ + res.status(404).send("404: Not found"); +}) + +app.listen(settings["port"], settings["host"], () => console.log(`App is running on ${settings["host"]}:${settings["port"]}`)); \ No newline at end of file diff --git a/src/components/BaseBackButton.vue b/src/components/BaseBackButton.vue deleted file mode 100644 index 64b1286..0000000 --- a/src/components/BaseBackButton.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - \ No newline at end of file diff --git a/src/components/CommitPatch.vue b/src/components/CommitPatch.vue deleted file mode 100644 index 53edeb9..0000000 --- a/src/components/CommitPatch.vue +++ /dev/null @@ -1,149 +0,0 @@ - \ No newline at end of file diff --git a/src/components/HomeHeader.vue b/src/components/HomeHeader.vue deleted file mode 100644 index f0366a3..0000000 --- a/src/components/HomeHeader.vue +++ /dev/null @@ -1,39 +0,0 @@ - - - \ No newline at end of file diff --git a/src/components/RepositoryHeader.vue b/src/components/RepositoryHeader.vue deleted file mode 100644 index b0db4f9..0000000 --- a/src/components/RepositoryHeader.vue +++ /dev/null @@ -1,50 +0,0 @@ - - - \ No newline at end of file diff --git a/src/components/RepositoryNavbar.vue b/src/components/RepositoryNavbar.vue deleted file mode 100644 index a1e1002..0000000 --- a/src/components/RepositoryNavbar.vue +++ /dev/null @@ -1,32 +0,0 @@ - - - \ No newline at end of file diff --git a/src/frontend/App.vue b/src/frontend/App.vue new file mode 100644 index 0000000..cbdce56 --- /dev/null +++ b/src/frontend/App.vue @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/src/frontend/app.html b/src/frontend/app.html new file mode 100644 index 0000000..348ca45 --- /dev/null +++ b/src/frontend/app.html @@ -0,0 +1,11 @@ + + + + + + + +
+ + + \ No newline at end of file diff --git a/src/frontend/app.js b/src/frontend/app.js new file mode 100644 index 0000000..1b43bbe --- /dev/null +++ b/src/frontend/app.js @@ -0,0 +1,7 @@ +import { createApp } from "vue/dist/vue.esm-bundler"; +import App from "./App.vue"; +import router from "./router"; + +createApp(App) + .use(router) + .mount("#app"); \ No newline at end of file diff --git a/src/frontend/components/BaseBackButton.vue b/src/frontend/components/BaseBackButton.vue new file mode 100644 index 0000000..64b1286 --- /dev/null +++ b/src/frontend/components/BaseBackButton.vue @@ -0,0 +1,25 @@ + + + \ No newline at end of file diff --git a/src/frontend/components/CommitPatch.vue b/src/frontend/components/CommitPatch.vue new file mode 100644 index 0000000..53edeb9 --- /dev/null +++ b/src/frontend/components/CommitPatch.vue @@ -0,0 +1,149 @@ + \ No newline at end of file diff --git a/src/frontend/components/HomeHeader.vue b/src/frontend/components/HomeHeader.vue new file mode 100644 index 0000000..f0366a3 --- /dev/null +++ b/src/frontend/components/HomeHeader.vue @@ -0,0 +1,39 @@ + + + \ No newline at end of file diff --git a/src/frontend/components/RepositoryHeader.vue b/src/frontend/components/RepositoryHeader.vue new file mode 100644 index 0000000..b0db4f9 --- /dev/null +++ b/src/frontend/components/RepositoryHeader.vue @@ -0,0 +1,50 @@ + + + \ No newline at end of file diff --git a/src/frontend/components/RepositoryNavbar.vue b/src/frontend/components/RepositoryNavbar.vue new file mode 100644 index 0000000..a1e1002 --- /dev/null +++ b/src/frontend/components/RepositoryNavbar.vue @@ -0,0 +1,32 @@ + + + \ No newline at end of file diff --git a/src/frontend/router/index.js b/src/frontend/router/index.js new file mode 100644 index 0000000..68762cd --- /dev/null +++ b/src/frontend/router/index.js @@ -0,0 +1,39 @@ +import { createRouter, createWebHistory } from "vue-router"; +import Home from "../views/Home"; +import Repository from "../views/Repository"; +import RepositoryLog from "../views/RepositoryLog"; +import RepositoryCommit from "../views/RepositoryCommit"; + +const routes = [ + { + name: "Home", + path: "/", + component: Home + }, + { + name: "Repository", + path: '/:repo([a-zA-Z0-9\\.\\-_]+)', + component: Repository, + props: route => ({ repository: route.params.repo }), + children: [ + { + name: "Repository Log", + path: "log", + component: RepositoryLog, + }, + { + name: "Commit", + path: "log/:commit([a-fA-F0-9]{40}$)", + component: RepositoryCommit, + props: route => ({ commit: route.params.commit }) + } + ] + } +] + +const router = createRouter({ + history: createWebHistory(process.env.BASE_URL), + routes +}); + +export default router; \ No newline at end of file diff --git a/src/frontend/scss/abstracts/_colors.scss b/src/frontend/scss/abstracts/_colors.scss new file mode 100644 index 0000000..d7c43f5 --- /dev/null +++ b/src/frontend/scss/abstracts/_colors.scss @@ -0,0 +1,9 @@ +$primary: #023E8A; +$primary-light: #0096C7; +$secondary: #F48C06; +$success: #40916C; +$new: #06d6a0; +$danger: #D00000; +$text: #ffffff; +$text-gray: #6c757d; +$background: #121212; \ No newline at end of file diff --git a/src/frontend/scss/abstracts/_fonts.scss b/src/frontend/scss/abstracts/_fonts.scss new file mode 100644 index 0000000..6af5233 --- /dev/null +++ b/src/frontend/scss/abstracts/_fonts.scss @@ -0,0 +1,5 @@ +@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Oxygen:wght@300&display=swap'); + +$title: 'Oxygen', sans-serif; +$primary: 'Open Sans', sans-serif; \ No newline at end of file diff --git a/src/frontend/scss/style.scss b/src/frontend/scss/style.scss new file mode 100644 index 0000000..77fee90 --- /dev/null +++ b/src/frontend/scss/style.scss @@ -0,0 +1,284 @@ +@use "abstracts/colors"; +@use "abstracts/fonts"; + +@import "../../../node_modules/bootstrap/scss/functions"; +@import "../../../node_modules/bootstrap/scss/variables"; +@import "../../../node_modules/bootstrap/scss/mixins"; + +$theme-colors: ( + "primary": colors.$primary, + "secondary": colors.$secondary, + "success": colors.$success, + "info": $info, + "warning": $warning, + "danger": colors.$danger, + "light": $light, + "dark": $dark +); + +$font-size-base: 0.75rem; + +$h1-font-size: $font-size-base * 2.5; +$h2-font-size: $font-size-base * 2; +$h3-font-size: $font-size-base * 1.75; +$h4-font-size: $font-size-base * 1.5; +$h5-font-size: $font-size-base * 1.125; +$h6-font-size: $font-size-base; + +$font-sizes: ( + 1: $h1-font-size, + 2: $h2-font-size, + 3: $h3-font-size, + 4: $h4-font-size, + 5: $h5-font-size, + 6: $h6-font-size +); + +$navbar-nav-link-padding-x: 0.5rem; + +@import "../../../node_modules/bootstrap/scss/breadcrumb"; +@import "../../../node_modules/bootstrap/scss/utilities"; +@import "../../../node_modules/bootstrap/scss/utilities/api"; +@import "../../../node_modules/bootstrap/scss/nav"; +@import "../../../node_modules/bootstrap/scss/navbar"; + +$table-cell-padding-x: 1rem; +$table-cell-padding-y: 0.2rem; + +$table-variants: ( + "primary": shift-color($primary, $table-bg-scale), + "secondary": shift-color($secondary, $table-bg-scale), + "success": shift-color($success, $table-bg-scale), + "info": shift-color($info, $table-bg-scale), + "warning": shift-color($warning, $table-bg-scale), + "danger": shift-color($danger, $table-bg-scale), + "light": $light, + "dark": colors.$background, +); + +@import "../../../node_modules/bootstrap/scss/tables"; + +@import "../../../node_modules/bootstrap/scss/containers"; +@import "../../../node_modules/bootstrap/scss/grid"; + +@import "../../../node_modules/highlight.js/scss/srcery.scss"; + +body { + background-color: colors.$background; + color: colors.$text; + font-family: fonts.$primary; + margin: 0px; +} + +ul { + list-style-type: none; + padding: 0; +} + +li { + margin-bottom: 25px; + div { + h2 { + margin: 0px; + } + } +} + +p { + margin: 0px; +} + +#title { + font-family: fonts.$title; + font-weight: 300; + line-height: 0.6; +} + +#about { + font-weight: 300; + padding-left: 1px; +} + +#projects-search { + align-items: center; + form { + display: flex; + align-items: center; + height: 35px; + input[type=search] { + margin-right: 15px; + } + } +} + +#repos { + margin-top: 25px; +} + +.repo-last-updated { + display: block; + font-weight: 300; + font-style: italic; +} + +input[type=submit] { + background-color: colors.$primary; + color: colors.$text; + font-size: 1rem; + border: 0px; + border-radius: 7px; + padding: 8px 15px 8px 15px; +} + +a { + color: colors.$text; + text-decoration: none; + &:hover { + color: colors.$primary-light; + } +} + +.breadcrumb { + li { + margin-bottom: 0.5rem; + } +} + +#commit-info { + margin-bottom: 2rem; + tbody tr { + td { + padding: 0px; + padding-right: 10px; + } + } +} + +.commit-file { + margin-bottom: 50px; + table { + padding-top: 15px; + tbody tr td { + padding: 0px; + padding-left: 8px; + vertical-align: top; + &:nth-child(2) { + padding-right: 7px; + } + &:nth-child(3) { + padding-right: 15px; + } + } + } +} + +.commit-file-add-del { + margin-left: auto; + margin-right: 23px; + span { + margin-right: 10px !important; + font-weight: 700; + &:nth-child(1) { + color: colors.$new; + } + } +} + +.commit-file-pos-change { + color: colors.$text-gray; +} + +.commit-file-no-newline { + color: colors.$text-gray; +} + +.line-new { + color: colors.$new; +} +.line-deleted { + color: colors.$danger; +} + +.line-unchanged { + color: colors.$text-gray; +} + +.line-highlight-new { + border-right: 1px solid colors.$new; +} +.line-highlight-deleted { + border-right: 1px solid colors.$danger; +} + +code { + white-space: pre-wrap; + word-wrap: anywhere; +} + +.commit-file-header { + display: flex; + background-color: rgba($color: #ffffff, $alpha: 0.08); + padding: 10px; + span { + margin-right: 30px; + &:nth-child(2) { + color: colors.$danger; + } + } +} + +#back:hover { + fill: colors.$primary-light; +} + +#navbar { + line-height: 0; +} + +th { + text-align: start; +} + +.commit-info-title { + color: colors.$secondary; + padding-right: 30px; + width: 20px; +} + +.patch-too-large { + font-weight: 600; +} + + +@include media-breakpoint-down(sm) { + .commit-file table tbody tr td { + padding-left: 4px; + &:nth-child(2) { + padding-right: 4px; + } + &:nth-child(3) { + padding-right: 5px; + } + } + .table > :not(caption) > * > * { + padding: 0.1rem; + } +} + +@media (max-width: 1200px) { + .fs-1 { + font-size: calc(1.375rem + 0.667vw) !important; + } + .fs-2 { + font-size: calc(1.325rem + 1.584vw) !important; + } + .fs-3 { + font-size: calc(1.3rem + 0.017vw) !important; + } + .fs-4 { + font-size: calc(0.82rem + 0.4vw) !important; + } + .fs-5 { + font-size: calc(0.65rem + 0.25vw) !important; + } +} \ No newline at end of file diff --git a/src/frontend/util/hljs-languages.js b/src/frontend/util/hljs-languages.js new file mode 100644 index 0000000..c8576e0 --- /dev/null +++ b/src/frontend/util/hljs-languages.js @@ -0,0 +1,45 @@ +const languages = [ + { "name": "arduino", "extensions": [ ".ino" ]}, + { "name": "actionscript", "extensions": [ ".as" ]}, + { "name": "bash", "extensions": [ ".sh", ".zsh" ]}, + { "name": "csharp", "extensions": [ ".cs" ]}, + { "name": "c", "extensions": [ ".c", ".h" ]}, + { "name": "cpp", "extensions": [ ".cpp", ".hpp" ]}, + { "name": "cmake", "extensions": [ "cmake.in" ]}, + { "name": "css", "extensions": [ ".css" ]}, + { "name": "d", "extensions": [ ".d" ]}, + { "name": "dos", "extensions": [ ".bat", ".cmd" ]}, + { "name": "dockerfile", "extensions": [ "dockerfile", "Dockerfile" ]}, + { "name": "go", "extensions": [ ".go" ]}, + { "name": "gradle", "extensions": [ ".gradle" ]}, + { "name": "xml", "extensions": [ ".xml", ".html", ".xhtml", ".rss", ".atom", ".xjb", ".xsd", ".xsl", ".plist", ".svg" ]}, + { "name": "haskell", "extensions": [ ".hs" ]}, + { "name": "ini", "extensions": [ ".ini", ".toml" ]}, + { "name": "json", "extensions": [ ".json" ]}, + { "name": "java", "extensions": [ ".java", ".jsp" ]}, + { "name": "javascript", "extensions": [ ".js", ".jsx" ]}, + { "name": "kotlin", "extensions": [ ".kt" ]}, + { "name": "lua", "extensions": [ ".lua" ]}, + { "name": "makefile", "extensions": [ "makefile", "Makefile" ]}, + { "name": "markdown", "extensions": [ ".md" ]}, + { "name": "objectivec", "extensions": [ ".m", ".mm", ".M" ]}, + { "name": "php", "extensions": [ ".php" ]}, + { "name": "perl", "extensions": [ ".pl", ".pm" ]}, + { "name": "plaintext", "extensions": [ ".txt" ]}, + { "name": "pgsql", "extensions": [ ".pgsql" ]}, + { "name": "powershell", "extensions": [ ".ps", ".ps1" ]}, + { "name": "python", "extensions": [ ".py" ]}, + { "name": "ruby", "extensions": [ ".rb" ]}, + { "name": "rust", "extensions": [ ".rs" ]}, + { "name": "scss", "extensions": [ ".scss" ]}, + { "name": "sql", "extensions": [ ".sql" ]}, + { "name": "swift", "extensions": [ ".swift" ]}, + { "name": "typescript", "extensions": [ ".ts" ]}, + { "name": "vbnet", "extensions": [ ".vb" ]}, + { "name": "vba", "extensions": [ ".vba" ]}, + { "name": "vbscript", "extensions": [ ".vbs" ]}, + { "name": "vim", "extensions": [ ".vim" ]}, + { "name": "yml", "extensions": [ ".yml" ]} +]; + +export default languages; \ No newline at end of file diff --git a/src/frontend/views/Home.vue b/src/frontend/views/Home.vue new file mode 100644 index 0000000..79ec4ab --- /dev/null +++ b/src/frontend/views/Home.vue @@ -0,0 +1,62 @@ + + + \ No newline at end of file diff --git a/src/frontend/views/Repository.vue b/src/frontend/views/Repository.vue new file mode 100644 index 0000000..8863529 --- /dev/null +++ b/src/frontend/views/Repository.vue @@ -0,0 +1,29 @@ + + + \ No newline at end of file diff --git a/src/frontend/views/RepositoryCommit.vue b/src/frontend/views/RepositoryCommit.vue new file mode 100644 index 0000000..283ed69 --- /dev/null +++ b/src/frontend/views/RepositoryCommit.vue @@ -0,0 +1,98 @@ + + + diff --git a/src/frontend/views/RepositoryLog.vue b/src/frontend/views/RepositoryLog.vue new file mode 100644 index 0000000..399fc78 --- /dev/null +++ b/src/frontend/views/RepositoryLog.vue @@ -0,0 +1,91 @@ + + + \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js deleted file mode 100644 index 68762cd..0000000 --- a/src/router/index.js +++ /dev/null @@ -1,39 +0,0 @@ -import { createRouter, createWebHistory } from "vue-router"; -import Home from "../views/Home"; -import Repository from "../views/Repository"; -import RepositoryLog from "../views/RepositoryLog"; -import RepositoryCommit from "../views/RepositoryCommit"; - -const routes = [ - { - name: "Home", - path: "/", - component: Home - }, - { - name: "Repository", - path: '/:repo([a-zA-Z0-9\\.\\-_]+)', - component: Repository, - props: route => ({ repository: route.params.repo }), - children: [ - { - name: "Repository Log", - path: "log", - component: RepositoryLog, - }, - { - name: "Commit", - path: "log/:commit([a-fA-F0-9]{40}$)", - component: RepositoryCommit, - props: route => ({ commit: route.params.commit }) - } - ] - } -] - -const router = createRouter({ - history: createWebHistory(process.env.BASE_URL), - routes -}); - -export default router; \ No newline at end of file diff --git a/src/scss/abstracts/_colors.scss b/src/scss/abstracts/_colors.scss deleted file mode 100644 index d7c43f5..0000000 --- a/src/scss/abstracts/_colors.scss +++ /dev/null @@ -1,9 +0,0 @@ -$primary: #023E8A; -$primary-light: #0096C7; -$secondary: #F48C06; -$success: #40916C; -$new: #06d6a0; -$danger: #D00000; -$text: #ffffff; -$text-gray: #6c757d; -$background: #121212; \ No newline at end of file diff --git a/src/scss/abstracts/_fonts.scss b/src/scss/abstracts/_fonts.scss deleted file mode 100644 index 6af5233..0000000 --- a/src/scss/abstracts/_fonts.scss +++ /dev/null @@ -1,5 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700&display=swap'); -@import url('https://fonts.googleapis.com/css2?family=Oxygen:wght@300&display=swap'); - -$title: 'Oxygen', sans-serif; -$primary: 'Open Sans', sans-serif; \ No newline at end of file diff --git a/src/scss/style.scss b/src/scss/style.scss deleted file mode 100644 index 89ea349..0000000 --- a/src/scss/style.scss +++ /dev/null @@ -1,284 +0,0 @@ -@use "abstracts/colors"; -@use "abstracts/fonts"; - -@import "../../node_modules/bootstrap/scss/functions"; -@import "../../node_modules/bootstrap/scss/variables"; -@import "../../node_modules/bootstrap/scss/mixins"; - -$theme-colors: ( - "primary": colors.$primary, - "secondary": colors.$secondary, - "success": colors.$success, - "info": $info, - "warning": $warning, - "danger": colors.$danger, - "light": $light, - "dark": $dark -); - -$font-size-base: 0.75rem; - -$h1-font-size: $font-size-base * 2.5; -$h2-font-size: $font-size-base * 2; -$h3-font-size: $font-size-base * 1.75; -$h4-font-size: $font-size-base * 1.5; -$h5-font-size: $font-size-base * 1.125; -$h6-font-size: $font-size-base; - -$font-sizes: ( - 1: $h1-font-size, - 2: $h2-font-size, - 3: $h3-font-size, - 4: $h4-font-size, - 5: $h5-font-size, - 6: $h6-font-size -); - -$navbar-nav-link-padding-x: 0.5rem; - -@import "../../node_modules/bootstrap/scss/breadcrumb"; -@import "../../node_modules/bootstrap/scss/utilities"; -@import "../../node_modules/bootstrap/scss/utilities/api"; -@import "../../node_modules/bootstrap/scss/nav"; -@import "../../node_modules/bootstrap/scss/navbar"; - -$table-cell-padding-x: 1rem; -$table-cell-padding-y: 0.2rem; - -$table-variants: ( - "primary": shift-color($primary, $table-bg-scale), - "secondary": shift-color($secondary, $table-bg-scale), - "success": shift-color($success, $table-bg-scale), - "info": shift-color($info, $table-bg-scale), - "warning": shift-color($warning, $table-bg-scale), - "danger": shift-color($danger, $table-bg-scale), - "light": $light, - "dark": colors.$background, -); - -@import "../../node_modules/bootstrap/scss/tables"; - -@import "../../node_modules/bootstrap/scss/containers"; -@import "../../node_modules/bootstrap/scss/grid"; - -@import "../../node_modules/highlight.js/scss/srcery.scss"; - -body { - background-color: colors.$background; - color: colors.$text; - font-family: fonts.$primary; - margin: 0px; -} - -ul { - list-style-type: none; - padding: 0; -} - -li { - margin-bottom: 25px; - div { - h2 { - margin: 0px; - } - } -} - -p { - margin: 0px; -} - -#title { - font-family: fonts.$title; - font-weight: 300; - line-height: 0.6; -} - -#about { - font-weight: 300; - padding-left: 1px; -} - -#projects-search { - align-items: center; - form { - display: flex; - align-items: center; - height: 35px; - input[type=search] { - margin-right: 15px; - } - } -} - -#repos { - margin-top: 25px; -} - -.repo-last-updated { - display: block; - font-weight: 300; - font-style: italic; -} - -input[type=submit] { - background-color: colors.$primary; - color: colors.$text; - font-size: 1rem; - border: 0px; - border-radius: 7px; - padding: 8px 15px 8px 15px; -} - -a { - color: colors.$text; - text-decoration: none; - &:hover { - color: colors.$primary-light; - } -} - -.breadcrumb { - li { - margin-bottom: 0.5rem; - } -} - -#commit-info { - margin-bottom: 2rem; - tbody tr { - td { - padding: 0px; - padding-right: 10px; - } - } -} - -.commit-file { - margin-bottom: 50px; - table { - padding-top: 15px; - tbody tr td { - padding: 0px; - padding-left: 8px; - vertical-align: top; - &:nth-child(2) { - padding-right: 7px; - } - &:nth-child(3) { - padding-right: 15px; - } - } - } -} - -.commit-file-add-del { - margin-left: auto; - margin-right: 23px; - span { - margin-right: 10px !important; - font-weight: 700; - &:nth-child(1) { - color: colors.$new; - } - } -} - -.commit-file-pos-change { - color: colors.$text-gray; -} - -.commit-file-no-newline { - color: colors.$text-gray; -} - -.line-new { - color: colors.$new; -} -.line-deleted { - color: colors.$danger; -} - -.line-unchanged { - color: colors.$text-gray; -} - -.line-highlight-new { - border-right: 1px solid colors.$new; -} -.line-highlight-deleted { - border-right: 1px solid colors.$danger; -} - -code { - white-space: pre-wrap; - word-wrap: anywhere; -} - -.commit-file-header { - display: flex; - background-color: rgba($color: #ffffff, $alpha: 0.08); - padding: 10px; - span { - margin-right: 30px; - &:nth-child(2) { - color: colors.$danger; - } - } -} - -#back:hover { - fill: colors.$primary-light; -} - -#navbar { - line-height: 0; -} - -th { - text-align: start; -} - -.commit-info-title { - color: colors.$secondary; - padding-right: 30px; - width: 20px; -} - -.patch-too-large { - font-weight: 600; -} - - -@include media-breakpoint-down(sm) { - .commit-file table tbody tr td { - padding-left: 4px; - &:nth-child(2) { - padding-right: 4px; - } - &:nth-child(3) { - padding-right: 5px; - } - } - .table > :not(caption) > * > * { - padding: 0.1rem; - } -} - -@media (max-width: 1200px) { - .fs-1 { - font-size: calc(1.375rem + 0.667vw) !important; - } - .fs-2 { - font-size: calc(1.325rem + 1.584vw) !important; - } - .fs-3 { - font-size: calc(1.3rem + 0.017vw) !important; - } - .fs-4 { - font-size: calc(0.82rem + 0.4vw) !important; - } - .fs-5 { - font-size: calc(0.65rem + 0.25vw) !important; - } -} \ No newline at end of file diff --git a/src/util/hljs-languages.js b/src/util/hljs-languages.js deleted file mode 100644 index c8576e0..0000000 --- a/src/util/hljs-languages.js +++ /dev/null @@ -1,45 +0,0 @@ -const languages = [ - { "name": "arduino", "extensions": [ ".ino" ]}, - { "name": "actionscript", "extensions": [ ".as" ]}, - { "name": "bash", "extensions": [ ".sh", ".zsh" ]}, - { "name": "csharp", "extensions": [ ".cs" ]}, - { "name": "c", "extensions": [ ".c", ".h" ]}, - { "name": "cpp", "extensions": [ ".cpp", ".hpp" ]}, - { "name": "cmake", "extensions": [ "cmake.in" ]}, - { "name": "css", "extensions": [ ".css" ]}, - { "name": "d", "extensions": [ ".d" ]}, - { "name": "dos", "extensions": [ ".bat", ".cmd" ]}, - { "name": "dockerfile", "extensions": [ "dockerfile", "Dockerfile" ]}, - { "name": "go", "extensions": [ ".go" ]}, - { "name": "gradle", "extensions": [ ".gradle" ]}, - { "name": "xml", "extensions": [ ".xml", ".html", ".xhtml", ".rss", ".atom", ".xjb", ".xsd", ".xsl", ".plist", ".svg" ]}, - { "name": "haskell", "extensions": [ ".hs" ]}, - { "name": "ini", "extensions": [ ".ini", ".toml" ]}, - { "name": "json", "extensions": [ ".json" ]}, - { "name": "java", "extensions": [ ".java", ".jsp" ]}, - { "name": "javascript", "extensions": [ ".js", ".jsx" ]}, - { "name": "kotlin", "extensions": [ ".kt" ]}, - { "name": "lua", "extensions": [ ".lua" ]}, - { "name": "makefile", "extensions": [ "makefile", "Makefile" ]}, - { "name": "markdown", "extensions": [ ".md" ]}, - { "name": "objectivec", "extensions": [ ".m", ".mm", ".M" ]}, - { "name": "php", "extensions": [ ".php" ]}, - { "name": "perl", "extensions": [ ".pl", ".pm" ]}, - { "name": "plaintext", "extensions": [ ".txt" ]}, - { "name": "pgsql", "extensions": [ ".pgsql" ]}, - { "name": "powershell", "extensions": [ ".ps", ".ps1" ]}, - { "name": "python", "extensions": [ ".py" ]}, - { "name": "ruby", "extensions": [ ".rb" ]}, - { "name": "rust", "extensions": [ ".rs" ]}, - { "name": "scss", "extensions": [ ".scss" ]}, - { "name": "sql", "extensions": [ ".sql" ]}, - { "name": "swift", "extensions": [ ".swift" ]}, - { "name": "typescript", "extensions": [ ".ts" ]}, - { "name": "vbnet", "extensions": [ ".vb" ]}, - { "name": "vba", "extensions": [ ".vba" ]}, - { "name": "vbscript", "extensions": [ ".vbs" ]}, - { "name": "vim", "extensions": [ ".vim" ]}, - { "name": "yml", "extensions": [ ".yml" ]} -]; - -export default languages; \ No newline at end of file diff --git a/src/views/Home.vue b/src/views/Home.vue deleted file mode 100644 index 79ec4ab..0000000 --- a/src/views/Home.vue +++ /dev/null @@ -1,62 +0,0 @@ - - - \ No newline at end of file diff --git a/src/views/Repository.vue b/src/views/Repository.vue deleted file mode 100644 index 8863529..0000000 --- a/src/views/Repository.vue +++ /dev/null @@ -1,29 +0,0 @@ - - - \ No newline at end of file diff --git a/src/views/RepositoryCommit.vue b/src/views/RepositoryCommit.vue deleted file mode 100644 index 283ed69..0000000 --- a/src/views/RepositoryCommit.vue +++ /dev/null @@ -1,98 +0,0 @@ - - - diff --git a/src/views/RepositoryLog.vue b/src/views/RepositoryLog.vue deleted file mode 100644 index 399fc78..0000000 --- a/src/views/RepositoryLog.vue +++ /dev/null @@ -1,91 +0,0 @@ - - - \ No newline at end of file -- cgit v1.2.3-18-g5258