[3.x] Support pages with more output file extensions (Refactors)#2540
Closed
emmadesilva wants to merge 17 commits into
Closed
[3.x] Support pages with more output file extensions (Refactors)#2540emmadesilva wants to merge 17 commits into
emmadesilva wants to merge 17 commits into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## v3/non-html-pages #2540 +/- ##
=======================================================
- Coverage 100.00% 99.95% -0.05%
+ Complexity 1793 1784 -9
=======================================================
Files 179 177 -2
Lines 4472 4449 -23
=======================================================
- Hits 4472 4447 -25
- Misses 0 2 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Member
Author
|
Alright I let the AI drift way to far here. I have no idea what this even solves. |
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.
Non-HTML Page Simplification Task Specification
Objective
Reduce the accidental complexity left by the first-class non-HTML page work while preserving its user-facing behavior:
InMemoryPage::file()remains the explicit arbitrary-file API;showInSitemap();build:sitemapandbuild:rsscommands remain available.The implementation is split into isolated issues so each change can be reviewed, tested, and committed independently.
Issue 1: Derive route keys from resolved output paths
Problem in the current code
HydePageconstructs its stored route key withRouteKey::fromPage()before the instance output path is considered.RouteKey::fromPage()independently combines the page class output directory, identifier, and static$outputExtension.InMemoryPage::file()then overridesgetOutputPath()at the instance level.This creates two representations of the same output semantics:
packages/framework/src/Support/Models/RouteKey.phpderives a route from class-level declarations;packages/framework/src/Pages/InMemoryPage.phpcan resolve a different exact instance output path.DocumentationPagealso overrides bothgetRouteKey()andgetOutputPath()to keep flattened documentation routes aligned, illustrating the same duplication.Implementation
RouteKey::fromOutputPath(string $outputPath), with the single route rule: remove a trailing.html; retain every other path and extension verbatim.HydePageconstruction so the stored route key is derived from the instance's resolvedgetOutputPath().HydePage::outputPath()to construct the output path directly from the normalized page identifier, output directory, and output extension instead of round-tripping through a route key.RouteKey::fromPage()as a compatibility/helper API, but implement it by passing the page class's resolved static output path tofromOutputPath().DocumentationPage::getRouteKey()once its resolvedgetOutputPath()automatically determines the stored route key.Acceptance criteria
foo/bar.htmlhas route keyfoo/bar.foo/bar.jsonhas route keyfoo/bar.json.feedhas route keyfeed.InMemoryPage::file('robots.txt')has output path and route keyrobots.txt.getOutputPath()receives a matching route key without also overridinggetRouteKey().Issue 2: Consolidate generated-file page wiring
Problem in the current code
The following internal classes repeat the same page shell:
Framework/Features/XmlGenerators/SitemapPage.phpFramework/Features/XmlGenerators/RssFeedPage.phpFramework/Features/TextGenerators/RobotsTxtPage.phpFramework/Features/TextGenerators/LlmsTxtPage.phpEach class supplies an exact path, hidden navigation, a container-resolved generator, and a small
compile()adapter.HydeCoreExtensionrepeats a feature check and discovery method for each shell. XML generators return themselves fromgenerate()and requiregetXml(), while text generators return their final strings directly.Implementation
GeneratedFileGeneratorcontract with one final rendering method returning a string.BaseXmlGeneratorthrough compatibility adapters, retaining the existing publicgenerate()behavior for generator subclasses and callers.GeneratedFilePagethat stores an exact output path and generator class, hides itself from navigation, resolves the generator from the container at compile time, and returns the contract's final string.HydeCoreExtensionloop over the registry and add only missing routes.build:sitemap,build:rss, and the robots sitemap link to use registry paths instead of specialized page classes.GeneratedFilePageplus route behavior.Acceptance criteria
generate()and XMLgetXml()generator APIs continue to work.build:sitemapandbuild:rssretain their current success, failure, configured-filename, and user-page override behavior.Issue 3: Register framework defaults after user pages
Problem in the current code
PageCollection::runExtensionHandlers()invokes extensions in registration order.HydeCoreExtensionis registered first, so generated pages are added before user extensions. A user extension currently wins because adding an exact-path page happens to replace the generated page under the same page-collection source key, or later wins in the route collection.That makes “user pages beat framework defaults” dependent on collection keys and timing rather than a lifecycle guarantee.
Implementation
discoverDefaultPages(PageCollection $collection)extension hook for fallback pages.discoverPages()hooks first, then alldiscoverDefaultPages()hooks.HydeCoreExtension::discoverPages()intodiscoverDefaultPages().Acceptance criteria
Verification
For each issue:
Deliberate non-goals
OutputPathvalue object in this refactor. Existing framework APIs expose paths as strings; changing all of them would add migration surface without being necessary to establish one source of truth.hyde build:routecommand. Removing command-driven page subclasses solves the immediate coupling; a new CLI API should be evaluated separately.$fileExtensionto$sourceExtensionrename here. It is an independent v3 API cleanup already implemented on this branch, not a dependency of these simplifications.