initial commit
This commit is contained in:
21
node_modules/serve-placeholder/LICENSE
generated
vendored
Normal file
21
node_modules/serve-placeholder/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 - 2022 UnJS
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
163
node_modules/serve-placeholder/README.md
generated
vendored
Normal file
163
node_modules/serve-placeholder/README.md
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
# ♡ serve-placeholder
|
||||
|
||||
> Smart placeholder for missing assets
|
||||
|
||||
[![npm version][npm-version-src]][npm-version-href]
|
||||
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
||||
[![Github Actions][github-actions-src]][github-actions-href]
|
||||
[![Codecov][codecov-src]][codecov-href]
|
||||
|
||||
## Why?
|
||||
|
||||
**💵 Rendering Errors is costly**
|
||||
|
||||
Serving each 404 page for assets adds extra load to the server and increases crashing chances. This is crucial for setups with server-side-rendering and removes additional SSR loads when assets like `robots.txt` or `favicon.ico` don't exist.
|
||||
|
||||
**👌 Meaningful Responses**
|
||||
|
||||
We can always send a better 404 response than an HTML page by knowing file extensions. For example, we send a fallback transparent 1x1 image for image extensions.
|
||||
|
||||
**🔍 SEO Friendly**
|
||||
|
||||
Instead of indexing invalid URLs with HTML pages, we properly send 404 and the right content type.
|
||||
|
||||
## Usage
|
||||
|
||||
Install package:
|
||||
|
||||
```sh
|
||||
# npm
|
||||
npm install serve-placeholder
|
||||
|
||||
# yarn
|
||||
yarn install serve-placeholder
|
||||
|
||||
# pnpm
|
||||
pnpm install serve-placeholder
|
||||
```
|
||||
|
||||
Import:
|
||||
|
||||
```js
|
||||
// ESM
|
||||
import { servePlaceholder } from 'serve-placeholder'
|
||||
|
||||
// CommonJS
|
||||
const { servePlaceholder } = require('serve-placeholder')
|
||||
```
|
||||
|
||||
Create and add server middleware between serve-static and router middleware:
|
||||
|
||||
```diff
|
||||
app.use('/assets', serveStatic(..))
|
||||
++ app.use('/assets', servePlaceholder())
|
||||
app.use('/', router)
|
||||
```
|
||||
|
||||
Additionally, we can have a default placeholder for arbitrary routes which handles known extensions **assuming other routes have no extension**:
|
||||
|
||||
```diff
|
||||
app.use('/assets', serveStatic(..))
|
||||
app.use('/assets', servePlaceholder())
|
||||
++ app.use('/', placeholder({ skipUnkown: true }))
|
||||
app.use('/', router)
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### `handlers`
|
||||
|
||||
A mapping from file extensions to the handler. Extensions should start with *dot* like `.js`.
|
||||
|
||||
You can disable any of the handlers by setting the value to `null`
|
||||
|
||||
If the value of a handler is set to `false`, the middleware will be ignored for that extension.
|
||||
|
||||
### `statusCode`
|
||||
|
||||
- Default: `404`
|
||||
|
||||
Sets `statusCode` for all handled responses. Set to `false` to disable overriding statusCode.
|
||||
|
||||
### `skipUnknown`
|
||||
|
||||
- Default: `false`
|
||||
|
||||
Skip middleware when no handler is defined for the current request.
|
||||
|
||||
Please note that if this option is set to `true`, then `default` handler will be disabled!
|
||||
|
||||
### `placeholders`
|
||||
|
||||
- Type: `Object`
|
||||
|
||||
A mapping from handler to placeholder. Values can be `String` or `Buffer`. You can disable any of the placeholders by setting the value to `false`.
|
||||
|
||||
### `mimes`
|
||||
|
||||
- Type: `Object`
|
||||
|
||||
A mapping from handler to the mime type. Mime type will be set as `Content-Type` header. You can disable sending any of the mimes by setting the value to `false`.
|
||||
|
||||
### `cacheHeaders`
|
||||
|
||||
- Default: `true`
|
||||
|
||||
Set headers to prevent accidentally caching 404 resources.
|
||||
|
||||
When enabled, these headers will be sent:
|
||||
|
||||
```js
|
||||
{
|
||||
'cache-control': 'no-cache, no-store, must-revalidate',
|
||||
'expires': '0',
|
||||
'pragma': 'no-cache'
|
||||
}
|
||||
```
|
||||
|
||||
### `placeholderHeader`
|
||||
|
||||
- Default: `true`
|
||||
|
||||
Sets an `X-Placeholder` header with value of handler name.
|
||||
|
||||
## Defaults
|
||||
|
||||
These are [default handlers](./src/defaults.js). You can override every of them using provided options.
|
||||
|
||||
Handler | Extensions | Mime type | Placeholder
|
||||
-----------|------------------------|--------------------------|-------------------
|
||||
`default` | any unknown extension | - | -
|
||||
`css` | `.css` | `text/css` | `/* style not found */`
|
||||
`html` | `.html`, `.htm` | `text/html` | `<!-- page not found -->`
|
||||
`js` | `.js` | `application/javascript` | `/* script not found */`
|
||||
`json` | `.json` | `application/json` | `{}`
|
||||
`map` | `.map` | `application/json` | [empty sourcemap v3 json]
|
||||
`plain` | `.txt`, `.text`, `.md` | `text/plain` | [empty]
|
||||
`image` | `.png`, `.jpg`, `.jpeg`, `.gif`, `.svg`, `.webp`, `.bmp`, `.ico` | `image/gif` | [transparent 1x1 image]
|
||||
|
||||
## 💻 Development
|
||||
|
||||
- Clone this repository
|
||||
- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable` (use `npm i -g corepack` for Node.js < 16.10)
|
||||
- Install dependencies using `pnpm install`
|
||||
- Run interactive tests using `pnpm dev`
|
||||
|
||||
## License
|
||||
|
||||
Made with 💛
|
||||
|
||||
Published under [MIT License](./LICENSE).
|
||||
|
||||
<!-- Badges -->
|
||||
[npm-version-src]: https://img.shields.io/npm/v/serve-placeholder?style=flat-square
|
||||
[npm-version-href]: https://npmjs.com/package/serve-placeholder
|
||||
|
||||
[npm-downloads-src]: https://img.shields.io/npm/dm/serve-placeholder?style=flat-square
|
||||
[npm-downloads-href]: https://npmjs.com/package/serve-placeholder
|
||||
|
||||
[github-actions-src]: https://img.shields.io/github/workflow/status/unjs/serve-placeholder/ci/main?style=flat-square
|
||||
[github-actions-href]: https://github.com/unjs/serve-placeholder/actions?query=workflow%3Aci
|
||||
|
||||
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/serve-placeholder/main?style=flat-square
|
||||
[codecov-href]: https://codecov.io/gh/unjs/serve-placeholder
|
||||
97
node_modules/serve-placeholder/dist/index.cjs
generated
vendored
Normal file
97
node_modules/serve-placeholder/dist/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
const defu = require('defu');
|
||||
|
||||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
|
||||
|
||||
const defu__default = /*#__PURE__*/_interopDefaultLegacy(defu);
|
||||
|
||||
const DefaultOptions = {
|
||||
statusCode: 404,
|
||||
skipUnknown: false,
|
||||
cacheHeaders: true,
|
||||
placeholderHeader: true,
|
||||
handlers: {
|
||||
".css": "css",
|
||||
".html": "html",
|
||||
".htm": "html",
|
||||
".png": "image",
|
||||
".jpg": "image",
|
||||
".jpeg": "image",
|
||||
".gif": "image",
|
||||
".svg": "image",
|
||||
".webp": "image",
|
||||
".bmp": "image",
|
||||
".ico": "image",
|
||||
".js": "js",
|
||||
".json": "json",
|
||||
".map": "map",
|
||||
".txt": "plain",
|
||||
".text": "plain",
|
||||
".md": "plain"
|
||||
},
|
||||
placeholders: {
|
||||
css: "/* style not found */",
|
||||
default: void 0,
|
||||
html: "<!-- page not found -->",
|
||||
image: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
|
||||
js: "/* script not found */",
|
||||
json: "{}",
|
||||
map: '{"version": "3", "sources": [], "mappings": "" }',
|
||||
plain: ""
|
||||
},
|
||||
mimes: {
|
||||
css: "text/css",
|
||||
default: void 0,
|
||||
html: "text/html",
|
||||
js: "application/javascript",
|
||||
json: "application/json",
|
||||
image: "image/gif",
|
||||
map: "application/json",
|
||||
plain: "text/plain"
|
||||
}
|
||||
};
|
||||
|
||||
const EXT_REGEX = /\.[a-zA-Z0-9]+$/;
|
||||
function servePlaceholder(_options = {}) {
|
||||
const options = defu__default(_options, DefaultOptions);
|
||||
return function servePlaceholderMiddleware(req, res, next) {
|
||||
if (res.writableEnded) {
|
||||
return;
|
||||
}
|
||||
const url = req.url.split("?")[0];
|
||||
const ext = (url.match(EXT_REGEX) || [])[0] || "";
|
||||
let handler = options.handlers[ext];
|
||||
if (handler === false) {
|
||||
return next();
|
||||
}
|
||||
if (typeof handler === "undefined") {
|
||||
if (options.skipUnknown) {
|
||||
return next();
|
||||
} else {
|
||||
handler = "default";
|
||||
}
|
||||
}
|
||||
if (options.statusCode) {
|
||||
res.statusCode = options.statusCode;
|
||||
}
|
||||
const mime = options.mimes[handler];
|
||||
if (mime) {
|
||||
res.setHeader("Content-Type", mime);
|
||||
}
|
||||
if (options.cacheHeaders) {
|
||||
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
res.setHeader("Pragma", "no-cache");
|
||||
res.setHeader("Expires", "0");
|
||||
}
|
||||
if (options.placeholderHeader) {
|
||||
res.setHeader("X-Placeholder", handler);
|
||||
}
|
||||
const placeholder = options.placeholders[handler];
|
||||
res.end(placeholder);
|
||||
};
|
||||
}
|
||||
|
||||
exports.servePlaceholder = servePlaceholder;
|
||||
47
node_modules/serve-placeholder/dist/index.d.ts
generated
vendored
Normal file
47
node_modules/serve-placeholder/dist/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
import { IncomingMessage, ServerResponse } from 'http';
|
||||
|
||||
interface ServePlaceholderOptions {
|
||||
/**
|
||||
* Sets `statusCode` for all handled responses. Set to `false` to disable overriding statusCode.
|
||||
*
|
||||
* @default 404
|
||||
*/
|
||||
statusCode?: number;
|
||||
/**
|
||||
* Skip middleware when no handler is defined for the current request.
|
||||
* Please note that if this option is set to `true`, then `default` handler will be disabled
|
||||
* @default false
|
||||
*/
|
||||
skipUnknown?: boolean;
|
||||
/**
|
||||
* Set headers to prevent accidentally caching 404 resources.
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
cacheHeaders?: boolean;
|
||||
/**
|
||||
* Sets an `X-Placeholder` header with value of handler name.
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
placeholderHeader?: boolean;
|
||||
/**
|
||||
* A mapping from file extensions to the handler. Extensions should start with *dot* like `.js`.
|
||||
* You can disable any of the handlers by setting the value to `null`
|
||||
* If the value of a handler is set to `false`, the middleware will be ignored for that extension.
|
||||
*/
|
||||
handlers?: Record<string, string | false>;
|
||||
/**
|
||||
* A mapping from handler to placeholder. Values can be `String` or `Buffer`. You can disable any of the placeholders by setting the value to `false`.
|
||||
*/
|
||||
placeholders?: Record<string, string | undefined>;
|
||||
/**
|
||||
* A mapping from handler to the mime type. Mime type will be set as `Content-Type` header. You can disable sending any of the mimes by setting the value to `false`.
|
||||
*/
|
||||
mimes?: Record<string, string | undefined>;
|
||||
}
|
||||
|
||||
declare type ServerMiddleware = (req: IncomingMessage, res: ServerResponse, next: () => void) => void;
|
||||
declare function servePlaceholder(_options?: ServePlaceholderOptions): ServerMiddleware;
|
||||
|
||||
export { ServerMiddleware, servePlaceholder };
|
||||
89
node_modules/serve-placeholder/dist/index.mjs
generated
vendored
Normal file
89
node_modules/serve-placeholder/dist/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
import defu from 'defu';
|
||||
|
||||
const DefaultOptions = {
|
||||
statusCode: 404,
|
||||
skipUnknown: false,
|
||||
cacheHeaders: true,
|
||||
placeholderHeader: true,
|
||||
handlers: {
|
||||
".css": "css",
|
||||
".html": "html",
|
||||
".htm": "html",
|
||||
".png": "image",
|
||||
".jpg": "image",
|
||||
".jpeg": "image",
|
||||
".gif": "image",
|
||||
".svg": "image",
|
||||
".webp": "image",
|
||||
".bmp": "image",
|
||||
".ico": "image",
|
||||
".js": "js",
|
||||
".json": "json",
|
||||
".map": "map",
|
||||
".txt": "plain",
|
||||
".text": "plain",
|
||||
".md": "plain"
|
||||
},
|
||||
placeholders: {
|
||||
css: "/* style not found */",
|
||||
default: void 0,
|
||||
html: "<!-- page not found -->",
|
||||
image: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
|
||||
js: "/* script not found */",
|
||||
json: "{}",
|
||||
map: '{"version": "3", "sources": [], "mappings": "" }',
|
||||
plain: ""
|
||||
},
|
||||
mimes: {
|
||||
css: "text/css",
|
||||
default: void 0,
|
||||
html: "text/html",
|
||||
js: "application/javascript",
|
||||
json: "application/json",
|
||||
image: "image/gif",
|
||||
map: "application/json",
|
||||
plain: "text/plain"
|
||||
}
|
||||
};
|
||||
|
||||
const EXT_REGEX = /\.[a-zA-Z0-9]+$/;
|
||||
function servePlaceholder(_options = {}) {
|
||||
const options = defu(_options, DefaultOptions);
|
||||
return function servePlaceholderMiddleware(req, res, next) {
|
||||
if (res.writableEnded) {
|
||||
return;
|
||||
}
|
||||
const url = req.url.split("?")[0];
|
||||
const ext = (url.match(EXT_REGEX) || [])[0] || "";
|
||||
let handler = options.handlers[ext];
|
||||
if (handler === false) {
|
||||
return next();
|
||||
}
|
||||
if (typeof handler === "undefined") {
|
||||
if (options.skipUnknown) {
|
||||
return next();
|
||||
} else {
|
||||
handler = "default";
|
||||
}
|
||||
}
|
||||
if (options.statusCode) {
|
||||
res.statusCode = options.statusCode;
|
||||
}
|
||||
const mime = options.mimes[handler];
|
||||
if (mime) {
|
||||
res.setHeader("Content-Type", mime);
|
||||
}
|
||||
if (options.cacheHeaders) {
|
||||
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
res.setHeader("Pragma", "no-cache");
|
||||
res.setHeader("Expires", "0");
|
||||
}
|
||||
if (options.placeholderHeader) {
|
||||
res.setHeader("X-Placeholder", handler);
|
||||
}
|
||||
const placeholder = options.placeholders[handler];
|
||||
res.end(placeholder);
|
||||
};
|
||||
}
|
||||
|
||||
export { servePlaceholder };
|
||||
45
node_modules/serve-placeholder/package.json
generated
vendored
Normal file
45
node_modules/serve-placeholder/package.json
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user