mirror of
https://github.com/kevin-DL/sapper.git
synced 2026-01-12 19:25:10 +00:00
190 lines
5.7 KiB
TypeScript
190 lines
5.7 KiB
TypeScript
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
import * as glob from 'glob';
|
|
import { posixify, write_if_changed } from './utils';
|
|
import { dev, locations } from '../config';
|
|
import { Page, PageComponent, ServerRoute } from '../interfaces';
|
|
|
|
export function create_main_manifests({ routes, dev_port }: {
|
|
routes: { components: PageComponent[], pages: Page[], server_routes: ServerRoute[] };
|
|
dev_port?: number;
|
|
}) {
|
|
const path_to_routes = path.relative(`${locations.app()}/manifest`, locations.routes());
|
|
|
|
const client_manifest = generate_client(routes, path_to_routes, dev_port);
|
|
const server_manifest = generate_server(routes, path_to_routes);
|
|
|
|
write_if_changed(
|
|
`${locations.app()}/manifest/default-layout.html`,
|
|
`<svelte:component this={child.component} {...child.props}/>`
|
|
);
|
|
write_if_changed(`${locations.app()}/manifest/client.js`, client_manifest);
|
|
write_if_changed(`${locations.app()}/manifest/server.js`, server_manifest);
|
|
}
|
|
|
|
export function create_serviceworker_manifest({ routes, client_files }: {
|
|
routes: { components: PageComponent[], pages: Page[], server_routes: ServerRoute[] };
|
|
client_files: string[];
|
|
}) {
|
|
const assets = glob.sync('**', { cwd: 'assets', nodir: true });
|
|
|
|
let code = `
|
|
// This file is generated by Sapper — do not edit it!
|
|
export const timestamp = ${Date.now()};
|
|
|
|
export const assets = [\n\t${assets.map((x: string) => `"${x}"`).join(',\n\t')}\n];
|
|
|
|
export const shell = [\n\t${client_files.map((x: string) => `"${x}"`).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 right_pad(str: string, len: number) {
|
|
while (str.length < len) str += ' ';
|
|
return str;
|
|
}
|
|
|
|
function generate_client(
|
|
routes: { root: PageComponent, 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 '${get_file(path_to_routes, routes.root)}';
|
|
import error from '${posixify(`${path_to_routes}/_error.html`)}';
|
|
|
|
${routes.components.map(component =>
|
|
`const ${component.name} = () =>
|
|
import(/* webpackChunkName: "${component.name}" */ '${get_file(path_to_routes, component)}');`)
|
|
.join('\n')}
|
|
|
|
export const manifest = {
|
|
ignore: [${server_routes_to_ignore.map(route => route.pattern).join(', ')}],
|
|
|
|
pages: [
|
|
${routes.pages.map(page => `{
|
|
// ${page.parts[page.parts.length - 1].component.file}
|
|
pattern: ${page.pattern},
|
|
parts: [
|
|
${page.parts.map(part => {
|
|
if (part === null) return 'null';
|
|
|
|
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 `{ component: ${part.component.name} }`;
|
|
}).join(',\n\t\t\t\t\t\t')}
|
|
]
|
|
}`).join(',\n\n\t\t\t\t')}
|
|
],
|
|
|
|
root,
|
|
|
|
error
|
|
};
|
|
|
|
// this is included for legacy reasons
|
|
export const routes = {};`.replace(/^\t\t/gm, '').trim();
|
|
|
|
if (dev()) {
|
|
const sapper_dev_client = posixify(
|
|
path.resolve(__dirname, '../sapper-dev-client.js')
|
|
);
|
|
|
|
code += `
|
|
|
|
if (module.hot) {
|
|
import('${sapper_dev_client}').then(client => {
|
|
client.connect(${dev_port});
|
|
});
|
|
}`.replace(/^\t{3}/gm, '');
|
|
}
|
|
|
|
return code;
|
|
}
|
|
|
|
function generate_server(
|
|
routes: { root: PageComponent, components: PageComponent[], pages: Page[], server_routes: ServerRoute[] },
|
|
path_to_routes: string
|
|
) {
|
|
const imports = [].concat(
|
|
routes.server_routes.map(route =>
|
|
`import * as ${route.name} from '${posixify(`${path_to_routes}/${route.file}`)}';`),
|
|
routes.components.map(component =>
|
|
`import ${component.name} from '${get_file(path_to_routes, component)}';`),
|
|
`import root from '${get_file(path_to_routes, routes.root)}';`,
|
|
`import error from '${posixify(`${path_to_routes}/_error.html`)}';`
|
|
);
|
|
|
|
let code = `
|
|
// This file is generated by Sapper — do not edit it!
|
|
${imports.join('\n')}
|
|
|
|
export const manifest = {
|
|
server_routes: [
|
|
${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: [
|
|
${routes.pages.map(page => `{
|
|
// ${page.parts[page.parts.length - 1].component.file}
|
|
pattern: ${page.pattern},
|
|
parts: [
|
|
${page.parts.map(part => {
|
|
if (part === null) return 'null';
|
|
|
|
const props = [
|
|
`name: "${part.component.name}"`,
|
|
`component: ${part.component.name}`
|
|
];
|
|
|
|
if (part.params.length > 0) {
|
|
const params = part.params.map((param, i) => `${param}: match[${i + 1}]`);
|
|
props.push(`params: match => ({ ${params.join(', ')} })`);
|
|
}
|
|
|
|
return `{ ${props.join(', ')} }`;
|
|
}).join(',\n\t\t\t\t\t\t')}
|
|
]
|
|
}`).join(',\n\n\t\t\t\t')}
|
|
],
|
|
|
|
root,
|
|
|
|
error
|
|
};
|
|
|
|
// this is included for legacy reasons
|
|
export const routes = {};`.replace(/^\t\t/gm, '').trim();
|
|
|
|
return code;
|
|
}
|
|
|
|
function get_file(path_to_routes: string, component: PageComponent) {
|
|
if (component.default) {
|
|
return `./default-layout.html`;
|
|
}
|
|
|
|
return posixify(`${path_to_routes}/${component.file}`);
|
|
} |