Preserve live URL query trailing slashes#732
Conversation
Greptile SummaryThis PR fixes a bug where
Confidence Score: 4/5Safe to merge — the targeted bug is correctly fixed and tested; the remaining gap is a pre-existing limitation, not a regression. The regex fix works correctly for every case where a path trailing slash precedes Both changed files are small and low-risk; Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["normalizeUrl(u)"] --> B{"URL contains\npath trailing slash\nbefore ? or #?"}
B -- "Yes\ne.g. /search/?q=/" --> C["regex matches /\\/+(?=[?#]|$)/\nfirst match = path slash\nno g flag → stops here"]
C --> D["Strips path slash only\n→ /search?q=/\n(query preserved ✓)"]
B -- "No path slash\ne.g. /search?q=/" --> E["regex scans to end\nfirst match = trailing /\ninside query value"]
E --> F["Strips query trailing slash\n→ /search?q=\n(query modified ⚠)"]
B -- "No ? or # at all\ne.g. /pricing/" --> G["regex matches trailing /\nbefore end-of-string"]
G --> H["Strips path slash\n→ /pricing ✓"]
Reviews (1): Last reviewed commit: "Preserve live URL query trailing slashes" | Re-trigger Greptile |
| return u.replace(/\/+$/, ''); | ||
| // For live-site URLs keep query strings and fragments intact; only strip | ||
| // trailing slashes from the path segment. | ||
| return u.replace(/\/+(?=[?#]|$)/, ''); |
There was a problem hiding this comment.
Query/fragment trailing slash still stripped when no path slash precedes it
When the URL has no path trailing slash but the query or fragment itself ends with /, the regex still matches that final / and strips it. For example, https://example.com/search?q=/ → https://example.com/search?q= because the regex scans left-to-right, finds no slash before ?, and then matches the / at end-of-string inside the query value. The no-g-flag design only protects fragment/query slashes when a path slash is found first.
A URL-based approach (new URL(u)) would be more surgical — it lets you rewrite only pathname and reconstruct the full URL with search and hash untouched, regardless of whether those components happen to end in /.
| it('preserves query and fragment trailing slashes for live-site urls', () => { | ||
| expect(resolveInput('https://example.com/search/?q=/').value).toBe( | ||
| 'https://example.com/search?q=/', | ||
| ); | ||
| expect(resolveInput('https://example.com/docs/#/intro/').value).toBe( | ||
| 'https://example.com/docs#/intro/', | ||
| ); | ||
| }); |
There was a problem hiding this comment.
Missing coverage for query-only trailing slash (no path slash)
The test suite covers the case where a path trailing slash exists (/search/, /docs/) before the ? or #, but there's no test for the complementary case where there is no path trailing slash yet the query or fragment ends in / — e.g. https://example.com/search?q=/. Under the current implementation that URL normalizes to https://example.com/search?q= (trailing slash stripped), which may surprise callers. Adding an assertion for this input would make the boundary of the fix explicit and prevent silent regressions.
|
CI is green for PR #732. Verification:
Note: the package typecheck still hits pre-existing workspace resolution errors unrelated to this patch, as documented in the PR body. uGig invoice evidence has been sent for this PR. |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
8 similar comments
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
Fixes #731.
What changed
/.Validation
corepack pnpm vitest run packages/cli/src/input.test.tscorepack pnpm --filter @profullstack/sh1pt typecheckcurrently fails on existing workspace/type errors outside this change, including unresolved workspace package imports and unrelated implicit-any errors.