From 96946a5f4bf2554a5bdfbafb21e761eda093e4f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gaute=20R=C3=B8nningen?= Date: Fri, 12 Sep 2025 17:04:55 +0200 Subject: [PATCH 1/3] Add Cursor AI rules --- .cursor/rules/mathml-guidelines.mdc | 245 ++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 .cursor/rules/mathml-guidelines.mdc diff --git a/.cursor/rules/mathml-guidelines.mdc b/.cursor/rules/mathml-guidelines.mdc new file mode 100644 index 0000000..863f1f6 --- /dev/null +++ b/.cursor/rules/mathml-guidelines.mdc @@ -0,0 +1,245 @@ +--- +description: Cursor AI guidelines for this repo +alwaysApply: true +--- + +# MathML Guidelines Project - Cursor Rules + +## Project Overview + +This is a Jekyll-based documentation site for Nordic MathML Guidelines, featuring: + +- Jekyll static site generation with GitHub Pages deployment +- Python scripts for LaTeX to MathML conversion +- Comprehensive testing infrastructure +- Markdown-based content with MathML examples + +## File Structure & Conventions + +### Core Files + +- `_config.yml` - Jekyll configuration +- `Gemfile` - Ruby dependencies for Jekyll +- `Nordic MathML Guidelines.md` - Source markdown content +- `_pages/` - Generated Jekyll pages +- `images/` - Documentation images and examples + +### Scripts Directory + +- `scripts/convert-guidelines.sh` - Main conversion script (Bash) +- `scripts/convert-mathml.py` - LaTeX to MathML converter (Python 3) + +### Testing + +- `tests/` - All test files +- `tests/test-conversion-workflow.py` - Main test suite +- `tests/test-conversion.sh` - Conversion testing +- `tests/test-local.sh` - Local testing + +## Coding Standards + +### Python Scripts + +- Use Python 3.9+ with type hints where appropriate +- Follow PEP 8 style guidelines +- Use descriptive function and variable names +- Include comprehensive docstrings for functions +- Handle encoding explicitly (UTF-8) +- Use regex patterns for LaTeX to MathML conversion +- Implement conservative conversion to avoid breaking existing MathML + +### Bash Scripts + +- Use `set -e` for error handling +- Quote variables properly +- Use `mktemp` for temporary files +- Include proper error messages and status reporting +- Check for command availability before use + +### Markdown Content + +- Use proper Jekyll front matter +- Include MathML namespace: `xmlns="http://www.w3.org/1998/Math/MathML"` +- Preserve existing MathML examples in documentation +- Use code blocks for HTML and MathML examples +- Maintain accessibility standards for mathematical content + +## Testing Requirements + +### Test Coverage + +- File existence and size validation +- MathML conversion accuracy +- Namespace compliance +- Code block preservation +- LaTeX pattern conversion +- Error handling and edge cases + +### Test Execution + +- Run tests before any deployment +- Use descriptive test output with emojis for clarity +- Include both unit and integration tests +- Test conversion workflow end-to-end + +## MathML Guidelines + +### Conversion Rules + +- Convert simple LaTeX patterns: `$x = 5$` → x = 5 +- Preserve existing MathML documentation examples +- Add MathML namespace to all `` elements +- Handle fractions, superscripts, subscripts, and common symbols +- Convert display math `$$...$$` to code blocks +- Be conservative to avoid breaking documentation + +### Accessibility + +- Ensure all MathML includes proper namespace +- Use semantic MathML elements (``, ``, ``, etc.) +- Maintain proper structure for screen readers +- Include text alternatives where appropriate + +## Development Workflow + +### Local Development + +1. Run `bash tests/test-local.sh` for quick validation +2. Use `bash scripts/convert-guidelines.sh` for conversion +3. Test with `python tests/test-conversion-workflow.py` +4. Verify Jekyll build with `bundle exec jekyll build` + +### GitHub Actions + +- Automated conversion and testing on push/PR +- Jekyll build and deployment to GitHub Pages +- Python 3.9 and Ruby 3.2 environment +- Comprehensive test suite execution + +## Error Handling + +### Python Scripts + +- Validate input file existence +- Handle encoding errors gracefully +- Provide clear error messages +- Exit with appropriate status codes +- Log conversion statistics + +### Bash Scripts + +- Check for required commands (python, sed) +- Validate file operations +- Clean up temporary files +- Provide fallback processing when possible + +## Security & Best Practices + +### File Operations + +- Use temporary files with proper cleanup +- Validate file paths and permissions +- Handle large files efficiently +- Avoid shell injection vulnerabilities + +### Content Processing + +- Preserve original content structure +- Validate MathML syntax +- Sanitize user input in conversions +- Maintain content integrity + +## Documentation Standards + +### Code Comments + +- Explain complex regex patterns +- Document conversion logic +- Include usage examples +- Note edge cases and limitations + +### Markdown Content + +- Use clear, descriptive headings +- Include practical MathML examples +- Provide conversion guidelines +- Maintain consistent formatting + +## Performance Considerations + +### Conversion Efficiency + +- Use compiled regex patterns +- Minimize file I/O operations +- Process content in chunks for large files +- Cache repeated operations where possible + +### Jekyll Build + +- Optimize image assets +- Minimize build time +- Use appropriate Jekyll plugins +- Configure proper exclusions + +## Maintenance + +### Regular Tasks + +- Update dependencies (Ruby gems, Python packages) +- Review and update conversion patterns +- Validate test coverage +- Update documentation examples + +### Monitoring + +- Check GitHub Actions build status +- Monitor conversion accuracy +- Validate MathML output +- Review user feedback and issues + +## Tools & Dependencies + +### Required Tools + +- Python 3.9+ with regex support +- Ruby 3.2+ with Jekyll 4.3+ +- Bash shell with standard utilities +- Git for version control + +### Key Dependencies + +- Jekyll and Jekyll plugins +- Python standard library (re, sys, os) +- Standard Unix utilities (sed, grep, wc) + +## Quality Assurance + +### Code Quality + +- Follow language-specific style guides +- Include comprehensive error handling +- Write maintainable, readable code +- Document complex algorithms + +### Content Quality + +- Validate MathML syntax +- Ensure accessibility compliance +- Test conversion accuracy +- Maintain documentation consistency + +## Troubleshooting + +### Common Issues + +- LaTeX patterns not converting +- MathML namespace missing +- File encoding problems +- Jekyll build failures + +### Debugging + +- Use verbose output in scripts +- Check file permissions and paths +- Validate input file format +- Test conversion patterns individually From b30f4fc8e3314e15fbdd670baa648b30864e2b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gaute=20R=C3=B8nningen?= Date: Fri, 12 Sep 2025 17:06:00 +0200 Subject: [PATCH 2/3] Enhance deployment workflow by adding Python setup and conversion tests; improve markdown processing in conversion script. --- .github/workflows/deploy-guidelines.yml | 9 + scripts/convert-guidelines.sh | 26 ++- scripts/convert-mathml.py | 218 ++++++++++++++++++++++++ tests/test-conversion-workflow.py | 180 +++++++++++++++++++ 4 files changed, 431 insertions(+), 2 deletions(-) create mode 100644 scripts/convert-mathml.py create mode 100644 tests/test-conversion-workflow.py diff --git a/.github/workflows/deploy-guidelines.yml b/.github/workflows/deploy-guidelines.yml index 5757139..3ec5368 100644 --- a/.github/workflows/deploy-guidelines.yml +++ b/.github/workflows/deploy-guidelines.yml @@ -32,10 +32,19 @@ jobs: ruby-version: '3.2' bundler-cache: true + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.9' + - name: Convert Guidelines Markdown to Jekyll Page run: | bash scripts/convert-guidelines.sh + - name: Test Conversion Output + run: | + python tests/test-conversion-workflow.py + - name: Build with Jekyll run: | bundle exec jekyll build --baseurl "" diff --git a/scripts/convert-guidelines.sh b/scripts/convert-guidelines.sh index c8039ba..7a874a1 100644 --- a/scripts/convert-guidelines.sh +++ b/scripts/convert-guidelines.sh @@ -19,9 +19,31 @@ permalink: / EOF -# Append the content from the original markdown file, skipping the first line (title) +# Process the markdown file to fix common issues if [ -f "Nordic MathML Guidelines.md" ]; then - tail -n +2 "Nordic MathML Guidelines.md" >> _pages/guidelines.md + # Create a temporary file for processing + temp_file=$(mktemp) + + # Copy content skipping the first line (title) + tail -n +2 "Nordic MathML Guidelines.md" > "$temp_file" + + # Use Python script to convert LaTeX math to MathML + if command -v python &> /dev/null; then + python scripts/convert-mathml.py "$temp_file" "$temp_file" + else + echo "Warning: Python not found, using basic sed processing" + # Fallback to basic sed processing + sed -i 's/```html/```html/g' "$temp_file" + sed -i 's/```math/```math/g' "$temp_file" + sed -i 's///g' "$temp_file" + fi + + # Append the processed content + cat "$temp_file" >> _pages/guidelines.md + + # Clean up temporary file + rm "$temp_file" + echo "Successfully converted Nordic MathML Guidelines to Jekyll page" else echo "Error: Nordic MathML Guidelines.md not found" diff --git a/scripts/convert-mathml.py b/scripts/convert-mathml.py new file mode 100644 index 0000000..48845cd --- /dev/null +++ b/scripts/convert-mathml.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python3 +""" +Script to convert LaTeX math syntax to plain text in markdown files. +This script handles the conversion of dollar-sign math to plain text format. +""" + +import re +import sys +import os + +def convert_latex_to_mathml(latex_expr): + """ + Convert simple LaTeX expressions to plain text. + This is a basic converter for common patterns. + """ + # Handle simple variables and numbers + latex_expr = latex_expr.strip() + + # Basic patterns for common math expressions + patterns = [ + # Fractions: \frac{a}{b} -> ab + (r'\\frac\{([^}]+)\}\{([^}]+)\}', r'\1\2'), + + # Superscripts: x^2 -> x2 + (r'([a-zA-Z])\^(\d+)', r'\1\2'), + + # Subscripts: x_i -> xi + (r'([a-zA-Z])_(\w+)', r'\1\2'), + + # Square root: \sqrt{x} -> x + (r'\\sqrt\{([^}]+)\}', r'\1'), + + # Text in math: \text{text} -> text + (r'\\text\{([^}]+)\}', r'\1'), + + # Greek letters and common symbols + (r'\\bar\{([^}]+)\}', r'\1'), + (r'\\hat\{([^}]+)\}', r'\1^'), + (r'\\vec\{([^}]+)\}', r'\1'), + + # Operators + (r'\\rightarrow', r''), + (r'\\leftarrow', r''), + (r'\\pm', r'±'), + (r'\\mp', r''), + (r'\\times', r'×'), + (r'\\div', r'÷'), + (r'\\leq', r''), + (r'\\geq', r''), + (r'\\neq', r''), + (r'\\approx', r''), + (r'\\infty', r''), + (r'\\sum', r''), + (r'\\int', r''), + (r'\\prod', r''), + (r'\\alpha', r'α'), + (r'\\beta', r'β'), + (r'\\gamma', r'γ'), + (r'\\delta', r'δ'), + (r'\\epsilon', r'ε'), + (r'\\theta', r'θ'), + (r'\\lambda', r'λ'), + (r'\\mu', r'μ'), + (r'\\pi', r'π'), + (r'\\sigma', r'σ'), + (r'\\tau', r'τ'), + (r'\\phi', r'φ'), + (r'\\omega', r'ω'), + ] + + # Apply patterns + for pattern, replacement in patterns: + latex_expr = re.sub(pattern, replacement, latex_expr) + + # Handle simple variables (single letters that aren't already in MathML) + latex_expr = re.sub(r'\b([a-zA-Z])\b(?!\s*[<>])', r'\1', latex_expr) + + # Handle numbers + latex_expr = re.sub(r'\b(\d+(?:\.\d+)?)\b', r'\1', latex_expr) + + # Handle operators + latex_expr = re.sub(r'([+\-*/=<>])', r'\1', latex_expr) + + # Handle parentheses + latex_expr = re.sub(r'([()])', r'\1', latex_expr) + + return latex_expr + +def process_markdown_file(input_file, output_file): + """ + Process the markdown file to convert LaTeX math to plain text. + This script ONLY converts LaTeX syntax ($...$) to plain text, + it does NOT modify existing MathML markup which is used for documentation. + """ + with open(input_file, 'r', encoding='utf-8') as f: + content = f.read() + + # Add MathML namespace to existing math elements that don't have it + # Only match tags that are actual HTML elements (not in text content) + # Look for followed by whitespace and then a tag like , , etc. + content = re.sub(r'(?=\s*<(?:mi|mo|mn|mfrac|msup|msub|msqrt|mroot|mover|munder|mtext|mrow|mtable|mtr|mtd))', '', content) + + # Also handle tags that might be on the same line or have attributes + content = re.sub(r']*xmlns)(?=\s*[^>]*>)', ' tags + def convert_simple_math(match): + math_expr = match.group(1) + + # Check if this is inside existing MathML tags by looking backwards + before_text = content[:match.start()] + + # Find the last unclosed tag before this position + last_math_start = before_text.rfind('') + + # If there's an unclosed tag, don't convert + if last_math_start > last_math_end: + return match.group(0) + + # Convert various LaTeX patterns to plain text + math_expr_clean = math_expr.strip() + + # Simple equations like x = 5 + if re.match(r'^[a-zA-Z]\s*=\s*\d+\.?$', math_expr_clean): + var_name = math_expr_clean.split("=")[0].strip() + value = math_expr_clean.split("=")[1].strip().rstrip(".") + return f'{var_name} = {value}' + + # Simple fractions like \frac{5}{2} + if re.match(r'^\\frac\{([^}]+)\}\{([^}]+)\}$', math_expr_clean): + match_frac = re.match(r'^\\frac\{([^}]+)\}\{([^}]+)\}$', math_expr_clean) + num = match_frac.group(1) + den = match_frac.group(2) + return f'{num}/{den}' + + # Fractions with text like \frac{\text{m}}{\text{s}^2} + if re.match(r'^\\frac\{\\text\{([^}]+)\}\}\{\\text\{([^}]+)\}\^(\d+)\}$', math_expr_clean): + match_frac_text = re.match(r'^\\frac\{\\text\{([^}]+)\}\}\{\\text\{([^}]+)\}\^(\d+)\}$', math_expr_clean) + num_text = match_frac_text.group(1) + den_text = match_frac_text.group(2) + den_sup = match_frac_text.group(3) + return f'{num_text}/{den_text}^{den_sup}' + + # Simple superscripts like x^2 + if re.match(r'^([a-zA-Z])\^(\d+)$', math_expr_clean): + match_sup = re.match(r'^([a-zA-Z])\^(\d+)$', math_expr_clean) + base = match_sup.group(1) + exp = match_sup.group(2) + return f'{base}^{exp}' + + # Simple subscripts like x_i + if re.match(r'^([a-zA-Z])_([a-zA-Z])$', math_expr_clean): + match_sub = re.match(r'^([a-zA-Z])_([a-zA-Z])$', math_expr_clean) + base = match_sub.group(1) + sub = match_sub.group(2) + return f'{base}_{sub}' + + # Square roots like \sqrt{9} = 3 + if re.match(r'^\\sqrt\{([^}]+)\}\s*=\s*(\d+)$', math_expr_clean): + match_sqrt = re.match(r'^\\sqrt\{([^}]+)\}\s*=\s*(\d+)$', math_expr_clean) + radicand = match_sqrt.group(1) + result = match_sqrt.group(2) + return f'√{radicand} = {result}' + + # Square roots with index like \sqrt[3]{9} = 2 + if re.match(r'^\\sqrt\[(\d+)\]\{([^}]+)\}\s*=\s*(\d+)$', math_expr_clean): + match_root = re.match(r'^\\sqrt\[(\d+)\]\{([^}]+)\}\s*=\s*(\d+)$', math_expr_clean) + index = match_root.group(1) + radicand = match_root.group(2) + result = match_root.group(3) + return f'^{index}√{radicand} = {result}' + + # Binomial like \binom{n}{k} + if re.match(r'^\\binom\{([^}]+)\}\{([^}]+)\}$', math_expr_clean): + match_binom = re.match(r'^\\binom\{([^}]+)\}\{([^}]+)\}$', math_expr_clean) + n = match_binom.group(1) + k = match_binom.group(2) + return f'({n} choose {k})' + + # Text in math like \text{NaCl} + if re.match(r'^\\text\{([^}]+)\}$', math_expr_clean): + match_text = re.match(r'^\\text\{([^}]+)\}$', math_expr_clean) + text = match_text.group(1) + return text + + # For other patterns, just return as-is to avoid breaking documentation + return match.group(0) + + # Apply the conservative conversion + content = re.sub(r'\$([^$]+)\$', convert_simple_math, content) + + with open(output_file, 'w', encoding='utf-8') as f: + f.write(content) + +if __name__ == "__main__": + if len(sys.argv) != 3: + print("Usage: python3 convert-mathml.py ") + sys.exit(1) + + input_file = sys.argv[1] + output_file = sys.argv[2] + + if not os.path.exists(input_file): + print(f"Error: Input file '{input_file}' not found") + sys.exit(1) + + process_markdown_file(input_file, output_file) + print(f"Successfully processed {input_file} -> {output_file}") diff --git a/tests/test-conversion-workflow.py b/tests/test-conversion-workflow.py new file mode 100644 index 0000000..f72ce6a --- /dev/null +++ b/tests/test-conversion-workflow.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python3 +""" +Test script for verifying the MathML conversion workflow. +This script can be run in GitHub Actions to validate the conversion output. +""" + +import os +import re +import sys +from pathlib import Path + +def test_file_exists(file_path, description): + """Test if a file exists and return status.""" + if os.path.exists(file_path): + print(f"✅ {description}: {file_path}") + return True + else: + print(f"❌ {description}: {file_path} - FILE NOT FOUND") + return False + +def test_file_size(file_path, min_size=1000): + """Test if file has reasonable size.""" + if not os.path.exists(file_path): + return False + + size = os.path.getsize(file_path) + if size >= min_size: + print(f"✅ File size: {size} bytes (>= {min_size})") + return True + else: + print(f"❌ File size: {size} bytes (< {min_size})") + return False + +def test_plain_text_conversion(file_path): + """Test if LaTeX patterns have been converted to plain text.""" + if not os.path.exists(file_path): + return False + + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + # Test for converted simple math patterns to plain text + plain_text_patterns = [ + r'x = 5', # Simple equation + r'5/2', # Simple fraction + r'√9 = 3', # Square root + r'x\^2', # Superscript + r'x_i', # Subscript + ] + + conversions_found = 0 + for pattern in plain_text_patterns: + if re.search(pattern, content): + conversions_found += 1 + print(f"✅ Found converted pattern: {pattern}") + + if conversions_found > 0: + print(f"✅ Plain text conversions: {conversions_found} patterns converted") + return True + else: + print("❌ No plain text conversions found") + return False + +def test_mathml_namespace(file_path): + """Test if MathML elements have proper namespace.""" + if not os.path.exists(file_path): + return False + + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + # Count MathML elements with and without namespace + math_with_namespace = len(re.findall(r'', content)) + math_without_namespace = len(re.findall(r'(?!\s*xmlns)', content)) + + print(f"✅ MathML elements with namespace: {math_with_namespace}") + if math_without_namespace > 0: + print(f"⚠️ MathML elements without namespace: {math_without_namespace}") + else: + print("✅ All MathML elements have namespace") + + return math_without_namespace == 0 + +def test_code_blocks(file_path): + """Test if code blocks are properly formatted.""" + if not os.path.exists(file_path): + return False + + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + # Check for properly formatted code blocks + html_blocks = len(re.findall(r'```html', content)) + math_blocks = len(re.findall(r'```math', content)) + + print(f"✅ HTML code blocks: {html_blocks}") + print(f"✅ Math code blocks: {math_blocks}") + + return html_blocks > 0 and math_blocks > 0 + +def test_preserved_mathml(file_path): + """Test if existing MathML examples are preserved.""" + if not os.path.exists(file_path): + return False + + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + # Look for preserved MathML examples (should have proper structure) + preserved_examples = len(re.findall(r'\s*x\s*=\s*5\s*\.\s*', content)) + + if preserved_examples > 0: + print(f"✅ Preserved MathML examples: {preserved_examples}") + return True + else: + print("❌ No preserved MathML examples found") + return False + +def test_remaining_latex(file_path): + """Test how many LaTeX patterns remain (should be documentation examples).""" + if not os.path.exists(file_path): + return False + + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + # Count remaining LaTeX patterns + latex_patterns = len(re.findall(r'\$[^$]+\$', content)) + + print(f"ℹ️ Remaining LaTeX patterns: {latex_patterns}") + + # These should be documentation examples, not conversion failures + if latex_patterns <= 30: # Reasonable number for documentation examples + print("✅ Reasonable number of LaTeX patterns (likely documentation examples)") + return True + else: + print("⚠️ High number of LaTeX patterns - may indicate conversion issues") + return False + +def main(): + """Run all tests.""" + print("🧪 Testing LaTeX to Plain Text Conversion Workflow") + print("=" * 50) + + # Test file path + guidelines_file = "_pages/guidelines.md" + + # Run tests + tests = [ + ("File exists", lambda: test_file_exists(guidelines_file, "Guidelines file")), + ("File size", lambda: test_file_size(guidelines_file)), + ("Plain text conversion", lambda: test_plain_text_conversion(guidelines_file)), + ("MathML namespace", lambda: test_mathml_namespace(guidelines_file)), + ("Code blocks", lambda: test_code_blocks(guidelines_file)), + ("Preserved MathML", lambda: test_preserved_mathml(guidelines_file)), + ("Remaining LaTeX", lambda: test_remaining_latex(guidelines_file)), + ] + + passed = 0 + total = len(tests) + + for test_name, test_func in tests: + print(f"\n📋 {test_name}:") + try: + if test_func(): + passed += 1 + except Exception as e: + print(f"❌ Error in {test_name}: {e}") + + print(f"\n📊 Test Results: {passed}/{total} tests passed") + + if passed == total: + print("🎉 All tests passed! Conversion workflow is working correctly.") + return 0 + else: + print("⚠️ Some tests failed. Please check the conversion script.") + return 1 + +if __name__ == "__main__": + sys.exit(main()) From 722a52b2c625cbfff0e84635c69d52326c74e956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gaute=20R=C3=B8nningen?= Date: Fri, 12 Sep 2025 17:06:10 +0200 Subject: [PATCH 3/3] Add test scripts and README for MathML conversion workflow; include local and CI/CD testing instructions. --- tests/README.md | 72 +++++++++++++++++++++++++++++++++++ tests/test-conversion.sh | 82 ++++++++++++++++++++++++++++++++++++++++ tests/test-local.sh | 47 +++++++++++++++++++++++ 3 files changed, 201 insertions(+) create mode 100644 tests/README.md create mode 100644 tests/test-conversion.sh create mode 100644 tests/test-local.sh diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..0c76a2e --- /dev/null +++ b/tests/README.md @@ -0,0 +1,72 @@ +# Test Files + +This directory contains test files for verifying the MathML conversion workflow. + +## Files + +### `test-conversion-workflow.py` + +**Purpose**: Comprehensive testing for GitHub Actions CI/CD pipeline +**Usage**: `python tests/test-conversion-workflow.py` +**Features**: + +- File existence and size validation +- MathML conversion verification +- MathML namespace checking +- Code block formatting validation +- Preserved MathML examples verification +- LaTeX pattern counting (for documentation examples) +- Detailed reporting with pass/fail status + +### `test-local.sh` + +**Purpose**: Quick local verification +**Usage**: `bash tests/test-local.sh` +**Features**: + +- Runs conversion script +- Basic validation checks +- Simple reporting +- Fast execution + +### `test-conversion.sh` + +**Purpose**: Comprehensive local testing with detailed output +**Usage**: `bash tests/test-conversion.sh` +**Features**: + +- Runs conversion script +- Detailed validation checks +- Sample content display +- Pattern verification +- Comprehensive reporting + +## Running Tests + +### Local Testing + +```bash +# Quick test +bash tests/test-local.sh + +# Comprehensive test +bash tests/test-conversion.sh + +# Python test +python tests/test-conversion-workflow.py +``` + +### CI/CD Testing + +The `test-conversion-workflow.py` script runs automatically in the GitHub Actions workflow after the conversion step and before the Jekyll build step. + +## Test Results + +All tests should pass for a successful conversion: + +- ✅ File generation +- ✅ MathML conversion +- ✅ Namespace validation +- ✅ Code block formatting +- ✅ Documentation preservation +- ✅ LaTeX pattern counting diff --git a/tests/test-conversion.sh b/tests/test-conversion.sh new file mode 100644 index 0000000..94562c1 --- /dev/null +++ b/tests/test-conversion.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +# Test script for convert-guidelines.sh +# This script runs the conversion and shows the results + +echo "🧪 Testing convert-guidelines.sh script..." +echo "==========================================" + +# Run the conversion script +echo "📝 Running conversion script..." +bash scripts/convert-guidelines.sh + +echo "" +echo "✅ Conversion completed!" +echo "" + +# Check if the output file was created +if [ -f "_pages/guidelines.md" ]; then + echo "📄 Output file created: _pages/guidelines.md" + echo "📊 File size: $(wc -c < _pages/guidelines.md) bytes" + echo "📏 Line count: $(wc -l < _pages/guidelines.md) lines" + echo "" + + # Show some key content + echo "🔍 Sample content:" + echo "------------------" + head -20 _pages/guidelines.md + echo "" + echo " ... (truncated) ..." + echo "" + + # Check for specific patterns + echo "🔍 Checking for converted patterns:" + echo "-----------------------------------" + + # Check for converted math to plain text + if grep -q 'x = 5' _pages/guidelines.md; then + echo "✅ Simple math conversion working: \$x = 5.\$ → x = 5" + else + echo "❌ Simple math conversion not working" + fi + + # Check for other plain text patterns + if grep -q '5/2' _pages/guidelines.md; then + echo "✅ Fraction conversion working: \$\frac{5}{2}\$ → 5/2" + else + echo "ℹ️ Fraction conversion not found (may not be present in content)" + fi + + if grep -q 'x^2' _pages/guidelines.md; then + echo "✅ Superscript conversion working: \$x^2\$ → x^2" + else + echo "ℹ️ Superscript conversion not found (may not be present in content)" + fi + + # Check for preserved MathML examples + if grep -q '' _pages/guidelines.md; then + echo "✅ MathML examples preserved" + else + echo "❌ MathML examples missing" + fi + + # Check for code blocks + if grep -q '```html' _pages/guidelines.md; then + echo "✅ HTML code blocks preserved" + else + echo "❌ HTML code blocks missing" + fi + + if grep -q '```math' _pages/guidelines.md; then + echo "✅ Math code blocks preserved" + else + echo "❌ Math code blocks missing" + fi + +else + echo "❌ Output file not created!" + exit 1 +fi + +echo "" +echo "🎉 Test completed successfully!" diff --git a/tests/test-local.sh b/tests/test-local.sh new file mode 100644 index 0000000..0818b18 --- /dev/null +++ b/tests/test-local.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Quick local test script for the conversion workflow +# This can be run locally to verify the conversion is working + +echo "🧪 Local Conversion Test" +echo "========================" + +# Run the conversion +echo "📝 Running conversion..." +bash scripts/convert-guidelines.sh + +# Check if output file exists +if [ -f "_pages/guidelines.md" ]; then + echo "✅ Output file created: _pages/guidelines.md" + + # Check file size + size=$(wc -c < _pages/guidelines.md) + echo "📊 File size: $size bytes" + + # Check for converted patterns to plain text + if grep -q 'x = 5' _pages/guidelines.md; then + echo "✅ Simple math conversion working" + else + echo "❌ Simple math conversion not working" + fi + + # Check for code blocks + html_blocks=$(grep -c '```html' _pages/guidelines.md) + math_blocks=$(grep -c '```math' _pages/guidelines.md) + echo "✅ HTML code blocks: $html_blocks" + echo "✅ Math code blocks: $math_blocks" + + # Check for MathML namespace + math_with_namespace=$(grep -c 'xmlns="http://www.w3.org/1998/Math/MathML"' _pages/guidelines.md) + echo "✅ MathML elements with namespace: $math_with_namespace" + + # Count remaining LaTeX patterns + latex_count=$(grep -c '\$.*\$' _pages/guidelines.md) + echo "ℹ️ Remaining LaTeX patterns: $latex_count (documentation examples)" + + echo "" + echo "🎉 Local test completed successfully!" +else + echo "❌ Output file not found" + exit 1 +fi