Skip to content

feat: add .plain.html support for HTML folder serving#2631

Merged
karlpauls merged 8 commits into
mainfrom
plainhtml
Nov 13, 2025
Merged

feat: add .plain.html support for HTML folder serving#2631
karlpauls merged 8 commits into
mainfrom
plainhtml

Conversation

@karlpauls
Copy link
Copy Markdown
Contributor

@karlpauls karlpauls commented Nov 12, 2025

Summary

Adds support for .plain.html files in HTML folder mode with metadata extraction. When a request comes in for a path without an extension (e.g., /drafts/page), the server now:

  1. First checks for a .html file (existing behavior)
  2. If not found, checks for a .plain.html file (new)
  3. Extracts and processes metadata blocks from .plain.html content
  4. Wraps content in proper HTML structure: <html><head><body><header><main><footer>
  5. Applies live reload injection to both file types

This enables content preview workflows where users can create simple HTML fragments with metadata, and the CLI automatically provides the complete page structure with proper meta tags.

Changes

  • Refactored handleHtmlFolderRequest() to use DRY approach with shared serving logic
  • Added resolveHtmlFolderFile() to check .html then .plain.html with proper priority
  • Added transformPlainHtml() to wrap plain content with HeadHtmlSupport integration

Testing

All tests pass (25 HTML folder tests, 252 total). New tests verify:

  • .plain.html files wrapped with proper HTML structure
  • .html files take precedence over .plain.html
  • Metadata extraction and meta tag generation
  • Special properties (title:suffix, canonical, tags)
  • Default value extraction (H1, paragraph, image)
  • Image src extraction from tags in metadata
  • HTML stripping from metadata values (using proper parsing)
  • Special character escaping in meta tags
  • Live reload works identically for both file types
  • Path traversal protection applies to both file types
  • Nested directory support
  • Remote head.html integration with HeadHtmlSupport
  • Behavior when head.html is missing

Documentation

  • Updated README.md with html-folder feature documentation and examples
  • Added CLI help text for --html-folder option

@github-actions
Copy link
Copy Markdown

This PR will trigger a minor release when merged.

Copy link
Copy Markdown
Contributor

trieloff commented Nov 13, 2025

Code Review

Overview

This PR adds support for serving .plain.html files in HTML folder mode, automatically wrapping them with full HTML structure including head.html content. The implementation maintains backward compatibility while enabling a streamlined content preview workflow.

✅ Strengths

  1. Well-structured refactoring - The code extraction into resolveHtmlFolderFile() and transformPlainHtml() follows DRY principles and improves maintainability
  2. Security-conscious - Path traversal protection is consistently applied to both file types with proper validation
  3. Comprehensive test coverage - 6 new tests covering edge cases (precedence, nesting, security, missing head.html, live reload)
  4. Clear precedence logic - .html files correctly take priority over .plain.html, preventing unexpected behavior
  5. Live reload integration - Properly applies live reload to both file types uniformly

💡 Suggestions for Improvement

1. Duplicate Security Validation (src/server/HelixServer.js:182-190)

Both .html and .plain.html paths perform identical security checks. Consider extracting this into a helper:

// Add after resolveHtmlFolderFile:
validatePathSecurity(filePath) {
  const resolvedProjectDir = path.resolve(this._project.directory);
  const relPath = path.relative(resolvedProjectDir, filePath);
  return !relPath.startsWith('..');
}

Then use: if (!this.validatePathSecurity(htmlFile)) return null;

4. Test Enhancement Opportunity

All new tests use the same head.html setup. Consider adding a test that verifies behavior with remote head.html (successful fetch from proxy URL) to ensure HeadHtmlSupport integration works in all scenarios.

🔍 Code Quality Assessment

  • Correctness: Logic is sound, handles all documented cases
  • Performance: Efficient file resolution, minimal overhead
  • Security: Proper path validation prevents directory traversal
  • Maintainability: Clean separation of concerns
  • Test Coverage: Excellent coverage of edge cases

Minor Observations

  1. The isPlain flag is clear and well-used
  2. Error handling uses try-catch appropriately (fails gracefully to next middleware)
  3. Logging maintains consistency with existing patterns

Verdict

Approved - This is a solid implementation. The suggestions above are minor optimizations and don't block merging. The feature works as designed, maintains security, and has excellent test coverage.

Great work on the refactoring! The extracted methods make the code much more readable than the original implementation.

Comment thread src/server/utils.js Fixed
karlpauls and others added 2 commits November 12, 2025 20:48
…ter sanitization

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Comment thread src/server/utils.js Fixed
Comment thread src/server/utils.js Fixed
Comment thread src/server/utils.js Fixed
@karlpauls karlpauls merged commit 2186d4c into main Nov 13, 2025
9 checks passed
@karlpauls karlpauls deleted the plainhtml branch November 13, 2025 19:28
adobe-bot pushed a commit that referenced this pull request Nov 13, 2025
# [16.16.0](v16.15.13...v16.16.0) (2025-11-13)

### Features

* add .plain.html support for HTML folder serving ([#2631](#2631)) ([2186d4c](2186d4c))
@adobe-bot
Copy link
Copy Markdown
Collaborator

🎉 This PR is included in version 16.16.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants