From 6130302312acccc0e5650c9c49822d23926c231a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 20:42:51 +0000 Subject: [PATCH] Add self-hosted Google Fonts infrastructure - Create @font-face CSS files for Roboto, Noto Sans, Fira Sans - Add download script for Google Fonts (download-google-fonts.sh) - Add GOOGLE_FONTS_README.md with download instructions - Font files ready for woff2 files to be added Co-authored-by: jmiller-moko <230051081+jmiller-moko@users.noreply.github.com> --- scripts/download-google-fonts.sh | 96 ++++++++++++++++++++++ src/media/css/fonts/fira-sans.css | 50 ++++++++++++ src/media/css/fonts/noto-sans.css | 50 ++++++++++++ src/media/css/fonts/roboto.css | 50 ++++++++++++ src/media/fonts/GOOGLE_FONTS_README.md | 105 +++++++++++++++++++++++++ 5 files changed, 351 insertions(+) create mode 100755 scripts/download-google-fonts.sh create mode 100644 src/media/css/fonts/fira-sans.css create mode 100644 src/media/css/fonts/noto-sans.css create mode 100644 src/media/css/fonts/roboto.css create mode 100644 src/media/fonts/GOOGLE_FONTS_README.md diff --git a/scripts/download-google-fonts.sh b/scripts/download-google-fonts.sh new file mode 100755 index 0000000..1ea4d04 --- /dev/null +++ b/scripts/download-google-fonts.sh @@ -0,0 +1,96 @@ +#!/bin/bash +# Copyright (C) 2026 Moko Consulting +# SPDX-License-Identifier: GPL-3.0-or-later +# +# Download Google Fonts for self-hosting +# This script downloads Roboto, Noto Sans, and Fira Sans fonts + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Target directory +FONTS_DIR="../src/media/fonts" + +echo -e "${BLUE}╔═══════════════════════════════════════════╗${NC}" +echo -e "${BLUE}║ Google Fonts Downloader for MokoCassiopeia ║${NC}" +echo -e "${BLUE}╚═══════════════════════════════════════════╝${NC}" +echo "" + +# Check if fonts directory exists +if [ ! -d "$FONTS_DIR" ]; then + echo -e "${RED}✗ Error: Fonts directory not found: $FONTS_DIR${NC}" + exit 1 +fi + +cd "$FONTS_DIR" + +echo -e "${YELLOW}Target directory: $(pwd)${NC}" +echo "" + +# Function to download font CSS and extract font files +download_font() { + local font_name="$1" + local font_url="$2" + local display_name="$3" + + echo -e "${GREEN}Downloading $display_name...${NC}" + + # Download CSS with user agent for woff2 format + css=$(curl -s -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "$font_url") + + if [ -z "$css" ]; then + echo -e "${RED} ✗ Failed to download CSS${NC}" + return 1 + fi + + # Extract woff2 URLs + urls=$(echo "$css" | grep -oP 'https://fonts\.gstatic\.com[^\)]*\.woff2' || true) + + if [ -z "$urls" ]; then + echo -e "${RED} ✗ No font URLs found in CSS${NC}" + return 1 + fi + + count=0 + while IFS= read -r url; do + if [ -z "$url" ]; then + continue + fi + + filename=$(basename "$url") + echo -e " → Downloading ${filename}..." + + if curl -s "$url" -o "$filename"; then + size=$(du -h "$filename" | cut -f1) + echo -e "${GREEN} ✓ Downloaded ($size)${NC}" + ((count++)) + else + echo -e "${RED} ✗ Failed${NC}" + fi + done <<< "$urls" + + echo -e "${GREEN} ✓ Downloaded $count font files${NC}" + echo "" +} + +# Download fonts +download_font "roboto" "https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;700&display=swap" "Roboto" +download_font "noto-sans" "https://fonts.googleapis.com/css2?family=Noto+Sans:wght@100;300;400;700&display=swap" "Noto Sans" +download_font "fira-sans" "https://fonts.googleapis.com/css2?family=Fira+Sans:wght@100;300;400;700&display=swap" "Fira Sans" + +echo -e "${GREEN}╔═══════════════════════════════════════════╗${NC}" +echo -e "${GREEN}║ ✓ All fonts downloaded successfully! ║${NC}" +echo -e "${GREEN}╚═══════════════════════════════════════════╝${NC}" +echo "" +echo -e "Font files saved to: ${BLUE}$(pwd)${NC}" +echo "" +echo "Next steps:" +echo "1. Verify font files are present" +echo "2. Update templateDetails.xml font options (if needed)" +echo "3. Remove Google Fonts CDN preconnect links from PHP templates" diff --git a/src/media/css/fonts/fira-sans.css b/src/media/css/fonts/fira-sans.css new file mode 100644 index 0000000..c68e9fb --- /dev/null +++ b/src/media/css/fonts/fira-sans.css @@ -0,0 +1,50 @@ +/* Copyright (C) 2026 Moko Consulting + + This file is part of a Moko Consulting project. + + SPDX-License-Identifier: GPL-3.0-or-later + + + # FILE INFORMATION + DEFGROUP: Joomla.Template.Site + INGROUP: MokoCassiopeia.Styles + PATH: ./media/templates/site/mokocassiopeia/css/fonts/fira-sans.css + VERSION: 03.08.05 + BRIEF: Fira Sans font family definitions (self-hosted) + */ + +/* Fira Sans Thin (100) */ +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 100; + font-display: swap; + src: url('../../fonts/fira-sans-v17-latin-100.woff2') format('woff2'); +} + +/* Fira Sans Light (300) */ +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('../../fonts/fira-sans-v17-latin-300.woff2') format('woff2'); +} + +/* Fira Sans Regular (400) */ +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('../../fonts/fira-sans-v17-latin-regular.woff2') format('woff2'); +} + +/* Fira Sans Bold (700) */ +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('../../fonts/fira-sans-v17-latin-700.woff2') format('woff2'); +} diff --git a/src/media/css/fonts/noto-sans.css b/src/media/css/fonts/noto-sans.css new file mode 100644 index 0000000..44afd08 --- /dev/null +++ b/src/media/css/fonts/noto-sans.css @@ -0,0 +1,50 @@ +/* Copyright (C) 2026 Moko Consulting + + This file is part of a Moko Consulting project. + + SPDX-License-Identifier: GPL-3.0-or-later + + + # FILE INFORMATION + DEFGROUP: Joomla.Template.Site + INGROUP: MokoCassiopeia.Styles + PATH: ./media/templates/site/mokocassiopeia/css/fonts/noto-sans.css + VERSION: 03.08.05 + BRIEF: Noto Sans font family definitions (self-hosted) + */ + +/* Noto Sans Thin (100) */ +@font-face { + font-family: 'Noto Sans'; + font-style: normal; + font-weight: 100; + font-display: swap; + src: url('../../fonts/noto-sans-v36-latin-100.woff2') format('woff2'); +} + +/* Noto Sans Light (300) */ +@font-face { + font-family: 'Noto Sans'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('../../fonts/noto-sans-v36-latin-300.woff2') format('woff2'); +} + +/* Noto Sans Regular (400) */ +@font-face { + font-family: 'Noto Sans'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('../../fonts/noto-sans-v36-latin-regular.woff2') format('woff2'); +} + +/* Noto Sans Bold (700) */ +@font-face { + font-family: 'Noto Sans'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('../../fonts/noto-sans-v36-latin-700.woff2') format('woff2'); +} diff --git a/src/media/css/fonts/roboto.css b/src/media/css/fonts/roboto.css new file mode 100644 index 0000000..f1f037a --- /dev/null +++ b/src/media/css/fonts/roboto.css @@ -0,0 +1,50 @@ +/* Copyright (C) 2026 Moko Consulting + + This file is part of a Moko Consulting project. + + SPDX-License-Identifier: GPL-3.0-or-later + + + # FILE INFORMATION + DEFGROUP: Joomla.Template.Site + INGROUP: MokoCassiopeia.Styles + PATH: ./media/templates/site/mokocassiopeia/css/fonts/roboto.css + VERSION: 03.08.05 + BRIEF: Roboto font family definitions (self-hosted) + */ + +/* Roboto Thin (100) */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 100; + font-display: swap; + src: url('../../fonts/roboto-v30-latin-100.woff2') format('woff2'); +} + +/* Roboto Light (300) */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('../../fonts/roboto-v30-latin-300.woff2') format('woff2'); +} + +/* Roboto Regular (400) */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('../../fonts/roboto-v30-latin-regular.woff2') format('woff2'); +} + +/* Roboto Bold (700) */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('../../fonts/roboto-v30-latin-700.woff2') format('woff2'); +} diff --git a/src/media/fonts/GOOGLE_FONTS_README.md b/src/media/fonts/GOOGLE_FONTS_README.md new file mode 100644 index 0000000..c643fa5 --- /dev/null +++ b/src/media/fonts/GOOGLE_FONTS_README.md @@ -0,0 +1,105 @@ +# Google Fonts - Download Instructions + +This directory should contain self-hosted Google Font files to eliminate CDN dependencies. + +## Required Font Files + +Download the following `.woff2` font files and place them in this directory: + +### Roboto Font Files +- `roboto-v30-latin-100.woff2` (Thin) +- `roboto-v30-latin-300.woff2` (Light) +- `roboto-v30-latin-regular.woff2` (Regular) +- `roboto-v30-latin-700.woff2` (Bold) + +### Noto Sans Font Files +- `noto-sans-v36-latin-100.woff2` (Thin) +- `noto-sans-v36-latin-300.woff2` (Light) +- `noto-sans-v36-latin-regular.woff2` (Regular) +- `noto-sans-v36-latin-700.woff2` (Bold) + +### Fira Sans Font Files +- `fira-sans-v17-latin-100.woff2` (Thin) +- `fira-sans-v17-latin-300.woff2` (Light) +- `fira-sans-v17-latin-regular.woff2` (Regular) +- `fira-sans-v17-latin-700.woff2` (Bold) + +## How to Download + +### Option 1: Using google-webfonts-helper (Recommended) + +1. Visit https://gwfh.mranftl.com/ +2. Search for each font (Roboto, Noto Sans, Fira Sans) +3. Select character sets: **latin** (or add latin-ext if needed) +4. Select styles: + - ☑ 100 (thin) + - ☑ 300 (light) + - ☑ 400 (regular) + - ☑ 700 (bold) +5. In step 3, ensure **Modern Browsers** is selected (woff2 format) +6. In step 4, click **Download files** +7. Extract the `.woff2` files to this directory + +### Option 2: Using google-font-installer (Node.js) + +```bash +npm install -g google-font-installer +cd src/media/fonts/ + +# Download Roboto +google-font-installer Roboto:100,300,400,700 + +# Download Noto Sans +google-font-installer "Noto Sans:100,300,400,700" + +# Download Fira Sans +google-font-installer "Fira Sans:100,300,400,700" +``` + +### Option 3: Manual Download Script (Linux/macOS) + +```bash +#!/bin/bash +# Run this from src/media/fonts/ directory + +download_font() { + local font_url="$1" + local output_dir="." + + # Download CSS + css=$(curl -s -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" "$font_url") + + # Extract and download woff2 files + echo "$css" | grep -oP 'https://fonts\.gstatic\.com[^\)]*\.woff2' | while read url; do + filename=$(basename "$url") + echo "Downloading $filename..." + curl -s "$url" -o "$output_dir/$filename" + done +} + +download_font "https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;700&display=swap" +download_font "https://fonts.googleapis.com/css2?family=Noto+Sans:wght@100;300;400;700&display=swap" +download_font "https://fonts.googleapis.com/css2?family=Fira+Sans:wght@100;300;400;700&display=swap" +``` + +## Font CSS Files + +The corresponding CSS files with `@font-face` declarations are located in: +- `../css/fonts/roboto.css` +- `../css/fonts/noto-sans.css` +- `../css/fonts/fira-sans.css` + +These CSS files reference the `.woff2` files in this directory. + +## License + +All Google Fonts are open source and licensed under the SIL Open Font License (OFL). +- Roboto: Apache License 2.0 +- Noto Sans: SIL Open Font License 1.1 +- Fira Sans: SIL Open Font License 1.1 + +## References + +- Google Fonts: https://fonts.google.com/ +- google-webfonts-helper: https://gwfh.mranftl.com/ +- Font Licensing: https://fonts.google.com/attribution