diff --git a/_scripts/add-index-html-links.sh b/_scripts/add-index-html-links.sh new file mode 100644 index 00000000000..64da55347ff --- /dev/null +++ b/_scripts/add-index-html-links.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# Post-processing script for Siemens internal deployment. +# Rewrites directory-style href links (ending with /) to explicit /index.html +# links in all HTML files under public/, so the Siemens server can serve them +# without requiring automatic directory index support. +# +# When built with the siemens-internal environment, canonifyURLs=true causes Hugo +# to expand all internal links to full absolute URLs using the baseURL. Pass that +# baseURL as the second argument so those links are rewritten too. +# +# Rewrites both plain directory links and directory links with anchors: +# href=".../path/" → href=".../path/index.html" +# href=".../path/#anchor" → href=".../path/index.html#anchor" +# +# Skips: +# - External links (contain :// but do not start with base-url) +# - Anchor-only links starting with # +# - Links already containing index.html or ending in .html/.htm +# +# Usage: bash _scripts/add-index-html-links.sh [public-dir] [base-url] +# Default public-dir: public +# Default base-url: (empty — only root-relative and relative links are rewritten) +# +# Example (siemens-internal build): +# bash _scripts/add-index-html-links.sh public \ +# https://internal.docs.sw.siemens.com/documentation/internal/PL20260323299104942/en-US/Mendix-Docs/public/ + +set -euo pipefail + +PUBLIC_DIR="${1:-public}" +BASE_URL="${2:-}" + +if [ ! -d "$PUBLIC_DIR" ]; then + echo "Error: directory '$PUBLIC_DIR' not found. Run hugo build first." >&2 + exit 1 +fi + +echo "Adding index.html to directory links in $PUBLIC_DIR..." +[ -n "$BASE_URL" ] && echo "Treating '$BASE_URL' as internal base URL." + +python3 - "$PUBLIC_DIR" "$BASE_URL" << 'PYTHON' +import re, sys +from pathlib import Path + +public_dir = sys.argv[1] +base_url = sys.argv[2].rstrip("/") + "/" if sys.argv[2] else "" + +HREF_RE = re.compile(r"""(href=["'])([^"']*)(["'])""") + +def rewrite_href(m): + pre, url, quote = m.group(1), m.group(2), m.group(3) + + # Treat absolute URLs that start with base_url as internal; skip all others + if "://" in url: + if not (base_url and url.startswith(base_url)): + return m.group(0) + + # Skip anchor-only links + if url.startswith("#"): + return m.group(0) + + # Split off any fragment (e.g. /path/#anchor → path=/path/, fragment=#anchor) + fragment = "" + if "#" in url: + url, fragment = url.split("#", 1) + fragment = "#" + fragment + + # Skip already-explicit file links + if url.endswith(".html") or url.endswith(".htm"): + return f"{pre}{url}{fragment}{quote}" + + if url.endswith("/"): + url = url + "index.html" + return f"{pre}{url}{fragment}{quote}" + +count = 0 +for path in Path(public_dir).rglob("*.html"): + original = path.read_text(encoding="utf-8", errors="replace") + updated = HREF_RE.sub(rewrite_href, original) + if updated != original: + path.write_text(updated, encoding="utf-8") + count += 1 + +print(f"Updated {count} HTML files.") +PYTHON diff --git a/_scripts/fix-siemens-paths.sh b/_scripts/fix-siemens-paths.sh new file mode 100644 index 00000000000..42673ae6d59 --- /dev/null +++ b/_scripts/fix-siemens-paths.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# Post-processing script for Siemens internal deployment +# NOTE: As of Hugo v0.156.0, the doubled-path bug has been fixed. +# This script is kept for backwards compatibility but no longer performs any actions. + +echo "Siemens internal deployment post-processing..." +echo "✓ Hugo v0.156.0+ correctly handles deep baseURL paths" +echo "✓ No file copying needed - all asset references are correct" +echo "Done!" diff --git a/assets/scss/_font-face.scss b/assets/scss/_font-face.scss index db27cd448a2..afe1020d3d4 100644 --- a/assets/scss/_font-face.scss +++ b/assets/scss/_font-face.scss @@ -1,35 +1,35 @@ @font-face { // LZ - Added for MxDock by request 2024-01-30 font-family: "noto-sans"; - src: local("noto-sans"), url("/fonts/noto-sans/noto-sans-400.woff2") format("woff2"); + src: local("noto-sans"), url("../fonts/noto-sans/noto-sans-400.woff2") format("woff2"); font-style: normal; font-weight: 400; font-display: swap; } - + @font-face { font-family: "noto-sans"; - src: local("noto-sans"), url("/fonts/noto-sans/noto-sans-400-italic.woff2") format("woff2"); + src: local("noto-sans"), url("../fonts/noto-sans/noto-sans-400-italic.woff2") format("woff2"); font-style: italic; font-weight: 400; font-display: swap; } - + @font-face { font-family: "noto-sans"; - src: local("noto-sans"), url("/fonts/noto-sans/noto-sans-600.woff2") format("woff2"); + src: local("noto-sans"), url("../fonts/noto-sans/noto-sans-600.woff2") format("woff2"); font-style: normal; font-weight: 600; font-display: swap; } - + @font-face { font-family: "noto-sans"; - src: local("noto-sans"), url("/fonts/noto-sans/noto-sans-600-italic.woff2") format("woff2"); + src: local("noto-sans"), url("../fonts/noto-sans/noto-sans-600-italic.woff2") format("woff2"); font-style: italic; font-weight: 600; font-display: swap; } - + /* Medium */ @font-face { font-family: "Patron"; @@ -37,9 +37,9 @@ font-weight: 500; font-display: swap; src: local("Patron Medium"), local("Patron-Medium"), - url("/fonts/patron/PatronWEB-Medium.woff2") format("woff2"); + url("../fonts/patron/PatronWEB-Medium.woff2") format("woff2"); } - + /* Light */ @font-face { font-family: "Patron"; @@ -47,7 +47,7 @@ font-weight: 300; font-display: swap; src: local("Patron Light"), local("Patron-Light"), - url("/fonts/patron/PatronWEB-Light.woff2") format("woff2"); + url("../fonts/patron/PatronWEB-Light.woff2") format("woff2"); } /* The main font is Noto Sans */ diff --git a/config/siemens-internal/INDEX-HTML-WORKAROUND.md b/config/siemens-internal/INDEX-HTML-WORKAROUND.md new file mode 100644 index 00000000000..42263ef3ac5 --- /dev/null +++ b/config/siemens-internal/INDEX-HTML-WORKAROUND.md @@ -0,0 +1,157 @@ +# Adding index.html to Directory Links for Siemens Deployment + +## The Problem + +The Siemens internal web server does not automatically serve `index.html` when a directory URL is requested. When a user or browser requests `https://internal.docs.sw.siemens.com/documentation/internal/PL20260323299104942/en-US/Mendix-Docs/public/refguide/`, the server does not automatically serve the `refguide/index.html` file. + +Hugo's `uglyURLs = true` setting helps by making URLs explicit where possible, but Hugo still generates many directory-style links (ending with `/`) throughout the site, particularly in: + +* Navigation menus +* Breadcrumbs +* Internal page links +* Table of contents + +## Recommended Solution: Post-Processing + +The cleanest approach is to post-process the HTML files after Hugo builds them, rewriting directory links to explicitly include `/index.html`. + +### How It Works + +1. **Hugo builds the site normally** using the siemens-internal environment +2. **Post-processing script runs** and: + * Scans all HTML files in the `public/` directory + * Identifies internal links that end with `/` (directory links) + * Rewrites them to end with `/index.html` + * Preserves external links, anchor links, and explicit file references unchanged + +3. **Resulting HTML has explicit paths** that the Siemens server can serve correctly + +### Link Transformation Examples + +**Navigation links:** + +```html + + + + + +``` + +**Breadcrumb links:** + +```html + + + + + +``` + +### What Gets Changed + +✅ **Internal directory links**: `href=".../"` → `href=".../index.html"` +✅ **Internal directory links with anchors**: `href=".../#section"` → `href=".../index.html#section"` + +❌ **External links**: `href="https://example.com/..."` (unchanged) +❌ **Anchor-only links**: `href="#section"` (unchanged) +❌ **File links**: `href=".../page.html"` (unchanged) +❌ **Protocol links**: `href="mailto:..."`, `href="javascript:..."` (unchanged) + +### Implementation Approach + +The post-processing can be implemented using standard text processing tools: + +**Option 1: Using sed (bash)** + +* Fast and simple for straightforward pattern matching +* May require careful escaping of special characters +* Best for simple, well-defined patterns + +**Option 2: Using a scripting language (Python/Node.js)** + +* More reliable HTML parsing +* Better handling of edge cases +* Can use proper HTML parsers (BeautifulSoup, cheerio, etc.) +* More maintainable for complex transformations + +**Option 3: Using specialized tools (htmlq, pup)** + +* Purpose-built for HTML manipulation +* Balance between sed simplicity and full scripting power + +### Integration with Build Process + +Update the build workflow to: + +```bash +# Build the site +hugo --environment siemens-internal --cleanDestinationDir + +# Post-process to add index.html to directory links +bash _scripts/add-index-html-links.sh public \ + https://internal.docs.sw.siemens.com/documentation/internal/PL20260323299104942/en-US/Mendix-Docs/public/ +``` + +The script is kept in `_scripts/` alongside the existing (now no-op) `fix-siemens-paths.sh`. + +### Advantages + +* ✅ **Non-invasive**: Does not require modifying Hugo templates or Docsy theme files +* ✅ **Environment-specific**: Only affects siemens-internal builds +* ✅ **Maintainable**: Clear separation between Hugo build and Siemens-specific processing +* ✅ **Reversible**: Disable by skipping the post-processing step +* ✅ **Hugo-version independent**: Works regardless of Hugo updates +* ✅ **Preserves other outputs**: Standard HTML and print versions remain unchanged + +### Disadvantages + +* ❌ **Build-time overhead**: Adds processing time (likely 5-30 seconds depending on implementation) +* ❌ **Two-step process**: Requires running a script after Hugo build +* ❌ **Pattern matching complexity**: Must identify which links to transform precisely + +## Alternative Solution: Hugo Render Hooks and Custom Layouts + +Instead of post-processing, modify Hugo's rendering behavior at build time. + +### How It Works + +1. **Create custom render hooks** for Markdown links in `.layouts/_default/_markup/` +2. **Override navigation partials** from Docsy theme to append `/index.html` +3. **Configure hooks** to only apply for siemens-internal environment + +### Required Changes + +* Copy Docsy navigation partial files to local `layouts/` directory +* Modify link generation logic to append `/index.html` to directory URLs +* Create Markdown render hooks for content links +* Add conditional logic to check environment + +### Advantages + +* ✅ **Build-time only**: No post-processing step required +* ✅ **Single build command**: Just run `hugo --environment siemens-internal` + +### Disadvantages + +* ❌ **More invasive**: Requires copying and modifying theme files +* ❌ **Maintenance burden**: Must update custom layouts when Docsy updates +* ❌ **Complexity**: Multiple layout files need modification +* ❌ **Testing required**: Must verify all link types work correctly +* ❌ **Harder to isolate**: Siemens-specific logic mixed with layout code + +## Recommendation + +Use the **post-processing approach** because: + +1. Hugo v0.156.0 already eliminated the need for the previous doubled-path workaround, and the post-processing approach proved straightforward to implement +2. The script can be kept simple and focused on one task +3. It does not require maintaining customized Docsy theme files +4. It is easier to test, debug, and modify +5. It keeps the Siemens-specific logic isolated and well-documented + +The slight increase in build time is acceptable for a deployment that happens infrequently, and the maintainability benefits outweigh the minor inconvenience of a two-step build process. + +## Status + +This solution has been implemented. The script is at `_scripts/add-index-html-links.sh` and the build steps are documented in `config/siemens-internal/README.md`. diff --git a/config/siemens-internal/README.md b/config/siemens-internal/README.md new file mode 100644 index 00000000000..4a8bb409b64 --- /dev/null +++ b/config/siemens-internal/README.md @@ -0,0 +1,114 @@ +# Siemens Internal Deployment Configuration + +This directory contains the Hugo environment configuration for deploying the Mendix documentation to the Siemens internal documentation portal. + +## Deployment URL + +The site is deployed at: + +``` +https://internal.docs.sw.siemens.com/documentation/internal/PL20260323299104942/en-US/Mendix-Docs/public/ +``` + +## The Problems + +### 1. Deep URL Path (Fixed in Hugo v0.156.0+) + +**Historical Issue**: Earlier versions of Hugo had a bug where `canonifyURLs` generated doubled paths for CSS and JS assets when deploying to a deep URL path (not at the domain root). + +Example of the old bug: + +* Expected: `https://internal.docs.sw.siemens.com/documentation/internal/PL20260323299104942/en-US/Mendix-Docs/public/scss/main.css` +* Generated: `https://internal.docs.sw.siemens.com/documentation/internal/PL20260323299104942/en-US/Mendix-Docs/public/documentation/internal/PL20260323299104942/en-US/public/scss/main.css` + +**Status**: ✅ This issue was fixed in Hugo v0.156.0. The `canonifyURLs` setting now correctly handles deep baseURL paths without generating doubled paths. + +### 2. Pretty URLs Not Supported + +The Siemens internal server does not serve Hugo's default "pretty URLs" (like `/page/` resolving to `/page/index.html`). `uglyURLs = true` helps, but Hugo still generates many directory-style links (ending with `/`) in navigation menus, breadcrumbs, and table-of-contents entries. + +A post-processing script rewrites all remaining directory-style `href` links to include `/index.html` explicitly. + +## The Solution + +Configure Hugo with the appropriate settings for deep URL deployment, then run the post-processing script: + +1. **Set the full baseURL** including the deep path +2. **Enable `canonifyURLs = true`** to convert all root-relative URLs to use the baseURL +3. **Enable `uglyURLs = true`** to reduce (but not eliminate) directory-style links +4. **Use relative font paths** in CSS (`../fonts/` instead of `/fonts/`) to work across all environments +5. **Run `add-index-html-links.sh`** to rewrite remaining `href=".../"` links to `href=".../index.html"` + +## How to Build + +Run these commands from the repository root: + +```bash +# Build the site with the siemens-internal environment +hugo --environment siemens-internal --cleanDestinationDir + +# Rewrite directory-style links to include index.html. +# The second argument (the site's baseURL) is required: the siemens-internal build uses +# canonifyURLs=true, which expands all internal links to full absolute URLs. Without the +# baseURL argument, the script cannot tell internal links from external ones and skips them. +bash _scripts/add-index-html-links.sh public \ + https://internal.docs.sw.siemens.com/documentation/internal/PL20260323299104942/en-US/Mendix-Docs/public/ +``` + +The built site will be in the `public/` directory, ready for deployment to the Siemens internal portal. + +## Configuration Files + +### Hugo.toml + +Sets the baseURL and enables: + +* `canonifyURLs = true` to handle the deep deployment path +* `uglyURLs = true` to ensure proper URL resolution on the Siemens server + +### _scripts/add-index-html-links.sh + +Rewrites all `href=".../"` directory-style links in the built HTML to `href=".../index.html"` so the Siemens server can serve them without automatic directory index support. Run this after every Hugo build. + +Skips external links, anchor links, links that already end in `.html`, and print URLs. + +### _scripts/fix-siemens-paths.sh + +**Legacy script** — kept for backward compatibility but no longer needed with Hugo v0.156.0+. + +Previously used to work around a Hugo bug where `canonifyURLs` generated doubled paths for CSS and JS files. The bug has been fixed, and the script now only prints a confirmation message. + +## Technical Details + +### Why CanonifyURLs? + +The `canonifyURLs = true` setting converts all root-relative URLs (like `/images/foo.svg`) to absolute URLs using the baseURL. This is necessary because: + +* Images in templates use hardcoded paths like `/images/...` and `/icons/...` +* Internal page links need the full path +* Without it, all these references would be broken + +### Why Relative Font Paths? + +Font files are referenced in CSS using relative paths (`../fonts/`, `../webfonts/`) rather than root-relative paths (`/fonts/`). This approach: + +* Works consistently across all deployment environments (production, development, siemens-internal) +* Does not require environment-specific processing +* Avoids issues with deep URL paths + +### Hugo Version Requirements + +* **Hugo v0.156.0 or later** is required for correct handling of deep baseURL paths with `canonifyURLs` +* Earlier versions had a bug where `canonifyURLs` would generate doubled paths for CSS and JS assets + +## Updating the Deployment Path + +If the Siemens deployment URL changes, update the `baseURL` in `config/siemens-internal/hugo.toml`. + +## Alternative Approaches Considered + +1. **Using relativeURLs**: Breaks the landing page images and requires template changes +2. **Path-only baseURL**: Requires web server configuration and does not work with direct file access +3. **Template modifications**: Requires maintaining custom versions of Docsy theme files + +The current solution (Hugo configuration plus a focused post-processing script) is the simplest and most maintainable approach. diff --git a/config/siemens-internal/hugo.toml b/config/siemens-internal/hugo.toml new file mode 100644 index 00000000000..37370ec4398 --- /dev/null +++ b/config/siemens-internal/hugo.toml @@ -0,0 +1,17 @@ +# Merges with _default/config.toml if --environment internal +# Configuration for internal Siemens documentation deployment +# Need to set _merge = 'deep' to overwrite original value +# ============================================================= + +baseURL = "https://internal.docs.sw.siemens.com/documentation/internal/PL20260323299104942/en-US/Mendix-Docs/public/" +title = "Mendix Documentation (Internal)" + +# Convert all absolute paths (starting with /) to use the full baseURL +# This fixes images and most links. The CSS path doubling issue can be fixed with post-processing. +canonifyURLs = true + +# Disable robots.txt for internal deployment +enableRobotsTXT = false + +# Enable ugly URLs to help links work on the Siemens site +uglyURLs = true \ No newline at end of file