Skip to content
Merged

Dev #17

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.DS_Store
assets/.DS_Store

node_modules/
18 changes: 18 additions & 0 deletions linkinator.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"skip": [
"^mailto:",
"^#",
"^https://icons8\\.com/",
"^https://github\\.com/safesploitOrg/\\.dotfiles(?:[/?#]|$)",
"^https://github\\.com/safesploitOrg/ansible-configs(?:[/?#]|$)",
"^https://github\\.com/safesploitOrg/confluence-mirror(?:[/?#]|$)",
"^https://github\\.com/safesploitOrg/dns-configs(?:[/?#]|$)",
"^https://github\\.com/safesploitOrg/hugo-static(?:[/?#]|$)",
"^https://github\\.com/safesploitOrg/iam-homelab(?:[/?#]|$)",
"^https://github\\.com/safesploitOrg/k8s-configs(?:[/?#]|$)",
"^https://github\\.com/safesploitOrg/kickstarter-scripts(?:[/?#]|$)",
"^https://github\\.com/safesploitOrg/network-scripts(?:[/?#]|$)",
"^https://github\\.com/safesploitOrg/project1-ci-cd-test(?:[/?#]|$)",
"^https://github\\.com/safesploitOrg/terraform-configs(?:[/?#]|$)"
]
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"format:check": "prettier --check \"public/**/*.{html,css,js,json}\" \"tests/**/*.js\" \"*.md\"",
"lint:js": "eslint public/assets/js/**/*.js tests/**/*.js",
"lint:html": "html-validate public/index.html",
"check:links": "linkinator public/index.html README.md --recurse --silent --skip \"^mailto:\" --skip \"^#\" --skip \"^https://icons8\\.com/\""
"check:links": "linkinator public/index.html README.md --recurse --silent"
},
"devDependencies": {
"@eslint/js": "^9.28.0",
Expand Down
79 changes: 78 additions & 1 deletion public/assets/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,19 @@ h1 {
}

/* Dropdown Menu */
.header-actions {
display: flex;
justify-content: center;
align-items: flex-start;
flex-wrap: wrap;
gap: 10px;
margin-top: 16px;
}

.dropdown {
position: relative;
display: inline-block;
text-align: left;
}

.dropdown-btn {
Expand All @@ -60,6 +70,17 @@ h1 {
font-size: 0.9em;
}

.dropdown-btn:hover,
.dropdown-btn:focus-visible {
background-color: #0056b3;
}

.dropdown-btn:focus-visible,
.dropdown-content a:focus-visible {
outline: 3px solid #80bdff;
outline-offset: 2px;
}

.dropdown-content {
display: none;
position: absolute;
Expand All @@ -68,7 +89,7 @@ h1 {
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
border-radius: 4px;
padding: 10px 0;
z-index: 1;
z-index: 10;
}

.dropdown-content a {
Expand All @@ -83,11 +104,67 @@ h1 {
background-color: #e8f1fa;
}

.repository-menu {
right: 0;
width: min(380px, calc(100vw - 40px));
max-height: min(70vh, 620px);
overflow-y: auto;
}

.repository-group + .repository-group {
border-top: 1px solid #d8e2ec;
margin-top: 8px;
padding-top: 8px;
}

.repository-group h2 {
color: #4d5966;
font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.04em;
padding: 4px 16px;
text-transform: uppercase;
}

.repository-menu a {
font-size: 0.9rem;
overflow-wrap: anywhere;
}

.repo-note {
color: #6c757d;
font-size: 0.85em;
}

/* Show dropdown on click */
.show {
display: block;
}

@media (max-width: 520px) {
.header-actions {
align-items: stretch;
flex-direction: column;
}

.dropdown,
.dropdown-btn {
width: 100%;
}

.dropdown-btn {
display: flex;
justify-content: space-between;
}

.dropdown-content,
.repository-menu {
left: 0;
right: auto;
width: 100%;
}
}

/* Link Cards */
.links-grid {
display: grid;
Expand Down
Binary file added public/assets/images/network-command-helper.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
89 changes: 36 additions & 53 deletions public/assets/js/script.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
const DROPDOWN_VISIBLE_CLASS = "show";
const DROPDOWN_BUTTON_SELECTOR = ".dropdown-btn";
const DROPDOWN_MENU_ID = "dropdownMenu";
const CURRENT_YEAR_ID = "currentYear";

let isDropdownButtonInitialised = false;
const initialisedDropdownButtons = new WeakSet();
let areGlobalDropdownListenersInitialised = false;

function setCurrentYear() {
Expand All @@ -16,65 +15,51 @@ function setCurrentYear() {
yearElement.textContent = String(new Date().getFullYear());
}

function getDropdownMenu() {
return document.getElementById(DROPDOWN_MENU_ID);
function getDropdownButtons() {
return [...document.querySelectorAll(DROPDOWN_BUTTON_SELECTOR)];
}

function getDropdownButton() {
return document.querySelector(DROPDOWN_BUTTON_SELECTOR);
}

function setDropdownExpanded(isExpanded) {
const dropdownButton = getDropdownButton();

if (!dropdownButton) {
return;
}
function getControlledMenu(dropdownButton) {
const menuId = dropdownButton?.getAttribute("aria-controls");

dropdownButton.setAttribute("aria-expanded", String(isExpanded));
return menuId ? document.getElementById(menuId) : null;
}

function toggleDropdown() {
const dropdownMenu = getDropdownMenu();
function closeDropdowns(exceptButton = null) {
for (const dropdownButton of getDropdownButtons()) {
if (dropdownButton === exceptButton) {
continue;
}

if (!dropdownMenu) {
return;
getControlledMenu(dropdownButton)?.classList.remove(
DROPDOWN_VISIBLE_CLASS,
);
dropdownButton.setAttribute("aria-expanded", "false");
}

const isNowExpanded = dropdownMenu.classList.toggle(DROPDOWN_VISIBLE_CLASS);
setDropdownExpanded(isNowExpanded);
}

function closeDropdown() {
const dropdownMenu = getDropdownMenu();
function toggleDropdown(dropdownButton = getDropdownButtons()[0]) {
const dropdownMenu = getControlledMenu(dropdownButton);

if (!dropdownMenu) {
if (!dropdownButton || !dropdownMenu) {
return;
}

dropdownMenu.classList.remove(DROPDOWN_VISIBLE_CLASS);
setDropdownExpanded(false);
const willOpen = !dropdownMenu.classList.contains(DROPDOWN_VISIBLE_CLASS);
closeDropdowns(dropdownButton);
dropdownMenu.classList.toggle(DROPDOWN_VISIBLE_CLASS, willOpen);
dropdownButton.setAttribute("aria-expanded", String(willOpen));
}

function handleDocumentClick(event) {
const dropdownMenu = getDropdownMenu();
const dropdownButton = getDropdownButton();

if (!dropdownMenu || !dropdownButton) {
return;
}

const clickedInsideMenu = dropdownMenu.contains(event.target);
const clickedButton = dropdownButton.contains(event.target);

if (!clickedInsideMenu && !clickedButton) {
closeDropdown();
if (!event.target.closest?.(".dropdown")) {
closeDropdowns();
}
}

function handleDocumentKeydown(event) {
if (event.key === "Escape") {
closeDropdown();
closeDropdowns();
}
}

Expand All @@ -89,24 +74,22 @@ function initialiseGlobalDropdownListeners() {
areGlobalDropdownListenersInitialised = true;
}

function initialiseDropdownButton() {
const dropdownButton = getDropdownButton();
function initialiseDropdownButtons() {
for (const dropdownButton of getDropdownButtons()) {
if (initialisedDropdownButtons.has(dropdownButton)) {
continue;
}

if (!dropdownButton || isDropdownButtonInitialised) {
return;
dropdownButton.addEventListener("click", () => {
toggleDropdown(dropdownButton);
});
initialisedDropdownButtons.add(dropdownButton);
}

dropdownButton.addEventListener("click", (event) => {
event.stopPropagation();
toggleDropdown();
});

isDropdownButtonInitialised = true;
}

function initialiseSite() {
setCurrentYear();
initialiseDropdownButton();
initialiseDropdownButtons();
initialiseGlobalDropdownListeners();
}

Expand All @@ -122,5 +105,5 @@ if (document.readyState === "loading") {

window.setCurrentYear = setCurrentYear;
window.toggleDropdown = toggleDropdown;
window.closeDropdown = closeDropdown;
window.closeDropdown = closeDropdowns;
window.initialiseSite = initialiseSite;
Loading
Loading