diff --git a/runtime/src/app/app.ts b/runtime/src/app/app.ts index 3056b31..3f5e8e1 100644 --- a/runtime/src/app/app.ts +++ b/runtime/src/app/app.ts @@ -101,7 +101,11 @@ export function select_target(url: URL): Target { if (url.origin !== location.origin) return null; if (!url.pathname.startsWith(initial_data.baseUrl)) return null; - const path = url.pathname.slice(initial_data.baseUrl.length); + let path = url.pathname.slice(initial_data.baseUrl.length); + + if (path === '') { + path = '/'; + } // avoid accidental clashes between server routes and page routes if (ignore.some(pattern => pattern.test(path))) return; diff --git a/src/core/create_manifest_data.ts b/src/core/create_manifest_data.ts index 12cabe2..f7e2853 100644 --- a/src/core/create_manifest_data.ts +++ b/src/core/create_manifest_data.ts @@ -86,6 +86,7 @@ export default function create_manifest_data(cwd: string): ManifestData { const parts = get_parts(segment); const is_index = is_dir ? false : basename.startsWith('index.'); const is_page = component_extensions.indexOf(ext) !== -1; + const route_suffix = basename.slice(basename.indexOf('.'), -ext.length); parts.forEach(part => { if (/\]\[/.test(part.content)) { @@ -104,7 +105,8 @@ export default function create_manifest_data(cwd: string): ManifestData { file: posixify(file), is_dir, is_index, - is_page + is_page, + route_suffix }; }) .filter(Boolean) @@ -113,25 +115,25 @@ export default function create_manifest_data(cwd: string): ManifestData { items.forEach(item => { const segments = parent_segments.slice(); - if (item.is_index && segments.length > 0) { - const suffix = item.basename - .slice(0, -item.ext.length) - .replace('index', ''); + if (item.is_index) { + if (item.route_suffix) { + if (segments.length > 0) { + const last_segment = segments[segments.length - 1].slice(); + const last_part = last_segment[last_segment.length - 1]; - if (suffix) { - const last_segment = segments[segments.length - 1].slice(); - const last_part = last_segment[last_segment.length - 1]; + if (last_part.dynamic) { + last_segment.push({ dynamic: false, content: item.route_suffix }); + } else { + last_segment[last_segment.length - 1] = { + dynamic: false, + content: `${last_part.content}${item.route_suffix}` + }; + } - if (last_part.dynamic) { - last_segment.push({ dynamic: false, content: suffix }); + segments[segments.length - 1] = last_segment; } else { - last_segment[last_segment.length - 1] = { - dynamic: false, - content: `${last_part.content}${suffix}` - }; + segments.push(item.parts); } - - segments[segments.length - 1] = last_segment; } } else { segments.push(item.parts); @@ -156,8 +158,6 @@ export default function create_manifest_data(cwd: string): ManifestData { } else if (item.is_page) { - const is_index = item.basename === `index${item.ext}`; - const component = { name: get_slug(item.file), file: item.file, @@ -166,22 +166,20 @@ export default function create_manifest_data(cwd: string): ManifestData { components.push(component); - const parts = (is_index && stack[stack.length - 1] === null) + const parts = (item.is_index && stack[stack.length - 1] === null) ? stack.slice(0, -1).concat({ component, params }) : stack.concat({ component, params }) - const page = { - pattern: get_pattern(is_index ? parent_segments : segments, true), + pages.push({ + pattern: get_pattern(segments, true), parts - }; - - pages.push(page); + }); } else { server_routes.push({ name: `route_${get_slug(item.file)}`, - pattern: get_pattern(segments, false), + pattern: get_pattern(segments, !item.route_suffix), file: item.file, params: params }); @@ -321,7 +319,6 @@ function get_parts(part: string): Part[] { function get_slug(file: string) { let name = file .replace(/[\\\/]index/, '') - .replace(/_default([\/\\index])?\.html$/, 'index') .replace(/[\/\\]/g, '_') .replace(/\.\w+$/, '') .replace(/\[([^(]+)(?:\([^(]+\))?\]/, '$$$1') @@ -334,19 +331,19 @@ function get_slug(file: string) { } function get_pattern(segments: Part[][], add_trailing_slash: boolean) { - return new RegExp( - `^` + - segments.map(segment => { - return '\\/' + segment.map(part => { - return part.dynamic - ? part.qualifier || part.spread ? '(.+)' : '([^\\/]+?)' - : encodeURI(part.content.normalize()) - .replace(/\?/g, '%3F') - .replace(/#/g, '%23') - .replace(/%5B/g, '[') - .replace(/%5D/g, ']'); - }).join(''); - }).join('') + - (add_trailing_slash ? '\\\/?$' : '$') - ); + const path = segments.map(segment => { + return segment.map(part => { + return part.dynamic + ? part.qualifier || part.spread ? '(.+)' : '([^\\/]+?)' + : encodeURI(part.content.normalize()) + .replace(/\?/g, '%3F') + .replace(/#/g, '%23') + .replace(/%5B/g, '[') + .replace(/%5D/g, ']'); + }).join(''); + }).join('\\/'); + + const trailing = add_trailing_slash && segments.length ? '\\/?$' : '$'; + + return new RegExp(`^\\/${path}${trailing}`); } diff --git a/test/unit/create_manifest_data/samples/basic/index.js b/test/unit/create_manifest_data/samples/basic/index.js new file mode 100644 index 0000000..e69de29 diff --git a/test/unit/create_manifest_data/test.ts b/test/unit/create_manifest_data/test.ts index 7286dbe..01f7714 100644 --- a/test/unit/create_manifest_data/test.ts +++ b/test/unit/create_manifest_data/test.ts @@ -20,7 +20,7 @@ describe('manifest_data', () => { assert.deepEqual(pages, [ { - pattern: /^\/?$/, + pattern: /^\/$/, parts: [ { component: index, params: [] } ] @@ -50,6 +50,13 @@ describe('manifest_data', () => { ]); assert.deepEqual(server_routes, [ + { + name: 'route_index', + pattern: /^\/$/, + file: 'index.js', + params: [] + }, + { name: 'route_blog_json', pattern: /^\/blog.json$/, @@ -167,7 +174,7 @@ describe('manifest_data', () => { file: 'foo.js', name: 'route_foo', params: [], - pattern: /^\/foo$/ + pattern: /^\/foo\/?$/ }]); }); });