diff --git a/docs/customization.md b/docs/customization.md index c7e35f4..fa035ca 100644 --- a/docs/customization.md +++ b/docs/customization.md @@ -16,13 +16,19 @@ This file should contain a JSON object that can have the following optional keys: - **`"styles"`**\ - A path to a single custom style sheet, or an array of multiple style sheets - applied in order. These will be applied after Vivify's [default - styles](./static/) are applied so that there are always sensible fallbacks but - you can override everything. + A path to a single custom style sheet, or an array of paths for multiple style + sheets applied in order. The paths can be absolute, start with a tilde (`~`) + for your home directory, or be relative to your config file's directory. The + paths can also include [glob patterns](https://www.npmjs.com/package/glob).\ + The styles will be applied after Vivify's [default styles](../static/) are + applied so that there are always sensible fallbacks but you can override + everything. - **`"scripts"`**\ A path to a single custom JavaScript to inject into the viewing pages, or an - array of multiple custom scripts. + array of paths for multiple custom scripts injected in order. The paths can be + absolute, start with a tilde (`~`) for your home directory, or be relative to + your config file's directory. The paths can also include [glob + patterns](https://www.npmjs.com/package/glob). - **`"dirListIgnore"`**\ A path to a file with globs to ignore in Vivify's directory viewer, or an array of multiple paths to ignore files. The syntax here is the same as in diff --git a/src/config.ts b/src/config.ts index 7bebd8e..bbf5c80 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,4 +1,5 @@ import fs from 'fs'; +import { globSync } from 'glob'; import { homedir } from 'os'; import path from 'path'; @@ -45,11 +46,23 @@ const configPaths = [ ]; // read contents of file at paths or files at paths -const getFileContents = (paths: string[] | string | undefined): string => { +const getFileContents = ( + paths: string[] | string | undefined, + baseDir: string | undefined, +): string => { if (paths === undefined) return ''; + const getFileContent = (p: string): string => { - const resolved = p[0] === '~' ? path.join(homedir(), p.slice(1)) : p; - return fs.existsSync(resolved) ? fs.readFileSync(resolved, 'utf8') : ''; + let resolved = p; + if (resolved[0] === '~') { + resolved = path.join(homedir(), p.slice(1)); + } + if (resolved[0] !== '/' && baseDir !== undefined) { + resolved = path.join(baseDir, resolved); + } + return globSync(resolved) + .map((p) => fs.readFileSync(p, 'utf8')) + .join('\n'); }; if (Array.isArray(paths)) { @@ -60,11 +73,13 @@ const getFileContents = (paths: string[] | string | undefined): string => { const config = ((): Config => { let config = undefined; + let configBaseDir = undefined; // greedily find config for (const cp of configPaths) { if (!fs.existsSync(cp)) continue; try { config = JSON.parse(fs.readFileSync(cp, 'utf8')); + configBaseDir = path.dirname(cp); } catch {} break; } @@ -77,9 +92,9 @@ const config = ((): Config => { } // get styles, scripts and ignore files - config.styles = getFileContents(config.styles); - config.scripts = getFileContents(config.scripts); - config.dirListIgnore = getFileContents(config.dirListIgnore) + config.styles = getFileContents(config.styles, configBaseDir); + config.scripts = getFileContents(config.scripts, configBaseDir); + config.dirListIgnore = getFileContents(config.dirListIgnore, configBaseDir) .split('\n') .filter((pattern) => pattern !== '' && pattern[0] !== '#');