Refactor page-compiler format API to modular transforms pipeline#72
Merged
YusukeHirao merged 22 commits intomainfrom Feb 3, 2026
Merged
Refactor page-compiler format API to modular transforms pipeline#72YusukeHirao merged 22 commits intomainfrom
YusukeHirao merged 22 commits intomainfrom
Conversation
…essors BREAKING CHANGE: Add boolean support to minifier option type Split the 130+ line formatHtml function into 9 separate processor functions: - buildTransformContext: Builds TransformContext for hooks - beforeSerialize: Executes beforeSerialize hook - domSerialize: DOM serialization with image size injection - characterEntities: Converts characters to HTML entities - doctype: Inserts DOCTYPE declaration - prettier: Formats HTML with Prettier - minifier: Minifies HTML with html-minifier-terser - lineBreak: Normalizes line breaks - replace: Final content replacement Each processor follows a curried pattern: initialized with context/options, returns a function that processes content. Processors are executed in a pipeline array for clear, sequential transformation flow. Type change: - PageCompilerOptions.minifier: HMTOptions → HMTOptions | boolean (now supports false to disable minification) Benefits: - Single responsibility: Each function has one clear purpose - Testability: Individual processors can be tested independently - Maintainability: Easy to add, modify, or remove processing steps - Readability: Main function is now a clear pipeline Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
BREAKING CHANGE: Replace formatHtml with pageTransform
- Rename formatHtml function to pageTransform
- Rename FormatHtmlContext to PageTransformContext
- Rename FormatHtmlOptions to PageTransformOptions
- Reorganize options by transformation phase (beforeFormat, domManipulation, afterFormat)
- Update all documentation and examples
The transformation pipeline is now explicitly divided into three phases:
1. Phase 1: beforeFormat - String transformations before DOM parsing
2. Phase 2: domManipulation - DOM-based transformations
3. Phase 3: afterFormat - String transformations after DOM serialization
Migration:
- Import { pageTransform } instead of { formatHtml }
- Use PageTransformContext instead of FormatHtmlContext
- Use PageTransformOptions instead of FormatHtmlOptions
- Function signature and options remain the same
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
BREAKING CHANGE: Rename format.ts to page-transform.ts - Rename src/format.ts to src/page-transform.ts - Rename src/format.spec.ts to src/page-transform.spec.ts - Update package.json exports: ./format -> ./page-transform - Update all import statements to use ./page-transform.js - Update README.md import examples This aligns file names with the function name pageTransform. Migration: - Import from '@kamado-io/page-compiler/page-transform' instead of '@kamado-io/page-compiler/format' Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
BREAKING CHANGE: Rename format processor files to match pageTransform API File renames: - before-serialize.ts -> preprocess-content.ts - dom-serialize.ts -> manipulate-dom.ts - replace.ts -> postprocess-content.ts This is the first step of the breaking change. The next commit will update internal implementations and API names.
BREAKING CHANGE: Rename pageTransform hook APIs for clarity API renames: - beforeSerialize -> preprocessContent (content preprocessing before DOM parsing) - afterSerialize -> manipulateDOM (DOM manipulation after parsing) - replace -> postprocessContent (content postprocessing after serialization) Updated type definitions and internal implementations: - PageCompilerOptions, PageTransformOptions interfaces - PreprocessContentContext, ManipulateDOMContext, PostprocessContentContext types - preprocessContent(), manipulateDOM(), postprocessContent() processor functions - Updated JSDoc comments to reflect new phase names
…mpiler BREAKING CHANGE: Update pageTransform call to use new option names Updated option names when calling pageTransform: - beforeSerialize -> preprocessContent - afterSerialize -> manipulateDOM - replace -> postprocessContent This aligns the pageCompiler implementation with the renamed pageTransform API.
Update test suites and test cases to use new hook names: - "beforeSerialize hook" -> "preprocessContent hook" - "afterSerialize hook" -> "manipulateDOM hook" - Update option names in all test cases
Update all documentation to use new hook names: - beforeSerialize -> preprocessContent - afterSerialize -> manipulateDOM - replace -> postprocessContent Updated sections: - Options section - TransformContext section - Transform Utilities examples - Standalone API section (phase descriptions and options)
…vServer BREAKING CHANGE: Rename ResponseTransform to Transform and extend TransformContext Type changes: - ResponseTransform -> Transform - Transform.name is now required (was optional) - TransformContext extended with filePath, outputDir, and compile properties This unifies the transform interfaces between page-compiler and devServer.transforms, enabling better code reuse and consistency across the compilation pipeline. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ied transforms option
BREAKING CHANGE: Replace granular formatting options with flexible Transform Pipeline
Removed options:
- imageSizes (boolean | ImageSizesOptions)
- minifier (boolean | HMTOptions)
- prettier (boolean | PrettierOptions)
- lineBreak ('\n' | '\r\n')
- characterEntities (boolean)
Added option:
- transforms: Transform[] | ((defaultTransforms: readonly Transform[]) => Transform[])
Users must now configure transforms explicitly or use defaultPageTransforms.
Function variant allows extending defaults without importing defaultPageTransforms.
Migration guide:
```typescript
// Before
pageCompiler({ imageSizes: true, minifier: { collapseWhitespace: true } })
// After (using defaults)
pageCompiler({ transforms: defaultPageTransforms })
// After (customizing)
import { manipulateDOM, minifier } from '@kamado-io/page-compiler';
pageCompiler({
transforms: [
manipulateDOM({ imageSizes: true }),
minifier({ options: { collapseWhitespace: true } })
]
})
// After (extending defaults without import)
pageCompiler({
transforms: (defaults) => [customTransform, ...defaults]
})
```
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
BREAKING CHANGE: Move and refactor format/ transforms to transform/ directory File movements and removals: - Delete format/build-transform-context.ts (no longer needed) - Delete format/preprocess-content.ts (functionality removed) - Delete format/postprocess-content.ts (functionality removed) - Move format/character-entities.ts -> transform/character-entities.ts - Move format/doctype.ts -> transform/doctype.ts - Move format/line-break.ts -> transform/line-break.ts - Move format/manipulate-dom.ts -> transform/manipulate-dom.ts - Move format/minifier.ts -> transform/minifier.ts - Move format/prettier.ts -> transform/prettier.ts All transform factory functions now: - Accept options parameter only (no context parameter) - Return Transform object directly - Have simpler, unified API surface - Remove unused preprocess/postprocess transform builders Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Move transform tests from page-transform.spec.ts to individual spec files: - character-entities.spec.ts (2 tests) - doctype.spec.ts (2 tests) - line-break.spec.ts (3 tests) - manipulate-dom.spec.ts (5 tests) - minifier.spec.ts (2 tests) - prettier.spec.ts (3 tests) page-transform.spec.ts now only contains defaultPageTransforms array tests (7 tests). This improves test organization and maintainability. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add support for function-based transforms configuration:
transforms option now accepts:
- Transform[] (existing behavior)
- (defaultTransforms: readonly Transform[]) => Transform[] (new)
The function variant receives defaultPageTransforms and returns modified array,
enabling users to prepend/append/filter transforms without explicit import.
Changes:
- page-compiler.ts: Add runtime type check and function invocation
- page-transform.ts: Simplify by removing transform builders, only export defaults
- page-compiler.spec.ts: Add test for function-based transforms extension
- Re-export transform factories from page-compiler.ts for convenience
Example usage:
```typescript
// No import needed
pageCompiler({
transforms: (defaults) => [customTransform, ...defaults]
})
// vs. old way
import { defaultPageTransforms } from '@kamado-io/page-compiler/page-transform';
pageCompiler({
transforms: [customTransform, ...defaultPageTransforms]
})
```
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ansform type Update dev transform utilities to use unified Transform type: - Replace ResponseTransform with Transform type - Update default names: inject-to-head -> injectToHead, ssi-shim -> ssiShim - Update parameter names: context -> ctx for consistency - Update JSDoc to reference Transform instead of ResponseTransform - Remove name option from SSIShimOptions (fixed to "ssiShim") These utilities now use the same Transform interface as page compiler transforms, improving consistency across the codebase. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Export individual transform factories to support direct imports: - manipulate-dom - character-entities - doctype - prettier - minifier - line-break Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Update all documentation to reflect Transform API changes: page-compiler README: - Fix all function names (manipulateDOM, characterEntities, etc.) - Remove non-existent functions (preprocessContentTransform, postprocessContentTransform) - Document function support for transforms option - Update all code examples with correct API - Change variable name from imgs to images - Add comprehensive migration guide for v2 to v3 kamado README: - Update Transform API references - Fix function names in examples - Add correct imports for transform factories kamado ARCHITECTURE: - Update function references to match actual implementation - Fix Transform interface documentation - Correct hook references (manipulateDOM() instead of manipulateDOMTransform) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Simplify hook signature by removing redundant parameters: - Before: (elements, window, isServe, context, compile) - After: (elements, window, context) isServe and compile are already available in context: - context.isServe - context.compile This makes the API more consistent and less redundant. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…eSizes Replace direct JSDOM usage with kamado's domSerialize utility to ensure consistent fragment handling. Pass parent elements array to imageSizes instead of img elements directly. The bug was that img elements were being passed to imageSizes, which then tried to query for images within those img elements using querySelectorAll, resulting in empty arrays. imageSizes expects parent elements to query from. Changes: - Use domSerialize from kamado/utils/dom instead of creating JSDOM directly - Pass elements (from domSerialize) to imageSizes instead of querying img elements - Change hook window type from JSDOM['window'] to standard Window type - Fragments remain as fragments, full documents remain as full documents Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove jsdom and @types/jsdom from package-compiler's direct dependencies. The package now uses kamado's domSerialize utility which internally handles jsdom, eliminating duplicate dependencies. Benefits: - Simpler dependency tree (jsdom only in kamado) - Centralized jsdom version management - Reduced bundle size through deduplication Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fix test expectations that were incorrectly changed to expect DOCTYPE and full HTML structure from fragment inputs. Fragments should remain as fragments after processing. Corrected expectations: - Fragment input '<p>Hello, world!</p>' outputs '<p>Hello, world!</p>\n' - Plain text 'p Hello, world!' outputs '' (empty, as it's not valid HTML) - Pug-compiled fragments output as fragments, not full documents These test expectations match the v1.3.0 behavior where domSerialize preserves the input format (fragments stay fragments, full docs stay full). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Update documentation to reflect that imageSizes defaults to true, matching v1.3.0 behavior: - Update manipulate-dom.ts comment to state default: true - Update README.md to clearly document default: `true` - Clarify host option default behavior (dev server vs production) - Add note about domSerialize preserving fragments Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove characterEntities from defaultPageTransforms to match v1.3.0 behavior where character entity conversion was opt-in only. In v1.3.0, characterEntities option was optional and disabled by default. Users had to explicitly enable it. The transform is still available for explicit use via import. Changes: - Remove characterEntities from defaultPageTransforms (5 transforms now) - Update README to document that characterEntities is not included by default - Add usage example for explicitly adding characterEntities - Update tests to reflect 5 transforms instead of 6 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Complete refactoring of page-compiler's format API into a modular transforms pipeline with improved extensibility and v1.3.0 compatibility fixes.
Breaking Changes
transformsoption replaces individual format options (prettier,minifier,imageSizes, etc.)formatHtml→pageTransform,FormatHtmlOptions→ integrated intoPageCompilerOptions./format→./page-transform+ individual transform exportsNew Features
Bug Fixes & Compatibility
Files Changed
New Files
src/page-transform.ts- defaultPageTransforms exportsrc/page-transform.spec.ts- Transform pipeline testssrc/transform/manipulate-dom.ts- DOM manipulation transform (with imageSizes)src/transform/character-entities.ts- Character entity conversionsrc/transform/doctype.ts- DOCTYPE declarationsrc/transform/prettier.ts- HTML formattingsrc/transform/minifier.ts- HTML minificationsrc/transform/line-break.ts- Line break normalizationRemoved Files
src/format.ts- replaced by modular transformssrc/format.spec.ts- replaced by transform-specific testsModified Files
src/page-compiler.ts- Use transforms pipeline instead of formatHtmlsrc/types.ts- Replace format options with transforms optionpackage.json- Update exports, remove jsdom dependenciesREADME.md- Complete documentation rewritesrc/transform/inject-to-head.ts- Updated to Transform interfacesrc/transform/ssi-shim.ts- Updated to Transform interfacekamado/src/config/types.ts- Unified Transform interfaceMigration Guide
Before (v1.x)
After (v2.x)
API Changes
defaultPageTransforms
Transform Interface
Package Exports
Test Coverage
🤖 Generated with Claude Code