From bdf37b4cde5202410c6d8fdaa9665a9ae546e7d1 Mon Sep 17 00:00:00 2001 From: Jon Witting Date: Mon, 17 Apr 2023 14:55:33 +0100 Subject: [PATCH] feat: expose `contentBasePublicPath` --- index.d.ts | 6 ++++++ src/index.js | 22 ++++++++++++++++------ test/frames.html | 28 ++++++++++++++++++++++++++++ test/rollup.config.js | 1 + 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/index.d.ts b/index.d.ts index 82a5eb7..1a02438 100644 --- a/index.d.ts +++ b/index.d.ts @@ -26,6 +26,12 @@ export interface RollupServeOptions { */ contentBase?: string | string[] + /** + * URL path prefix applied to all requests. + * E.g. If `contentBasePublicPath="/foo/bar"` and a request is made to `/foo/bar/baz.js`, `baz.js` will be returned from `contentBase`. + */ + contentBasePublicPath?: string + /** * Set to `true` to return index.html (200) instead of error page (404) * or path to fallback page diff --git a/src/index.js b/src/index.js index 58f6ce8..53bdb8f 100644 --- a/src/index.js +++ b/src/index.js @@ -17,6 +17,7 @@ function serve (options = { contentBase: '' }) { options = { contentBase: options } } options.contentBase = Array.isArray(options.contentBase) ? options.contentBase : [options.contentBase || ''] + options.contentBasePublicPath = options.contentBasePublicPath || '' options.port = options.port || 10001 options.headers = options.headers || {} options.https = options.https || false @@ -39,7 +40,7 @@ function serve (options = { contentBase: '' }) { response.setHeader(key, options.headers[key]) }) - readFileFromContentBase(options.contentBase, urlPath, function (error, content, filePath) { + readFileFromContentBase(options.contentBase, options.contentBasePublicPath, urlPath, function (error, content, filePath) { if (!error) { return found(response, filePath, content) } @@ -53,7 +54,7 @@ function serve (options = { contentBase: '' }) { } if (options.historyApiFallback) { const fallbackPath = typeof options.historyApiFallback === 'string' ? options.historyApiFallback : '/index.html' - readFileFromContentBase(options.contentBase, fallbackPath, function (error, content, filePath) { + readFileFromContentBase(options.contentBase, options.contentBasePublicPath, fallbackPath, function (error, content, filePath) { if (error) { notFound(response, filePath) } else { @@ -120,18 +121,27 @@ function serve (options = { contentBase: '' }) { } } -function readFileFromContentBase (contentBase, urlPath, callback) { - let filePath = resolve(contentBase[0] || '.', '.' + urlPath) +function readFileFromContentBase (contentBase, contentBasePublicPath, urlPath, callback) { + let internalUrlPath = urlPath + if (contentBasePublicPath) { + if (urlPath === contentBasePublicPath) { + internalUrlPath = '/' + } else if (urlPath.startsWith(contentBasePublicPath)) { + internalUrlPath = internalUrlPath.replace(contentBasePublicPath, '') + } + } + + let filePath = resolve(contentBase[0] || '.', '.' + internalUrlPath) // Load index.html in directories - if (urlPath.endsWith('/')) { + if (internalUrlPath.endsWith('/')) { filePath = resolve(filePath, 'index.html') } readFile(filePath, (error, content) => { if (error && contentBase.length > 1) { // Try to read from next contentBase - readFileFromContentBase(contentBase.slice(1), urlPath, callback) + readFileFromContentBase(contentBase.slice(1), contentBasePublicPath, urlPath, callback) } else { // We know enough callback(error, content, filePath) diff --git a/test/frames.html b/test/frames.html index 4351cbb..611f0c4 100644 --- a/test/frames.html +++ b/test/frames.html @@ -26,16 +26,32 @@ + + /foo/bar + + + + ./base1 + + /foo/bar/base1 + + + ./base2 + + /foo/bar/base2 + + + ./ @@ -48,10 +64,22 @@ + + /foo/bar/test1.html + + + + test2.html + + /foo/bar/test2.html + + + + diff --git a/test/rollup.config.js b/test/rollup.config.js index 1ba0a4d..dfe0717 100644 --- a/test/rollup.config.js +++ b/test/rollup.config.js @@ -28,6 +28,7 @@ export default { openPage: '/frames.html', historyApiFallback: '/fallback.html', contentBase: ['.', 'base1', 'base2'], + contentBasePublicPath: '/foo/bar', onListening: testOnListening(), }) ]