diff --git a/src/server/components/link.tsx b/src/server/components/link.tsx index 9c549af..8295f47 100644 --- a/src/server/components/link.tsx +++ b/src/server/components/link.tsx @@ -1,6 +1,7 @@ import type { FC } from 'hono/jsx' import type { JSX } from 'hono/jsx/jsx-runtime' import type { Manifest } from 'vite' +import { ensureTrailngSlash } from '../utils/path' type Options = { manifest?: Manifest; prod?: boolean } & JSX.IntrinsicElements['link'] @@ -23,7 +24,12 @@ export const Link: FC = (options) => { const assetInManifest = manifest[href.replace(/^\//, '')] if (assetInManifest) { if (href.startsWith('/')) { - return + return ( + + ) } return diff --git a/src/server/components/script.tsx b/src/server/components/script.tsx index 062071c..c38730f 100644 --- a/src/server/components/script.tsx +++ b/src/server/components/script.tsx @@ -1,4 +1,5 @@ import type { Manifest } from 'vite' +import { ensureTrailngSlash } from '../utils/path.js' import { HasIslands } from './has-islands.js' type Options = { @@ -33,7 +34,7 @@ export const Script = (options: Options): any => { diff --git a/src/server/utils/path.test.ts b/src/server/utils/path.test.ts new file mode 100644 index 0000000..170d90d --- /dev/null +++ b/src/server/utils/path.test.ts @@ -0,0 +1,12 @@ +import { ensureTrailngSlash } from './path' + +describe('ensureTrailngSlash', () => { + it('Should ensure trailing slash', () => { + expect(ensureTrailngSlash('./')).toBe('./') + expect(ensureTrailngSlash('/')).toBe('/') + expect(ensureTrailngSlash('/subdir')).toBe('/subdir/') + expect(ensureTrailngSlash('/subdir/')).toBe('/subdir/') + expect(ensureTrailngSlash('https://example.com')).toBe('https://example.com/') + expect(ensureTrailngSlash('https://example.com/subdir')).toBe('https://example.com/subdir/') + }) +}) diff --git a/src/server/utils/path.ts b/src/server/utils/path.ts new file mode 100644 index 0000000..f4ce168 --- /dev/null +++ b/src/server/utils/path.ts @@ -0,0 +1,3 @@ +export const ensureTrailngSlash = (path: string) => { + return path.endsWith('/') ? path : path + '/' +} diff --git a/test-integration/apps.test.ts b/test-integration/apps.test.ts index 5ad05ae..570ce83 100644 --- a/test-integration/apps.test.ts +++ b/test-integration/apps.test.ts @@ -489,6 +489,69 @@ describe('

Component

' ) }) + + describe('with base path - root relative', () => { + const originalBaseURL = import.meta.env.BASE_URL + + beforeAll(() => { + // this means `base: "/base/path/"` in vite.config.ts + import.meta.env.BASE_URL = '/base/path/' + }) + + afterAll(() => { + import.meta.env.BASE_URL = originalBaseURL + }) + + it('Should convert the script path correctly', async () => { + const res = await app.request('/') + expect(res.status).toBe(200) + expect(await res.text()).toBe( + '

Component

' + ) + }) + }) + + describe('with base path - root relative, without trailing slash', () => { + const originalBaseURL = import.meta.env.BASE_URL + + beforeAll(() => { + // this means `base: "/base/path"` in vite.config.ts + import.meta.env.BASE_URL = '/base/path' + }) + + afterAll(() => { + import.meta.env.BASE_URL = originalBaseURL + }) + + it('Should convert the script path correctly', async () => { + const res = await app.request('/') + expect(res.status).toBe(200) + expect(await res.text()).toBe( + '

Component

' + ) + }) + }) + + describe('with base path - absolute url', () => { + const originalBaseURL = import.meta.env.BASE_URL + + beforeAll(() => { + // this means `base: "https://example.com/base/path/"` in vite.config.ts + import.meta.env.BASE_URL = 'https://example.com/base/path/' + }) + + afterAll(() => { + import.meta.env.BASE_URL = originalBaseURL + }) + + it('Should convert the script path correctly', async () => { + const res = await app.request('/') + expect(res.status).toBe(200) + expect(await res.text()).toBe( + '

Component

' + ) + }) + }) }) describe('With async', () => { @@ -555,6 +618,69 @@ describe(' component', () => { '
' ) }) + + describe('with base path - root relative', () => { + const originalBaseURL = import.meta.env.BASE_URL + + beforeAll(() => { + // this means `base: "/base/path/"` in vite.config.ts + import.meta.env.BASE_URL = '/base/path/' + }) + + afterAll(() => { + import.meta.env.BASE_URL = originalBaseURL + }) + + it('Should convert the link path correctly', async () => { + const res = await app.request('/') + expect(res.status).toBe(200) + expect(await res.text()).toBe( + '
' + ) + }) + }) + + describe('with base path - root relative, without trailing slash', () => { + const originalBaseURL = import.meta.env.BASE_URL + + beforeAll(() => { + // this means `base: "/base/path"` in vite.config.ts + import.meta.env.BASE_URL = '/base/path' + }) + + afterAll(() => { + import.meta.env.BASE_URL = originalBaseURL + }) + + it('Should convert the link path correctly', async () => { + const res = await app.request('/') + expect(res.status).toBe(200) + expect(await res.text()).toBe( + '
' + ) + }) + }) + + describe('with base path - absolute url', () => { + const originalBaseURL = import.meta.env.BASE_URL + + beforeAll(() => { + // this means `base: "https://example.com/base/path/"` in vite.config.ts + import.meta.env.BASE_URL = 'https://example.com/base/path/' + }) + + afterAll(() => { + import.meta.env.BASE_URL = originalBaseURL + }) + + it('Should convert the link path correctly', async () => { + const res = await app.request('/') + expect(res.status).toBe(200) + expect(await res.text()).toBe( + '
' + ) + }) + }) }) })