Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,9 @@ jobs:

- name: Build documentation
run: |
# Run make doc (which runs FORD then copies media)
make doc

# Copy media files to build directory after FORD runs (preserving structure)
mkdir -p build/doc/media/examples
cp -r doc/media/examples/* build/doc/media/examples/ 2>/dev/null || true

# Copy example documentation pages to build directory
mkdir -p build/doc/page/example
cp -r doc/example/*.md build/doc/page/example/ 2>/dev/null || true
Expand Down
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ run-release:

# Build documentation with FORD
doc:
ford README.md
# Copy example media files to doc build directory for proper linking
# Copy example media files to doc build directory BEFORE running FORD for proper linking
mkdir -p build/doc/media/examples
# Copy from doc/media if it exists (GitHub Actions workflow populates this)
if [ -d doc/media/examples ]; then cp -r doc/media/examples/* build/doc/media/examples/ 2>/dev/null || true; fi
Expand All @@ -106,6 +105,8 @@ doc:
cp "$$dir"*.mp4 "build/doc/media/examples/$$example_name/" 2>/dev/null || true; \
fi; \
done
# Now run FORD after media files are in place
ford README.md

# Generate coverage report
coverage:
Expand Down
122 changes: 122 additions & 0 deletions scripts/validate_github_pages_images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#!/bin/bash

# Validation script for GitHub Pages image paths - Issue #205
#
# This script validates that documentation images are correctly staged
# for GitHub Pages deployment with working relative path resolution

set -e

echo "============================================================"
echo "VALIDATING GITHUB PAGES IMAGE PATHS - Issue #205"
echo "============================================================"

# Test results
TESTS_PASSED=0
TESTS_FAILED=0
CRITICAL_ISSUES=0

function test_result() {
local test_name="$1"
local result="$2"
local message="$3"

if [ "$result" = "PASS" ]; then
echo "✓ PASS: $test_name"
[ -n "$message" ] && echo " $message"
TESTS_PASSED=$((TESTS_PASSED + 1))
elif [ "$result" = "FAIL" ]; then
echo "✗ FAIL: $test_name"
[ -n "$message" ] && echo " $message"
TESTS_FAILED=$((TESTS_FAILED + 1))
elif [ "$result" = "CRITICAL" ]; then
echo "❌ CRITICAL: $test_name"
[ -n "$message" ] && echo " $message"
CRITICAL_ISSUES=$((CRITICAL_ISSUES + 1))
TESTS_FAILED=$((TESTS_FAILED + 1))
else
echo "⚠ SKIP: $test_name"
[ -n "$message" ] && echo " $message"
fi
}

# Test 1: Check if documentation build directory exists
if [ -d "build/doc" ]; then
test_result "Documentation build directory" "PASS" "build/doc exists"
else
test_result "Documentation build directory" "FAIL" "build/doc not found - run 'make doc' first"
fi

# Test 2: Check if media staging directory exists
if [ -d "build/doc/media/examples" ]; then
test_result "Media staging directory" "PASS" "build/doc/media/examples exists"
else
test_result "Media staging directory" "CRITICAL" "build/doc/media/examples missing - images will be broken"
fi

# Test 3: Check workflow and Makefile for proper media staging
if [ -f ".github/workflows/docs.yml" ]; then
# Get lines around 'make doc' and check if cp comes BEFORE (which is correct)
context=$(grep -B 5 -A 5 "make doc" .github/workflows/docs.yml)
# Check if cp appears BEFORE make doc (in the -B 5 lines)
if echo "$context" | grep -B 5 "make doc" | grep -q "cp -r doc/media/examples"; then
test_result "Workflow media staging" "PASS" "Media copied before 'make doc' - paths will work correctly"
elif echo "$context" | grep -A 5 "make doc" | grep -q "cp -r doc/media/examples"; then
test_result "Workflow media staging" "CRITICAL" "Media copied after 'make doc' - will break image paths"
else
test_result "Workflow media staging" "PASS" "No media copy found near 'make doc'"
fi
else
test_result "Workflow file" "FAIL" "GitHub Actions workflow not found"
fi

if [ -f "Makefile" ]; then
doc_section=$(sed -n '/^doc:/,/^[a-zA-Z]/p' Makefile)
# Check if ford comes BEFORE any cp commands (which would be wrong)
ford_line=$(echo "$doc_section" | grep -n "ford" | cut -d: -f1)
first_cp_line=$(echo "$doc_section" | grep -n "cp.*doc/media" | head -1 | cut -d: -f1)

if [ -n "$ford_line" ] && [ -n "$first_cp_line" ]; then
if [ "$ford_line" -lt "$first_cp_line" ]; then
test_result "Makefile media staging" "CRITICAL" "FORD runs before media copy - will break image paths"
else
test_result "Makefile media staging" "PASS" "Media copied before FORD - paths will work correctly"
fi
elif [ -n "$ford_line" ]; then
test_result "Makefile media staging" "PASS" "FORD found, no media copy needed"
else
test_result "Makefile media staging" "FAIL" "FORD command not found in doc target"
fi
else
test_result "Makefile" "FAIL" "Makefile not found"
fi

# Summary
echo ""
echo "============================================================"
echo "VALIDATION SUMMARY"
echo "============================================================"
echo "Tests passed: $TESTS_PASSED"
echo "Tests failed: $TESTS_FAILED"
echo "Critical issues: $CRITICAL_ISSUES"

if [ $CRITICAL_ISSUES -gt 0 ]; then
echo ""
echo "❌ CRITICAL ISSUES FOUND"
echo "GitHub Pages documentation will have broken images!"
echo ""
echo "REQUIRED FIXES:"
echo "1. Copy media files BEFORE running FORD in both Makefile and workflow"
echo "2. Ensure media staging happens early in build process"
echo "3. Validate relative path resolution works correctly"
echo ""
exit 1
elif [ $TESTS_FAILED -gt 0 ]; then
echo ""
echo "⚠ Some tests failed - check configuration"
exit 1
else
echo ""
echo "✅ All tests passed - GitHub Pages images should work correctly"
exit 0
fi
234 changes: 234 additions & 0 deletions test/test_github_pages_image_paths_issue_205.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
!! Test for GitHub Pages image path resolution - Issue #205
!!
!! Given-When-Then Documentation:
!!
!! GIVEN:
!! - Documentation markdown files reference images with relative paths like "../../media/examples/basic_plots/simple_plot.png"
!! - FORD generates HTML files in subdirectories like "build/doc/page/example/"
!! - Media files need to be accessible at the correct relative paths for deployed GitHub Pages
!!
!! WHEN:
!! - Documentation build process runs
!! - FORD processes markdown files and generates HTML
!! - Media files are copied to build directory
!!
!! THEN:
!! - Media files should be accessible at the expected relative paths from generated HTML
!! - Image links in generated HTML should resolve correctly
!! - Both local builds and GitHub Pages deployment should work
!!
!! TEST SCENARIOS:
!! 1. Media file staging validation (pre-FORD copy requirement)
!! 2. Relative path resolution from generated HTML directories
!! 3. Documentation build process integration test
!! 4. Image accessibility validation for GitHub Pages structure
!!
program test_github_pages_image_paths_issue_205
use fortplot_security, only: get_test_output_path
implicit none

call test_media_file_staging_validation()
call test_relative_path_resolution_from_html()
call test_documentation_build_process_integration()
call test_image_accessibility_validation()

contains

subroutine test_media_file_staging_validation()
!! Given-When-Then: Test that media files are staged correctly before FORD runs
!!
!! GIVEN: Media files exist in source and output locations
!! WHEN: Documentation build process prepares files for FORD
!! THEN: Media files should be accessible at paths expected by markdown relative references

logical :: source_media_exists, staged_media_exists
character(len=:), allocatable :: source_path, expected_staged_path

print *, "=== Testing Media File Staging Validation ==="

! Given: Check source media files exist
source_path = "doc/media/examples/basic_plots/simple_plot.png"
inquire(file=source_path, exist=source_media_exists)

if (.not. source_media_exists) then
print *, "WARNING: Source media file not found: ", source_path
print *, "This test requires media files to be generated first"
endif

! When: Check if media files are staged where FORD-generated HTML expects them
! For HTML at build/doc/page/example/*.html, the path ../../media/examples/* should resolve to build/doc/media/examples/*
expected_staged_path = "build/doc/media/examples/basic_plots/simple_plot.png"
inquire(file=expected_staged_path, exist=staged_media_exists)

! Then: Media files should be staged correctly
if (source_media_exists .and. .not. staged_media_exists) then
print *, "FAIL: Media files not staged correctly for GitHub Pages"
print *, "Expected: ", expected_staged_path
print *, "This indicates media files are copied AFTER FORD runs (current broken behavior)"
call exit(1) ! This should fail until fix is implemented
elseif (staged_media_exists) then
print *, "PASS: Media files staged correctly at: ", expected_staged_path
else
print *, "SKIP: No source media files to test staging"
endif

print *, "=== Media File Staging Validation Complete ==="
end subroutine test_media_file_staging_validation

subroutine test_relative_path_resolution_from_html()
!! Given-When-Then: Test that relative paths resolve correctly from generated HTML locations
!!
!! GIVEN: FORD generates HTML files in nested directory structures
!! WHEN: Markdown uses relative paths like "../../media/examples/"
!! THEN: These paths should resolve correctly from the generated HTML location

logical :: html_dir_exists, target_media_exists
character(len=:), allocatable :: html_dir, relative_path_target

print *, "=== Testing Relative Path Resolution ==="

! Given: Check if FORD generates HTML in the expected location
html_dir = "build/doc/page/example"
inquire(file=trim(html_dir)//'/.', exist=html_dir_exists)

if (.not. html_dir_exists) then
print *, "INFO: HTML directory not found: ", html_dir
print *, "This test requires documentation to be built first"
endif

! When: Relative path from HTML should resolve to media location
! From build/doc/page/example/*.html, ../../media/examples/* should resolve to build/doc/media/examples/*
relative_path_target = "build/doc/media/examples"
inquire(file=trim(relative_path_target)//'/.', exist=target_media_exists)

! Then: Target directory should exist for relative paths to work
if (html_dir_exists .and. .not. target_media_exists) then
print *, "FAIL: Relative path target directory does not exist"
print *, "HTML dir exists: ", html_dir
print *, "Expected target: ", relative_path_target
print *, "Relative paths in generated HTML will be broken"
elseif (target_media_exists) then
print *, "PASS: Relative path target directory exists: ", relative_path_target
else
print *, "SKIP: Documentation not built, cannot test relative path resolution"
endif

print *, "=== Relative Path Resolution Test Complete ==="
end subroutine test_relative_path_resolution_from_html

subroutine test_documentation_build_process_integration()
!! Given-When-Then: Test the complete documentation build process
!!
!! GIVEN: Source documentation and media files exist
!! WHEN: Documentation build process runs (make doc)
!! THEN: Generated HTML should have working image references

logical :: makefile_exists, readme_exists

print *, "=== Testing Documentation Build Process Integration ==="

! Given: Check build environment prerequisites
inquire(file="Makefile", exist=makefile_exists)
inquire(file="README.md", exist=readme_exists)

if (.not. makefile_exists .or. .not. readme_exists) then
print *, "FAIL: Missing build prerequisites"
print *, "Makefile exists: ", makefile_exists
print *, "README.md exists: ", readme_exists
call exit(1)
endif

! When: Documentation build process should work
! This is validated by checking that the staging happens correctly
print *, "INFO: Documentation build integration requires:"
print *, " 1. Media files copied to build/doc/media/examples/ BEFORE FORD runs"
print *, " 2. FORD processes markdown files with working relative paths"
print *, " 3. Generated HTML can access images via ../../media/examples/ paths"

! Then: The build process structure should support GitHub Pages deployment
print *, "VALIDATION: Current build process analysis:"
print *, " - Makefile copies media AFTER FORD (lines 95-108): BROKEN"
print *, " - GitHub Actions copies media AFTER FORD (lines 83-85): BROKEN"
print *, " - Need to copy media BEFORE FORD for relative paths to work"

print *, "=== Documentation Build Process Integration Test Complete ==="
end subroutine test_documentation_build_process_integration

subroutine test_image_accessibility_validation()
!! Given-When-Then: Test that images are accessible for GitHub Pages deployment
!!
!! GIVEN: Documentation is built with media files
!! WHEN: Deployed to GitHub Pages at lazy-fortran.github.io/fortplot/
!! THEN: Image links should work correctly in the deployed environment

logical :: build_doc_exists, media_examples_exists
character(len=:), allocatable :: github_pages_media_path

print *, "=== Testing Image Accessibility for GitHub Pages ==="

! Given: Check if documentation build directory exists
inquire(file="build/doc/.", exist=build_doc_exists)

if (.not. build_doc_exists) then
print *, "INFO: build/doc directory not found, cannot test accessibility"
print *, "Run 'make doc' first to generate documentation"
return
endif

! When: Check if media files are in the correct location for GitHub Pages
github_pages_media_path = "build/doc/media/examples"
inquire(file=trim(github_pages_media_path)//'/.', exist=media_examples_exists)

! Then: Media files should be accessible at the expected GitHub Pages URLs
if (.not. media_examples_exists) then
print *, "FAIL: Media files not accessible for GitHub Pages deployment"
print *, "Expected at: ", github_pages_media_path
print *, "This will cause broken images in deployed documentation"
print *, "Current broken URL pattern: https://lazy-fortran.github.io/fortplot/page/example/basic_plots.html"
print *, "Tries to access: ../../media/examples/basic_plots/simple_plot.png"
print *, "Should resolve to: https://lazy-fortran.github.io/fortplot/media/examples/basic_plots/simple_plot.png"
else
print *, "PASS: Media files accessible for GitHub Pages at: ", github_pages_media_path
endif

! Additional validation for specific example files
call validate_specific_image_files()

print *, "=== Image Accessibility Validation Complete ==="
end subroutine test_image_accessibility_validation

subroutine validate_specific_image_files()
!! Validate specific image files mentioned in the issue
logical :: basic_plots_png_exists, basic_plots_pdf_exists
character(len=:), allocatable :: png_path, pdf_path

print *, " --- Validating Specific Files ---"

! Check for basic_plots example files (mentioned in issue)
png_path = "build/doc/media/examples/basic_plots/simple_plot.png"
pdf_path = "build/doc/media/examples/basic_plots/simple_plot.pdf"

inquire(file=png_path, exist=basic_plots_png_exists)
inquire(file=pdf_path, exist=basic_plots_pdf_exists)

if (basic_plots_png_exists) then
print *, " PASS: basic_plots PNG accessible: ", png_path
else
print *, " FAIL: basic_plots PNG not accessible: ", png_path
endif

if (basic_plots_pdf_exists) then
print *, " PASS: basic_plots PDF accessible: ", pdf_path
else
print *, " FAIL: basic_plots PDF not accessible: ", pdf_path
endif

! Validate that these files would be accessible via GitHub Pages URLs
if (basic_plots_png_exists .and. basic_plots_pdf_exists) then
print *, " SUCCESS: Files should be accessible at GitHub Pages URLs:"
print *, " PNG: https://lazy-fortran.github.io/fortplot/media/examples/basic_plots/simple_plot.png"
print *, " PDF: https://lazy-fortran.github.io/fortplot/media/examples/basic_plots/simple_plot.pdf"
endif
end subroutine validate_specific_image_files

end program test_github_pages_image_paths_issue_205
Loading