diff --git a/src/core/create_manifests.ts b/src/core/create_manifests.ts index 7f0c4b5..d178fe9 100644 --- a/src/core/create_manifests.ts +++ b/src/core/create_manifests.ts @@ -3,10 +3,10 @@ import * as path from 'path'; import * as glob from 'glob'; import { posixify, write_if_changed } from './utils'; import { dev, locations } from '../config'; -import { Route } from '../interfaces'; +import { Page, PageComponent, ServerRoute } from '../interfaces'; export function create_main_manifests({ routes, dev_port }: { - routes: Route[]; + routes: { components: PageComponent[], pages: Page[], server_routes: ServerRoute[] }; dev_port?: number; }) { const path_to_routes = path.relative(`${locations.app()}/manifest`, locations.routes()); @@ -19,7 +19,7 @@ export function create_main_manifests({ routes, dev_port }: { } export function create_serviceworker_manifest({ routes, client_files }: { - routes: Route[]; + routes: { components: PageComponent[], pages: Page[], server_routes: ServerRoute[] }; client_files: string[]; }) { const assets = glob.sync('**', { cwd: 'assets', nodir: true }); @@ -32,37 +32,61 @@ export function create_serviceworker_manifest({ routes, client_files }: { export const shell = [\n\t${client_files.map((x: string) => `"${x}"`).join(',\n\t')}\n]; - export const routes = [\n\t${routes.pages.filter(r => r.id !== '_error').map((r: Route) => `{ pattern: ${r.pattern} }`).join(',\n\t')}\n]; + export const routes = [\n\t${routes.pages.map((r: Page) => `{ pattern: ${r.pattern} }`).join(',\n\t')}\n]; `.replace(/^\t\t/gm, '').trim(); write_if_changed(`${locations.app()}/manifest/service-worker.js`, code); } -function generate_client(routes: Route[], path_to_routes: string, dev_port?: number) { - const page_ids = new Set(routes.pages.map(page => page.id)); - const server_routes_to_ignore = routes.server_routes.filter(route => !page_ids.has(route.id)); +function right_pad(str: string, len: number) { + while (str.length < len) str += ' '; + return str; +} - const pages = routes.pages.filter(page => page.id !== '_error'); - const error_route = routes.pages.find(page => page.id === '_error'); +function generate_client( + routes: { components: PageComponent[], pages: Page[], server_routes: ServerRoute[] }, + path_to_routes: string, + dev_port?: number +) { + const page_ids = new Set(routes.pages.map(page => + page.pattern.toString())); + + const server_routes_to_ignore = routes.server_routes.filter(route => + !page_ids.has(route.pattern.toString())); + + const len = Math.max(...routes.components.map(c => c.name.length)); let code = ` // This file is generated by Sapper — do not edit it! + import root from '${posixify(`${path_to_routes}/index.html`)}'; + + ${routes.components.map(component => + `const ${right_pad(component.name, len)} = () => import('${posixify(`${path_to_routes}/${component.file}`)}');`) + .join('\n')} + export const routes = { ignore: [${server_routes_to_ignore.map(route => route.pattern).join(', ')}], + root, + pages: [ - ${pages.map(page => { - const file = posixify(`${path_to_routes}/${page.file}`); + ${routes.pages.map(page => `{ + // ${page.parts[page.parts.length - 1].component.file} + pattern: ${page.pattern}, + parts: [ + ${page.parts.map(part => { + if (part.params.length > 0) { + const props = part.params.map((param, i) => `${param}: match[${i + 1}]`); + return `{ component: ${part.component.name}, params: match => ({ ${props.join(', ')} }) }`; + } - const params = page.params.length === 0 - ? '{}' - : `{ ${page.params.map((part, i) => `${part}: match[${i + 1}]`).join(', ')} }`; - - return `{ pattern: ${page.pattern}, params: ${page.params.length > 0 ? `match` : `()`} => (${params}), load: () => import(/* webpackChunkName: "${page.id}" */ '${file}') }`; - }).join(',\n\t\t\t\t')} + return `{ component: ${part.component.name} }`; + }).join(',\n\t\t\t\t\t\t')} + ] + }`).join(',\n\n\t\t\t\t')} ], - error: () => import(/* webpackChunkName: '_error' */ '${posixify(`${path_to_routes}/${error_route.file}`)}') + error: () => import(/* webpackChunkName: '_error' */ '${posixify(`${path_to_routes}/_error.html`)}') };`.replace(/^\t\t/gm, '').trim(); if (dev()) { @@ -82,16 +106,17 @@ function generate_client(routes: Route[], path_to_routes: string, dev_port?: num return code; } -function generate_server(routes: Route[], path_to_routes: string) { - const pages = routes.pages.filter(page => page.id !== '_error'); - const error_route = routes.pages.find(page => page.id === '_error'); - +function generate_server( + routes: { components: PageComponent[], pages: Page[], server_routes: ServerRoute[] }, + path_to_routes: string +) { const imports = [].concat( routes.server_routes.map(route => - `import * as route_${route.id} from '${posixify(`${path_to_routes}/${route.file}`)}';`), - pages.map(page => - `import page_${page.id} from '${posixify(`${path_to_routes}/${page.file}`)}';`), - `import error from '${posixify(`${path_to_routes}/${error_route.file}`)}';` + `import * as ${route.name} from '${posixify(`${path_to_routes}/${route.file}`)}';`), + routes.components.map(component => + `import ${component.name} from '${posixify(`${path_to_routes}/${component.file}`)}';`), + `import root from '${posixify(`${path_to_routes}/index.html`)}';`, + `import error from '${posixify(`${path_to_routes}/_error.html`)}';` ); let code = ` @@ -100,29 +125,36 @@ function generate_server(routes: Route[], path_to_routes: string) { export const routes = { server_routes: [ - ${routes.server_routes.map(route => { - const params = route.params.length === 0 - ? '{}' - : `{ ${route.params.map((part, i) => `${part}: match[${i + 1}]`).join(', ')} }`; - - return `{ id: '${route.id}', pattern: ${route.pattern}, params: ${route.params.length > 0 ? `match` : `()`} => (${params}), handlers: route_${route.id} }`; - }).join(',\n\t\t\t\t')} + ${routes.server_routes.map(route => `{ + // ${route.file} + pattern: ${route.pattern}, + handlers: ${route.name}, + params: ${route.params.length > 0 + ? `match => ({ ${route.params.map((param, i) => `${param}: match[${i + 1}]`).join(', ')} })` + : `() => ({})`} + }`).join(',\n\n\t\t\t\t')} ], pages: [ - ${pages.map(page => { - const params = page.params.length === 0 - ? '{}' - : `{ ${page.params.map((part, i) => `${part}: match[${i + 1}]`).join(', ')} }`; + ${routes.pages.map(page => `{ + // ${page.parts[page.parts.length - 1].component.file} + pattern: ${page.pattern}, + parts: [ + ${page.parts.map(part => { + if (part.params.length > 0) { + const props = part.params.map((param, i) => `${param}: match[${i + 1}]`); + return `{ component: ${part.component.name}, params: match => ({ ${props.join(', ')} }) }`; + } - return `{ id: '${page.id}', pattern: ${page.pattern}, params: ${page.params.length > 0 ? `match` : `()`} => (${params}), handler: page_${page.id} }`; - }).join(',\n\t\t\t\t')} + return `{ component: ${part.component.name} }`; + }).join(',\n\t\t\t\t\t\t')} + ] + }`).join(',\n\n\t\t\t\t')} ], - error: { - error: true, - handler: error - } + root, + + error };`.replace(/^\t\t/gm, '').trim(); return code; diff --git a/src/core/create_routes.ts b/src/core/create_routes.ts index d05ee16..ec6df9b 100644 --- a/src/core/create_routes.ts +++ b/src/core/create_routes.ts @@ -1,29 +1,10 @@ import * as fs from 'fs'; import * as path from 'path'; import { locations } from '../config'; - -type Component = { - name: string; - file: string; -}; - -type Page = { - pattern: RegExp; - parts: Array<{ - component: Component; - params: string[]; - }> -}; - -type ServerRoute = { - name: string; - pattern: RegExp; - file: string; - params: string[]; -}; +import { Page, PageComponent, ServerRoute } from '../interfaces'; export default function create_routes(cwd = locations.routes()) { - const components: Component[] = []; + const components: PageComponent[] = []; const pages: Page[] = []; const server_routes: ServerRoute[] = []; @@ -32,7 +13,7 @@ export default function create_routes(cwd = locations.routes()) { parent_segments: Part[][], parent_params: string[], stack: Array<{ - component: Component, + component: PageComponent, params: string[] }> ) { diff --git a/src/interfaces.ts b/src/interfaces.ts index 82f6b3b..a01fda7 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -18,4 +18,24 @@ export type Template = { export type Store = { get: () => any; +}; + +export type PageComponent = { + name: string; + file: string; +}; + +export type Page = { + pattern: RegExp; + parts: Array<{ + component: PageComponent; + params: string[]; + }> +}; + +export type ServerRoute = { + name: string; + pattern: RegExp; + file: string; + params: string[]; }; \ No newline at end of file