@tanstack/react-router 1.153.2 → 1.154.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/llms/rules/api.d.ts +1 -1
- package/dist/llms/rules/api.js +47 -0
- package/dist/llms/rules/guide.d.ts +1 -1
- package/dist/llms/rules/guide.js +497 -0
- package/package.json +3 -3
package/dist/llms/rules/guide.js
CHANGED
|
@@ -2759,6 +2759,8 @@ paraglideVitePlugin({
|
|
|
2759
2759
|
|
|
2760
2760
|
### URL Localization via Router Rewrite
|
|
2761
2761
|
|
|
2762
|
+
The router's \`rewrite\` option enables bidirectional URL transformation, perfect for locale prefixes. For comprehensive documentation on URL rewrites including advanced patterns, see the [URL Rewrites guide](./url-rewrites.md).
|
|
2763
|
+
|
|
2762
2764
|
\`\`\`ts
|
|
2763
2765
|
import { deLocalizeUrl, localizeUrl } from './paraglide/runtime'
|
|
2764
2766
|
|
|
@@ -7591,4 +7593,499 @@ const { enable, disable, navigate } = useConditionalNavigate({
|
|
|
7591
7593
|
})
|
|
7592
7594
|
\`\`\`
|
|
7593
7595
|
|
|
7596
|
+
# URL Rewrites
|
|
7597
|
+
|
|
7598
|
+
URL rewrites allow you to transform URLs bidirectionally between what the browser displays and what the router interprets internally. This powerful feature enables patterns like locale prefixes, subdomain routing, legacy URL migration, and multi-tenant applications without duplicating routes or complicating your route tree.
|
|
7599
|
+
|
|
7600
|
+
## When to Use URL Rewrites
|
|
7601
|
+
|
|
7602
|
+
URL rewrites are useful when you need to:
|
|
7603
|
+
|
|
7604
|
+
- **i18n locale prefixes**: Display \`/en/about\` in the browser but route to \`/about\` internally
|
|
7605
|
+
- **Subdomain routing**: Route \`admin.example.com/users\` to \`/admin/users\` internally
|
|
7606
|
+
- **Legacy URL migration**: Support old URLs like \`/old-path\` that map to new routes
|
|
7607
|
+
- **Multi-tenant applications**: Route \`tenant1.example.com\` to tenant-specific routes
|
|
7608
|
+
- **Custom URL schemes**: Transform any URL pattern to match your route structure
|
|
7609
|
+
|
|
7610
|
+
## How URL Rewrites Work
|
|
7611
|
+
|
|
7612
|
+
URL rewrites operate in two directions:
|
|
7613
|
+
|
|
7614
|
+
1. **Input rewrite**: Transforms the URL **from the browser** before the router interprets it
|
|
7615
|
+
2. **Output rewrite**: Transforms the URL **from the router** before it's written to the browser
|
|
7616
|
+
|
|
7617
|
+
\`\`\`
|
|
7618
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
7619
|
+
│ Browser URL Bar │
|
|
7620
|
+
│ /en/about?q=test │
|
|
7621
|
+
└─────────────────────────┬───────────────────────────────────────┘
|
|
7622
|
+
│
|
|
7623
|
+
▼ input rewrite
|
|
7624
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
7625
|
+
│ Router Internal URL │
|
|
7626
|
+
│ /about?q=test │
|
|
7627
|
+
│ │
|
|
7628
|
+
│ (matches routes, runs loaders) │
|
|
7629
|
+
└─────────────────────────┬───────────────────────────────────────┘
|
|
7630
|
+
│
|
|
7631
|
+
▼ output rewrite
|
|
7632
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
7633
|
+
│ Browser URL Bar │
|
|
7634
|
+
│ /en/about?q=test │
|
|
7635
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
7636
|
+
\`\`\`
|
|
7637
|
+
|
|
7638
|
+
The router exposes two href properties on the location object:
|
|
7639
|
+
|
|
7640
|
+
- \`location.href\` - The internal URL (after input rewrite)
|
|
7641
|
+
- \`location.publicHref\` - The external URL displayed in the browser (after output rewrite)
|
|
7642
|
+
|
|
7643
|
+
## Basic Usage
|
|
7644
|
+
|
|
7645
|
+
Configure rewrites when creating your router:
|
|
7646
|
+
|
|
7647
|
+
\`\`\`tsx
|
|
7648
|
+
import { createRouter } from '@tanstack/react-router'
|
|
7649
|
+
|
|
7650
|
+
const router = createRouter({
|
|
7651
|
+
routeTree,
|
|
7652
|
+
rewrite: {
|
|
7653
|
+
input: ({ url }) => {
|
|
7654
|
+
// Transform browser URL → router internal URL
|
|
7655
|
+
// Return the modified URL, a new URL, or undefined to skip
|
|
7656
|
+
return url
|
|
7657
|
+
},
|
|
7658
|
+
output: ({ url }) => {
|
|
7659
|
+
// Transform router internal URL → browser URL
|
|
7660
|
+
// Return the modified URL, a new URL, or undefined to skip
|
|
7661
|
+
return url
|
|
7662
|
+
},
|
|
7663
|
+
},
|
|
7664
|
+
})
|
|
7665
|
+
\`\`\`
|
|
7666
|
+
|
|
7667
|
+
The \`input\` and \`output\` functions receive a \`URL\` object and can:
|
|
7668
|
+
|
|
7669
|
+
- Mutate and return the same \`url\` object
|
|
7670
|
+
- Return a new \`URL\` instance
|
|
7671
|
+
- Return a full href string (will be parsed into a URL)
|
|
7672
|
+
- Return \`undefined\` to skip the rewrite
|
|
7673
|
+
|
|
7674
|
+
## Common Patterns
|
|
7675
|
+
|
|
7676
|
+
### Pattern 1: i18n Locale Prefix
|
|
7677
|
+
|
|
7678
|
+
Strip locale prefixes on input and add them back on output:
|
|
7679
|
+
|
|
7680
|
+
\`\`\`tsx
|
|
7681
|
+
const locales = ['en', 'fr', 'es', 'de']
|
|
7682
|
+
const defaultLocale = 'en'
|
|
7683
|
+
|
|
7684
|
+
// Get current locale (from cookie, localStorage, or detection)
|
|
7685
|
+
function getLocale() {
|
|
7686
|
+
return localStorage.getItem('locale') || defaultLocale
|
|
7687
|
+
}
|
|
7688
|
+
|
|
7689
|
+
const router = createRouter({
|
|
7690
|
+
routeTree,
|
|
7691
|
+
rewrite: {
|
|
7692
|
+
input: ({ url }) => {
|
|
7693
|
+
// Check if pathname starts with a locale prefix
|
|
7694
|
+
const segments = url.pathname.split('/').filter(Boolean)
|
|
7695
|
+
const firstSegment = segments[0]
|
|
7696
|
+
|
|
7697
|
+
if (firstSegment && locales.includes(firstSegment)) {
|
|
7698
|
+
// Strip the locale prefix: /en/about → /about
|
|
7699
|
+
url.pathname = '/' + segments.slice(1).join('/') || '/'
|
|
7700
|
+
}
|
|
7701
|
+
return url
|
|
7702
|
+
},
|
|
7703
|
+
output: ({ url }) => {
|
|
7704
|
+
const locale = getLocale()
|
|
7705
|
+
// Add locale prefix: /about → /en/about
|
|
7706
|
+
if (locale !== defaultLocale || true) {
|
|
7707
|
+
// Always prefix, or conditionally skip default locale
|
|
7708
|
+
url.pathname = \`/\${locale}\${url.pathname === '/' ? '' : url.pathname}\`
|
|
7709
|
+
}
|
|
7710
|
+
return url
|
|
7711
|
+
},
|
|
7712
|
+
},
|
|
7713
|
+
})
|
|
7714
|
+
\`\`\`
|
|
7715
|
+
|
|
7716
|
+
For production i18n, consider using a library like Paraglide that provides \`localizeUrl\` and \`deLocalizeUrl\` functions. See the [Internationalization guide](./internationalization-i18n.md) for integration details.
|
|
7717
|
+
|
|
7718
|
+
### Pattern 2: Subdomain to Path Routing
|
|
7719
|
+
|
|
7720
|
+
Route subdomain requests to path-based routes:
|
|
7721
|
+
|
|
7722
|
+
\`\`\`tsx
|
|
7723
|
+
const router = createRouter({
|
|
7724
|
+
routeTree,
|
|
7725
|
+
rewrite: {
|
|
7726
|
+
input: ({ url }) => {
|
|
7727
|
+
const subdomain = url.hostname.split('.')[0]
|
|
7728
|
+
|
|
7729
|
+
// admin.example.com/users → /admin/users
|
|
7730
|
+
if (subdomain === 'admin') {
|
|
7731
|
+
url.pathname = '/admin' + url.pathname
|
|
7732
|
+
}
|
|
7733
|
+
// api.example.com/v1/users → /api/v1/users
|
|
7734
|
+
else if (subdomain === 'api') {
|
|
7735
|
+
url.pathname = '/api' + url.pathname
|
|
7736
|
+
}
|
|
7737
|
+
|
|
7738
|
+
return url
|
|
7739
|
+
},
|
|
7740
|
+
output: ({ url }) => {
|
|
7741
|
+
// Reverse the transformation for link generation
|
|
7742
|
+
if (url.pathname.startsWith('/admin')) {
|
|
7743
|
+
url.hostname = 'admin.example.com'
|
|
7744
|
+
url.pathname = url.pathname.replace(/^\/admin/, '') || '/'
|
|
7745
|
+
} else if (url.pathname.startsWith('/api')) {
|
|
7746
|
+
url.hostname = 'api.example.com'
|
|
7747
|
+
url.pathname = url.pathname.replace(/^\/api/, '') || '/'
|
|
7748
|
+
}
|
|
7749
|
+
return url
|
|
7750
|
+
},
|
|
7751
|
+
},
|
|
7752
|
+
})
|
|
7753
|
+
\`\`\`
|
|
7754
|
+
|
|
7755
|
+
### Pattern 3: Legacy URL Migration
|
|
7756
|
+
|
|
7757
|
+
Support old URLs while maintaining new route structure:
|
|
7758
|
+
|
|
7759
|
+
\`\`\`tsx
|
|
7760
|
+
const legacyPaths: Record<string, string> = {
|
|
7761
|
+
'/old-about': '/about',
|
|
7762
|
+
'/old-contact': '/contact',
|
|
7763
|
+
'/blog-posts': '/blog',
|
|
7764
|
+
'/user-profile': '/account/profile',
|
|
7765
|
+
}
|
|
7766
|
+
|
|
7767
|
+
const router = createRouter({
|
|
7768
|
+
routeTree,
|
|
7769
|
+
rewrite: {
|
|
7770
|
+
input: ({ url }) => {
|
|
7771
|
+
const newPath = legacyPaths[url.pathname]
|
|
7772
|
+
if (newPath) {
|
|
7773
|
+
url.pathname = newPath
|
|
7774
|
+
}
|
|
7775
|
+
return url
|
|
7776
|
+
},
|
|
7777
|
+
// No output rewrite needed - new URLs will be used going forward
|
|
7778
|
+
},
|
|
7779
|
+
})
|
|
7780
|
+
\`\`\`
|
|
7781
|
+
|
|
7782
|
+
### Pattern 4: Multi-tenant Routing
|
|
7783
|
+
|
|
7784
|
+
Route tenant-specific domains to a unified route structure:
|
|
7785
|
+
|
|
7786
|
+
\`\`\`tsx
|
|
7787
|
+
const router = createRouter({
|
|
7788
|
+
routeTree,
|
|
7789
|
+
rewrite: {
|
|
7790
|
+
input: ({ url }) => {
|
|
7791
|
+
// Extract tenant from subdomain: acme.app.com → acme
|
|
7792
|
+
const parts = url.hostname.split('.')
|
|
7793
|
+
if (parts.length >= 3) {
|
|
7794
|
+
const tenant = parts[0]
|
|
7795
|
+
// Inject tenant into the path: /dashboard → /tenant/acme/dashboard
|
|
7796
|
+
url.pathname = \`/tenant/\${tenant}\${url.pathname}\`
|
|
7797
|
+
}
|
|
7798
|
+
return url
|
|
7799
|
+
},
|
|
7800
|
+
output: ({ url }) => {
|
|
7801
|
+
// Extract tenant from path and move to subdomain
|
|
7802
|
+
const match = url.pathname.match(/^\/tenant\/([^/]+)(.*)$/)
|
|
7803
|
+
if (match) {
|
|
7804
|
+
const [, tenant, rest] = match
|
|
7805
|
+
url.hostname = \`\${tenant}.app.com\`
|
|
7806
|
+
url.pathname = rest || '/'
|
|
7807
|
+
}
|
|
7808
|
+
return url
|
|
7809
|
+
},
|
|
7810
|
+
},
|
|
7811
|
+
})
|
|
7812
|
+
\`\`\`
|
|
7813
|
+
|
|
7814
|
+
### Pattern 5: Search Parameter Transformation
|
|
7815
|
+
|
|
7816
|
+
Transform search parameters during rewrites:
|
|
7817
|
+
|
|
7818
|
+
\`\`\`tsx
|
|
7819
|
+
const router = createRouter({
|
|
7820
|
+
routeTree,
|
|
7821
|
+
rewrite: {
|
|
7822
|
+
input: ({ url }) => {
|
|
7823
|
+
// Convert legacy search param format
|
|
7824
|
+
// ?filter_status=active → ?status=active
|
|
7825
|
+
const filterStatus = url.searchParams.get('filter_status')
|
|
7826
|
+
if (filterStatus) {
|
|
7827
|
+
url.searchParams.delete('filter_status')
|
|
7828
|
+
url.searchParams.set('status', filterStatus)
|
|
7829
|
+
}
|
|
7830
|
+
return url
|
|
7831
|
+
},
|
|
7832
|
+
output: ({ url }) => {
|
|
7833
|
+
// Optionally transform back for external display
|
|
7834
|
+
return url
|
|
7835
|
+
},
|
|
7836
|
+
},
|
|
7837
|
+
})
|
|
7838
|
+
\`\`\`
|
|
7839
|
+
|
|
7840
|
+
## Composing Multiple Rewrites
|
|
7841
|
+
|
|
7842
|
+
When you need multiple independent rewrite transformations, use \`composeRewrites\` to combine them:
|
|
7843
|
+
|
|
7844
|
+
\`\`\`tsx
|
|
7845
|
+
import { composeRewrites } from '@tanstack/react-router'
|
|
7846
|
+
|
|
7847
|
+
const localeRewrite = {
|
|
7848
|
+
input: ({ url }) => {
|
|
7849
|
+
// Strip locale prefix
|
|
7850
|
+
const match = url.pathname.match(/^\/(en|fr|es)(\/.*)$/)
|
|
7851
|
+
if (match) {
|
|
7852
|
+
url.pathname = match[2] || '/'
|
|
7853
|
+
}
|
|
7854
|
+
return url
|
|
7855
|
+
},
|
|
7856
|
+
output: ({ url }) => {
|
|
7857
|
+
// Add locale prefix
|
|
7858
|
+
url.pathname = \`/en\${url.pathname === '/' ? '' : url.pathname}\`
|
|
7859
|
+
return url
|
|
7860
|
+
},
|
|
7861
|
+
}
|
|
7862
|
+
|
|
7863
|
+
const legacyRewrite = {
|
|
7864
|
+
input: ({ url }) => {
|
|
7865
|
+
if (url.pathname === '/old-page') {
|
|
7866
|
+
url.pathname = '/new-page'
|
|
7867
|
+
}
|
|
7868
|
+
return url
|
|
7869
|
+
},
|
|
7870
|
+
}
|
|
7871
|
+
|
|
7872
|
+
const router = createRouter({
|
|
7873
|
+
routeTree,
|
|
7874
|
+
rewrite: composeRewrites([localeRewrite, legacyRewrite]),
|
|
7875
|
+
})
|
|
7876
|
+
\`\`\`
|
|
7877
|
+
|
|
7878
|
+
**Order of operations:**
|
|
7879
|
+
|
|
7880
|
+
- **Input rewrites**: Execute in order (first to last)
|
|
7881
|
+
- **Output rewrites**: Execute in reverse order (last to first)
|
|
7882
|
+
|
|
7883
|
+
This ensures that composed rewrites "unwrap" correctly. In the example above:
|
|
7884
|
+
|
|
7885
|
+
- Input: locale strips \`/en\`, then legacy redirects \`/old-page\`
|
|
7886
|
+
- Output: legacy runs first (no-op), then locale adds \`/en\` back
|
|
7887
|
+
|
|
7888
|
+
## Interaction with Basepath
|
|
7889
|
+
|
|
7890
|
+
When you configure a \`basepath\`, the router internally implements it as a rewrite. If you also provide a custom \`rewrite\`, they are automatically composed together:
|
|
7891
|
+
|
|
7892
|
+
\`\`\`tsx
|
|
7893
|
+
const router = createRouter({
|
|
7894
|
+
routeTree,
|
|
7895
|
+
basepath: '/app',
|
|
7896
|
+
rewrite: {
|
|
7897
|
+
input: ({ url }) => {
|
|
7898
|
+
// This runs AFTER basepath is stripped
|
|
7899
|
+
// Browser: /app/en/about → After basepath: /en/about → Your rewrite: /about
|
|
7900
|
+
return url
|
|
7901
|
+
},
|
|
7902
|
+
output: ({ url }) => {
|
|
7903
|
+
// This runs BEFORE basepath is added
|
|
7904
|
+
// Your rewrite: /about → After your rewrite: /en/about → Basepath adds: /app/en/about
|
|
7905
|
+
return url
|
|
7906
|
+
},
|
|
7907
|
+
},
|
|
7908
|
+
})
|
|
7909
|
+
\`\`\`
|
|
7910
|
+
|
|
7911
|
+
The composition order ensures:
|
|
7912
|
+
|
|
7913
|
+
1. **Input**: Basepath stripped first, then your rewrite runs
|
|
7914
|
+
2. **Output**: Your rewrite runs first, then basepath added
|
|
7915
|
+
|
|
7916
|
+
## Working with Links and Navigation
|
|
7917
|
+
|
|
7918
|
+
### Link Component
|
|
7919
|
+
|
|
7920
|
+
The \`<Link>\` component automatically applies output rewrites when generating \`href\` attributes:
|
|
7921
|
+
|
|
7922
|
+
\`\`\`tsx
|
|
7923
|
+
// With locale rewrite configured (adds /en prefix)
|
|
7924
|
+
<Link to="/about">About</Link>
|
|
7925
|
+
// Renders: <a href="/en/about">About</a>
|
|
7926
|
+
\`\`\`
|
|
7927
|
+
|
|
7928
|
+
### Programmatic Navigation
|
|
7929
|
+
|
|
7930
|
+
Programmatic navigation via \`navigate()\` or \`router.navigate()\` also respects rewrites:
|
|
7931
|
+
|
|
7932
|
+
\`\`\`tsx
|
|
7933
|
+
const navigate = useNavigate()
|
|
7934
|
+
|
|
7935
|
+
// Navigates to /about internally, displays /en/about in browser
|
|
7936
|
+
navigate({ to: '/about' })
|
|
7937
|
+
\`\`\`
|
|
7938
|
+
|
|
7939
|
+
### Hard Links for Cross-Origin Rewrites
|
|
7940
|
+
|
|
7941
|
+
When an output rewrite changes the origin (hostname), the \`<Link>\` component automatically renders a standard anchor tag instead of using client-side navigation:
|
|
7942
|
+
|
|
7943
|
+
\`\`\`tsx
|
|
7944
|
+
// Rewrite that changes hostname for /admin paths
|
|
7945
|
+
const router = createRouter({
|
|
7946
|
+
routeTree,
|
|
7947
|
+
rewrite: {
|
|
7948
|
+
output: ({ url }) => {
|
|
7949
|
+
if (url.pathname.startsWith('/admin')) {
|
|
7950
|
+
url.hostname = 'admin.example.com'
|
|
7951
|
+
url.pathname = url.pathname.replace(/^\/admin/, '') || '/'
|
|
7952
|
+
}
|
|
7953
|
+
return url
|
|
7954
|
+
},
|
|
7955
|
+
},
|
|
7956
|
+
})
|
|
7957
|
+
|
|
7958
|
+
// This link will be a hard navigation (full page load)
|
|
7959
|
+
<Link to="/admin/dashboard">Admin Dashboard</Link>
|
|
7960
|
+
// Renders: <a href="https://admin.example.com/dashboard">Admin Dashboard</a>
|
|
7961
|
+
\`\`\`
|
|
7962
|
+
|
|
7963
|
+
## The publicHref Property
|
|
7964
|
+
|
|
7965
|
+
The router's location object includes a \`publicHref\` property that contains the external URL (after output rewrite):
|
|
7966
|
+
|
|
7967
|
+
\`\`\`tsx
|
|
7968
|
+
function MyComponent() {
|
|
7969
|
+
const location = useLocation()
|
|
7970
|
+
|
|
7971
|
+
// Internal URL used for routing
|
|
7972
|
+
console.log(location.href) // "/about"
|
|
7973
|
+
|
|
7974
|
+
// External URL shown in browser
|
|
7975
|
+
console.log(location.publicHref) // "/en/about"
|
|
7976
|
+
|
|
7977
|
+
return (
|
|
7978
|
+
<div>
|
|
7979
|
+
{/* Use publicHref for sharing, canonical URLs, etc. */}
|
|
7980
|
+
<ShareButton url={window.location.origin + location.publicHref} />
|
|
7981
|
+
</div>
|
|
7982
|
+
)
|
|
7983
|
+
}
|
|
7984
|
+
\`\`\`
|
|
7985
|
+
|
|
7986
|
+
Use \`publicHref\` when you need the actual browser URL for:
|
|
7987
|
+
|
|
7988
|
+
- Social sharing
|
|
7989
|
+
- Canonical URLs
|
|
7990
|
+
- Analytics tracking
|
|
7991
|
+
- Copying links to clipboard
|
|
7992
|
+
|
|
7993
|
+
## Server-side Considerations
|
|
7994
|
+
|
|
7995
|
+
URL rewrites apply on both client and server. When using TanStack Start:
|
|
7996
|
+
|
|
7997
|
+
### Server Middleware
|
|
7998
|
+
|
|
7999
|
+
Rewrites are applied when parsing incoming requests:
|
|
8000
|
+
|
|
8001
|
+
\`\`\`tsx
|
|
8002
|
+
// router.tsx
|
|
8003
|
+
export const router = createRouter({
|
|
8004
|
+
routeTree,
|
|
8005
|
+
rewrite: {
|
|
8006
|
+
input: ({ url }) => deLocalizeUrl(url),
|
|
8007
|
+
output: ({ url }) => localizeUrl(url),
|
|
8008
|
+
},
|
|
8009
|
+
})
|
|
8010
|
+
\`\`\`
|
|
8011
|
+
|
|
8012
|
+
The server handler will use the same rewrite configuration to parse incoming URLs and generate responses with the correct external URLs.
|
|
8013
|
+
|
|
8014
|
+
### SSR Hydration
|
|
8015
|
+
|
|
8016
|
+
The router ensures that the server-rendered HTML and client hydration use consistent URLs. The \`publicHref\` is serialized during SSR so the client can hydrate with the correct external URL.
|
|
8017
|
+
|
|
8018
|
+
## API Reference
|
|
8019
|
+
|
|
8020
|
+
### \`rewrite\` option
|
|
8021
|
+
|
|
8022
|
+
- Type: [\`LocationRewrite\`](#locationrewrite-type)
|
|
8023
|
+
- Optional
|
|
8024
|
+
- Configures bidirectional URL transformation between browser and router.
|
|
8025
|
+
|
|
8026
|
+
### LocationRewrite type
|
|
8027
|
+
|
|
8028
|
+
\`\`\`tsx
|
|
8029
|
+
type LocationRewrite = {
|
|
8030
|
+
/**
|
|
8031
|
+
* Transform the URL before the router interprets it.
|
|
8032
|
+
* Called when reading from browser history.
|
|
8033
|
+
*/
|
|
8034
|
+
input?: LocationRewriteFunction
|
|
8035
|
+
|
|
8036
|
+
/**
|
|
8037
|
+
* Transform the URL before it's written to browser history.
|
|
8038
|
+
* Called when generating links and committing navigation.
|
|
8039
|
+
*/
|
|
8040
|
+
output?: LocationRewriteFunction
|
|
8041
|
+
}
|
|
8042
|
+
\`\`\`
|
|
8043
|
+
|
|
8044
|
+
### LocationRewriteFunction type
|
|
8045
|
+
|
|
8046
|
+
\`\`\`tsx
|
|
8047
|
+
type LocationRewriteFunction = (opts: { url: URL }) => undefined | string | URL
|
|
8048
|
+
\`\`\`
|
|
8049
|
+
|
|
8050
|
+
**Parameters:**
|
|
8051
|
+
|
|
8052
|
+
- \`url\`: A \`URL\` object representing the current URL
|
|
8053
|
+
|
|
8054
|
+
**Returns:**
|
|
8055
|
+
|
|
8056
|
+
- \`URL\`: The transformed URL object (can be the same mutated object or a new instance)
|
|
8057
|
+
- \`string\`: A full href string that will be parsed into a URL
|
|
8058
|
+
- \`undefined\`: Skip the rewrite, use the original URL
|
|
8059
|
+
|
|
8060
|
+
### composeRewrites function
|
|
8061
|
+
|
|
8062
|
+
\`\`\`tsx
|
|
8063
|
+
import { composeRewrites } from '@tanstack/react-router'
|
|
8064
|
+
|
|
8065
|
+
function composeRewrites(rewrites: Array<LocationRewrite>): LocationRewrite
|
|
8066
|
+
\`\`\`
|
|
8067
|
+
|
|
8068
|
+
Combines multiple rewrite pairs into a single rewrite. Input rewrites execute in order, output rewrites execute in reverse order.
|
|
8069
|
+
|
|
8070
|
+
**Example:**
|
|
8071
|
+
|
|
8072
|
+
\`\`\`tsx
|
|
8073
|
+
const composedRewrite = composeRewrites([
|
|
8074
|
+
{ input: rewrite1Input, output: rewrite1Output },
|
|
8075
|
+
{ input: rewrite2Input, output: rewrite2Output },
|
|
8076
|
+
])
|
|
8077
|
+
|
|
8078
|
+
// Input execution order: rewrite1Input → rewrite2Input
|
|
8079
|
+
// Output execution order: rewrite2Output → rewrite1Output
|
|
8080
|
+
\`\`\`
|
|
8081
|
+
|
|
8082
|
+
## Examples
|
|
8083
|
+
|
|
8084
|
+
Complete working examples are available in the TanStack Router repository:
|
|
8085
|
+
|
|
8086
|
+
- [React + Paraglide (Client-side i18n)](https://github.com/TanStack/router/tree/main/examples/react/i18n-paraglide)
|
|
8087
|
+
- [React + TanStack Start + Paraglide (SSR i18n)](https://github.com/TanStack/router/tree/main/examples/react/start-i18n-paraglide)
|
|
8088
|
+
- [Solid + Paraglide (Client-side i18n)](https://github.com/TanStack/router/tree/main/examples/solid/i18n-paraglide)
|
|
8089
|
+
- [Solid + TanStack Start + Paraglide (SSR i18n)](https://github.com/TanStack/router/tree/main/examples/solid/start-i18n-paraglide)
|
|
8090
|
+
|
|
7594
8091
|
`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-router",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.154.2",
|
|
4
4
|
"description": "Modern and scalable routing for React applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -81,8 +81,8 @@
|
|
|
81
81
|
"isbot": "^5.1.22",
|
|
82
82
|
"tiny-invariant": "^1.3.3",
|
|
83
83
|
"tiny-warning": "^1.0.3",
|
|
84
|
-
"@tanstack/
|
|
85
|
-
"@tanstack/
|
|
84
|
+
"@tanstack/history": "1.153.2",
|
|
85
|
+
"@tanstack/router-core": "1.154.2"
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
88
|
"@testing-library/jest-dom": "^6.6.3",
|