Skip to content

Commit

Permalink
Anchor (#834)
Browse files Browse the repository at this point in the history
* 🎉 NEW: anchor support

* add changeset
  • Loading branch information
jycouet authored Jan 15, 2025
1 parent b54be76 commit b8c5eab
Show file tree
Hide file tree
Showing 27 changed files with 466 additions and 97 deletions.
5 changes: 5 additions & 0 deletions .changeset/rich-panthers-sniff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'vite-plugin-kit-routes': patch
---

add anchor support
18 changes: 16 additions & 2 deletions packages/vite-plugin-kit-routes/src/lib/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ const PAGES = {
'/a/[...rest]/z': (params: { rest: (string | number)[] }) => {
return `/a/${params['rest']?.join('/')}/z`
},
'/anchors': (params: {
anchor: 'section0' | 'section1' | 'section2' | 'section3'
anotherOne?: string
}) => {
return `/anchors${appendSp({ __KIT_ROUTES_ANCHOR__: params['anchor'], anotherOne: params['anotherOne'] })}`
},
'/lay/normal': `/lay/normal`,
'/lay/root-layout': `/lay/root-layout`,
'/lay/skip': `/lay/skip`,
Expand Down Expand Up @@ -183,7 +189,12 @@ export const appendSp = (
}
}

let anchor = ''
for (const [name, val] of Object.entries(sp)) {
if (name === '__KIT_ROUTES_ANCHOR__') {
anchor = `#${val}`
continue
}
if (Array.isArray(val)) {
for (const v of val) {
append(name, v)
Expand All @@ -194,8 +205,8 @@ export const appendSp = (
}

const formatted = params.toString()
if (formatted) {
return `${prefix}${formatted}`
if (formatted || anchor) {
return `${prefix}${formatted}${anchor}`
}
return ''
}
Expand Down Expand Up @@ -286,6 +297,7 @@ export type KIT_ROUTES = {
'/site/[id]': 'lang' | 'id'
'/site_contract/[siteId]-[contractId]': 'siteId' | 'contractId' | 'lang'
'/a/[...rest]/z': 'rest'
'/anchors': never
'/lay/normal': never
'/lay/root-layout': never
'/lay/skip': never
Expand Down Expand Up @@ -323,6 +335,8 @@ export type KIT_ROUTES = {
siteId: never
contractId: never
rest: never
anchor: never
anotherOne: never
ids: never
locale: never
redirectTo: never
Expand Down
14 changes: 11 additions & 3 deletions packages/vite-plugin-kit-routes/src/lib/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ export const appendSp = `type ParamValue = string | number | undefined
/**
* Append search params to a string
*/
export const appendSp = (sp?: Record<string, ParamValue | ParamValue[]>, prefix: '?' | '&' = '?') => {
export const appendSp = (
sp?: Record<string, ParamValue | ParamValue[]>,
prefix: '?' | '&' = '?',
) => {
if (sp === undefined) return ''
const params = new URLSearchParams()
Expand All @@ -34,7 +37,12 @@ export const appendSp = (sp?: Record<string, ParamValue | ParamValue[]>, prefix:
}
}
let anchor = ''
for (const [name, val] of Object.entries(sp)) {
if (name === '__KIT_ROUTES_ANCHOR__') {
anchor = \`#\${val}\`
continue
}
if (Array.isArray(val)) {
for (const v of val) {
append(name, v)
Expand All @@ -45,8 +53,8 @@ export const appendSp = (sp?: Record<string, ParamValue | ParamValue[]>, prefix:
}
const formatted = params.toString()
if (formatted) {
return \`\${prefix}\${formatted}\`
if (formatted || anchor) {
return \`\${prefix}\${formatted}\${anchor}\`
}
return ''
}
Expand Down
29 changes: 26 additions & 3 deletions packages/vite-plugin-kit-routes/src/lib/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,23 @@ export type ExplicitSearchParam = ExtendParam & {
* @default 'split'
*/
arrayMode?: 'join' | 'split'

/**
* If `true`, the key has no impact on the route.
* and one of the type will be used as the #hash.
* @example
* explicit_search_params: {
* anchor: {
* type: '"section1" | "section2" | "section3"',
* required: true,
* isAnchor: true
* }
* }
* will result in something like : /anchors#section1
*
* @default false
*/
isAnchor?: boolean
}

export const log = new Log('Kit Routes')
Expand Down Expand Up @@ -593,6 +610,7 @@ export function buildMetadata(
type: sp[1].type,
default: sp[1].default,
isArray: false,
isAnchor: sp[1].isAnchor,
}

paramsFromPath.push(param)
Expand All @@ -617,7 +635,12 @@ export function buildMetadata(
Object.entries(customConf.explicit_search_params).forEach((sp) => {
const val = paramsIsOptional ? `params?.['${sp[0]}']` : `params['${sp[0]}']`

explicit_search_params_to_function.push([sp[0], getSpValue(val, sp[1])])
let key = sp[0]
if (sp[1].isAnchor) {
key = `__KIT_ROUTES_ANCHOR__`
}

explicit_search_params_to_function.push([key, getSpValue(val, sp[1])])
})
}

Expand All @@ -631,10 +654,10 @@ export function buildMetadata(
// If it's in the explicite and it's THIS one, let's change the array...
if (
explicit_search_params_to_function.length === 1 &&
explicit_search_params_to_function[0][0] === paramsReq[0].name
(explicit_search_params_to_function[0][0] === paramsReq[0].name ||
explicit_search_params_to_function[0][0] === `__KIT_ROUTES_ANCHOR__`)
) {
const sp = customConf.explicit_search_params![paramsReq[0].name]

explicit_search_params_to_function[0][1] = getSpValue(paramsReq[0].name, sp)
} else {
// in params
Expand Down
18 changes: 18 additions & 0 deletions packages/vite-plugin-kit-routes/src/lib/plugins.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,18 @@ describe('run()', async () => {
spArrayComma: {
explicit_search_params: { ids: { type: 'number[]', required: true, arrayMode: 'join' } },
},
anchors: {
explicit_search_params: {
anchor: {
type: '"section0" | "section1" | "section2" | "section3"',
required: true,
isAnchor: true,
},
// anotherOne: {
// type: 'string',
// },
},
},
},
SERVERS: {},
ACTIONS: {
Expand All @@ -387,6 +399,7 @@ describe('run()', async () => {
'/match/[id=int]': commonConfig_variables.PAGES?.match_id_int,
'/site_contract/[siteId]-[contractId]':
commonConfig_variables.PAGES?.site_contract_siteId_contractId,
'/anchors': commonConfig_variables.PAGES?.anchors,
},
SERVERS: {},
ACTIONS: {
Expand All @@ -405,6 +418,7 @@ describe('run()', async () => {
'/[[lang]]/match/[id=int]': commonConfig_variables.PAGES?.match_id_int,
'/[[lang]]/site_contract/[siteId]-[contractId]':
commonConfig_variables.PAGES?.site_contract_siteId_contractId,
'/anchors': commonConfig_variables.PAGES?.anchors,
},
SERVERS: {},
ACTIONS: {
Expand Down Expand Up @@ -914,6 +928,7 @@ describe('rmv Helper', () => {
"/site_contract/[siteId]-[contractId]/+page.server.ts",
"/site_contract/[siteId]-[contractId]/+page.svelte",
"a/[...rest]/z/+page.svelte",
"anchors/+page.svelte",
"api/graphql/+server.ts",
"data/errors/[locale].json/+server.ts",
"lay/(layVerySpecial)/+layout.svelte",
Expand Down Expand Up @@ -963,6 +978,7 @@ describe('rmv Helper', () => {
"[[lang]]/site_contract/[siteId]-[contractId]/+page.server.ts",
"[[lang]]/site_contract/[siteId]-[contractId]/+page.svelte",
"a/[...rest]/z/+page.svelte",
"anchors/+page.svelte",
"api/graphql/+server.ts",
"data/errors/[locale].json/+server.ts",
"lay/(layVerySpecial)/+layout.svelte",
Expand Down Expand Up @@ -1005,6 +1021,7 @@ describe('rmv Helper', () => {
"[[lang]]/site_contract/[siteId]-[contractId]/+page.server.ts",
"[[lang]]/site_contract/[siteId]-[contractId]/+page.svelte",
"a/[...rest]/z/+page.svelte",
"anchors/+page.svelte",
"api/graphql/+server.ts",
"data/errors/[locale].json/+server.ts",
"lay/+layout.svelte",
Expand Down Expand Up @@ -1050,6 +1067,7 @@ describe('rmv Helper', () => {
"/site_contract/[siteId]-[contractId]/+page.server.ts",
"/site_contract/[siteId]-[contractId]/+page.svelte",
"a/[...rest]/z/+page.svelte",
"anchors/+page.svelte",
"api/graphql/+server.ts",
"data/errors/[locale].json/+server.ts",
"lay/+layout.svelte",
Expand Down
7 changes: 6 additions & 1 deletion packages/vite-plugin-kit-routes/src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,12 @@
<a href={route('/spArray', { ids: [1, 2, 3] })}>Array Search Params</a> |
<a href={route('/spArrayComma', { ids: [1, 2, 3] })}>Array Search Params (comma-separated)</a>
</li>
<a href="/COUCOU-Yop">Unsafe Link</a>
<li>
<a href="/COUCOU-Yop">Unsafe Link</a>
</li>
<li>
<a href={route('/anchors', { anchor: 'section0', anotherOne: 'coucou' })}>Anchors</a>
</li>
</ul>

<hr />
Expand Down
89 changes: 89 additions & 0 deletions packages/vite-plugin-kit-routes/src/routes/anchors/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<script lang="ts">
import { goto } from '$app/navigation'
</script>

<div class="mx-auto max-w-3xl p-6">
<nav class="sticky top-0 mb-8 rounded-lg bg-gray-100 p-4">
<button class="text-blue-600 hover:underline" on:click={() => goto('anchors#section1')}>
Section 1
</button>

<button class="text-blue-600 hover:underline" on:click={() => goto('anchors#section2')}>
Section 2
</button>

<button class="text-blue-600 hover:underline" on:click={() => goto('anchors#section3')}>
Section 3
</button>
</nav>

<section id="section1" class="mb-12">
<h2 class="mb-4 text-2xl font-bold">Section 1</h2>
<p class="mb-4">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat.
</p>
<p class="mb-4">
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
<p class="mb-4">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat.
</p>
<p class="mb-4">
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
</section>

<section id="section2" class="mb-12">
<h2 class="mb-4 text-2xl font-bold">Section 2</h2>
<p class="mb-4">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque
laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto
beatae vitae dicta sunt explicabo.
</p>
<p class="mb-4">
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia
consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
</p>
<p class="mb-4">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat.
</p>
<p class="mb-4">
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
</section>

<section id="section3" class="mb-12">
<h2 class="mb-4 text-2xl font-bold">Section 3</h2>
<p class="mb-4">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium
voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati
cupiditate non provident.
</p>
<p class="mb-4">
Similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga.
Et harum quidem rerum facilis est et expedita distinctio.
</p>
<p class="mb-4">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat.
</p>
<p class="mb-4">
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
</section>
</div>
17 changes: 13 additions & 4 deletions packages/vite-plugin-kit-routes/src/test/ROUTES_base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const PAGES = {
"/a/[...rest]/z": (params: { rest: (string | number)[] }) => {
return `${base}/a/${params['rest']?.join('/')}/z`
},
"/anchors": `${base}/anchors`,
"/lay/normal": `${base}/lay/normal`,
"/lay/root-layout": `${base}/lay/root-layout`,
"/lay/skip": `${base}/lay/skip`,
Expand Down Expand Up @@ -114,7 +115,10 @@ type ParamValue = string | number | undefined
/**
* Append search params to a string
*/
export const appendSp = (sp?: Record<string, ParamValue | ParamValue[]>, prefix: '?' | '&' = '?') => {
export const appendSp = (
sp?: Record<string, ParamValue | ParamValue[]>,
prefix: '?' | '&' = '?',
) => {
if (sp === undefined) return ''

const params = new URLSearchParams()
Expand All @@ -124,7 +128,12 @@ export const appendSp = (sp?: Record<string, ParamValue | ParamValue[]>, prefix:
}
}

let anchor = ''
for (const [name, val] of Object.entries(sp)) {
if (name === '__KIT_ROUTES_ANCHOR__') {
anchor = `#${val}`
continue
}
if (Array.isArray(val)) {
for (const v of val) {
append(name, v)
Expand All @@ -135,8 +144,8 @@ export const appendSp = (sp?: Record<string, ParamValue | ParamValue[]>, prefix:
}

const formatted = params.toString()
if (formatted) {
return `${prefix}${formatted}`
if (formatted || anchor) {
return `${prefix}${formatted}${anchor}`
}
return ''
}
Expand Down Expand Up @@ -206,7 +215,7 @@ export function route<T extends keyof AllTypes>(key: T, ...params: any[]): strin
* ```
*/
export type KIT_ROUTES = {
PAGES: { '/': never, '/subGroup': never, '/subGroup/user': never, '/subGroup2': never, '/contract': 'lang', '/contract/[id]': 'id' | 'lang', '/gp/one': 'lang', '/gp/two': 'lang', '/main': 'lang', '/match/[id=ab]': 'id' | 'lang', '/match/[id=int]': 'id' | 'lang', '/site': 'lang', '/site/[id]': 'id' | 'lang', '/site_contract/[siteId]-[contractId]': 'siteId' | 'contractId' | 'lang', '/a/[...rest]/z': 'rest', '/lay/normal': never, '/lay/root-layout': never, '/lay/skip': never, '/sp': never, '/spArray': never, '/spArrayComma': never }
PAGES: { '/': never, '/subGroup': never, '/subGroup/user': never, '/subGroup2': never, '/contract': 'lang', '/contract/[id]': 'id' | 'lang', '/gp/one': 'lang', '/gp/two': 'lang', '/main': 'lang', '/match/[id=ab]': 'id' | 'lang', '/match/[id=int]': 'id' | 'lang', '/site': 'lang', '/site/[id]': 'id' | 'lang', '/site_contract/[siteId]-[contractId]': 'siteId' | 'contractId' | 'lang', '/a/[...rest]/z': 'rest', '/anchors': never, '/lay/normal': never, '/lay/root-layout': never, '/lay/skip': never, '/sp': never, '/spArray': never, '/spArrayComma': never }
SERVERS: { 'GET /server_func_get': never, 'GET /server_func_get_and_': never, 'POST /server_func_post': never, 'GET /contract': 'lang', 'POST /contract': 'lang', 'GET /site': 'lang', 'GET /api/graphql': never, 'POST /api/graphql': never, 'GET /data/errors/[locale].json': 'locale' }
ACTIONS: { 'default /contract/[id]': 'id' | 'lang', 'create /site': 'lang', 'update /site/[id]': 'id' | 'lang', 'delete /site/[id]': 'id' | 'lang', 'noSatisfies /site_contract': 'lang', 'send /site_contract/[siteId]-[contractId]': 'siteId' | 'contractId' | 'lang' }
LINKS: Record<string, never>
Expand Down
Loading

0 comments on commit b8c5eab

Please sign in to comment.