Testing pre-push hook. Added some fonts.
151
.checks/pre-push
Executable file
|
|
@ -0,0 +1,151 @@
|
|||
#!/usr/bin/env bash
|
||||
# Pre-push hook for comprehensive repository checks
|
||||
|
||||
# Fail fast on any error
|
||||
set -euo pipefail
|
||||
|
||||
# Color codes
|
||||
readonly RED='\033[0;31m'
|
||||
readonly GREEN='\033[0;32m'
|
||||
readonly YELLOW='\033[1;33m'
|
||||
readonly NC='\033[0m'
|
||||
|
||||
# Paths
|
||||
readonly REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
|
||||
readonly CONTENT_DIR="${REPO_ROOT}/content"
|
||||
readonly ZENSICAL_CFG_PATH="${REPO_ROOT}/zensical.toml"
|
||||
readonly SITE_DIR="${REPO_ROOT}/deploy"
|
||||
readonly LOG_DIR="${REPO_ROOT}/logs"
|
||||
|
||||
# Logging and error handling
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR] $*${NC}" >&2
|
||||
}
|
||||
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO] $*${NC}"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING] $*${NC}"
|
||||
}
|
||||
|
||||
# Cleanup function
|
||||
cleanup() {
|
||||
if [[ -n "${SERVER_PID:-}" ]] && ps -p "$SERVER_PID" >/dev/null 2>&1; then
|
||||
kill "$SERVER_PID" >/dev/null 2>&1 || true
|
||||
for _ in {1..30}; do
|
||||
ps -p "$SERVER_PID" >/dev/null 2>&1 || break
|
||||
sleep 0.1
|
||||
done
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
# Initialize log directory
|
||||
prepare_log_directory() {
|
||||
rm -rf "$LOG_DIR"
|
||||
mkdir -p "$LOG_DIR"
|
||||
}
|
||||
|
||||
# Vulnerability Scanning
|
||||
run_trivy_scan() {
|
||||
if ! command -v trivy &>/dev/null; then
|
||||
log_warning "Trivy not installed. Skipping vulnerability scan."
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_info "Running Trivy scan..."
|
||||
trivy fs . \
|
||||
--exit-code 1 \
|
||||
--severity CRITICAL,HIGH,MEDIUM,LOW,UNKNOWN \
|
||||
--no-progress \
|
||||
>"$LOG_DIR/trivy.log" 2>&1 || {
|
||||
log_error "Trivy failed. See $LOG_DIR/trivy.log"
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
# Secrets Detection
|
||||
run_trufflehog_scan() {
|
||||
if ! (command -v trufflehog &>/dev/null && command -v jq &>/dev/null); then
|
||||
log_warning "TruffleHog or jq not installed. Skipping secrets scan."
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_info "Running TruffleHog (verified only)..."
|
||||
local tmpf
|
||||
tmpf="$(mktemp)"
|
||||
|
||||
trufflehog filesystem . --json >"$tmpf" 2>"$LOG_DIR/trufflehog.log" || true
|
||||
|
||||
local verified
|
||||
verified="$(jq 'select(.verified==true)' "$tmpf" | wc -l | tr -d ' ')"
|
||||
|
||||
if [[ "$verified" -gt 0 ]]; then
|
||||
cp "$tmpf" "$LOG_DIR/trufflehog-findings.json"
|
||||
log_error "Verified secrets found. See $LOG_DIR/trufflehog-findings.json"
|
||||
rm -f "$tmpf"
|
||||
return 1
|
||||
fi
|
||||
|
||||
rm -f "$tmpf"
|
||||
}
|
||||
|
||||
# Additional security and lint checks
|
||||
run_additional_checks() {
|
||||
# Git Secrets
|
||||
if command -v git-secrets &>/dev/null; then
|
||||
log_info "Running git-secrets scan..."
|
||||
git-secrets --scan >"$LOG_DIR/git-secrets.log" 2>&1 || {
|
||||
log_error "git-secrets detected potential secrets. See $LOG_DIR/git-secrets.log"
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
|
||||
# Python Security (Bandit)
|
||||
if command -v bandit &>/dev/null; then
|
||||
log_info "Running Bandit Python security scan..."
|
||||
local py_files
|
||||
py_files="$(find . -type f -name "*.py")"
|
||||
if [[ -n "$py_files" ]]; then
|
||||
# shellcheck disable=SC2086
|
||||
bandit -r $py_files -n 5 -lll -f json -o "$LOG_DIR/bandit.json" 2>"$LOG_DIR/bandit.log" || {
|
||||
log_error "Bandit issues found. See $LOG_DIR/bandit.log"
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
fi
|
||||
|
||||
# Dependabot-like checks
|
||||
if command -v npm &>/dev/null && [[ -f package.json ]]; then
|
||||
log_info "Running npm audit..."
|
||||
npm audit --audit-level=high >"$LOG_DIR/npm-audit.log" 2>&1 || {
|
||||
log_error "npm audit found issues. See $LOG_DIR/npm-audit.log"
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
|
||||
# Stylelint
|
||||
if command -v stylelint &>/dev/null; then
|
||||
log_info "Running Stylelint..."
|
||||
stylelint "**/*.{css,scss}" --formatter json >"$LOG_DIR/stylelint.json" 2>"$LOG_DIR/stylelint.log" || {
|
||||
log_error "Stylelint issues found. See $LOG_DIR/stylelint.log"
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
prepare_log_directory
|
||||
|
||||
run_trivy_scan
|
||||
run_trufflehog_scan
|
||||
run_additional_checks
|
||||
|
||||
log_info "All pre-push checks passed successfully!"
|
||||
}
|
||||
|
||||
# Run the main function
|
||||
main "$@"
|
||||
16
.cspell.json
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"ignorePaths": [
|
||||
"**/node_modules/**",
|
||||
"**/vscode-extension/**",
|
||||
"**/.git/**",
|
||||
"**/.pnpm-lock.json",
|
||||
".vscode",
|
||||
"megalinter",
|
||||
"package-lock.json",
|
||||
"report"
|
||||
],
|
||||
"language": "en",
|
||||
"noConfigSearch": true,
|
||||
"words": ["megalinter", "oxsecurity"],
|
||||
"version": "0.2"
|
||||
}
|
||||
141
.gitignore
vendored
|
|
@ -1,141 +0,0 @@
|
|||
.DS_Store
|
||||
.vs-code/
|
||||
|
||||
# Special excludes
|
||||
archive/
|
||||
*.bak
|
||||
deploy/
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
.pdm.toml
|
||||
.pdm-python
|
||||
.pdm-build/
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.venv
|
||||
.venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
# /site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyPI configuration file
|
||||
.pypirc
|
||||
|
||||
# uv lock files
|
||||
uv.lock
|
||||
*.pyc
|
||||
.python-version
|
||||
megalinter-reports/
|
||||
15
.jscpd.json
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"threshold": 0,
|
||||
"reporters": ["html", "markdown"],
|
||||
"ignore": [
|
||||
"**/node_modules/**",
|
||||
"**/.git/**",
|
||||
"**/.rbenv/**",
|
||||
"**/.venv/**",
|
||||
"**/*cache*/**",
|
||||
"**/.github/**",
|
||||
"**/.idea/**",
|
||||
"**/report/**",
|
||||
"**/*.svg"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
# Configuration file for MegaLinter
|
||||
#
|
||||
# See all available variables at https://megalinter.io/latest/config-file/ and in
|
||||
# linters documentation
|
||||
|
||||
# all, none, or list of linter keys
|
||||
APPLY_FIXES: none
|
||||
|
||||
# If you use ENABLE variable, all other languages/formats/tooling-formats will
|
||||
# be disabled by default
|
||||
# ENABLE:
|
||||
|
||||
# If you use ENABLE_LINTERS variable, all other linters will be disabled by
|
||||
# default
|
||||
# ENABLE_LINTERS:
|
||||
|
||||
# DISABLE:
|
||||
# - COPYPASTE # Uncomment to disable checks of excessive copy-pastes
|
||||
# - SPELL # Uncomment to disable checks of spelling mistakes
|
||||
|
||||
SHOW_ELAPSED_TIME: true
|
||||
|
||||
# Uncomment if you want MegaLinter to detect errors but not block CI to pass
|
||||
# DISABLE_ERRORS: true
|
||||
|
|
@ -1,50 +1,50 @@
|
|||
@import url(_colours.css);
|
||||
|
||||
/*****************************
|
||||
* CHAPTER
|
||||
* Styling for chapter pages.
|
||||
*****************************/
|
||||
|
||||
/* Removing all padding, margins, etc. The content covers the entire viewing area */
|
||||
body,
|
||||
.md-content__inner,
|
||||
.md-main__inner,
|
||||
.md-grid,
|
||||
html,
|
||||
body,
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
.md-grid {
|
||||
box-sizing: border-box;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
article,
|
||||
.md-container {
|
||||
min-height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
max-width: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: white;
|
||||
min-height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
article,
|
||||
.md-container,
|
||||
div.md-content {
|
||||
margin: 0;
|
||||
min-height: 100%;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
header,
|
||||
.md-content .md-typeset h1 {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
article.md-content__inner.md-typeset:before,
|
||||
article.md-content__inner.md-typeset:after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
/* Hide announcements bar on chapter pages */
|
||||
header,
|
||||
[data-md-component="skip"],
|
||||
[data-md-component="announce"],
|
||||
.md-content .md-typeset h1 {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Hide the repo stuff */
|
||||
.md-source {
|
||||
display: none !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
/*****************************
|
||||
* COLOURS
|
||||
*****************************/
|
||||
|
||||
:root {
|
||||
--background-colour: #FFF;
|
||||
--primary-colour: #323036;
|
||||
--secondary-colour: #EFE5DC;
|
||||
--tertiary-colour: #818589;
|
||||
--quarternary-colour: #FAF9F6;
|
||||
--transparent: transparent;
|
||||
}
|
||||
|
||||
/* Adjust Mkdocs colours */
|
||||
|
||||
:root {
|
||||
--md-primary-fg-color: var(--primary-colour);
|
||||
--md-primary-fg-color--light: var(--tertiary-colour);
|
||||
--md-primary-fg-color--dark: var(--primary-colour);
|
||||
--md-primary-bg-color: var(--background-colour);
|
||||
--md-footer-bg-color: var(--background-colour);
|
||||
--md-default-bg-color: var(--background-colour);
|
||||
}
|
||||
|
||||
[data-md-color-accent=custom] {
|
||||
--md-primary-fg-color: var(--primary-colour);
|
||||
--md-primary-fg-color--light: var(--tertiary-colour);
|
||||
--md-primary-fg-color--dark: var(--primary-colour);
|
||||
--md-accent-fg-color: var(--secondary-colour);
|
||||
}
|
||||
|
||||
/* Font colours */
|
||||
|
||||
.md-typeset {
|
||||
|
||||
p,
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
figcaption,
|
||||
a,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
color: var(--tertiary-colour);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--secondary-color);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,202 +0,0 @@
|
|||
/*****************************
|
||||
* FONTS
|
||||
*****************************/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Baskerville';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
src: url('../fonts/libre-baskerville/LibreBaskerville-Regular.woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Baskerville';
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
src: url('../fonts/libre-baskerville/LibreBaskerville-Bold.woff');
|
||||
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Baskerville';
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
src: url('../fonts/libre-baskerville/LibreBaskerville-Italic.woff');
|
||||
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
src: url('../fonts/lato/Lato-Regular.ttf');
|
||||
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
src: url('../fonts/lato/Lato-Italic.ttf');
|
||||
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
src: url('../fonts/lato/Lato-Bold.woff2');
|
||||
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
src: url('../fonts/lato/Lato-BoldItalic.woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-weight: light;
|
||||
font-style: normal;
|
||||
src: url('../fonts/lato/Lato-Regular.woff2');
|
||||
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-weight: light;
|
||||
font-style: italic;
|
||||
src: url('../fonts/lato/Lato-Italic.woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-weight: bolder;
|
||||
font-style: normal;
|
||||
src: url('../fonts/lato/Lato-Black.ttf');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-weight: bolder;
|
||||
font-style: italic;
|
||||
src: url('../fonts/lato/Lato-BlackItalic.ttf');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-weight: thin;
|
||||
font-style: normal;
|
||||
src: url('../fonts/lato/Lato-Light.ttf');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-weight: thin;
|
||||
font-style: italic;
|
||||
src: url('../fonts/lato/Lato-ThinItalic.ttf');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DM Mono';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
src: url('../fonts/dm-mono/DMMono-Regular.woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DM Mono';
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
src: url('../fonts/dm-mono/DMMono-Italic.woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DM Mono';
|
||||
font-weight: medium;
|
||||
font-style: italic;
|
||||
src: url('../fonts/dm-mono/DMMono-MediumItalic.woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DM Mono';
|
||||
font-weight: medium;
|
||||
font-style: normal;
|
||||
src: url('../fonts/dm-mono/DMMono-Medium.woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DM Mono';
|
||||
font-weight: light;
|
||||
font-style: normal;
|
||||
src: url('../fonts/dm-mono/DMMono-Light.woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DM Mono';
|
||||
font-weight: light;
|
||||
font-style: italic;
|
||||
src: url('../fonts/dm-mono/DMMono-LightItalic.woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-weight: medium;
|
||||
font-style: normal;
|
||||
src: url('../fonts/open-sans/OpenSans-Medium.woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DM Serif';
|
||||
font-weight: bolder;
|
||||
font-style: italic;
|
||||
src: url('../fonts/open-sans/OpenSans-ExtraBold.woff2');
|
||||
}
|
||||
|
||||
/* Variables */
|
||||
|
||||
:root {
|
||||
--primary-font: 'Libre Baskerville', serif;
|
||||
--secondary-font: 'Lato', sans-serif;
|
||||
--tertiary-font: 'DM Mono', monospace;
|
||||
--number-font: 'Open Sans', sans-serif;
|
||||
}
|
||||
|
||||
/* Typeset */
|
||||
|
||||
.md-typeset {
|
||||
p, li, ul {
|
||||
font-family: var(--primary-font);
|
||||
}
|
||||
|
||||
figcaption {
|
||||
font-family: var(--secondary-font);
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
font-family: var(--secondary-font);
|
||||
}
|
||||
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: var(--secondary-font);
|
||||
}
|
||||
}
|
||||
|
||||
.md-typeset {
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/*****************************
|
||||
* MEDIA PLAYER
|
||||
*****************************/
|
||||
|
||||
media-player {
|
||||
margin: 5px 0;
|
||||
|
||||
* {
|
||||
filter: none;
|
||||
}
|
||||
}
|
||||
|
||||
.light .vds-time,
|
||||
.vds-button {
|
||||
--default-color: #818589 !important;
|
||||
color: #818589 !important;
|
||||
}
|
||||
|
||||
.light .vds-audio-layout .vds-play-button,
|
||||
.vds-audio-layout.light .vds-play-button {
|
||||
--default-bg: transparent !important;
|
||||
}
|
||||
|
||||
.media-audio-layout {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.vds-audio-layout.light {
|
||||
--default-bg: transparent !important;
|
||||
}
|
||||
|
||||
.vds-title {
|
||||
font-family: var(--secondary-font);
|
||||
font-size: 0.8em;
|
||||
font-weight: bold;
|
||||
color: #818589;
|
||||
}
|
||||
|
|
@ -1,230 +0,0 @@
|
|||
/*****************************
|
||||
* RESUMÉ
|
||||
*****************************/
|
||||
|
||||
/* Fade in content */
|
||||
.fade-in-up-section {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
transition: opacity 2s ease-in-out, transform 2s ease-in-out;
|
||||
}
|
||||
|
||||
.fade-in-up-section.visible {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.fade-in-up-content {
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
/* box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); */
|
||||
}
|
||||
|
||||
/* Career meta-information */
|
||||
.meta-icons {
|
||||
font-size: max(calc(var(--text-variable-size) + 3px), var(--text-min-size));
|
||||
font-family: var(--secondary-font);
|
||||
font-weight: 900;
|
||||
color: var(--tertiary-colour);
|
||||
text-align: left;
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
gap: 25px;
|
||||
width: fit-content;
|
||||
margin: 0;
|
||||
|
||||
& .md-typeset .twemoji {
|
||||
height: max(calc(var(--text-variable-size) + 5px), var(--text-min-size));
|
||||
}
|
||||
|
||||
& svg {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--secondary-colour);
|
||||
}
|
||||
}
|
||||
|
||||
/* Career timeline */
|
||||
.tabbed-labels {
|
||||
font-family: var(--number-font);
|
||||
font-weight: 900;
|
||||
margin-bottom: 0;
|
||||
|
||||
a:hover {
|
||||
color: var(--secondary-colour);
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: max(calc(var(--text-variable-size) + 9px), calc(var(--text-min-size) + 3px)) !important;
|
||||
}
|
||||
|
||||
>label:nth-child(1) {
|
||||
margin-left: 4vw;
|
||||
}
|
||||
|
||||
>label:nth-child(2) {
|
||||
margin-left: 12vw;
|
||||
}
|
||||
|
||||
>label:nth-child(3) {
|
||||
margin-left: 24vw;
|
||||
}
|
||||
|
||||
>label:nth-child(4) {
|
||||
margin-left: 12vw;
|
||||
}
|
||||
|
||||
>label:nth-child(5) {
|
||||
margin-left: 10vw;
|
||||
}
|
||||
}
|
||||
|
||||
.tabbed-content {
|
||||
background-color: var(--quarternary-colour);
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.tabbed-block {
|
||||
padding: 1em 2.5em;
|
||||
}
|
||||
|
||||
/* Timeline content */
|
||||
.logo-and-title {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
|
||||
img {
|
||||
height: max(15px, 0.5vh);
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
div.tags {
|
||||
font-family: var(--primary-font);
|
||||
font-size: max(var(--text-variable-size), var(--text-min-size));
|
||||
font-style: italic;
|
||||
color: var(--tertiary-colour);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.three-column {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
max-width: 1500px;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
|
||||
.column {
|
||||
justify-self: center;
|
||||
padding: 20px;
|
||||
text-align: left;
|
||||
|
||||
&:nth-child(1) {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
border-left: 1px solid var(--secondary-colour);
|
||||
border-right: 1px solid var(--secondary-colour);
|
||||
}
|
||||
|
||||
.content {
|
||||
h6 {
|
||||
font-size: max(calc(var(--text-variable-size) + 7px), calc(var(--text-min-size) + 2px));
|
||||
font-family: var(--secondary-font);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.blurb {
|
||||
font-family: var(--primary-font);
|
||||
font-size: max(calc(var(--text-variable-size) + 5px), var(--text-min-size));
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
/* Portfolio */
|
||||
.grid.cards {
|
||||
|
||||
li {
|
||||
background-color: var(--quarternary-colour);
|
||||
border: none !important;
|
||||
border-radius: 5px !important;
|
||||
box-shadow: none !important;
|
||||
padding: 2em !important;
|
||||
margin: 2em !important;
|
||||
|
||||
|
||||
h6 {
|
||||
span {
|
||||
margin-right: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: none !important;
|
||||
border: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.writing {
|
||||
padding: 4em;
|
||||
|
||||
h6 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.two-column {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
max-width: 1500px;
|
||||
padding: 20px 20px 20px 0;
|
||||
width: 100%;
|
||||
margin: 10px auto;
|
||||
|
||||
.column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
text-align: left;
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Contact */
|
||||
|
||||
div.contact-me {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
|
||||
div.button {
|
||||
font-size: 1.8em;
|
||||
color: var(--tertiary-colour);
|
||||
border: none;
|
||||
|
||||
&:hover {
|
||||
color: var(--secondary-colour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
/*****************************
|
||||
* SIZE
|
||||
*****************************/
|
||||
|
||||
/* Standard screen size is based on 1728x1117 screen. */
|
||||
:root {
|
||||
--text-min-size: 8px;
|
||||
--text-variable-size: 0.7vw;
|
||||
--full-width: 100vw;
|
||||
--half-width: 50vw;
|
||||
--third-width: 33.3vw;
|
||||
--quarter-width: 25vw;
|
||||
--fifth-width: 20vw;
|
||||
--full-height: 100vh;
|
||||
--half-height: 50vh;
|
||||
--third-height: 33.3vh;
|
||||
--quarter-height: 25vh;
|
||||
--fifth-height: 20vh;
|
||||
--horizontal-spacing: 0.3vw;
|
||||
--vertical-spacing: 0.45vh;
|
||||
}
|
||||
|
||||
/* Font sizes */
|
||||
.md-typeset {
|
||||
p {
|
||||
font-size: max(calc(var(--text-variable-size) + 3px), var(--text-min-size));
|
||||
}
|
||||
|
||||
figcaption {
|
||||
font-size: max(calc(var(--text-variable-size)), var(--text-min-size));
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
letter-spacing: normal;
|
||||
margin: 0 0 5px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.md-typeset {
|
||||
h1 {
|
||||
font-size: max(calc(var(--text-variable-size) * 6), calc(var(--text-min-size) + 6px));
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: max(calc(var(--text-variable-size) * 4), calc(var(--text-min-size) + 5px));
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: max(calc(var(--text-variable-size) * 3.5), calc(var(--text-min-size) + 4px));
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: max(calc(var(--text-variable-size) * 2.8), calc(var(--text-min-size) + 3px));
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: max(calc(var(--text-variable-size) * 2), calc(var(--text-min-size) + 2px));
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: max(calc(var(--text-variable-size) + 8px), calc(var(--text-min-size) + 1px));
|
||||
}
|
||||
}
|
||||
|
||||
/* Default padding and margins */
|
||||
div {
|
||||
margin: calc(var(--vertical-spacing) * 2) 0;
|
||||
padding: calc(var(--vertical-spacing) * 2) 0;
|
||||
}
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
@import url(_colours.css);
|
||||
@import url(_fonts.css);
|
||||
@import url(_size.css);
|
||||
@import url(_media-player.css);
|
||||
|
||||
|
||||
/*****************************
|
||||
* GENERAL RULES
|
||||
*****************************/
|
||||
|
||||
body {
|
||||
background: var(--background);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
nav,
|
||||
.md-header {
|
||||
background-color: var(--transparent);
|
||||
}
|
||||
|
||||
a.md-header__button {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.md-typeset a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.md-header--shadow {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.md-header__topic:first-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Change colour of search highlighting. */
|
||||
.md-search-result__link:focus,
|
||||
.md-search-result__link:hover {
|
||||
background-color: var(--transparent);
|
||||
}
|
||||
|
||||
.md-typeset mark {
|
||||
background-color: var(--transparent);
|
||||
}
|
||||
|
||||
/* This was creating an annoying space at the top. */
|
||||
article.md-content__inner.md-typeset:before,
|
||||
article.md-content__inner.md-typeset:after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
.md-typeset figcaption {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
/* Hide the repo stuff */
|
||||
.md-source {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/*****************************
|
||||
* BUTTON
|
||||
*****************************/
|
||||
|
||||
div.button {
|
||||
font-family: var(--secondary-font);
|
||||
border-bottom: 3px solid var(--secondary-colour);
|
||||
width: fit-content;
|
||||
padding-bottom: 3px;
|
||||
font-weight: bold;
|
||||
|
||||
&:hover {
|
||||
border-bottom: 3px solid white;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************
|
||||
* STATUS
|
||||
*****************************/
|
||||
|
||||
div.status-green {
|
||||
background-color: #007a5a;
|
||||
color: var(--background-colour);
|
||||
border-radius: 5px;
|
||||
padding: 5px 15px;
|
||||
text-transform: uppercase;
|
||||
font-family: var(--secondary-font);
|
||||
font-weight: 900;
|
||||
font-size: 0.8em;
|
||||
width: fit-content;
|
||||
margin: 0;
|
||||
letter-spacing: 0.3em;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
/*****************************
|
||||
* TOOLTIP
|
||||
*****************************/
|
||||
|
||||
.md-annotation__index {
|
||||
overflow: inherit;
|
||||
vertical-align: inherit;
|
||||
}
|
||||
|
||||
.md-tooltip {
|
||||
box-shadow: none;
|
||||
border: 1px solid var(--secondary-colour);
|
||||
padding: 3px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.md-tooltip__inner {
|
||||
font-family: var(--secondary-font);
|
||||
font-size: 0.8em;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
/*****************************
|
||||
* FOOTER
|
||||
*****************************/
|
||||
|
||||
div.footer {
|
||||
margin: 30px 5px 5px 0;
|
||||
padding-bottom: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
div.footer>*:not(:last-child)::after {
|
||||
content: " | ";
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
/*****************************
|
||||
* RESPONSIVE
|
||||
*****************************/
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.faces {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
.three-column {
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
.column:nth-child(1) {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.column:nth-child(2) {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,14 +1,10 @@
|
|||
@import url(_colours.css);
|
||||
@import url("theme.css");
|
||||
|
||||
/*****************************
|
||||
* HOME
|
||||
* INDEX
|
||||
* Styling for the homepage.
|
||||
*****************************/
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.content {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
|
|
@ -24,7 +20,6 @@
|
|||
.content ul {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
font-size: 30px;
|
||||
height: 1.4em;
|
||||
justify-content: center;
|
||||
left: 50%;
|
||||
|
|
@ -40,17 +35,17 @@
|
|||
top: 20px;
|
||||
transform: translateX(-50%);
|
||||
width: 100%;
|
||||
z-index: 5;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.content ul li {
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
font-size: calc((min(100vw, 900px)) / 10);
|
||||
font-size: 15vw;
|
||||
inset: 0;
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
margin: 0 !important;
|
||||
padding: 0;
|
||||
pointer-events: auto;
|
||||
position: absolute;
|
||||
|
|
@ -59,20 +54,24 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.content ul li:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.content ul li a {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.content ul li:nth-child(2) {
|
||||
font-family: var(--primary-font);
|
||||
font-family: var(--words-title) !important;
|
||||
}
|
||||
|
||||
.content ul li:nth-child(3) {
|
||||
font-family: var(--secondary-font);
|
||||
font-family: var(--visuals-title);
|
||||
}
|
||||
|
||||
.content ul li:nth-child(4) {
|
||||
font-family: var(--tertiary-font);
|
||||
font-family: var(--technical-title);
|
||||
}
|
||||
|
||||
.content .faces {
|
||||
|
|
@ -86,6 +85,16 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.down-arrow {
|
||||
animation: flash 1s infinite;
|
||||
bottom: 20px;
|
||||
color: var(--tertiary-colour);
|
||||
font-size: 1rem;
|
||||
left: 50%;
|
||||
position: fixed;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.faces .slide {
|
||||
border-radius: 10px;
|
||||
left: 50%;
|
||||
|
|
@ -106,14 +115,27 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.down-arrow {
|
||||
animation: flash 1s infinite;
|
||||
bottom: 20px;
|
||||
color: var(--secondary-colour);
|
||||
font-size: 2rem;
|
||||
left: 50%;
|
||||
position: fixed;
|
||||
transform: translateX(-50%);
|
||||
footer {
|
||||
background: repeating-linear-gradient(0deg, transparent, transparent 19px, rgba(75, 85, 99, 0.08) 19px, rgba(75, 85, 99, 0.08) 20px, transparent 20px, transparent 39px, rgba(75, 85, 99, 0.08) 39px, rgba(75, 85, 99, 0.08) 40px),
|
||||
repeating-linear-gradient(90deg, transparent, transparent 19px, rgba(75, 85, 99, 0.08) 19px, rgba(75, 85, 99, 0.08) 20px, transparent 20px, transparent 39px, rgba(75, 85, 99, 0.08) 39px, rgba(75, 85, 99, 0.08) 40px),
|
||||
radial-gradient(circle at 20px 20px, rgba(55, 65, 81, 0.12) 2px, transparent 2px),
|
||||
radial-gradient(circle at 40px 40px, rgba(55, 65, 81, 0.12) 2px, transparent 2px);
|
||||
font-family: var(--general-sans);
|
||||
}
|
||||
|
||||
.hero {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@keyframes flash {
|
||||
|
|
@ -127,14 +149,3 @@
|
|||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.hero {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
181
content/assets/css/theme.css
Executable file
|
|
@ -0,0 +1,181 @@
|
|||
/*****************************
|
||||
* Theme
|
||||
* Base CSS file
|
||||
------------------------------
|
||||
* COLOURS
|
||||
*****************************/
|
||||
|
||||
/* Colour variables */
|
||||
:root {
|
||||
--background-colour: #FFF;
|
||||
--primary-colour: #323036;
|
||||
--quarternary-colour: #FAF9F6;
|
||||
--secondary-colour: #818589;
|
||||
--tertiary-colour: #E6E6E6;
|
||||
--transparent: transparent;
|
||||
}
|
||||
|
||||
/* Adjust Zensical colours */
|
||||
[data-md-color-accent=custom] {
|
||||
--md-default-bg-color: var(--background-colour);
|
||||
--md-footer-bg-color: var(--background-colour);
|
||||
--md-primary-bg-color: var(--background-colour);
|
||||
--md-primary-fg-color: var(--primary-colour);
|
||||
--md-primary-fg-color--dark: var(--primary-colour);
|
||||
--md-primary-fg-color--light: var(--tertiary-colour);
|
||||
}
|
||||
|
||||
/*****************************
|
||||
* FONTS
|
||||
*****************************/
|
||||
|
||||
/* General */
|
||||
@font-face {
|
||||
font-family: 'Source Code';
|
||||
font-style: normal;
|
||||
font-weight: 100 700;
|
||||
src: url('../fonts/source-code.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Source Sans';
|
||||
font-style: normal;
|
||||
font-weight: 100 700;
|
||||
src: url('../fonts/source-sans.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Source Serif';
|
||||
font-style: normal;
|
||||
font-weight: 100 700;
|
||||
src: url('../fonts/source-serif.ttf') format('truetype');
|
||||
}
|
||||
|
||||
/* Technical */
|
||||
@font-face {
|
||||
font-family: 'DM Mono';
|
||||
font-style: normal;
|
||||
font-weight: 100 700;
|
||||
src: url('../fonts/dm-mono.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DM Sans';
|
||||
font-style: normal;
|
||||
font-weight: 100 700;
|
||||
src: url('../fonts/dm-sans.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Tiny5';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
src: url('../fonts/tiny5.ttf') format('truetype');
|
||||
}
|
||||
|
||||
/* Visual */
|
||||
@font-face {
|
||||
font-family: 'Plaster';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
src: url('../fonts/plaster.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 100 700;
|
||||
src: url('../fonts/rubik.ttf') format('truetype');
|
||||
}
|
||||
|
||||
/* Words */
|
||||
@font-face {
|
||||
font-family: 'EB Garamond';
|
||||
font-style: italic;
|
||||
font-weight: 100 700;
|
||||
src: url('../fonts/eb-garamond-italics.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'EB Garamond';
|
||||
font-style: normal;
|
||||
font-weight: 100 700;
|
||||
src: url('../fonts/eb-garamond.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Playfair Display SC';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
src: url('../fonts/playfair-display-sc.ttf') format('truetype');
|
||||
}
|
||||
|
||||
/* Variables */
|
||||
:root {
|
||||
--general-sans: 'Source Sans', sans-serif;
|
||||
--general-serif: 'Source Serif', serif;
|
||||
--general-code: 'Source Code', monospace;
|
||||
--technical-code: 'DM Mono', monospace;
|
||||
--technical-text: 'DM Sans', monospace;
|
||||
--technical-title: 'Tiny5', 'DM Mono', monospace;
|
||||
--visuals-text: 'Rubik', sans-serif;
|
||||
--visuals-title: 'Plaster', 'Rubik', sans-serif;
|
||||
--words-text: 'EB Garamond', serif;
|
||||
--words-title: 'Playfair Display SC', 'EB Garamond', serif;
|
||||
}
|
||||
|
||||
/* Colours and weights */
|
||||
.md-typeset {
|
||||
|
||||
a,
|
||||
figcaption {
|
||||
color: var(--secondary-colour);
|
||||
max-width: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--teriary-color);
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
color: var(--secondary-colour);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p {
|
||||
color: var(--primary-colour);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************
|
||||
* RULES
|
||||
*****************************/
|
||||
|
||||
body {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
footer {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
margin-bottom: 5px;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
footer>*:not(:last-child)::after {
|
||||
content: " | ";
|
||||
margin: 0 8px;
|
||||
}
|
||||
BIN
content/assets/fonts/dm-mono.ttf
Executable file
BIN
content/assets/fonts/dm-sans.ttf
Executable file
BIN
content/assets/fonts/eb-garamond-italics.ttf
Executable file
BIN
content/assets/fonts/eb-garamond.ttf
Executable file
|
|
@ -1,93 +0,0 @@
|
|||
Copyright 2014-2020 The Fira Code Project Authors (https://github.com/tonsky/FiraCode)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
https://openfontlicense.org
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
Fira Code Variable Font
|
||||
=======================
|
||||
|
||||
This download contains Fira Code as both a variable font and static fonts.
|
||||
|
||||
Fira Code is a variable font with this axis:
|
||||
wght
|
||||
|
||||
This means all the styles are contained in a single file:
|
||||
Fira_Code/FiraCode-VariableFont_wght.ttf
|
||||
|
||||
If your app fully supports variable fonts, you can now pick intermediate styles
|
||||
that aren’t available as static fonts. Not all apps support variable fonts, and
|
||||
in those cases you can use the static font files for Fira Code:
|
||||
Fira_Code/static/FiraCode-Light.ttf
|
||||
Fira_Code/static/FiraCode-Regular.ttf
|
||||
Fira_Code/static/FiraCode-Medium.ttf
|
||||
Fira_Code/static/FiraCode-SemiBold.ttf
|
||||
Fira_Code/static/FiraCode-Bold.ttf
|
||||
|
||||
Get started
|
||||
-----------
|
||||
|
||||
1. Install the font files you want to use
|
||||
|
||||
2. Use your app's font picker to view the font family and all the
|
||||
available styles
|
||||
|
||||
Learn more about variable fonts
|
||||
-------------------------------
|
||||
|
||||
https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts
|
||||
https://variablefonts.typenetwork.com
|
||||
https://medium.com/variable-fonts
|
||||
|
||||
In desktop apps
|
||||
|
||||
https://theblog.adobe.com/can-variable-fonts-illustrator-cc
|
||||
https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts
|
||||
|
||||
Online
|
||||
|
||||
https://developers.google.com/fonts/docs/getting_started
|
||||
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide
|
||||
https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts
|
||||
|
||||
Installing fonts
|
||||
|
||||
MacOS: https://support.apple.com/en-us/HT201749
|
||||
Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux
|
||||
Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows
|
||||
|
||||
Android Apps
|
||||
|
||||
https://developers.google.com/fonts/docs/android
|
||||
https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts
|
||||
|
||||
License
|
||||
-------
|
||||
Please read the full license text (OFL.txt) to understand the permissions,
|
||||
restrictions and requirements for usage, redistribution, and modification.
|
||||
|
||||
You can use them in your products & projects – print or digital,
|
||||
commercial or otherwise.
|
||||
|
||||
This isn't legal advice, please consider consulting a lawyer and see the full
|
||||
license for all details.
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
Copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A.
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
https://openfontlicense.org
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
/* #### Generated By: http://font.download #### */
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Baskerville';
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
src: local('Libre Baskerville'), url('LibreBaskerville-Regular.woff') format('woff');
|
||||
}
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Baskerville Italic';
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
src: local('Libre Baskerville Italic'), url('LibreBaskerville-Italic.woff') format('woff');
|
||||
}
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Baskerville Bold';
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
src: local('Libre Baskerville Bold'), url('LibreBaskerville-Bold.woff') format('woff');
|
||||
}
|
||||
BIN
content/assets/fonts/plaster.ttf
Executable file
BIN
content/assets/fonts/playfair-display-sc.ttf
Executable file
BIN
content/assets/fonts/rubik.ttf
Executable file
BIN
content/assets/fonts/source-code.ttf
Executable file
BIN
content/assets/fonts/source-sans.ttf
Executable file
BIN
content/assets/fonts/source-serif.ttf
Executable file
BIN
content/assets/fonts/tiny5.ttf
Executable file
|
|
@ -1,4 +1,4 @@
|
|||
// HOME.js
|
||||
// INDEX.js
|
||||
// Manages the animations on the home page
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
|
@ -76,7 +76,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||
}
|
||||
|
||||
// Attach links to pages
|
||||
const links = ['#', 'https://gugulet.hu/words', 'https://gugulet.hu/visuals', 'https://gugulet.hu/technical'];
|
||||
const links = ['#', '/words', '/visuals', '/technical'];
|
||||
document.querySelectorAll('.list li').forEach((item, index) => {
|
||||
item.innerHTML = `<a href="${links[index]}">${item.innerHTML}</a>`;
|
||||
});
|
||||
|
|
@ -84,3 +84,10 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||
slide.innerHTML = `<a href="${links[index]}">${slide.innerHTML}</a>`;
|
||||
});
|
||||
});
|
||||
|
||||
// Hide the scroll icon when at the end of the page
|
||||
window.addEventListener('scroll', function () {
|
||||
if (window.innerHeight + window.scrollY >= document.body.offsetHeight) {
|
||||
document.getElementById('down-arrow').classList.add('hidden');
|
||||
}
|
||||
});
|
||||
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 142 KiB |
|
Before Width: | Height: | Size: 141 KiB |
|
Before Width: | Height: | Size: 178 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
BIN
content/assets/media/visuals-face-1276x1276.webp
Executable file
|
After Width: | Height: | Size: 8.8 KiB |
BIN
content/assets/media/words-face-1276x1276.webp
Executable file
|
After Width: | Height: | Size: 187 KiB |
|
|
@ -1,3 +1,4 @@
|
|||
<!-- List of defiintions that will appear in toptips -->
|
||||
<!-- List of definitions that will appear in toptips -->
|
||||
<!-- markdownlint-disable -->
|
||||
*[data]: Data defined as raw input, which when processed becomes information. Wisdom and knowledge are higher levels of information alloyed with experience.
|
||||
*[ADB]: The Android Debug Bridge lets you communicate with your Android or wearOS device via the terminal (or console). You can install apps, push orpull files, and change settings using commands.
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
---
|
||||
description: words, visual, technical.
|
||||
description: words, visuals, technical.
|
||||
extra_css:
|
||||
- assets/css/_chapter.css
|
||||
- assets/css/_home.css
|
||||
- assets/css/index.css
|
||||
extra_js:
|
||||
- assets/js/gsap/gsap.min.js
|
||||
- assets/js/gsap/ScrollTrigger.min.js
|
||||
- assets/js/home.js
|
||||
- assets/js/index.js
|
||||
hide:
|
||||
- toc
|
||||
- navigation
|
||||
search:
|
||||
exclude: true
|
||||
template: "chapter.html"
|
||||
title: Home
|
||||
---
|
||||
|
||||
|
|
@ -25,24 +25,23 @@ title: Home
|
|||
<li>visuals</li>
|
||||
<li>technical</li>
|
||||
</ul>
|
||||
<div class="fill"></div>
|
||||
<div class="faces">
|
||||
<div class="slide center">
|
||||
<img src="assets/media/gugulet.hu-unedited-face-1276x1276.webp" alt="1" />
|
||||
<img src="assets/media/face-1276x1276.webp" alt="gwabini" />
|
||||
</div>
|
||||
<div class="slide center">
|
||||
<img src="assets/media/gugulet.hu-writing-face-1276x1276.webp" alt="2" />
|
||||
<img src="assets/media/words-face-1276x1276.webp" alt="boya benyathi" />
|
||||
</div>
|
||||
<div class="slide center">
|
||||
<img src="assets/media/gugulet.hu-visual-face-1276x1276.webp" alt="3" />
|
||||
<img src="assets/media/visuals-face-1276x1276.webp" alt="bele elide" />
|
||||
</div>
|
||||
<div class="slide center">
|
||||
<img src="assets/media/gugulet.hu-technical-face-1276x1276.webp" alt="4" />
|
||||
<img src="assets/media/technical-face-1276x1276.webp" alt="our pride" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="down-arrow" markdown >
|
||||
:fontawesome-solid-angle-down:
|
||||
:fontawesome-solid-chevron-down:
|
||||
</div>
|
||||
|
|
|
|||
16
content/overrides/chapter.html
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
{% extends "main.html" %}
|
||||
|
||||
<!-- Use the chapter CSS on this page (in addition to the normal CSS) -->
|
||||
{% block styles %}
|
||||
|
||||
{{ super() }}
|
||||
|
||||
<link rel="stylesheet" href="{{ base_url }}/assets/css/_chapter.css">
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{{ super() }}
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<div class="footer">
|
||||
<footer>
|
||||
<span>© all rights reserved</span>
|
||||
<span><a href="https://www.linkedin.com/in/gugulet-hu/">contact</a></span>
|
||||
<span>made with <a href="https://zensical.org/">zensical</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
---
|
||||
title: Gugulethu Hlekwayo | Technical
|
||||
title: Technical
|
||||
---
|
||||
|
|
|
|||
8
content/words.md
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: Writing
|
||||
description: "arranging words in a pleasing way..."
|
||||
hide:
|
||||
- toc
|
||||
- navigation
|
||||
---
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
---
|
||||
title: Writing
|
||||
description: "arranging words in a pleasing way..."
|
||||
hide:
|
||||
- toc
|
||||
- navigation
|
||||
---
|
||||
|
||||
<link href='/assets/css/_index.css' rel='stylesheet'>
|
||||
|
||||
<div class='hero-text'>
|
||||
<h2>sawubona, i'm g*</h2>
|
||||
<h4>and i like making pretty arrangements of words</h4>
|
||||
<div class='accent-divider'></div>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='two-column fade-in-up-section'>
|
||||
<div class='column'>
|
||||
<div class='content'>
|
||||
</div>
|
||||
<div class='content'>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
184
hook.sh
|
|
@ -1,184 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
||||
|
||||
echo -e "${GREEN}Running pre-push checks...${NC}"
|
||||
|
||||
# Paths
|
||||
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
|
||||
CONTENT_DIR="$REPO_ROOT/core/content"
|
||||
MKDOCS_CFG_PATH="$CONTENT_DIR/mkdocs.yml"
|
||||
SITE_DIR="$REPO_ROOT/site"
|
||||
LOG_DIR="$REPO_ROOT/test/log"
|
||||
|
||||
# Clean logs
|
||||
rm -rf "$LOG_DIR"; mkdir -p "$LOG_DIR"
|
||||
|
||||
SERVER_PID=""
|
||||
cleanup() {
|
||||
if [[ -n "${SERVER_PID:-}" ]] && ps -p "$SERVER_PID" >/dev/null 2>&1; then
|
||||
kill "$SERVER_PID" >/dev/null 2>&1 || true
|
||||
for _ in {1..30}; do ps -p "$SERVER_PID" >/dev/null 2>&1 || break; sleep 0.1; done
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
# --- Optional lightweight checks (keep or remove) ---
|
||||
if command -v trivy &>/dev/null; then
|
||||
echo -e "${GREEN}Running Trivy scan...${NC}"
|
||||
trivy fs . --exit-code 1 --severity CRITICAL,HIGH,MEDIUM,LOW,UNKNOWN --no-progress \
|
||||
>"$LOG_DIR/trivy.log" 2>&1 || { echo -e "${RED}Trivy failed. See $LOG_DIR/trivy.log${NC}"; exit 1; }
|
||||
else
|
||||
echo -e "${YELLOW}Trivy not installed. Skipping vulnerability scan.${NC}"
|
||||
fi
|
||||
|
||||
if command -v trufflehog &>/dev/null && command -v jq &>/dev/null; then
|
||||
echo -e "${GREEN}Running TruffleHog (verified only)...${NC}"
|
||||
TMPF="$(mktemp)"
|
||||
trufflehog filesystem . --json >"$TMPF" 2>"$LOG_DIR/trufflehog.log" || true
|
||||
VERIFIED="$(jq 'select(.verified==true)' "$TMPF" | wc -l | tr -d ' ')"
|
||||
if [[ "$VERIFIED" -gt 0 ]]; then
|
||||
cp "$TMPF" "$LOG_DIR/trufflehog-findings.json"
|
||||
echo -e "${RED}Verified secrets found. See $LOG_DIR/trufflehog-findings.json${NC}"
|
||||
rm -f "$TMPF"; exit 1
|
||||
fi
|
||||
rm -f "$TMPF"
|
||||
else
|
||||
echo -e "${YELLOW}TruffleHog or jq not installed. Skipping secrets scan.${NC}"
|
||||
fi
|
||||
|
||||
if command -v markdownlint &>/dev/null; then
|
||||
echo -e "${GREEN}Running markdownlint...${NC}"
|
||||
MD_FILES="$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.md$' || true)"
|
||||
if [[ -n "$MD_FILES" ]]; then
|
||||
# shellcheck disable=SC2086
|
||||
echo $MD_FILES | xargs markdownlint >"$LOG_DIR/markdownlint.log" 2>&1 || {
|
||||
echo -e "${RED}markdownlint failed. See $LOG_DIR/markdownlint.log${NC}"; exit 1; }
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}markdownlint not installed. Skipping markdown check.${NC}"
|
||||
fi
|
||||
|
||||
if command -v vale &>/dev/null && [[ -f "$REPO_ROOT/.vale.ini" ]]; then
|
||||
echo -e "${GREEN}Running Vale...${NC}"
|
||||
VALE_FILES="$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.md$' || true)"
|
||||
if [[ -n "$VALE_FILES" ]]; then
|
||||
# shellcheck disable=SC2086
|
||||
echo $VALE_FILES | xargs vale >"$LOG_DIR/vale.log" 2>&1 || {
|
||||
echo -e "${RED}Vale issues. See $LOG_DIR/vale.log${NC}"; exit 1; }
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}Vale not installed or .vale.ini missing. Skipping Vale.${NC}"
|
||||
fi
|
||||
|
||||
# --- MkDocs build (strict) ---
|
||||
if ! command -v mkdocs >/dev/null 2>&1; then
|
||||
echo -e "${RED}MkDocs not installed; cannot build docs.${NC}"; exit 1
|
||||
fi
|
||||
echo -e "${GREEN}Building documentation (strict)…${NC}"
|
||||
mkdocs build -f "$MKDOCS_CFG_PATH" -d "$SITE_DIR" --strict >"$LOG_DIR/mkdocs-build.log" 2>&1 || {
|
||||
echo -e "${RED}MkDocs build failed. See $LOG_DIR/mkdocs-build.log${NC}"; exit 1; }
|
||||
|
||||
# --- Serve built site ---
|
||||
# if ! command -v python3 >/dev/null 2>&1; then
|
||||
# echo -e "${RED}python3 not found; cannot serve static site.${NC}"; exit 1
|
||||
# fi
|
||||
|
||||
# PORT="$(python3 - <<'PY'
|
||||
# import socket
|
||||
# s=socket.socket(); s.bind(('127.0.0.1',0))
|
||||
# print(s.getsockname()[1]); s.close()
|
||||
# PY
|
||||
# )"
|
||||
|
||||
# STATIC_LOG="$LOG_DIR/static-serve.log"
|
||||
# echo -e "${GREEN}Serving built site at http://127.0.0.1:$PORT …${NC}"
|
||||
# python3 -m http.server "$PORT" --bind 127.0.0.1 --directory "$SITE_DIR" >"$STATIC_LOG" 2>&1 &
|
||||
# SERVER_PID="$!"
|
||||
|
||||
# Wait for server
|
||||
# echo -e "${GREEN}Waiting for local server to be reachable…${NC}"
|
||||
# START_TIME="$(date +%s)"; TIMEOUT=60
|
||||
# while : ; do
|
||||
# if ! ps -p "$SERVER_PID" >/dev/null 2>&1; then
|
||||
# echo -e "${RED}Static server died during startup. See $STATIC_LOG${NC}"; exit 1
|
||||
# fi
|
||||
# if curl --fail --silent -I "http://127.0.0.1:$PORT/" >/dev/null 2>>"$STATIC_LOG"; then break; fi
|
||||
# if (( $(date +%s) - START_TIME >= TIMEOUT )); then
|
||||
# echo -e "${RED}Static server did not come up in ${TIMEOUT}s.${NC}"
|
||||
# tail -n 50 "$STATIC_LOG" || true; exit 1
|
||||
# fi
|
||||
# sleep 0.5
|
||||
# done
|
||||
|
||||
# --- Build URL list (all *.html pages) ---
|
||||
# URLS_FILE="$LOG_DIR/urls.txt"
|
||||
# BASE_URL="http://127.0.0.1:$PORT/"
|
||||
|
||||
# export SITE_DIR BASE_URL
|
||||
# python3 - <<'PY' > "$URLS_FILE"
|
||||
# import os
|
||||
# site = os.environ['SITE_DIR']; base = os.environ['BASE_URL']
|
||||
# urls = []
|
||||
# for root, _, files in os.walk(site):
|
||||
# for name in files:
|
||||
# if name.endswith('.html'):
|
||||
# rel = os.path.relpath(os.path.join(root, name), site).replace(os.sep, '/')
|
||||
# urls.append(base + rel)
|
||||
# for u in sorted(urls): print(u)
|
||||
# PY
|
||||
|
||||
# TOTAL="$(wc -l < "$URLS_FILE" | tr -d ' ')"
|
||||
# echo -e "${GREEN}Lychee will scan ${TOTAL} pages…${NC}"
|
||||
|
||||
# # --- Lychee (single run, unbuffered, higher FD limit) ---
|
||||
# if ! command -v lychee >/dev/null 2>&1; then
|
||||
# echo -e "${YELLOW}Lychee not installed. Skipping link check.${NC}"
|
||||
# cleanup; exit 0
|
||||
# fi
|
||||
|
||||
# # Raise macOS open-file limit (best-effort) to avoid mid-run aborts
|
||||
# ulimit -n 4096 || true
|
||||
|
||||
# CSV_OUT="$LOG_DIR/lychee.csv"
|
||||
# RUN_LOG="$LOG_DIR/lychee-run.log"
|
||||
|
||||
# echo -e "${GREEN}Starting Lychee…${NC}"
|
||||
# set +e
|
||||
# # Use script(1) to allocate a PTY so output is line-buffered; tee to file.
|
||||
# # Capture Lychee's real exit code via PIPESTATUS.
|
||||
# script -q /dev/null lychee \
|
||||
# --base-url "http://127.0.0.1:$PORT/" \
|
||||
# --format detailed \
|
||||
# --output "$CSV_OUT" \
|
||||
# --verbose \
|
||||
# --no-progress \
|
||||
# --max-concurrency 16 \
|
||||
# --timeout 30 \
|
||||
# --max-retries 2 \
|
||||
# --retry-wait-time 2 \
|
||||
# --accept '100..=103,200..=399' \
|
||||
# --exclude 'https?://(www\.)?github\.com/spread-ai' \
|
||||
# --exclude 'https?://[^/]*app\.spread\.ai' \
|
||||
# --exclude 'https?://[^/]*stage\.spread\.ai' \
|
||||
# --exclude '\?q=' \
|
||||
# --exclude '#__.*_annotation_.*' \
|
||||
# - < "$URLS_FILE" 2>&1 | tee "$RUN_LOG"
|
||||
# LYCHEE_RC=${PIPESTATUS[1]}
|
||||
# set -e
|
||||
|
||||
# Stop server
|
||||
# cleanup
|
||||
|
||||
# # Summarize and exit appropriately
|
||||
# if [[ "$LYCHEE_RC" -ne 0 ]]; then
|
||||
# echo -e "${RED}Lychee reported problems (exit $LYCHEE_RC). See:${NC}"
|
||||
# echo " - $RUN_LOG"
|
||||
# echo " - $CSV_OUT"
|
||||
# echo " - $STATIC_LOG"
|
||||
# exit 1
|
||||
# else
|
||||
# echo -e "${GREEN}Lychee completed successfully. See $CSV_OUT${NC}"
|
||||
# fi
|
||||
|
|
@ -2,16 +2,18 @@ click==8.3.1
|
|||
colorama==0.4.6
|
||||
deepmerge==2.0
|
||||
ghp-import==2.1.0
|
||||
griffe==1.15.0
|
||||
griffe==2.0.0
|
||||
griffecli==2.0.0
|
||||
griffelib==2.0.0
|
||||
Jinja2==3.1.6
|
||||
Markdown==3.10.1
|
||||
Markdown==3.10.2
|
||||
MarkupSafe==3.0.3
|
||||
mergedeep==1.3.4
|
||||
mkdocs==1.6.1
|
||||
mkdocs-autorefs==1.4.3
|
||||
mkdocs-autorefs==1.4.4
|
||||
mkdocs-get-deps==0.2.0
|
||||
mkdocstrings==1.0.2
|
||||
mkdocstrings-python==2.0.1
|
||||
mkdocstrings==1.0.3
|
||||
mkdocstrings-python==2.0.2
|
||||
packaging==26.0
|
||||
pathspec==1.0.4
|
||||
platformdirs==4.5.1
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
[project]
|
||||
copyright = "© Gugulethu Hlekwayo. All rights reserved."
|
||||
docs_dir = "content"
|
||||
extra_css = ["assets/css/g.css"]
|
||||
extra_css = ["assets/css/theme.css"]
|
||||
language = "en"
|
||||
nav = [{ 'Homepage' = "index.md" }, { 'Resume' = "resume.md" }]
|
||||
repo = "fontawesome/brands/git-alt"
|
||||
|
|
@ -9,7 +9,7 @@ repo_name = "g_it/gugulet.hu"
|
|||
repo_url = "https://git.gugulet.hu/g_it/site"
|
||||
site_author = "Gugulethu Hlekwayo"
|
||||
site_description = "Gwabini, Bele elide, bhoya benyathi"
|
||||
site_dir = "deploy"
|
||||
site_dir = "./deploy"
|
||||
site_name = "Gugulethu Hlekwayo"
|
||||
site_url = "https://gugulet.hu"
|
||||
|
||||
|
|
@ -52,8 +52,8 @@ pygments_lang_class = true
|
|||
[project.markdown_extensions.pymdownx.mark] # The mark extension allows the use of highlighting in text.
|
||||
|
||||
[project.markdown_extensions.pymdownx.smartsymbols] # The SmartSymbols extension converts some sequences of characters into their corresponding symbols.
|
||||
# [project.markdown_extensions.pymdownx.snippets] # The Snippets extension adds the ability to add a small tooltip to an element, by wrapping it with an abbr tag.
|
||||
# auto_append = ["includes/defintions.md"]
|
||||
# [project.markdown_extensions.pymdownx.snippets] # The Snippets extension adds the ability to add a small tooltip to an element, by wrapping it with an abbr tag.
|
||||
# auto_append = ["content/includes/definitions.md"]
|
||||
|
||||
[project.markdown_extensions.pymdownx.superfences] # The SuperFences extension allows for arbitrary nesting of code and content blocks inside each other.
|
||||
custom_fences = [
|
||||
|
|
|
|||