UNPKG

@tdb/web

Version:

Common condiguration for serving a web-site and testing web-based UI components.

125 lines (107 loc) 2.97 kB
import { fs, fsPath, value } from '../common'; import { IManifestResource, ManifestFileType, IManifestFolder, IManifestFile, IManifestJson, IManifestYaml, } from './types'; import { toManifestImage, parseJson, parseYaml, toManifestMarkdown, } from './util'; /** * Creates an IResource. */ export async function toResource(args: { rootPath: string; filePath: string; urlPrefix?: string; loadExtensions?: string[]; }): Promise<IManifestResource | undefined> { const { rootPath, filePath, urlPrefix, loadExtensions = [] } = args; const file = fsPath.parse(filePath); let body: string | undefined; let error: IManifestResource['error'] | undefined; const type = await toFileType(filePath); // Load body of document if requested. const ext = (file.ext || '').replace(/^\./, ''); if (loadExtensions.includes(ext)) { try { body = (await fs.readFile(filePath)).toString(); } catch (err) { const message = `Failed to load body. ${err.message}`; error = { message }; } } // Resolve path to the file. let path = filePath.substr(rootPath.length); path = urlPrefix ? fsPath.join(urlPrefix, path) : path; // Convert to specific manifest type. let result: IManifestResource | undefined; switch (type) { case 'FOLDER': const folder: IManifestFolder = { type: 'FOLDER', path }; result = folder; break; case 'FILE': const file: IManifestFile = { type: 'FILE', path }; result = file; break; case 'FILE/image': const image = await toManifestImage(filePath, path, { size: true }); result = image; break; case 'FILE/markdown': const markdown = await toManifestMarkdown(path, body); result = markdown; break; case 'FILE/json': const manifestJson: IManifestJson = { type: 'FILE/json', path, ...parseJson(body), }; result = manifestJson; break; case 'FILE/yaml': const manifestYaml: IManifestYaml = { type: 'FILE/yaml', path, ...parseYaml(body), }; result = manifestYaml; break; default: throw new Error(`File type '${type}' not supported.`); } // Finish up. error = result && result.error ? result.error : error; return result ? value.deleteUndefined({ ...result, error }) : undefined; } /** * Determine the file-type of the given file. */ export async function toFileType(path: string): Promise<ManifestFileType> { if ((await fs.lstat(path)).isDirectory()) { return 'FOLDER'; } const file = fsPath.parse(path); const ext = file.ext.toLowerCase(); if (['.md', '.markdown'].includes(ext)) { return 'FILE/markdown'; } if (['.jpg', '.jpeg', '.png', '.svg'].includes(ext)) { return 'FILE/image'; } if (['.json'].includes(ext)) { return 'FILE/json'; } if (['.yml', '.yaml'].includes(ext)) { return 'FILE/yaml'; } return 'FILE'; }