more
This commit is contained in:
parent
fa13ba83d7
commit
fe70fae95f
1
.yarnrc.yml
Normal file
1
.yarnrc.yml
Normal file
@ -0,0 +1 @@
|
||||
nodeLinker: node-modules
|
@ -1 +0,0 @@
|
||||
<h1>Heading</h1>
|
@ -1,2 +0,0 @@
|
||||
<!doctype html><title>abs3nt.dev</title>
|
||||
<p>hello i am abs3nt</p>
|
8
eleventy.config.js
Normal file
8
eleventy.config.js
Normal file
@ -0,0 +1,8 @@
|
||||
module.exports = function (eleventyConfig) {
|
||||
return {
|
||||
dir: {
|
||||
input: "src",
|
||||
output: "dist",
|
||||
},
|
||||
};
|
||||
};
|
@ -1,2 +0,0 @@
|
||||
<!doctype html><title>abs3nt.dev</title>
|
||||
<p>hello i am abs3nt</p>
|
1
node_modules/.bin/acorn
generated
vendored
Symbolic link
1
node_modules/.bin/acorn
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../acorn/bin/acorn
|
1
node_modules/.bin/cssesc
generated
vendored
Symbolic link
1
node_modules/.bin/cssesc
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../cssesc/bin/cssesc
|
1
node_modules/.bin/dev-ip
generated
vendored
Symbolic link
1
node_modules/.bin/dev-ip
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../dev-ip/lib/dev-ip.js
|
1
node_modules/.bin/ejs
generated
vendored
Symbolic link
1
node_modules/.bin/ejs
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../ejs/bin/cli.js
|
1
node_modules/.bin/eleventy
generated
vendored
Symbolic link
1
node_modules/.bin/eleventy
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../@11ty/eleventy/cmd.js
|
1
node_modules/.bin/eleventy-dev-server
generated
vendored
Symbolic link
1
node_modules/.bin/eleventy-dev-server
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../@11ty/eleventy-dev-server/cmd.js
|
1
node_modules/.bin/errno
generated
vendored
Symbolic link
1
node_modules/.bin/errno
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../errno/cli.js
|
1
node_modules/.bin/esparse
generated
vendored
Symbolic link
1
node_modules/.bin/esparse
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../esprima/bin/esparse.js
|
1
node_modules/.bin/esvalidate
generated
vendored
Symbolic link
1
node_modules/.bin/esvalidate
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../esprima/bin/esvalidate.js
|
1
node_modules/.bin/handlebars
generated
vendored
Symbolic link
1
node_modules/.bin/handlebars
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../handlebars/bin/handlebars
|
1
node_modules/.bin/jake
generated
vendored
Symbolic link
1
node_modules/.bin/jake
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../jake/bin/cli.js
|
1
node_modules/.bin/jiti
generated
vendored
Symbolic link
1
node_modules/.bin/jiti
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../jiti/bin/jiti.js
|
1
node_modules/.bin/js-yaml
generated
vendored
Symbolic link
1
node_modules/.bin/js-yaml
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../js-yaml/bin/js-yaml.js
|
1
node_modules/.bin/liquid
generated
vendored
Symbolic link
1
node_modules/.bin/liquid
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../liquidjs/bin/liquid.js
|
1
node_modules/.bin/liquidjs
generated
vendored
Symbolic link
1
node_modules/.bin/liquidjs
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../liquidjs/bin/liquid.js
|
1
node_modules/.bin/markdown-it
generated
vendored
Symbolic link
1
node_modules/.bin/markdown-it
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../markdown-it/bin/markdown-it.js
|
1
node_modules/.bin/mime
generated
vendored
Symbolic link
1
node_modules/.bin/mime
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../mime/cli.js
|
1
node_modules/.bin/mkdirp
generated
vendored
Symbolic link
1
node_modules/.bin/mkdirp
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../mkdirp/bin/cmd.js
|
1
node_modules/.bin/mustache
generated
vendored
Symbolic link
1
node_modules/.bin/mustache
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../mustache/bin/mustache
|
1
node_modules/.bin/nanoid
generated
vendored
Symbolic link
1
node_modules/.bin/nanoid
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../nanoid/bin/nanoid.cjs
|
1
node_modules/.bin/node-which
generated
vendored
Symbolic link
1
node_modules/.bin/node-which
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../which/bin/node-which
|
1
node_modules/.bin/nunjucks-precompile
generated
vendored
Symbolic link
1
node_modules/.bin/nunjucks-precompile
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../nunjucks/bin/precompile
|
1
node_modules/.bin/parser
generated
vendored
Symbolic link
1
node_modules/.bin/parser
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../@babel/parser/bin/babel-parser.js
|
1
node_modules/.bin/resolve
generated
vendored
Symbolic link
1
node_modules/.bin/resolve
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../resolve/bin/resolve
|
1
node_modules/.bin/rimraf
generated
vendored
Symbolic link
1
node_modules/.bin/rimraf
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../rimraf/bin.js
|
1
node_modules/.bin/semver
generated
vendored
Symbolic link
1
node_modules/.bin/semver
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../semver/bin/semver.js
|
1
node_modules/.bin/sucrase
generated
vendored
Symbolic link
1
node_modules/.bin/sucrase
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../sucrase/bin/sucrase
|
1
node_modules/.bin/sucrase-node
generated
vendored
Symbolic link
1
node_modules/.bin/sucrase-node
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../sucrase/bin/sucrase-node
|
1
node_modules/.bin/tailwind
generated
vendored
Symbolic link
1
node_modules/.bin/tailwind
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../tailwindcss/lib/cli.js
|
1
node_modules/.bin/tailwindcss
generated
vendored
Symbolic link
1
node_modules/.bin/tailwindcss
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../tailwindcss/lib/cli.js
|
1
node_modules/.bin/uglifyjs
generated
vendored
Symbolic link
1
node_modules/.bin/uglifyjs
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../uglify-js/bin/uglifyjs
|
1
node_modules/.bin/yaml
generated
vendored
Symbolic link
1
node_modules/.bin/yaml
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../yaml/bin.mjs
|
1169
node_modules/.yarn-state.yml
generated
vendored
Normal file
1169
node_modules/.yarn-state.yml
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
21
node_modules/@11ty/dependency-tree/LICENSE
generated
vendored
Normal file
21
node_modules/@11ty/dependency-tree/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Eleventy
|
||||
|
||||
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.
|
92
node_modules/@11ty/dependency-tree/README.md
generated
vendored
Normal file
92
node_modules/@11ty/dependency-tree/README.md
generated
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
# dependency-tree
|
||||
|
||||
Returns an unordered array of local paths to dependencies of a node JavaScript file (everything it or any of its dependencies `require`s).
|
||||
|
||||
Reduced feature (faster) alternative to the [`dependency-tree` package](https://www.npmjs.com/package/dependency-tree) that only works with stock node JS. This is used by Eleventy to find dependencies of a JavaScript file to watch for changes to re-run Eleventy’s build.
|
||||
|
||||
## Big Huge Caveat
|
||||
|
||||
⚠ A big caveat to this plugin is that it will require the file in order to build a dependency tree. So if your module has side effects and you don’t want it to execute—do not use this!
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
npm install --save-dev @11ty/dependency-tree
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
* Ignores `node_modules`
|
||||
* Or, use `nodeModuleNamesOnly` to return a list of node_modules packages (added in v2.0.0)
|
||||
* Ignores Node’s built-ins (e.g. `path`)
|
||||
* Handles circular dependencies (Node does this too)
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
// my-file.js
|
||||
|
||||
// if my-local-dependency.js has dependencies, it will include those too
|
||||
const test = require("./my-local-dependency.js");
|
||||
|
||||
// ignored, is a built-in
|
||||
const path = require("path");
|
||||
```
|
||||
|
||||
```js
|
||||
const DependencyTree = require("@11ty/dependency-tree");
|
||||
|
||||
DependencyTree("./my-file.js");
|
||||
// returns ["./my-local-dependency.js"]
|
||||
```
|
||||
|
||||
### `allowNotFound`
|
||||
|
||||
```js
|
||||
const DependencyTree = require("@11ty/dependency-tree");
|
||||
|
||||
DependencyTree("./this-does-not-exist.js"); // throws an error
|
||||
|
||||
DependencyTree("./this-does-not-exist.js", { allowNotFound: true });
|
||||
// returns []
|
||||
```
|
||||
|
||||
### `nodeModuleNames`
|
||||
|
||||
(Added in v2.0.1) Controls whether or not node package names are included in the list of dependencies.
|
||||
|
||||
* `nodeModuleNames: "include"`: included alongside the local JS files.
|
||||
* `nodeModuleNames: "exclude"` (default): node module package names are excluded.
|
||||
* `nodeModuleNames: "only"`: only node module package names are returned.
|
||||
|
||||
```js
|
||||
// my-file.js:
|
||||
|
||||
require("./my-local-dependency.js");
|
||||
require("@11ty/eleventy");
|
||||
```
|
||||
|
||||
```js
|
||||
const DependencyTree = require("@11ty/dependency-tree");
|
||||
|
||||
DependencyTree("./my-file.js");
|
||||
// returns ["./my-local-dependency.js"]
|
||||
|
||||
DependencyTree("./my-file.js", { nodeModuleNames: "exclude" });
|
||||
// returns ["./my-local-dependency.js"]
|
||||
|
||||
DependencyTree("./my-file.js", { nodeModuleNames: "include" });
|
||||
// returns ["./my-local-dependency.js", "@11ty/eleventy"]
|
||||
|
||||
DependencyTree("./my-file.js", { nodeModuleNames: "only" });
|
||||
// returns ["@11ty/eleventy"]
|
||||
```
|
||||
|
||||
#### (Deprecated) `nodeModuleNamesOnly`
|
||||
|
||||
(Added in v2.0.0) Changed to use `nodeModuleNames` option instead. Backwards compatibility is maintained automatically.
|
||||
|
||||
* `nodeModuleNamesOnly: false` is mapped to `nodeModuleNames: "exclude"`
|
||||
* `nodeModuleNamesOnly: true` is mapped to `nodeModuleNames: "only"`
|
||||
|
||||
If both `nodeModuleNamesOnly` and `nodeModuleNames` are included in options, `nodeModuleNames` takes precedence.
|
120
node_modules/@11ty/dependency-tree/main.js
generated
vendored
Normal file
120
node_modules/@11ty/dependency-tree/main.js
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
const path = require("path");
|
||||
|
||||
function getAbsolutePath(filename) {
|
||||
let normalizedFilename = path.normalize(filename); // removes dot slash
|
||||
let hasDotSlash = filename.startsWith("./");
|
||||
return hasDotSlash ? path.join(path.resolve("."), normalizedFilename) : normalizedFilename;
|
||||
}
|
||||
|
||||
function getRelativePath(filename) {
|
||||
let normalizedFilename = path.normalize(filename); // removes dot slash
|
||||
let workingDirectory = path.resolve(".");
|
||||
let result = "./" + (normalizedFilename.startsWith(workingDirectory) ? normalizedFilename.substr(workingDirectory.length + 1) : normalizedFilename);
|
||||
return result;
|
||||
}
|
||||
|
||||
function getNodeModuleName(filename) {
|
||||
let foundNodeModules = false;
|
||||
let moduleName = [];
|
||||
|
||||
let s = filename.split(path.sep);
|
||||
for(let entry of s) {
|
||||
if(foundNodeModules) {
|
||||
moduleName.push(entry);
|
||||
if(!entry.startsWith("@")) {
|
||||
return moduleName.join("/");
|
||||
}
|
||||
}
|
||||
|
||||
if(entry === "node_modules") {
|
||||
foundNodeModules = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* unordered */
|
||||
function getDependenciesFor(filename, avoidCircular, optionsArg = {}) {
|
||||
// backwards compatibility with `nodeModuleNamesOnly` boolean option
|
||||
// Using `nodeModuleNames` property moving forward
|
||||
if(("nodeModuleNamesOnly" in optionsArg) && !("nodeModuleNames" in optionsArg)) {
|
||||
if(optionsArg.nodeModuleNamesOnly === true) {
|
||||
optionsArg.nodeModuleNames = "only";
|
||||
}
|
||||
if(optionsArg.nodeModuleNamesOnly === false) {
|
||||
optionsArg.nodeModuleNames = "exclude";
|
||||
}
|
||||
}
|
||||
|
||||
let options = Object.assign({
|
||||
allowNotFound: false,
|
||||
nodeModuleNames: "exclude", // also "include" or "only"
|
||||
}, optionsArg);
|
||||
let absoluteFilename = getAbsolutePath(filename)
|
||||
|
||||
try {
|
||||
require(absoluteFilename);
|
||||
} catch(e) {
|
||||
if(e.code === "MODULE_NOT_FOUND" && options.allowNotFound) {
|
||||
// do nothing
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let mod;
|
||||
for(let entry in require.cache) {
|
||||
if(entry === absoluteFilename) {
|
||||
mod = require.cache[entry];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let dependencies = new Set();
|
||||
|
||||
if(!mod) {
|
||||
if(!options.allowNotFound) {
|
||||
throw new Error(`Could not find ${filename} in @11ty/dependency-tree`);
|
||||
}
|
||||
} else {
|
||||
let relativeFilename = getRelativePath(mod.filename);
|
||||
if(!avoidCircular) {
|
||||
avoidCircular = {};
|
||||
} else if(options.nodeModuleNames !== "only") {
|
||||
dependencies.add(relativeFilename);
|
||||
}
|
||||
|
||||
avoidCircular[relativeFilename] = true;
|
||||
|
||||
if(mod.children) {
|
||||
for(let child of mod.children) {
|
||||
let relativeChildFilename = getRelativePath(child.filename);
|
||||
let nodeModuleName = getNodeModuleName(child.filename);
|
||||
|
||||
if(options.nodeModuleNames !== "exclude" && nodeModuleName) {
|
||||
dependencies.add(nodeModuleName);
|
||||
}
|
||||
// Add dependencies of this dependency (not top level node_modules)
|
||||
if(nodeModuleName === false) {
|
||||
if(!dependencies.has(relativeChildFilename) && // avoid infinite looping with circular deps
|
||||
!avoidCircular[relativeChildFilename] ) {
|
||||
for(let dependency of getDependenciesFor(relativeChildFilename, avoidCircular, options)) {
|
||||
dependencies.add(dependency);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
function getCleanDependencyListFor(filename, options = {}) {
|
||||
return Array.from( getDependenciesFor(filename, null, options) );
|
||||
}
|
||||
|
||||
module.exports = getCleanDependencyListFor;
|
||||
module.exports.getNodeModuleName = getNodeModuleName;
|
30
node_modules/@11ty/dependency-tree/package.json
generated
vendored
Normal file
30
node_modules/@11ty/dependency-tree/package.json
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "@11ty/dependency-tree",
|
||||
"version": "2.0.1",
|
||||
"description": "Finds all JavaScript require dependencies from a filename.",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"test": "npx ava"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/11ty/eleventy-dependency-tree.git"
|
||||
},
|
||||
"author": {
|
||||
"name": "Zach Leatherman",
|
||||
"email": "zach@zachleat.com",
|
||||
"url": "https://zachleat.com/"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"ava": "^3.15.0"
|
||||
},
|
||||
"ava": {
|
||||
"files": [
|
||||
"./test/*.js"
|
||||
],
|
||||
"ignoredByWatcher": [
|
||||
"./test/stubs/**"
|
||||
]
|
||||
}
|
||||
}
|
92
node_modules/@11ty/dependency-tree/test/mainTest.js
generated
vendored
Normal file
92
node_modules/@11ty/dependency-tree/test/mainTest.js
generated
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
const test = require("ava");
|
||||
const DependencyTree = require("../main.js");
|
||||
|
||||
test("Nonexistent", t => {
|
||||
t.throws(() => {
|
||||
DependencyTree("./test/stubs/thisdoesnotexist.js");
|
||||
});
|
||||
});
|
||||
|
||||
test("Allow not Found", t => {
|
||||
DependencyTree("./test/stubs/thisdoesnotexist.js", { allowNotFound: true });
|
||||
t.true(true);
|
||||
});
|
||||
|
||||
test("Not require()’d before calling", t => {
|
||||
DependencyTree("./test/stubs/parent/parent.js");
|
||||
t.true(true);
|
||||
});
|
||||
|
||||
test("simple.js", t => {
|
||||
t.deepEqual(DependencyTree("./test/stubs/simple.js"), ["./test/stubs/simple2.js"]);
|
||||
});
|
||||
|
||||
test("parent.js", t => {
|
||||
t.deepEqual(DependencyTree("./test/stubs/parent/parent.js").sort(), [
|
||||
"./test/stubs/parent/child1.js",
|
||||
"./test/stubs/parent/child2.js",
|
||||
"./test/stubs/parent/grandchild.js",
|
||||
"./test/stubs/parent/greatgrandchild.js"
|
||||
]);
|
||||
|
||||
t.deepEqual(DependencyTree("./test/stubs/parent/child1.js").sort(), [
|
||||
"./test/stubs/parent/grandchild.js",
|
||||
"./test/stubs/parent/greatgrandchild.js"
|
||||
]);
|
||||
|
||||
t.deepEqual(DependencyTree("./test/stubs/parent/child2.js").sort(), [
|
||||
"./test/stubs/parent/grandchild.js",
|
||||
"./test/stubs/parent/greatgrandchild.js"
|
||||
]);
|
||||
|
||||
t.deepEqual(DependencyTree("./test/stubs/parent/grandchild.js"), [
|
||||
"./test/stubs/parent/greatgrandchild.js"
|
||||
]);
|
||||
|
||||
t.deepEqual(DependencyTree("./test/stubs/parent/greatgrandchild.js"), []);
|
||||
});
|
||||
|
||||
test("circular", t => {
|
||||
t.deepEqual(DependencyTree("./test/stubs/circular/circle-a.js").sort(), [
|
||||
"./test/stubs/circular/circle-b.js",
|
||||
"./test/stubs/circular/circle-c.js"]);
|
||||
});
|
||||
|
||||
test("another circular", t => {
|
||||
t.deepEqual(DependencyTree("./test/stubs/circular2/circle-a.js").sort(), [
|
||||
"./test/stubs/circular2/circle-b.js",
|
||||
"./test/stubs/circular2/circle-c.js"
|
||||
]);
|
||||
});
|
||||
|
||||
test("dot dot (dependency is up a directory)", t => {
|
||||
t.deepEqual(DependencyTree("./test/stubs/dotdot/dotdot.js").sort(), [
|
||||
"./test/stubs/simple2.js"
|
||||
]);
|
||||
});
|
||||
|
||||
test("only node_modules", t => {
|
||||
t.deepEqual(DependencyTree("./test/stubs/uses_node_modules.js", {
|
||||
nodeModuleNamesOnly: true
|
||||
}).sort(), [
|
||||
"@sindresorhus/is",
|
||||
"lodash",
|
||||
]);
|
||||
});
|
||||
|
||||
test("getNodeModuleName", t => {
|
||||
t.is(DependencyTree.getNodeModuleName("./eleventy-dependency-tree/node_modules/lodash/lodash.js"), "lodash");
|
||||
t.is(DependencyTree.getNodeModuleName("./eleventy-dependency-tree/node_modules/@sindresorhus/is/dist/index.js"), "@sindresorhus/is");
|
||||
});
|
||||
|
||||
test("both files and node_modules", t => {
|
||||
t.deepEqual(DependencyTree("./test/stubs/uses_node_modules.js", {
|
||||
nodeModuleNames: "include"
|
||||
}).sort(), [
|
||||
"./test/stubs/parent/child1.js",
|
||||
"./test/stubs/parent/grandchild.js",
|
||||
"./test/stubs/parent/greatgrandchild.js",
|
||||
"@sindresorhus/is",
|
||||
"lodash",
|
||||
]);
|
||||
});
|
1
node_modules/@11ty/dependency-tree/test/stubs/circular/circle-a.js
generated
vendored
Normal file
1
node_modules/@11ty/dependency-tree/test/stubs/circular/circle-a.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
const circleB = require("./circle-b");
|
1
node_modules/@11ty/dependency-tree/test/stubs/circular/circle-b.js
generated
vendored
Normal file
1
node_modules/@11ty/dependency-tree/test/stubs/circular/circle-b.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
const circleC = require("./circle-c");
|
1
node_modules/@11ty/dependency-tree/test/stubs/circular/circle-c.js
generated
vendored
Normal file
1
node_modules/@11ty/dependency-tree/test/stubs/circular/circle-c.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
const circleA = require("./circle-a");
|
1
node_modules/@11ty/dependency-tree/test/stubs/circular2/circle-a.js
generated
vendored
Normal file
1
node_modules/@11ty/dependency-tree/test/stubs/circular2/circle-a.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
const circleB = require("./circle-b");
|
1
node_modules/@11ty/dependency-tree/test/stubs/circular2/circle-b.js
generated
vendored
Normal file
1
node_modules/@11ty/dependency-tree/test/stubs/circular2/circle-b.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
const circleC = require("./circle-c");
|
1
node_modules/@11ty/dependency-tree/test/stubs/circular2/circle-c.js
generated
vendored
Normal file
1
node_modules/@11ty/dependency-tree/test/stubs/circular2/circle-c.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
const circleA = require("./circle-b");
|
1
node_modules/@11ty/dependency-tree/test/stubs/dotdot/dotdot.js
generated
vendored
Normal file
1
node_modules/@11ty/dependency-tree/test/stubs/dotdot/dotdot.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
const test = require("../simple2")
|
4
node_modules/@11ty/dependency-tree/test/stubs/parent/child1.js
generated
vendored
Normal file
4
node_modules/@11ty/dependency-tree/test/stubs/parent/child1.js
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
const test2 = require("./grandchild");
|
||||
const lodash = require("lodash");
|
||||
|
||||
module.exports = {};
|
3
node_modules/@11ty/dependency-tree/test/stubs/parent/child2.js
generated
vendored
Normal file
3
node_modules/@11ty/dependency-tree/test/stubs/parent/child2.js
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
const test = require("./grandchild");
|
||||
|
||||
module.exports = {};
|
2
node_modules/@11ty/dependency-tree/test/stubs/parent/grandchild.js
generated
vendored
Normal file
2
node_modules/@11ty/dependency-tree/test/stubs/parent/grandchild.js
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
const test = require("./greatgrandchild.js");
|
||||
module.exports = {};
|
0
node_modules/@11ty/dependency-tree/test/stubs/parent/greatgrandchild.js
generated
vendored
Normal file
0
node_modules/@11ty/dependency-tree/test/stubs/parent/greatgrandchild.js
generated
vendored
Normal file
5
node_modules/@11ty/dependency-tree/test/stubs/parent/parent.js
generated
vendored
Normal file
5
node_modules/@11ty/dependency-tree/test/stubs/parent/parent.js
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
const path = require("path");
|
||||
const test = require("./child1");
|
||||
const test2 = require("./child2");
|
||||
|
||||
module.exports = {};
|
1
node_modules/@11ty/dependency-tree/test/stubs/simple.js
generated
vendored
Normal file
1
node_modules/@11ty/dependency-tree/test/stubs/simple.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
const test = require("./simple2");
|
0
node_modules/@11ty/dependency-tree/test/stubs/simple2.js
generated
vendored
Normal file
0
node_modules/@11ty/dependency-tree/test/stubs/simple2.js
generated
vendored
Normal file
4
node_modules/@11ty/dependency-tree/test/stubs/uses_node_modules.js
generated
vendored
Normal file
4
node_modules/@11ty/dependency-tree/test/stubs/uses_node_modules.js
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
const is = require("@sindresorhus/is");
|
||||
const child1 = require("./parent/child1.js");
|
||||
|
||||
module.exports = {};
|
56
node_modules/@11ty/eleventy-dev-server/README.md
generated
vendored
Normal file
56
node_modules/@11ty/eleventy-dev-server/README.md
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<p align="center"><img src="https://www.11ty.dev/img/logo-github.svg" width="200" height="200" alt="11ty Logo"></p>
|
||||
|
||||
# eleventy-dev-server 🕚⚡️🎈🐀
|
||||
|
||||
A minimal, modern, generic, hot-reloading local web server to help web developers.
|
||||
|
||||
## ➡ [Documentation](https://www.11ty.dev/docs/watch-serve/#eleventy-dev-server)
|
||||
|
||||
- Please star [Eleventy on GitHub](https://github.com/11ty/eleventy/)!
|
||||
- Follow us on Twitter [@eleven_ty](https://twitter.com/eleven_ty)
|
||||
- Support [11ty on Open Collective](https://opencollective.com/11ty)
|
||||
- [11ty on npm](https://www.npmjs.com/org/11ty)
|
||||
- [11ty on GitHub](https://github.com/11ty)
|
||||
|
||||
[![npm Version](https://img.shields.io/npm/v/@11ty/eleventy-dev-server.svg?style=for-the-badge)](https://www.npmjs.com/package/@11ty/eleventy-dev-server)
|
||||
|
||||
## Installation
|
||||
|
||||
This is bundled with `@11ty/eleventy` (and you do not need to install it separately) in Eleventy v2.0.
|
||||
|
||||
## CLI
|
||||
|
||||
Eleventy Dev Server now also includes a CLI. The CLI is for **standalone** (non-Eleventy) use only: separate installation is unnecessary if you’re using this server with `@11ty/eleventy`.
|
||||
|
||||
```sh
|
||||
npm install -g @11ty/eleventy-dev-server
|
||||
|
||||
# Alternatively, install locally into your project
|
||||
npm install @11ty/eleventy-dev-server
|
||||
```
|
||||
|
||||
This package requires Node 14 or newer.
|
||||
|
||||
### CLI Usage
|
||||
|
||||
```sh
|
||||
# Serve the current directory
|
||||
npx @11ty/eleventy-dev-server
|
||||
|
||||
# Serve a different subdirectory (also aliased as --input)
|
||||
npx @11ty/eleventy-dev-server --dir=_site
|
||||
|
||||
# Disable the `domdiff` feature
|
||||
npx @11ty/eleventy-dev-server --domdiff=false
|
||||
|
||||
# Full command list in the Help
|
||||
npx @11ty/eleventy-dev-server --help
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
```
|
||||
npm run test
|
||||
```
|
||||
|
||||
- We use the [ava JavaScript test runner](https://github.com/avajs/ava) ([Assertions documentation](https://github.com/avajs/ava/blob/master/docs/03-assertions.md))
|
92
node_modules/@11ty/eleventy-dev-server/cli.js
generated
vendored
Normal file
92
node_modules/@11ty/eleventy-dev-server/cli.js
generated
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
const chokidar = require("chokidar");
|
||||
const fs = require("fs");
|
||||
|
||||
const pkg = require("./package.json");
|
||||
const EleventyDevServer = require("./server.js");
|
||||
|
||||
const Logger = {
|
||||
info: function(...args) {
|
||||
console.log( "[11ty/eleventy-dev-server]", ...args );
|
||||
},
|
||||
error: function(...args) {
|
||||
console.error( "[11ty/eleventy-dev-server]", ...args );
|
||||
},
|
||||
fatal: function(...args) {
|
||||
Logger.error(...args);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
};
|
||||
|
||||
Logger.log = Logger.info;
|
||||
|
||||
class Cli {
|
||||
static getVersion() {
|
||||
return pkg.version;
|
||||
}
|
||||
|
||||
static getHelp() {
|
||||
return `Usage:
|
||||
|
||||
eleventy-dev-server
|
||||
eleventy-dev-server --dir=_site
|
||||
eleventy-dev-server --port=3000
|
||||
|
||||
Arguments:
|
||||
|
||||
--version
|
||||
|
||||
--dir=.
|
||||
Directory to serve (default: \`.\`)
|
||||
|
||||
--input (alias for --dir)
|
||||
|
||||
--port=8080
|
||||
Run the web server on this port (default: \`8080\`)
|
||||
Will autoincrement if already in use.
|
||||
|
||||
--domdiff (enabled, default)
|
||||
--domdiff=false (disabled)
|
||||
Apply HTML changes without a full page reload.
|
||||
|
||||
--help`;
|
||||
}
|
||||
|
||||
static getDefaultOptions() {
|
||||
return {
|
||||
port: "8080",
|
||||
input: ".",
|
||||
domDiff: true,
|
||||
}
|
||||
}
|
||||
|
||||
async serve(options = {}) {
|
||||
this.options = Object.assign(Cli.getDefaultOptions(), options);
|
||||
|
||||
this.server = EleventyDevServer.getServer("eleventy-dev-server-cli", this.options.input, {
|
||||
// TODO allow server configuration extensions
|
||||
showVersion: true,
|
||||
logger: Logger,
|
||||
domDiff: this.options.domDiff,
|
||||
|
||||
// CLI watches all files in the folder by default
|
||||
// this is different from Eleventy usage!
|
||||
watch: [ this.options.input ],
|
||||
});
|
||||
|
||||
this.server.serve(this.options.port);
|
||||
|
||||
// TODO? send any errors here to the server too
|
||||
// with server.sendError({ error });
|
||||
}
|
||||
|
||||
close() {
|
||||
if(this.server) {
|
||||
this.server.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Logger,
|
||||
Cli
|
||||
}
|
259
node_modules/@11ty/eleventy-dev-server/client/reload-client.js
generated
vendored
Normal file
259
node_modules/@11ty/eleventy-dev-server/client/reload-client.js
generated
vendored
Normal file
@ -0,0 +1,259 @@
|
||||
class Util {
|
||||
static pad(num, digits = 2) {
|
||||
let zeroes = new Array(digits + 1).join(0);
|
||||
return `${zeroes}${num}`.slice(-1 * digits);
|
||||
}
|
||||
|
||||
static log(message) {
|
||||
Util.output("log", message);
|
||||
}
|
||||
static error(message, error) {
|
||||
Util.output("error", message, error);
|
||||
}
|
||||
static output(type, ...messages) {
|
||||
let now = new Date();
|
||||
let date = `${Util.pad(now.getUTCHours())}:${Util.pad(
|
||||
now.getUTCMinutes()
|
||||
)}:${Util.pad(now.getUTCSeconds())}.${Util.pad(
|
||||
now.getUTCMilliseconds(),
|
||||
3
|
||||
)}`;
|
||||
console[type](`[11ty][${date} UTC]`, ...messages);
|
||||
}
|
||||
|
||||
static capitalize(word) {
|
||||
return word.substr(0, 1).toUpperCase() + word.substr(1);
|
||||
}
|
||||
|
||||
static matchRootAttributes(htmlContent) {
|
||||
// Workaround for morphdom bug with attributes on <html> https://github.com/11ty/eleventy-dev-server/issues/6
|
||||
// Note also `childrenOnly: true` above
|
||||
const parser = new DOMParser();
|
||||
let parsed = parser.parseFromString(htmlContent, "text/html");
|
||||
let parsedDoc = parsed.documentElement;
|
||||
let newAttrs = parsedDoc.getAttributeNames();
|
||||
|
||||
let docEl = document.documentElement;
|
||||
// Remove old
|
||||
let removedAttrs = docEl.getAttributeNames().filter(name => !newAttrs.includes(name));
|
||||
for(let attr of removedAttrs) {
|
||||
docEl.removeAttribute(attr);
|
||||
}
|
||||
|
||||
// Add new
|
||||
for(let attr of newAttrs) {
|
||||
docEl.setAttribute(attr, parsedDoc.getAttribute(attr));
|
||||
}
|
||||
}
|
||||
|
||||
static isEleventyLinkNodeMatch(from, to) {
|
||||
// Issue #18 https://github.com/11ty/eleventy-dev-server/issues/18
|
||||
// Don’t update a <link> if the _11ty searchParam is the only thing that’s different
|
||||
if(from.tagName !== "LINK" || to.tagName !== "LINK") {
|
||||
return false;
|
||||
}
|
||||
|
||||
let oldWithoutHref = from.cloneNode();
|
||||
let newWithoutHref = to.cloneNode();
|
||||
|
||||
oldWithoutHref.removeAttribute("href");
|
||||
newWithoutHref.removeAttribute("href");
|
||||
|
||||
// if all other attributes besides href match
|
||||
if(!oldWithoutHref.isEqualNode(newWithoutHref)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let oldUrl = new URL(from.href);
|
||||
let newUrl = new URL(to.href);
|
||||
|
||||
// morphdom wants to force href="style.css?_11ty" => href="style.css"
|
||||
let isErasing = oldUrl.searchParams.has("_11ty") && !newUrl.searchParams.has("_11ty");
|
||||
if(!isErasing) {
|
||||
// not a match if _11ty has a new value (not being erased)
|
||||
return false;
|
||||
}
|
||||
|
||||
oldUrl.searchParams.set("_11ty", "");
|
||||
newUrl.searchParams.set("_11ty", "");
|
||||
|
||||
// is a match if erasing and the rest of the href matches too
|
||||
return oldUrl.toString() === newUrl.toString();
|
||||
}
|
||||
|
||||
// https://github.com/patrick-steele-idem/morphdom/issues/178#issuecomment-652562769
|
||||
static runScript(source, target) {
|
||||
let script = document.createElement('script');
|
||||
|
||||
//copy over the attributes
|
||||
for(let attr of [...source.attributes]) {
|
||||
script.setAttribute(attr.nodeName ,attr.nodeValue);
|
||||
}
|
||||
|
||||
script.innerHTML = source.innerHTML;
|
||||
(target || source).replaceWith(script);
|
||||
}
|
||||
}
|
||||
|
||||
class EleventyReload {
|
||||
constructor() {
|
||||
this.connectionMessageShown = false;
|
||||
this.reconnectEventCallback = this.reconnect.bind(this);
|
||||
}
|
||||
|
||||
init(options = {}) {
|
||||
if (!("WebSocket" in window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let { protocol, host } = new URL(document.location.href);
|
||||
|
||||
// works with http (ws) and https (wss)
|
||||
let websocketProtocol = protocol.replace("http", "ws");
|
||||
|
||||
let socket = new WebSocket(`${websocketProtocol}//${host}`);
|
||||
|
||||
socket.addEventListener("message", async (event) => {
|
||||
try {
|
||||
let data = JSON.parse(event.data);
|
||||
// Util.log( JSON.stringify(data, null, 2) );
|
||||
|
||||
let { type } = data;
|
||||
|
||||
if (type === "eleventy.reload") {
|
||||
await this.onreload(data);
|
||||
} else if (type === "eleventy.msg") {
|
||||
Util.log(`${data.message}`);
|
||||
} else if (type === "eleventy.error") {
|
||||
// Log Eleventy build errors
|
||||
// Extra parsing for Node Error objects
|
||||
let e = JSON.parse(data.error);
|
||||
Util.error(`Build error: ${e.message}`, e);
|
||||
} else if (type === "eleventy.status") {
|
||||
// Full page reload on initial reconnect
|
||||
if (data.status === "connected" && options.mode === "reconnect") {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
if(data.status === "connected") {
|
||||
// With multiple windows, only show one connection message
|
||||
if(!this.isConnected) {
|
||||
Util.log(Util.capitalize(data.status));
|
||||
}
|
||||
|
||||
this.connectionMessageShown = true;
|
||||
} else {
|
||||
if(data.status === "disconnected") {
|
||||
this.addReconnectListeners();
|
||||
}
|
||||
|
||||
Util.log(Util.capitalize(data.status));
|
||||
}
|
||||
} else {
|
||||
Util.log("Unknown event type", data);
|
||||
}
|
||||
} catch (e) {
|
||||
Util.error(`Error parsing ${event.data}: ${e.message}`, e);
|
||||
}
|
||||
});
|
||||
|
||||
socket.addEventListener("open", () => {
|
||||
// no reconnection when the connect is already open
|
||||
this.removeReconnectListeners();
|
||||
});
|
||||
|
||||
socket.addEventListener("close", () => {
|
||||
this.connectionMessageShown = false;
|
||||
this.addReconnectListeners();
|
||||
});
|
||||
}
|
||||
|
||||
reconnect() {
|
||||
Util.log( "Reconnecting…" );
|
||||
this.init({ mode: "reconnect" });
|
||||
}
|
||||
|
||||
async onreload({ subtype, files, build }) {
|
||||
if (subtype === "css") {
|
||||
for (let link of document.querySelectorAll(`link[rel="stylesheet"]`)) {
|
||||
let url = new URL(link.href);
|
||||
url.searchParams.set("_11ty", Date.now());
|
||||
link.href = url.toString();
|
||||
}
|
||||
Util.log(`CSS updated without page reload.`);
|
||||
} else {
|
||||
let morphed = false;
|
||||
|
||||
try {
|
||||
if((build.templates || []).length > 0) {
|
||||
// Important: using `./` in `./morphdom.js` allows the special `.11ty` folder to be changed upstream
|
||||
const { default: morphdom } = await import(`./morphdom.js`);
|
||||
|
||||
// { url, inputPath, content }
|
||||
for (let template of build.templates || []) {
|
||||
if (template.url === document.location.pathname) {
|
||||
// Importantly, if this does not match but is still relevant (layout/include/etc), a full reload happens below. This could be improved.
|
||||
if ((files || []).includes(template.inputPath)) {
|
||||
// Notable limitation: this won’t re-run script elements or JavaScript page lifecycle events (load/DOMContentLoaded)
|
||||
morphed = true;
|
||||
|
||||
morphdom(document.documentElement, template.content, {
|
||||
childrenOnly: true,
|
||||
onBeforeElUpdated: function (fromEl, toEl) {
|
||||
if (fromEl.nodeName === "SCRIPT" && toEl.nodeName === "SCRIPT") {
|
||||
Util.runScript(toEl, fromEl);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Speed-up trick from morphdom docs
|
||||
// https://dom.spec.whatwg.org/#concept-node-equals
|
||||
if (fromEl.isEqualNode(toEl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(Util.isEleventyLinkNodeMatch(fromEl, toEl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
onNodeAdded: function (node) {
|
||||
if (node.nodeName === 'SCRIPT') {
|
||||
Util.runScript(node);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Util.matchRootAttributes(template.content);
|
||||
Util.log(`HTML delta applied without page reload.`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Util.error( "Morphdom error", e );
|
||||
}
|
||||
|
||||
if (!morphed) {
|
||||
Util.log(`Page reload initiated.`);
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addReconnectListeners() {
|
||||
this.removeReconnectListeners();
|
||||
|
||||
window.addEventListener("focus", this.reconnectEventCallback);
|
||||
window.addEventListener("visibilitychange", this.reconnectEventCallback);
|
||||
}
|
||||
|
||||
removeReconnectListeners() {
|
||||
window.removeEventListener("focus", this.reconnectEventCallback);
|
||||
window.removeEventListener("visibilitychange", this.reconnectEventCallback);
|
||||
}
|
||||
}
|
||||
|
||||
let reloader = new EleventyReload();
|
||||
reloader.init();
|
69
node_modules/@11ty/eleventy-dev-server/cmd.js
generated
vendored
Executable file
69
node_modules/@11ty/eleventy-dev-server/cmd.js
generated
vendored
Executable file
@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const pkg = require("./package.json");
|
||||
|
||||
// Node check
|
||||
require("please-upgrade-node")(pkg, {
|
||||
message: function (requiredVersion) {
|
||||
return (
|
||||
"eleventy-dev-server requires Node " +
|
||||
requiredVersion +
|
||||
". You will need to upgrade Node!"
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const { Logger, Cli } = require("./cli.js");
|
||||
|
||||
const debug = require("debug")("EleventyDevServer:cmd");
|
||||
|
||||
try {
|
||||
const argv = require("minimist")(process.argv.slice(2), {
|
||||
string: [
|
||||
"dir",
|
||||
"input", // alias for dir
|
||||
"port",
|
||||
],
|
||||
boolean: [
|
||||
"version",
|
||||
"help",
|
||||
"domdiff",
|
||||
],
|
||||
default: Cli.getDefaultOptions(),
|
||||
unknown: function (unknownArgument) {
|
||||
throw new Error(
|
||||
`We don’t know what '${unknownArgument}' is. Use --help to see the list of supported commands.`
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
debug("command: eleventy-dev-server %o", argv);
|
||||
|
||||
process.on("unhandledRejection", (error, promise) => {
|
||||
Logger.fatal("Unhandled rejection in promise:", promise, error);
|
||||
});
|
||||
process.on("uncaughtException", (error) => {
|
||||
Logger.fatal("Uncaught exception:", error);
|
||||
});
|
||||
|
||||
if (argv.version) {
|
||||
console.log(Cli.getVersion());
|
||||
} else if (argv.help) {
|
||||
console.log(Cli.getHelp());
|
||||
} else {
|
||||
let cli = new Cli();
|
||||
|
||||
cli.serve({
|
||||
input: argv.dir || argv.input,
|
||||
port: argv.port,
|
||||
domDiff: argv.domdiff,
|
||||
});
|
||||
|
||||
process.on("SIGINT", () => {
|
||||
cli.close();
|
||||
process.exit();
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
Logger.fatal("Fatal Error:", e)
|
||||
}
|
56
node_modules/@11ty/eleventy-dev-server/package.json
generated
vendored
Normal file
56
node_modules/@11ty/eleventy-dev-server/package.json
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "@11ty/eleventy-dev-server",
|
||||
"version": "1.0.4",
|
||||
"description": "A minimal, modern, generic, hot-reloading local web server to help web developers.",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"test": "npx ava --verbose",
|
||||
"sample": "node cmd.js --input=test/stubs"
|
||||
},
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/11ty"
|
||||
},
|
||||
"bin": {
|
||||
"eleventy-dev-server": "./cmd.js"
|
||||
},
|
||||
"keywords": [
|
||||
"eleventy",
|
||||
"server",
|
||||
"cli"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"author": {
|
||||
"name": "Zach Leatherman",
|
||||
"email": "zachleatherman@gmail.com",
|
||||
"url": "https://zachleat.com/"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/11ty/eleventy-dev-server.git"
|
||||
},
|
||||
"bugs": "https://github.com/11ty/eleventy-dev-server/issues",
|
||||
"homepage": "https://github.com/11ty/eleventy-dev-server/",
|
||||
"dependencies": {
|
||||
"@11ty/eleventy-utils": "^1.0.1",
|
||||
"chokidar": "^3.5.3",
|
||||
"debug": "^4.3.4",
|
||||
"dev-ip": "^1.0.1",
|
||||
"finalhandler": "^1.2.0",
|
||||
"mime": "^3.0.0",
|
||||
"minimist": "^1.2.8",
|
||||
"morphdom": "^2.7.0",
|
||||
"please-upgrade-node": "^3.2.0",
|
||||
"ssri": "^8.0.1",
|
||||
"ws": "^8.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^5.2.0"
|
||||
}
|
||||
}
|
807
node_modules/@11ty/eleventy-dev-server/server.js
generated
vendored
Normal file
807
node_modules/@11ty/eleventy-dev-server/server.js
generated
vendored
Normal file
@ -0,0 +1,807 @@
|
||||
const pkg = require("./package.json");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const finalhandler = require("finalhandler");
|
||||
const WebSocket = require("ws");
|
||||
const { WebSocketServer } = WebSocket;
|
||||
const mime = require("mime");
|
||||
const ssri = require("ssri");
|
||||
const devip = require("dev-ip");
|
||||
const chokidar = require("chokidar");
|
||||
const { TemplatePath } = require("@11ty/eleventy-utils");
|
||||
|
||||
const debug = require("debug")("EleventyDevServer");
|
||||
|
||||
const wrapResponse = require("./server/wrapResponse.js");
|
||||
|
||||
const DEFAULT_OPTIONS = {
|
||||
port: 8080,
|
||||
liveReload: true, // Enable live reload at all
|
||||
showAllHosts: false, // IP address based hosts (other than localhost)
|
||||
injectedScriptsFolder: ".11ty", // Change the name of the special folder used for injected scripts
|
||||
portReassignmentRetryCount: 10, // number of times to increment the port if in use
|
||||
https: {}, // `key` and `cert`, required for http/2 and https
|
||||
domDiff: true, // Use morphdom to apply DOM diffing delta updates to HTML
|
||||
showVersion: false, // Whether or not to show the server version on the command line.
|
||||
encoding: "utf-8", // Default file encoding
|
||||
pathPrefix: "/", // May be overridden by Eleventy, adds a virtual base directory to your project
|
||||
watch: [], // Globs to pass to separate dev server chokidar for watching
|
||||
aliases: {}, // Aliasing feature
|
||||
|
||||
// Logger (fancier one is injected by Eleventy)
|
||||
logger: {
|
||||
info: console.log,
|
||||
log: console.log,
|
||||
error: console.error,
|
||||
}
|
||||
}
|
||||
|
||||
class EleventyDevServer {
|
||||
static getServer(...args) {
|
||||
return new EleventyDevServer(...args);
|
||||
}
|
||||
|
||||
constructor(name, dir, options = {}) {
|
||||
debug("Creating new Dev Server instance.")
|
||||
this.name = name;
|
||||
this.normalizeOptions(options);
|
||||
|
||||
this.fileCache = {};
|
||||
// Directory to serve
|
||||
if(!dir) {
|
||||
throw new Error("Missing `dir` to serve.");
|
||||
}
|
||||
this.dir = dir;
|
||||
this.logger = this.options.logger;
|
||||
|
||||
if(this.options.watch.length > 0) {
|
||||
this.getWatcher();
|
||||
}
|
||||
}
|
||||
|
||||
normalizeOptions(options = {}) {
|
||||
this.options = Object.assign({}, DEFAULT_OPTIONS, options);
|
||||
|
||||
// better names for options https://github.com/11ty/eleventy-dev-server/issues/41
|
||||
if(options.folder !== undefined) {
|
||||
this.options.injectedScriptsFolder = options.folder;
|
||||
delete this.options.folder;
|
||||
}
|
||||
if(options.domdiff !== undefined) {
|
||||
this.options.domDiff = options.domdiff;
|
||||
delete this.options.domdiff;
|
||||
}
|
||||
if(options.enabled !== undefined) {
|
||||
this.options.liveReload = options.enabled;
|
||||
delete this.options.enabled;
|
||||
}
|
||||
|
||||
this.options.pathPrefix = this.cleanupPathPrefix(this.options.pathPrefix);
|
||||
}
|
||||
|
||||
get watcher() {
|
||||
if(!this._watcher) {
|
||||
debug("Watching %O", this.options.watch);
|
||||
// TODO if using Eleventy and `watch` option includes output folder (_site) this will trigger two update events!
|
||||
this._watcher = chokidar.watch(this.options.watch, {
|
||||
// TODO allow chokidar configuration extensions (or re-use the ones in Eleventy)
|
||||
|
||||
ignored: ["**/node_modules/**", ".git"],
|
||||
ignoreInitial: true,
|
||||
|
||||
// same values as Eleventy
|
||||
awaitWriteFinish: {
|
||||
stabilityThreshold: 150,
|
||||
pollInterval: 25,
|
||||
},
|
||||
});
|
||||
|
||||
this._watcher.on("change", (path) => {
|
||||
this.logger.log( `File changed: ${path} (skips build)` );
|
||||
this.reloadFiles([path]);
|
||||
});
|
||||
|
||||
this._watcher.on("add", (path) => {
|
||||
this.logger.log( `File added: ${path} (skips build)` );
|
||||
this.reloadFiles([path]);
|
||||
});
|
||||
}
|
||||
|
||||
return this._watcher;
|
||||
}
|
||||
|
||||
getWatcher() {
|
||||
return this.watcher;
|
||||
}
|
||||
|
||||
watchFiles(files) {
|
||||
if(Array.isArray(files)) {
|
||||
files = files.map(entry => TemplatePath.stripLeadingDotSlash(entry));
|
||||
|
||||
debug("Also watching %O", files);
|
||||
this.watcher.add(files);
|
||||
}
|
||||
}
|
||||
|
||||
cleanupPathPrefix(pathPrefix) {
|
||||
if(!pathPrefix || pathPrefix === "/") {
|
||||
return "/";
|
||||
}
|
||||
if(!pathPrefix.startsWith("/")) {
|
||||
pathPrefix = `/${pathPrefix}`
|
||||
}
|
||||
if(!pathPrefix.endsWith("/")) {
|
||||
pathPrefix = `${pathPrefix}/`;
|
||||
}
|
||||
return pathPrefix;
|
||||
}
|
||||
|
||||
// Allowed list of files that can be served from outside `dir`
|
||||
setAliases(aliases) {
|
||||
if(aliases) {
|
||||
this.passthroughAliases = aliases;
|
||||
debug( "Setting aliases (emulated passthrough copy) %O", aliases );
|
||||
}
|
||||
}
|
||||
|
||||
matchPassthroughAlias(url) {
|
||||
let aliases = Object.assign({}, this.options.aliases, this.passthroughAliases);
|
||||
for(let targetUrl in aliases) {
|
||||
if(!targetUrl) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let file = aliases[targetUrl];
|
||||
if(url.startsWith(targetUrl)) {
|
||||
let inputDirectoryPath = file + url.slice(targetUrl.length);
|
||||
|
||||
// e.g. addPassthroughCopy("img/") but <img src="/img/built/IdthKOzqFA-350.png">
|
||||
// generated by the image plugin (written to the output folder)
|
||||
// If they do not exist in the input directory, this will fallback to the output directory.
|
||||
if(fs.existsSync(inputDirectoryPath)) {
|
||||
return inputDirectoryPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
isFileInDirectory(dir, file) {
|
||||
let absoluteDir = TemplatePath.absolutePath(dir);
|
||||
let absoluteFile = TemplatePath.absolutePath(file);
|
||||
return absoluteFile.startsWith(absoluteDir);
|
||||
}
|
||||
|
||||
getOutputDirFilePath(filepath, filename = "") {
|
||||
let computedPath;
|
||||
if(filename === ".html") {
|
||||
// avoid trailing slash for filepath/.html requests
|
||||
let prefix = path.join(this.dir, filepath);
|
||||
if(prefix.endsWith(path.sep)) {
|
||||
prefix = prefix.substring(0, prefix.length - path.sep.length);
|
||||
}
|
||||
computedPath = prefix + filename;
|
||||
} else {
|
||||
computedPath = path.join(this.dir, filepath, filename);
|
||||
}
|
||||
|
||||
computedPath = decodeURIComponent(computedPath);
|
||||
|
||||
if(!filename) { // is a direct URL request (not an implicit .html or index.html add)
|
||||
let alias = this.matchPassthroughAlias(filepath);
|
||||
|
||||
if(alias) {
|
||||
if(!this.isFileInDirectory(path.resolve("."), alias)) {
|
||||
throw new Error("Invalid path");
|
||||
}
|
||||
|
||||
return alias;
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the file is in the output path (error if folks try use `..` in the filepath)
|
||||
if(!this.isFileInDirectory(this.dir, computedPath)) {
|
||||
throw new Error("Invalid path");
|
||||
}
|
||||
|
||||
return computedPath;
|
||||
}
|
||||
|
||||
isOutputFilePathExists(rawPath) {
|
||||
return fs.existsSync(rawPath) && !TemplatePath.isDirectorySync(rawPath);
|
||||
}
|
||||
|
||||
/* Use conventions documented here https://www.zachleat.com/web/trailing-slash/
|
||||
* resource.html exists:
|
||||
* /resource matches
|
||||
* /resource/ redirects to /resource
|
||||
* resource/index.html exists:
|
||||
* /resource redirects to /resource/
|
||||
* /resource/ matches
|
||||
* both resource.html and resource/index.html exists:
|
||||
* /resource matches /resource.html
|
||||
* /resource/ matches /resource/index.html
|
||||
*/
|
||||
mapUrlToFilePath(url) {
|
||||
// Note: `localhost` is not important here, any host would work
|
||||
let u = new URL(url, "http://localhost/");
|
||||
url = u.pathname;
|
||||
|
||||
// Remove PathPrefix from start of URL
|
||||
if (this.options.pathPrefix !== "/") {
|
||||
// Requests to root should redirect to new pathPrefix
|
||||
if(url === "/") {
|
||||
return {
|
||||
statusCode: 302,
|
||||
url: this.options.pathPrefix,
|
||||
}
|
||||
}
|
||||
|
||||
// Requests to anything outside of root should fail with 404
|
||||
if (!url.startsWith(this.options.pathPrefix)) {
|
||||
return {
|
||||
statusCode: 404,
|
||||
};
|
||||
}
|
||||
|
||||
url = url.slice(this.options.pathPrefix.length - 1);
|
||||
}
|
||||
|
||||
let rawPath = this.getOutputDirFilePath(url);
|
||||
if (this.isOutputFilePathExists(rawPath)) {
|
||||
return {
|
||||
statusCode: 200,
|
||||
filepath: rawPath,
|
||||
};
|
||||
}
|
||||
|
||||
let indexHtmlPath = this.getOutputDirFilePath(url, "index.html");
|
||||
let indexHtmlExists = fs.existsSync(indexHtmlPath);
|
||||
|
||||
let htmlPath = this.getOutputDirFilePath(url, ".html");
|
||||
let htmlExists = fs.existsSync(htmlPath);
|
||||
|
||||
// /resource/ => /resource/index.html
|
||||
if (indexHtmlExists && url.endsWith("/")) {
|
||||
return {
|
||||
statusCode: 200,
|
||||
filepath: indexHtmlPath,
|
||||
};
|
||||
}
|
||||
// /resource => resource.html
|
||||
if (htmlExists && !url.endsWith("/")) {
|
||||
return {
|
||||
statusCode: 200,
|
||||
filepath: htmlPath,
|
||||
};
|
||||
}
|
||||
|
||||
// /resource => redirect to /resource/
|
||||
if (indexHtmlExists && !url.endsWith("/")) {
|
||||
return {
|
||||
statusCode: 301,
|
||||
url: url + "/",
|
||||
};
|
||||
}
|
||||
|
||||
// /resource/ => redirect to /resource
|
||||
if (htmlExists && url.endsWith("/")) {
|
||||
return {
|
||||
statusCode: 301,
|
||||
url: url.substring(0, url.length - 1),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
statusCode: 404,
|
||||
};
|
||||
}
|
||||
|
||||
_getFileContents(localpath, rootDir, useCache = true) {
|
||||
if(this.fileCache[localpath]) {
|
||||
return this.fileCache[localpath];
|
||||
}
|
||||
|
||||
let filepath;
|
||||
let searchLocations = [];
|
||||
|
||||
if(rootDir) {
|
||||
searchLocations.push(TemplatePath.absolutePath(rootDir, localpath));
|
||||
}
|
||||
// fallbacks for file:../ installations
|
||||
searchLocations.push(TemplatePath.absolutePath(__dirname, localpath));
|
||||
searchLocations.push(TemplatePath.absolutePath(__dirname, "../../../", localpath));
|
||||
|
||||
for(let loc of searchLocations) {
|
||||
if(fs.existsSync(loc)) {
|
||||
filepath = loc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let contents = fs.readFileSync(filepath, {
|
||||
encoding: this.options.encoding,
|
||||
});
|
||||
if(useCache) {
|
||||
this.fileCache[localpath] = contents;
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
augmentContentWithNotifier(content, inlineContents = false, options = {}) {
|
||||
let { integrityHash, scriptContents } = options;
|
||||
if(!scriptContents) {
|
||||
scriptContents = this._getFileContents("./client/reload-client.js");
|
||||
}
|
||||
if(!integrityHash) {
|
||||
integrityHash = ssri.fromData(scriptContents);
|
||||
}
|
||||
|
||||
// This isn’t super necessary because it’s a local file, but it’s included anyway
|
||||
let script = `<script type="module" integrity="${integrityHash}"${inlineContents ? `>${scriptContents}` : ` src="/${this.options.injectedScriptsFolder}/reload-client.js">`}</script>`;
|
||||
|
||||
if (content.includes("</head>")) {
|
||||
return content.replace("</head>", `${script}</head>`);
|
||||
}
|
||||
|
||||
// If the HTML document contains an importmap, insert the module script after the importmap element
|
||||
let importMapRegEx = /<script type=\\?importmap\\?[^>]*>(\n|.)*?<\/script>/gmi;
|
||||
let importMapMatch = content.match(importMapRegEx)?.[0];
|
||||
|
||||
if (importMapMatch) {
|
||||
return content.replace(importMapMatch, `${importMapMatch}${script}`);
|
||||
}
|
||||
|
||||
// <title> is the only *required* element in an HTML document
|
||||
if (content.includes("</title>")) {
|
||||
return content.replace("</title>", `</title>${script}`);
|
||||
}
|
||||
|
||||
// If you’ve reached this section, your HTML is invalid!
|
||||
// We want to be super forgiving here, because folks might be in-progress editing the document!
|
||||
if (content.includes("</body>")) {
|
||||
return content.replace("</body>", `${script}</body>`);
|
||||
}
|
||||
if (content.includes("</html>")) {
|
||||
return content.replace("</html>", `${script}</html>`);
|
||||
}
|
||||
if (content.includes("<!doctype html>")) {
|
||||
return content.replace("<!doctype html>", `<!doctype html>${script}`);
|
||||
}
|
||||
|
||||
// Notably, works without content at all!!
|
||||
return (content || "") + script;
|
||||
}
|
||||
|
||||
getFileContentType(filepath, res) {
|
||||
let contentType = res.getHeader("Content-Type");
|
||||
|
||||
// Content-Type might be already set via middleware
|
||||
if (contentType) {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
let mimeType = mime.getType(filepath);
|
||||
if (!mimeType) {
|
||||
return;
|
||||
}
|
||||
|
||||
contentType = mimeType;
|
||||
|
||||
// We only want to append charset if the header is not already set
|
||||
if (contentType === "text/html") {
|
||||
contentType = `text/html; charset=${this.options.encoding}`;
|
||||
}
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
renderFile(filepath, res) {
|
||||
let contents = fs.readFileSync(filepath);
|
||||
let contentType = this.getFileContentType(filepath, res);
|
||||
|
||||
if (!contentType) {
|
||||
return res.end(contents);
|
||||
}
|
||||
|
||||
res.setHeader("Content-Type", contentType);
|
||||
|
||||
if (contentType.startsWith("text/html")) {
|
||||
// the string is important here, wrapResponse expects strings internally for HTML content (for now)
|
||||
return res.end(contents.toString());
|
||||
}
|
||||
|
||||
return res.end(contents);
|
||||
}
|
||||
|
||||
eleventyDevServerMiddleware(req, res, next) {
|
||||
if(req.url === `/${this.options.injectedScriptsFolder}/reload-client.js`) {
|
||||
if(this.options.liveReload) {
|
||||
res.setHeader("Content-Type", mime.getType("js"));
|
||||
return res.end(this._getFileContents("./client/reload-client.js"));
|
||||
}
|
||||
} else if(req.url === `/${this.options.injectedScriptsFolder}/morphdom.js`) {
|
||||
if(this.options.domDiff) {
|
||||
res.setHeader("Content-Type", mime.getType("js"));
|
||||
return res.end(this._getFileContents("./node_modules/morphdom/dist/morphdom-esm.js", path.resolve(".")));
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
// This runs at the end of the middleware chain
|
||||
eleventyProjectMiddleware(req, res) {
|
||||
// Known issue with `finalhandler` and HTTP/2:
|
||||
// UnsupportedWarning: Status message is not supported by HTTP/2 (RFC7540 8.1.2.4)
|
||||
// https://github.com/pillarjs/finalhandler/pull/34
|
||||
|
||||
let lastNext = finalhandler(req, res, {
|
||||
onerror: (e) => {
|
||||
if (e.statusCode === 404) {
|
||||
let localPath = TemplatePath.stripLeadingSubPath(
|
||||
e.path,
|
||||
TemplatePath.absolutePath(this.dir)
|
||||
);
|
||||
this.logger.error(
|
||||
`HTTP ${e.statusCode}: Template not found in output directory (${this.dir}): ${localPath}`
|
||||
);
|
||||
} else {
|
||||
this.logger.error(`HTTP ${e.statusCode}: ${e.message}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// middleware (maybe a serverless request) already set a body upstream, skip this part
|
||||
if(!res._shouldForceEnd) {
|
||||
let match = this.mapUrlToFilePath(req.url);
|
||||
debug( req.url, match );
|
||||
|
||||
if (match) {
|
||||
if (match.statusCode === 200 && match.filepath) {
|
||||
return this.renderFile(match.filepath, res);
|
||||
}
|
||||
|
||||
// Redirects, usually for trailing slash to .html stuff
|
||||
if (match.url) {
|
||||
res.statusCode = match.statusCode;
|
||||
res.setHeader("Location", match.url);
|
||||
return res.end();
|
||||
}
|
||||
|
||||
let raw404Path = this.getOutputDirFilePath("404.html");
|
||||
if(match.statusCode === 404 && this.isOutputFilePathExists(raw404Path)) {
|
||||
res.statusCode = match.statusCode;
|
||||
res.isCustomErrorPage = true;
|
||||
return this.renderFile(raw404Path, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(res.body && !res.bodyUsed) {
|
||||
if(res._shouldForceEnd) {
|
||||
res.end();
|
||||
} else {
|
||||
let err = new Error("A response was never written to the stream. Are you missing a server middleware with `res.end()`?");
|
||||
err.statusCode = 500;
|
||||
lastNext(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lastNext();
|
||||
}
|
||||
|
||||
async onRequestHandler (req, res) {
|
||||
res = wrapResponse(res, content => {
|
||||
|
||||
// check to see if this is a client fetch and not a navigation
|
||||
let isXHR = req.headers["sec-fetch-mode"] && req.headers["sec-fetch-mode"] != "navigate";
|
||||
|
||||
if(this.options.liveReload !== false && !isXHR) {
|
||||
let scriptContents = this._getFileContents("./client/reload-client.js");
|
||||
let integrityHash = ssri.fromData(scriptContents);
|
||||
|
||||
// Bare (not-custom) finalhandler error pages have a Content-Security-Policy `default-src 'none'` that
|
||||
// prevents the client script from executing, so we override it
|
||||
if(res.statusCode !== 200 && !res.isCustomErrorPage) {
|
||||
res.setHeader("Content-Security-Policy", `script-src '${integrityHash}'`);
|
||||
}
|
||||
return this.augmentContentWithNotifier(content, res.statusCode !== 200, {
|
||||
scriptContents,
|
||||
integrityHash
|
||||
});
|
||||
}
|
||||
|
||||
return content;
|
||||
});
|
||||
|
||||
let middlewares = this.options.middleware || [];
|
||||
middlewares = middlewares.slice();
|
||||
|
||||
// TODO because this runs at the very end of the middleware chain,
|
||||
// if we move the static stuff up in the order we could use middleware to modify
|
||||
// the static content in middleware!
|
||||
middlewares.push(this.eleventyProjectMiddleware);
|
||||
middlewares.reverse();
|
||||
|
||||
// Runs very first in the middleware chain
|
||||
middlewares.push(this.eleventyDevServerMiddleware);
|
||||
|
||||
let bound = [];
|
||||
let next;
|
||||
|
||||
for(let ware of middlewares) {
|
||||
let fn;
|
||||
if(next) {
|
||||
fn = ware.bind(this, req, res, next);
|
||||
} else {
|
||||
fn = ware.bind(this, req, res);
|
||||
}
|
||||
bound.push(fn);
|
||||
next = fn;
|
||||
}
|
||||
|
||||
bound.reverse();
|
||||
|
||||
let [first] = bound;
|
||||
await first();
|
||||
}
|
||||
|
||||
get server() {
|
||||
if (this._server) {
|
||||
return this._server;
|
||||
}
|
||||
|
||||
this.start = Date.now();
|
||||
|
||||
// Check for secure server requirements, otherwise use HTTP
|
||||
let { key, cert } = this.options.https;
|
||||
if(key && cert) {
|
||||
const { createSecureServer } = require("http2");
|
||||
|
||||
let options = {
|
||||
allowHTTP1: true,
|
||||
|
||||
// Credentials
|
||||
key: fs.readFileSync(key),
|
||||
cert: fs.readFileSync(cert),
|
||||
};
|
||||
this._server = createSecureServer(options, this.onRequestHandler.bind(this));
|
||||
this._serverProtocol = "https:";
|
||||
} else {
|
||||
const { createServer } = require("http");
|
||||
|
||||
this._server = createServer(this.onRequestHandler.bind(this));
|
||||
this._serverProtocol = "http:";
|
||||
}
|
||||
|
||||
this.portRetryCount = 0;
|
||||
this._server.on("error", (err) => {
|
||||
if (err.code == "EADDRINUSE") {
|
||||
if (this.portRetryCount < this.options.portReassignmentRetryCount) {
|
||||
this.portRetryCount++;
|
||||
debug(
|
||||
"Server already using port %o, trying the next port %o. Retry number %o of %o",
|
||||
err.port,
|
||||
err.port + 1,
|
||||
this.portRetryCount,
|
||||
this.options.portReassignmentRetryCount
|
||||
);
|
||||
this._serverListen(err.port + 1);
|
||||
} else {
|
||||
throw new Error(
|
||||
`Tried ${this.options.portReassignmentRetryCount} different ports but they were all in use. You can a different starter port using --port on the command line.`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this._serverErrorHandler(err);
|
||||
}
|
||||
});
|
||||
|
||||
this._server.on("listening", (e) => {
|
||||
this.setupReloadNotifier();
|
||||
|
||||
let { port } = this._server.address();
|
||||
|
||||
let hostsStr = "";
|
||||
if(this.options.showAllHosts) {
|
||||
// TODO what happens when the cert doesn’t cover non-localhost hosts?
|
||||
let hosts = devip().map(host => `${this._serverProtocol}//${host}:${port}${this.options.pathPrefix} or`);
|
||||
hostsStr = hosts.join(" ") + " ";
|
||||
}
|
||||
|
||||
let startBenchmark = ""; // this.start ? ` ready in ${Date.now() - this.start}ms` : "";
|
||||
this.logger.info(`Server at ${hostsStr}${this._serverProtocol}//localhost:${port}${this.options.pathPrefix}${this.options.showVersion ? ` (v${pkg.version})` : ""}${startBenchmark}`);
|
||||
});
|
||||
|
||||
return this._server;
|
||||
}
|
||||
|
||||
_serverListen(port) {
|
||||
this.server.listen({
|
||||
port,
|
||||
});
|
||||
}
|
||||
|
||||
async getPort() {
|
||||
return new Promise(resolve => {
|
||||
this.server.on("listening", (e) => {
|
||||
let { port } = this._server.address();
|
||||
resolve(port);
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
serve(port) {
|
||||
this.getWatcher();
|
||||
|
||||
this._serverListen(port);
|
||||
}
|
||||
|
||||
_serverErrorHandler(err) {
|
||||
if (err.code == "EADDRINUSE") {
|
||||
this.logger.error(`Server error: Port in use ${err.port}`);
|
||||
} else {
|
||||
this.logger.error(`Server error: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Websocket Notifications
|
||||
setupReloadNotifier() {
|
||||
let updateServer = new WebSocketServer({
|
||||
// includes the port
|
||||
server: this.server,
|
||||
});
|
||||
|
||||
updateServer.on("connection", (ws) => {
|
||||
this.sendUpdateNotification({
|
||||
type: "eleventy.status",
|
||||
status: "connected",
|
||||
});
|
||||
});
|
||||
|
||||
updateServer.on("error", (err) => {
|
||||
this._serverErrorHandler(err);
|
||||
});
|
||||
|
||||
this.updateServer = updateServer;
|
||||
}
|
||||
|
||||
// Broadcasts to all open browser windows
|
||||
sendUpdateNotification(obj) {
|
||||
if(!this.updateServer?.clients) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(let client of this.updateServer.clients) {
|
||||
if (client.readyState === WebSocket.OPEN) {
|
||||
client.send(JSON.stringify(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
// TODO would be awesome to set a delayed redirect when port changed to redirect to new _server_
|
||||
this.sendUpdateNotification({
|
||||
type: "eleventy.status",
|
||||
status: "disconnected",
|
||||
});
|
||||
|
||||
if(this.server) {
|
||||
this.server.close();
|
||||
}
|
||||
if(this.updateServer) {
|
||||
this.updateServer.close();
|
||||
}
|
||||
if(this._watcher) {
|
||||
this._watcher.close();
|
||||
delete this._watcher;
|
||||
}
|
||||
}
|
||||
|
||||
sendError({ error }) {
|
||||
this.sendUpdateNotification({
|
||||
type: "eleventy.error",
|
||||
// Thanks https://stackoverflow.com/questions/18391212/is-it-not-possible-to-stringify-an-error-using-json-stringify
|
||||
error: JSON.stringify(error, Object.getOwnPropertyNames(error)),
|
||||
});
|
||||
}
|
||||
|
||||
// reverse of mapUrlToFilePath
|
||||
// /resource/ <= /resource/index.html
|
||||
// /resource <= resource.html
|
||||
getUrlsFromFilePath(path) {
|
||||
if(this.dir === ".") {
|
||||
path = `/${path}`
|
||||
} else {
|
||||
path = path.slice(this.dir.length);
|
||||
}
|
||||
|
||||
let urls = [];
|
||||
urls.push(path);
|
||||
|
||||
if(path.endsWith("/index.html")) {
|
||||
urls.push(path.slice(0, -1 * "index.html".length));
|
||||
} else if(path.endsWith(".html")) {
|
||||
urls.push(path.slice(0, -1 * ".html".length));
|
||||
}
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
// [{ url, inputPath, content }]
|
||||
getBuildTemplatesFromFilePath(path) {
|
||||
// We can skip this for non-html files, dom-diffing will not apply
|
||||
if(!path.endsWith(".html")) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let urls = this.getUrlsFromFilePath(path);
|
||||
let obj = {
|
||||
inputPath: path,
|
||||
content: fs.readFileSync(path, "utf8"),
|
||||
}
|
||||
|
||||
return urls.map(url => {
|
||||
return Object.assign({ url }, obj);
|
||||
});
|
||||
}
|
||||
|
||||
reloadFiles(files, useDomDiffingForHtml = true) {
|
||||
if(!Array.isArray(files)) {
|
||||
throw new Error("reloadFiles method requires an array of file paths.");
|
||||
}
|
||||
|
||||
let subtype;
|
||||
if(!files.some((entry) => !entry.endsWith(".css"))) {
|
||||
// all css changes
|
||||
subtype = "css";
|
||||
}
|
||||
|
||||
let templates = [];
|
||||
if(useDomDiffingForHtml && this.options.domDiff) {
|
||||
for(let filePath of files) {
|
||||
if(!filePath.endsWith(".html")) {
|
||||
continue;
|
||||
}
|
||||
for(let templateEntry of this.getBuildTemplatesFromFilePath(filePath)) {
|
||||
templates.push(templateEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.reload({
|
||||
files,
|
||||
subtype,
|
||||
build: {
|
||||
templates
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
reload(event) {
|
||||
let { subtype, files, build } = event;
|
||||
if (build?.templates) {
|
||||
build.templates = build.templates
|
||||
.filter(entry => {
|
||||
if(!this.options.domDiff) {
|
||||
// Don’t include any files if the dom diffing option is disabled
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filter to only include watched templates that were updated
|
||||
return (files || []).includes(entry.inputPath);
|
||||
});
|
||||
}
|
||||
|
||||
this.sendUpdateNotification({
|
||||
type: "eleventy.reload",
|
||||
subtype,
|
||||
files,
|
||||
build,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyDevServer;
|
129
node_modules/@11ty/eleventy-dev-server/server/wrapResponse.js
generated
vendored
Normal file
129
node_modules/@11ty/eleventy-dev-server/server/wrapResponse.js
generated
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
function getContentType(headers) {
|
||||
if(!headers) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(let key in headers) {
|
||||
if(key.toLowerCase() === "content-type") {
|
||||
return headers[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inspired by `resp-modifier` https://github.com/shakyShane/resp-modifier/blob/4a000203c9db630bcfc3b6bb8ea2abc090ae0139/index.js
|
||||
function wrapResponse(resp, transformHtml) {
|
||||
resp._wrappedOriginalWrite = resp.write;
|
||||
resp._wrappedOriginalWriteHead = resp.writeHead;
|
||||
resp._wrappedOriginalEnd = resp.end;
|
||||
|
||||
resp._wrappedHeaders = [];
|
||||
resp._wrappedTransformHtml = transformHtml;
|
||||
resp._hasEnded = false;
|
||||
resp._shouldForceEnd = false;
|
||||
|
||||
// Compatibility with web standards Response()
|
||||
Object.defineProperty(resp, "body", {
|
||||
// Returns write cache
|
||||
get: function() {
|
||||
if(typeof this._writeCache === "string") {
|
||||
return this._writeCache;
|
||||
}
|
||||
},
|
||||
// Usage:
|
||||
// res.body = ""; // overwrite existing content
|
||||
// res.body += ""; // append to existing content, can also res.write("") to append
|
||||
set: function(data) {
|
||||
if(typeof data === "string") {
|
||||
this._writeCache = data;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Compatibility with web standards Response()
|
||||
Object.defineProperty(resp, "bodyUsed", {
|
||||
get: function() {
|
||||
return this._hasEnded;
|
||||
}
|
||||
})
|
||||
|
||||
// Original signature writeHead(statusCode[, statusMessage][, headers])
|
||||
resp.writeHead = function(statusCode, ...args) {
|
||||
let headers = args[args.length - 1];
|
||||
// statusMessage is a string
|
||||
if(typeof headers !== "string") {
|
||||
this._contentType = getContentType(headers);
|
||||
}
|
||||
|
||||
if((this._contentType || "").startsWith("text/html")) {
|
||||
this._wrappedHeaders.push([statusCode, ...args]);
|
||||
} else {
|
||||
return this._wrappedOriginalWriteHead(statusCode, ...args);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// data can be a String or Buffer
|
||||
resp.write = function(data, ...args) {
|
||||
if(typeof data === "string") {
|
||||
if(!this._writeCache) {
|
||||
this._writeCache = "";
|
||||
}
|
||||
|
||||
// TODO encoding and callback args
|
||||
this._writeCache += data;
|
||||
} else {
|
||||
// Buffers
|
||||
return this._wrappedOriginalWrite(data, ...args);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// data can be a String or Buffer
|
||||
resp.end = function(data, encoding, callback) {
|
||||
resp._hasEnded = true;
|
||||
|
||||
if(typeof this._writeCache === "string" || typeof data === "string") {
|
||||
// Strings
|
||||
if(!this._writeCache) {
|
||||
this._writeCache = "";
|
||||
}
|
||||
if(typeof data === "string") {
|
||||
this._writeCache += data;
|
||||
}
|
||||
|
||||
let result = this._writeCache;
|
||||
|
||||
// Only transform HTML
|
||||
// Note the “setHeader versus writeHead” note on https://nodejs.org/api/http.html#responsewriteheadstatuscode-statusmessage-headers
|
||||
let contentType = this._contentType || getContentType(this.getHeaders());
|
||||
if(contentType && contentType.startsWith("text/html")) {
|
||||
if(this._wrappedTransformHtml && typeof this._wrappedTransformHtml === "function") {
|
||||
result = this._wrappedTransformHtml(result);
|
||||
this.setHeader("Content-Length", Buffer.byteLength(result));
|
||||
}
|
||||
}
|
||||
|
||||
for(let headers of this._wrappedHeaders) {
|
||||
this._wrappedOriginalWriteHead(...headers);
|
||||
}
|
||||
|
||||
this._writeCache = [];
|
||||
this._wrappedOriginalWrite(result, encoding)
|
||||
return this._wrappedOriginalEnd(callback);
|
||||
} else {
|
||||
// Buffers
|
||||
for(let headers of this._wrappedHeaders) {
|
||||
this._wrappedOriginalWriteHead(...headers);
|
||||
}
|
||||
|
||||
if(data) {
|
||||
this._wrappedOriginalWrite(data, encoding);
|
||||
}
|
||||
return this._wrappedOriginalEnd(callback);
|
||||
}
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
module.exports = wrapResponse;
|
21
node_modules/@11ty/eleventy-utils/LICENSE
generated
vendored
Normal file
21
node_modules/@11ty/eleventy-utils/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Zach Leatherman @zachleat
|
||||
|
||||
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.
|
29
node_modules/@11ty/eleventy-utils/README.md
generated
vendored
Normal file
29
node_modules/@11ty/eleventy-utils/README.md
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<p align="center"><img src="https://www.11ty.dev/img/logo-github.png" alt="eleventy Logo"></p>
|
||||
|
||||
# eleventy-utils 🕚⚡️🎈🐀
|
||||
|
||||
Low level internal utilities to be shared amongst Eleventy projects.
|
||||
|
||||
## ➡ [Documentation](https://www.11ty.dev/docs/)
|
||||
|
||||
- Please star [Eleventy on GitHub](https://github.com/11ty/eleventy/)!
|
||||
- Follow us on Twitter [@eleven_ty](https://twitter.com/eleven_ty)
|
||||
- Support [11ty on Open Collective](https://opencollective.com/11ty)
|
||||
- [11ty on npm](https://www.npmjs.com/org/11ty)
|
||||
- [11ty on GitHub](https://github.com/11ty)
|
||||
|
||||
[![npm Version](https://img.shields.io/npm/v/@11ty/eleventy-utils.svg?style=for-the-badge)](https://www.npmjs.com/package/@11ty/eleventy-utils)
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
npm install @11ty/eleventy-utils
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
```
|
||||
npm run test
|
||||
```
|
||||
|
||||
- We use the [ava JavaScript test runner](https://github.com/avajs/ava) ([Assertions documentation](https://github.com/avajs/ava/blob/master/docs/03-assertions.md))
|
11
node_modules/@11ty/eleventy-utils/index.js
generated
vendored
Normal file
11
node_modules/@11ty/eleventy-utils/index.js
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
const TemplatePath = require("./src/TemplatePath.js");
|
||||
const isPlainObject = require("./src/IsPlainObject.js");
|
||||
const Merge = require("./src/Merge.js");
|
||||
const { DeepCopy } = Merge;
|
||||
|
||||
module.exports = {
|
||||
TemplatePath,
|
||||
isPlainObject,
|
||||
Merge,
|
||||
DeepCopy,
|
||||
};
|
47
node_modules/@11ty/eleventy-utils/package.json
generated
vendored
Normal file
47
node_modules/@11ty/eleventy-utils/package.json
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "@11ty/eleventy-utils",
|
||||
"version": "1.0.3",
|
||||
"description": "Low level internal utilities to be shared amongst Eleventy projects",
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
"src",
|
||||
"src/**",
|
||||
"index.js",
|
||||
"!test",
|
||||
"!test/**"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "npx ava --verbose"
|
||||
},
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/11ty"
|
||||
},
|
||||
"keywords": [
|
||||
"eleventy"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"author": {
|
||||
"name": "Zach Leatherman",
|
||||
"email": "zachleatherman@gmail.com",
|
||||
"url": "https://zachleat.com/"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/11ty/eleventy-utils.git"
|
||||
},
|
||||
"bugs": "https://github.com/11ty/eleventy-utils/issues",
|
||||
"homepage": "https://github.com/11ty/eleventy-utils/",
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^6.1.3"
|
||||
}
|
||||
}
|
24
node_modules/@11ty/eleventy-utils/src/IsPlainObject.js
generated
vendored
Normal file
24
node_modules/@11ty/eleventy-utils/src/IsPlainObject.js
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
/* Prior art: this utility was created for https://github.com/11ty/eleventy/issues/2214
|
||||
|
||||
* Inspired by implementations from `is-what`, `typechecker`, `jQuery`, and `lodash`
|
||||
|
||||
* `is-what`
|
||||
* More reading at https://www.npmjs.com/package/is-what#user-content-isplainobject-vs-isanyobject
|
||||
* if (Object.prototype.toString.call(value).slice(8, -1) !== 'Object') return false;
|
||||
* return value.constructor === Object && Object.getPrototypeOf(value) === Object.prototype;
|
||||
|
||||
* `typechecker`
|
||||
* return value !== null && typeof value === 'object' && value.__proto__ === Object.prototype;
|
||||
|
||||
* Notably jQuery and lodash have very similar implementations.
|
||||
|
||||
* For later, remember the `value === Object(value)` trick
|
||||
*/
|
||||
|
||||
module.exports = function (value) {
|
||||
if (value === null || typeof value !== "object") {
|
||||
return false;
|
||||
}
|
||||
let proto = Object.getPrototypeOf(value);
|
||||
return !proto || proto === Object.prototype;
|
||||
};
|
84
node_modules/@11ty/eleventy-utils/src/Merge.js
generated
vendored
Normal file
84
node_modules/@11ty/eleventy-utils/src/Merge.js
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
"use strict";
|
||||
// above is required for Object.freeze to fail correctly.
|
||||
|
||||
const isPlainObject = require("./IsPlainObject.js");
|
||||
|
||||
const OVERRIDE_PREFIX = "override:";
|
||||
|
||||
function cleanKey(key, prefix) {
|
||||
if (prefix && key.startsWith(prefix)) {
|
||||
return key.slice(prefix.length);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
function getMergedItem(target, source, prefixes = {}) {
|
||||
let { override } = prefixes;
|
||||
|
||||
// Shortcut for frozen source (if target does not exist)
|
||||
if (!target && isPlainObject(source) && Object.isFrozen(source)) {
|
||||
return source;
|
||||
}
|
||||
|
||||
let sourcePlainObjectShortcut;
|
||||
if (!target && isPlainObject(source)) {
|
||||
// deep copy objects to avoid sharing and to effect key renaming
|
||||
target = {};
|
||||
sourcePlainObjectShortcut = true;
|
||||
}
|
||||
|
||||
if (Array.isArray(target) && Array.isArray(source)) {
|
||||
return target.concat(source);
|
||||
} else if (isPlainObject(target)) {
|
||||
if (sourcePlainObjectShortcut || isPlainObject(source)) {
|
||||
for (let key in source) {
|
||||
let overrideKey = cleanKey(key, override);
|
||||
|
||||
// An error happens here if the target is frozen
|
||||
target[overrideKey] = getMergedItem(target[key], source[key], prefixes);
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
// number, string, class instance, etc
|
||||
return source;
|
||||
}
|
||||
|
||||
// The same as Merge but without override prefixes
|
||||
function DeepCopy(targetObject, ...sources) {
|
||||
for (let source of sources) {
|
||||
if (!source) {
|
||||
continue;
|
||||
}
|
||||
|
||||
targetObject = getMergedItem(targetObject, source);
|
||||
}
|
||||
return targetObject;
|
||||
}
|
||||
|
||||
function Merge(target, ...sources) {
|
||||
// Remove override prefixes from root target.
|
||||
if (isPlainObject(target)) {
|
||||
for (let key in target) {
|
||||
if (key.indexOf(OVERRIDE_PREFIX) === 0) {
|
||||
target[key.slice(OVERRIDE_PREFIX.length)] = target[key];
|
||||
delete target[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let source of sources) {
|
||||
if (!source) {
|
||||
continue;
|
||||
}
|
||||
|
||||
target = getMergedItem(target, source, {
|
||||
override: OVERRIDE_PREFIX,
|
||||
});
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
module.exports = Merge;
|
||||
module.exports.DeepCopy = DeepCopy;
|
368
node_modules/@11ty/eleventy-utils/src/TemplatePath.js
generated
vendored
Normal file
368
node_modules/@11ty/eleventy-utils/src/TemplatePath.js
generated
vendored
Normal file
@ -0,0 +1,368 @@
|
||||
const path = require("path");
|
||||
const normalize = require("normalize-path");
|
||||
const fs = require("fs");
|
||||
|
||||
function TemplatePath() {}
|
||||
|
||||
/**
|
||||
* @returns {String} the absolute path to Eleventy’s project directory.
|
||||
*/
|
||||
TemplatePath.getWorkingDir = function () {
|
||||
return TemplatePath.normalize(path.resolve("."));
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the directory portion of a path.
|
||||
* Works for directory and file paths and paths ending in a glob pattern.
|
||||
*
|
||||
* @param {String} path A path
|
||||
* @returns {String} the directory portion of a path.
|
||||
*/
|
||||
TemplatePath.getDir = function (path) {
|
||||
if (TemplatePath.isDirectorySync(path)) {
|
||||
return path;
|
||||
}
|
||||
|
||||
return TemplatePath.getDirFromFilePath(path);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the directory portion of a path that either points to a file
|
||||
* or ends in a glob pattern. If `path` points to a directory,
|
||||
* the returned value will have its last path segment stripped
|
||||
* due to how [`path.parse`][1] works.
|
||||
*
|
||||
* [1]: https://nodejs.org/api/path.html#path_path_parse_path
|
||||
*
|
||||
* @param {String} path A path
|
||||
* @returns {String} the directory portion of a path.
|
||||
*/
|
||||
TemplatePath.getDirFromFilePath = function (filePath) {
|
||||
return path.parse(filePath).dir || ".";
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the last path segment in a path (no leading/trailing slashes).
|
||||
*
|
||||
* Assumes [`path.parse`][1] was called on `path` before.
|
||||
*
|
||||
* [1]: https://nodejs.org/api/path.html#path_path_parse_path
|
||||
*
|
||||
* @param {String} path A path
|
||||
* @returns {String} the last path segment in a path
|
||||
*/
|
||||
TemplatePath.getLastPathSegment = function (path) {
|
||||
if (!path.includes("/")) {
|
||||
return path;
|
||||
}
|
||||
|
||||
// Trim a trailing slash if there is one
|
||||
path = path.replace(/\/$/, "");
|
||||
|
||||
return path.substr(path.lastIndexOf("/") + 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} path A path
|
||||
* @returns {String[]} an array of paths pointing to each path segment of the
|
||||
* provided `path`.
|
||||
*/
|
||||
TemplatePath.getAllDirs = function (path) {
|
||||
// Trim a trailing slash if there is one
|
||||
path = path.replace(/\/$/, "");
|
||||
|
||||
if (!path.includes("/")) {
|
||||
return [path];
|
||||
}
|
||||
|
||||
return path
|
||||
.split("/")
|
||||
.map((segment, index, array) => array.slice(0, index + 1).join("/"))
|
||||
.filter((path) => path !== ".")
|
||||
.reverse();
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalizes a path, resolving single-dot and double-dot segments.
|
||||
*
|
||||
* Node.js’ [`path.normalize`][1] is called to strip a possible leading `"./"` segment.
|
||||
*
|
||||
* [1]: https://nodejs.org/api/path.html#path_path_normalize_path
|
||||
*
|
||||
* @param {String} thePath The path that should be normalized.
|
||||
* @returns {String} the normalized path.
|
||||
*/
|
||||
TemplatePath.normalize = function (thePath) {
|
||||
return normalize(path.normalize(thePath));
|
||||
};
|
||||
|
||||
/**
|
||||
* Joins all given path segments together.
|
||||
*
|
||||
* It uses Node.js’ [`path.join`][1] method and the [normalize-path][2] package.
|
||||
*
|
||||
* [1]: https://nodejs.org/api/path.html#path_path_join_paths
|
||||
* [2]: https://www.npmjs.com/package/normalize-path
|
||||
*
|
||||
* @param {String[]} paths An arbitrary amount of path segments.
|
||||
* @returns {String} the normalized and joined path.
|
||||
*/
|
||||
TemplatePath.join = function (...paths) {
|
||||
return normalize(path.join(...paths));
|
||||
};
|
||||
|
||||
/**
|
||||
* Joins the given URL path segments and normalizes the resulting path.
|
||||
* Maintains a single trailing slash if the last URL path argument
|
||||
* had at least one.
|
||||
*
|
||||
* @param {String[]} urlPaths
|
||||
* @returns {String} a normalized URL path described by the given URL path segments.
|
||||
*/
|
||||
TemplatePath.normalizeUrlPath = function (...urlPaths) {
|
||||
const urlPath = path.posix.join(...urlPaths);
|
||||
return urlPath.replace(/\/+$/, "/");
|
||||
};
|
||||
|
||||
/**
|
||||
* Joins the given path segments. Since the first path is absolute,
|
||||
* the resulting path will be absolute as well.
|
||||
*
|
||||
* @param {String[]} paths
|
||||
* @returns {String} the absolute path described by the given path segments.
|
||||
*/
|
||||
TemplatePath.absolutePath = function (...paths) {
|
||||
let i = 0;
|
||||
// check all the paths before we short circuit from the first index
|
||||
for (let p of paths) {
|
||||
if (path.isAbsolute(p) && i > 0) {
|
||||
throw new Error(
|
||||
`Only the first parameter to Template.absolutePath can be an absolute path. Received: ${p} from ${paths}`
|
||||
);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
let j = 0;
|
||||
for (let p of paths) {
|
||||
if (j === 0 && path.isAbsolute(p)) {
|
||||
return TemplatePath.join(...paths);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
return TemplatePath.join(TemplatePath.getWorkingDir(), ...paths);
|
||||
};
|
||||
|
||||
/**
|
||||
* Turns an absolute path into a path relative to the project directory.
|
||||
*
|
||||
* @param {String} absolutePath
|
||||
* @returns {String} the relative path.
|
||||
*/
|
||||
TemplatePath.relativePath = function (absolutePath) {
|
||||
return TemplatePath.stripLeadingSubPath(
|
||||
absolutePath,
|
||||
TemplatePath.getWorkingDir()
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a leading dot-slash segment to each path in the `paths` array.
|
||||
*
|
||||
* @param {String[]} paths
|
||||
* @returns {String[]}
|
||||
*/
|
||||
TemplatePath.addLeadingDotSlashArray = function (paths) {
|
||||
return paths.map((path) => TemplatePath.addLeadingDotSlash(path));
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a leading dot-slash segment to `path`.
|
||||
*
|
||||
* @param {String} path
|
||||
* @returns {String}
|
||||
*/
|
||||
TemplatePath.addLeadingDotSlash = function (pathArg) {
|
||||
if (pathArg === "." || pathArg === "..") {
|
||||
return pathArg + "/";
|
||||
}
|
||||
|
||||
if (
|
||||
path.isAbsolute(pathArg) ||
|
||||
pathArg.startsWith("./") ||
|
||||
pathArg.startsWith("../")
|
||||
) {
|
||||
return pathArg;
|
||||
}
|
||||
|
||||
return "./" + pathArg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a leading dot-slash segment.
|
||||
*
|
||||
* @param {String} path
|
||||
* @returns {String} the `path` without a leading dot-slash segment.
|
||||
*/
|
||||
TemplatePath.stripLeadingDotSlash = function (path) {
|
||||
return typeof path === "string" ? path.replace(/^\.\//, "") : path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether a path starts with a given sub path.
|
||||
*
|
||||
* @param {String} path A path
|
||||
* @param {String} subPath A path
|
||||
* @returns {Boolean} whether `path` starts with `subPath`.
|
||||
*/
|
||||
TemplatePath.startsWithSubPath = function (path, subPath) {
|
||||
path = TemplatePath.normalize(path);
|
||||
subPath = TemplatePath.normalize(subPath);
|
||||
|
||||
return path.startsWith(subPath);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the `subPath` at the start of `path` if present
|
||||
* and returns the remainding path.
|
||||
*
|
||||
* @param {String} path A path
|
||||
* @param {String} subPath A path
|
||||
* @returns {String} the `path` without `subPath` at the start of it.
|
||||
*/
|
||||
TemplatePath.stripLeadingSubPath = function (path, subPath) {
|
||||
path = TemplatePath.normalize(path);
|
||||
subPath = TemplatePath.normalize(subPath);
|
||||
|
||||
if (subPath !== "." && path.startsWith(subPath)) {
|
||||
return path.substr(subPath.length + 1);
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} path A path
|
||||
* @returns {Boolean} whether `path` points to an existing directory.
|
||||
*/
|
||||
TemplatePath.isDirectorySync = function (path) {
|
||||
return fs.existsSync(path) && fs.statSync(path).isDirectory();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} path A path
|
||||
* @returns {Boolean} whether `path` points to an existing directory.
|
||||
*/
|
||||
TemplatePath.isDirectory = async function (path) {
|
||||
return new Promise((resolve) => {
|
||||
fs.stat(path, (err, stats) => {
|
||||
if (stats) {
|
||||
resolve(stats.isDirectory());
|
||||
}
|
||||
resolve(false);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Appends a recursive wildcard glob pattern to `path`
|
||||
* unless `path` is not a directory; then, `path` is assumed to be a file path
|
||||
* and is left unchaged.
|
||||
*
|
||||
* @param {String} path
|
||||
* @returns {String}
|
||||
*/
|
||||
TemplatePath.convertToRecursiveGlobSync = function (path) {
|
||||
if (path === "") {
|
||||
return "./**";
|
||||
}
|
||||
|
||||
path = TemplatePath.addLeadingDotSlash(path);
|
||||
|
||||
if (TemplatePath.isDirectorySync(path)) {
|
||||
return path + (!path.endsWith("/") ? "/" : "") + "**";
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Appends a recursive wildcard glob pattern to `path`
|
||||
* unless `path` is not a directory; then, `path` is assumed to be a file path
|
||||
* and is left unchaged.
|
||||
*
|
||||
* @param {String} path
|
||||
* @returns {String}
|
||||
*/
|
||||
TemplatePath.convertToRecursiveGlob = async function (path) {
|
||||
if (path === "") {
|
||||
return "./**";
|
||||
}
|
||||
|
||||
path = TemplatePath.addLeadingDotSlash(path);
|
||||
|
||||
if (await TemplatePath.isDirectory(path)) {
|
||||
return path + (!path.endsWith("/") ? "/" : "") + "**";
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the extension of the path without the leading dot.
|
||||
* If the path has no extensions, the empty string is returned.
|
||||
*
|
||||
* @param {String} thePath
|
||||
* @returns {String} the path’s extension if it exists;
|
||||
* otherwise, the empty string.
|
||||
*/
|
||||
TemplatePath.getExtension = function (thePath) {
|
||||
return path.extname(thePath).replace(/^\./, "");
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the extension from a path.
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {String} extension
|
||||
* @returns {String}
|
||||
*/
|
||||
TemplatePath.removeExtension = function (path, extension = undefined) {
|
||||
if (extension === undefined) {
|
||||
return path;
|
||||
}
|
||||
|
||||
const pathExtension = TemplatePath.getExtension(path);
|
||||
if (pathExtension !== "" && extension.endsWith(pathExtension)) {
|
||||
return path.substring(0, path.lastIndexOf(pathExtension) - 1);
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Accepts a relative file path that is using a standard directory separator and
|
||||
* normalizes it using the local operating system separator.
|
||||
* e.g. `./my/dir/` stays `./my/dir/` on *nix and becomes `.\\my\\dir\\` on Windows
|
||||
*
|
||||
* @param {String} filePath
|
||||
* @returns {String} a file path with the correct local directory separator.
|
||||
*/
|
||||
TemplatePath.normalizeOperatingSystemFilePath = function (filePath, sep = "/") {
|
||||
return filePath.split(sep).join(path.sep);
|
||||
};
|
||||
|
||||
/**
|
||||
* Accepts a relative file path with the local operating system directory separator and
|
||||
* normalizes it using a forward slash directory separator. (Leaves trailing slash as-is)
|
||||
* e.g. `./my/dir/` stays `./my/dir/` on *nix and becomes `.\\my\\dir\\` on Windows
|
||||
*
|
||||
* @param {String} filePath
|
||||
* @returns {String} a file path with the correct local directory separator.
|
||||
*/
|
||||
TemplatePath.standardizeFilePath = function (filePath, sep = "/") {
|
||||
return TemplatePath.addLeadingDotSlash(filePath.split(path.sep).join(sep));
|
||||
};
|
||||
|
||||
module.exports = TemplatePath;
|
48
node_modules/@11ty/eleventy/CODE_OF_CONDUCT.md
generated
vendored
Normal file
48
node_modules/@11ty/eleventy/CODE_OF_CONDUCT.md
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
# Eleventy Community Code of Conduct
|
||||
|
||||
View the [Code of Conduct](https://www.11ty.dev/docs/code-of-conduct/) on 11ty.dev
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, chat messages, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at eleventy@zachleat.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
21
node_modules/@11ty/eleventy/LICENSE
generated
vendored
Normal file
21
node_modules/@11ty/eleventy/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017–2023 Zach Leatherman @zachleat
|
||||
|
||||
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.
|
49
node_modules/@11ty/eleventy/README.md
generated
vendored
Normal file
49
node_modules/@11ty/eleventy/README.md
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
<p align="center"><img src="https://www.11ty.dev/img/logo-github.svg" width="200" height="200" alt="eleventy Logo"></p>
|
||||
|
||||
# eleventy 🕚⚡️🎈🐀
|
||||
|
||||
A simpler static site generator. An alternative to Jekyll. Written in JavaScript. Transforms a directory of templates (of varying types) into HTML.
|
||||
|
||||
Works with HTML, Markdown, JavaScript, Liquid, Nunjucks, Handlebars, Mustache, EJS, Haml, and Pug.
|
||||
|
||||
## ➡ [Documentation](https://www.11ty.dev/docs/)
|
||||
|
||||
- Please star [this repo on GitHub](https://github.com/11ty/eleventy/)!
|
||||
- Follow us on Twitter [@eleven_ty](https://twitter.com/eleven_ty)
|
||||
- Support [11ty on Open Collective](https://opencollective.com/11ty)
|
||||
- [11ty on npm](https://www.npmjs.com/org/11ty)
|
||||
- [11ty on GitHub](https://github.com/11ty)
|
||||
- Continuous Integration:
|
||||
- [GitHub Actions](https://github.com/11ty/eleventy/actions?query=workflow%3A.github%2Fworkflows%2Fci.yml)
|
||||
|
||||
[![npm Version](https://img.shields.io/npm/v/@11ty/eleventy.svg?style=for-the-badge)](https://www.npmjs.com/package/@11ty/eleventy) [![GitHub issues](https://img.shields.io/github/issues/11ty/eleventy.svg?style=for-the-badge)](https://github.com/11ty/eleventy/issues) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=for-the-badge)](https://github.com/prettier/prettier) [![npm Downloads](https://img.shields.io/npm/dt/@11ty/eleventy.svg?style=for-the-badge)](https://www.npmjs.com/package/@11ty/eleventy)
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
npm install @11ty/eleventy --save-dev
|
||||
```
|
||||
|
||||
Read our [Getting Started guide](https://www.11ty.dev/docs/getting-started/).
|
||||
|
||||
## Tests
|
||||
|
||||
```
|
||||
npm run test
|
||||
```
|
||||
|
||||
- We use the [ava JavaScript test runner](https://github.com/avajs/ava) ([Assertions documentation](https://github.com/avajs/ava/blob/master/docs/03-assertions.md))
|
||||
- ℹ️ To keep tests fast, thou shalt try to avoid writing files in tests.
|
||||
- [Code Coverage Statistics](https://github.com/11ty/eleventy/blob/master/docs/coverage.md)
|
||||
- [Benchmark for Performance Regressions](https://github.com/11ty/eleventy-benchmark)
|
||||
|
||||
## Community Roadmap
|
||||
|
||||
- [Top Feature Requests](https://github.com/11ty/eleventy/issues?q=label%3Aneeds-votes+sort%3Areactions-%2B1-desc+label%3Aenhancement) (Add your own votes using the 👍 reaction)
|
||||
- [Documentation Requests](https://github.com/11ty/eleventy/issues?q=is%3Aissue+label%3Adocumentation+label%3Aneeds-votes+sort%3Areactions-%2B1-desc) (Add your own votes using the 👍 reaction)
|
||||
- [Top Bugs 😱](https://github.com/11ty/eleventy/issues?q=is%3Aissue+is%3Aopen+label%3Abug+sort%3Areactions-%2B1-desc) (Add your own votes using the 👍 reaction)
|
||||
- [Newest Bugs 🙀](https://github.com/11ty/eleventy/issues?q=is%3Aopen+is%3Aissue+label%3Abug)
|
||||
|
||||
## Plugins
|
||||
|
||||
See the [official docs on plugins](https://www.11ty.dev/docs/plugins/).
|
5
node_modules/@11ty/eleventy/SECURITY.md
generated
vendored
Normal file
5
node_modules/@11ty/eleventy/SECURITY.md
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please report security issues to `zach@zachleat.com`
|
132
node_modules/@11ty/eleventy/cmd.js
generated
vendored
Executable file
132
node_modules/@11ty/eleventy/cmd.js
generated
vendored
Executable file
@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env node
|
||||
const pkg = require("./package.json");
|
||||
require("please-upgrade-node")(pkg, {
|
||||
message: function (requiredVersion) {
|
||||
return (
|
||||
"Eleventy requires Node " +
|
||||
requiredVersion +
|
||||
". You will need to upgrade Node to use Eleventy!"
|
||||
);
|
||||
},
|
||||
});
|
||||
const debug = require("debug")("Eleventy:cmd");
|
||||
|
||||
const EleventyErrorHandler = require("./src/EleventyErrorHandler");
|
||||
|
||||
try {
|
||||
let errorHandler = new EleventyErrorHandler();
|
||||
const EleventyCommandCheckError = require("./src/EleventyCommandCheckError");
|
||||
const argv = require("minimist")(process.argv.slice(2), {
|
||||
string: ["input", "output", "formats", "config", "pathprefix", "port", "to"],
|
||||
boolean: [
|
||||
"quiet",
|
||||
"version",
|
||||
"watch",
|
||||
"dryrun",
|
||||
"help",
|
||||
"serve",
|
||||
"incremental",
|
||||
"ignore-initial",
|
||||
],
|
||||
default: {
|
||||
quiet: null,
|
||||
"ignore-initial": false,
|
||||
},
|
||||
unknown: function (unknownArgument) {
|
||||
throw new EleventyCommandCheckError(
|
||||
`We don’t know what '${unknownArgument}' is. Use --help to see the list of supported commands.`
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
debug("command: eleventy %o", argv);
|
||||
const Eleventy = require("./src/Eleventy");
|
||||
|
||||
process.on("unhandledRejection", (error, promise) => {
|
||||
errorHandler.fatal(error, "Unhandled rejection in promise");
|
||||
});
|
||||
process.on("uncaughtException", (error) => {
|
||||
errorHandler.fatal(error, "Uncaught exception");
|
||||
});
|
||||
process.on("rejectionHandled", (promise) => {
|
||||
errorHandler.warn(promise, "A promise rejection was handled asynchronously");
|
||||
});
|
||||
|
||||
if (argv.version) {
|
||||
console.log(Eleventy.getVersion());
|
||||
} else if (argv.help) {
|
||||
console.log(Eleventy.getHelp());
|
||||
} else {
|
||||
let elev = new Eleventy(argv.input, argv.output, {
|
||||
source: "cli",
|
||||
// --quiet and --quiet=true both resolve to true
|
||||
quietMode: argv.quiet,
|
||||
configPath: argv.config,
|
||||
pathPrefix: argv.pathprefix,
|
||||
runMode: argv.serve ? "serve" : argv.watch ? "watch" : "build",
|
||||
});
|
||||
|
||||
// reuse ErrorHandler instance in Eleventy
|
||||
errorHandler = elev.errorHandler;
|
||||
|
||||
if (argv.to === "json" || argv.to === "ndjson") {
|
||||
// override logging output
|
||||
elev.setIsVerbose(false);
|
||||
}
|
||||
|
||||
elev.setDryRun(argv.dryrun);
|
||||
elev.setIgnoreInitial(argv["ignore-initial"]);
|
||||
elev.setIncrementalBuild(argv.incremental);
|
||||
elev.setFormats(argv.formats);
|
||||
|
||||
// careful, we can’t use async/await here to error properly
|
||||
// with old node versions in `please-upgrade-node` above.
|
||||
elev
|
||||
.init()
|
||||
.then(function () {
|
||||
try {
|
||||
if (argv.serve) {
|
||||
let shouldStartServer = true;
|
||||
elev
|
||||
.watch()
|
||||
.catch((e) => {
|
||||
// Build failed but error message already displayed.
|
||||
shouldStartServer = false;
|
||||
// A build error occurred and we aren’t going to --serve
|
||||
})
|
||||
.then(function () {
|
||||
if (shouldStartServer) {
|
||||
elev.serve(argv.port);
|
||||
}
|
||||
});
|
||||
} else if (argv.watch) {
|
||||
elev.watch().catch((e) => {
|
||||
// A build error occurred and we aren’t going to --watch
|
||||
});
|
||||
} else {
|
||||
if (argv.to === "json") {
|
||||
elev.toJSON().then(function (result) {
|
||||
console.log(JSON.stringify(result, null, 2));
|
||||
});
|
||||
} else if (argv.to === "ndjson") {
|
||||
elev.toNDJSON().then(function (stream) {
|
||||
stream.pipe(process.stdout);
|
||||
});
|
||||
} else if (!argv.to || argv.to === "fs") {
|
||||
elev.write();
|
||||
} else {
|
||||
throw new EleventyCommandCheckError(
|
||||
`Invalid --to value: ${argv.to}. Supported values: \`fs\` (default), \`json\`, and \`ndjson\`.`
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
errorHandler.fatal(e, "Eleventy CLI Error");
|
||||
}
|
||||
})
|
||||
.catch(errorHandler.fatal.bind(errorHandler));
|
||||
}
|
||||
} catch (e) {
|
||||
let errorHandler = new EleventyErrorHandler();
|
||||
errorHandler.fatal(e, "Eleventy CLI Fatal Error");
|
||||
}
|
137
node_modules/@11ty/eleventy/package.json
generated
vendored
Executable file
137
node_modules/@11ty/eleventy/package.json
generated
vendored
Executable file
@ -0,0 +1,137 @@
|
||||
{
|
||||
"name": "@11ty/eleventy",
|
||||
"version": "2.0.1",
|
||||
"description": "A simpler (static) site generator.",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"main": "src/Eleventy.js",
|
||||
"types": "src/index.d.ts",
|
||||
"bin": {
|
||||
"eleventy": "./cmd.js"
|
||||
},
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/11ty"
|
||||
},
|
||||
"keywords": [
|
||||
"static-site-generator",
|
||||
"static-site",
|
||||
"ssg",
|
||||
"documentation",
|
||||
"website",
|
||||
"jekyll",
|
||||
"blog",
|
||||
"templates",
|
||||
"generator",
|
||||
"framework",
|
||||
"eleventy",
|
||||
"11ty",
|
||||
"html",
|
||||
"markdown",
|
||||
"liquid",
|
||||
"nunjucks",
|
||||
"pug",
|
||||
"handlebars",
|
||||
"mustache",
|
||||
"ejs",
|
||||
"haml"
|
||||
],
|
||||
"scripts": {
|
||||
"default": "npm run test",
|
||||
"format": "prettier src/ --write",
|
||||
"test": "npx ava --verbose",
|
||||
"lint-staged": "lint-staged",
|
||||
"coverage": "npx nyc ava && npx nyc report --reporter=json-summary && cp coverage/coverage-summary.json docs-src/_data/coverage.json && node cmd.js --config=docs-src/.eleventy.docs.js",
|
||||
"prepare": "husky install"
|
||||
},
|
||||
"author": {
|
||||
"name": "Zach Leatherman",
|
||||
"email": "zachleatherman@gmail.com",
|
||||
"url": "https://zachleat.com/"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/11ty/eleventy.git"
|
||||
},
|
||||
"bugs": "https://github.com/11ty/eleventy/issues",
|
||||
"homepage": "https://www.11ty.dev/",
|
||||
"ava": {
|
||||
"environmentVariables": {},
|
||||
"failFast": true,
|
||||
"files": [
|
||||
"./test/*.js",
|
||||
"./test/_issues/**/*test.js"
|
||||
],
|
||||
"ignoredByWatcher": [
|
||||
"./test/stubs*/**/*",
|
||||
".cache"
|
||||
]
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,css,md}": [
|
||||
"prettier --write"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@11ty/eleventy-plugin-syntaxhighlight": "^4.2.0",
|
||||
"@11ty/eleventy-plugin-vue": "1.0.0-canary.8",
|
||||
"@vue/server-renderer": "^3.2.47",
|
||||
"ava": "^5.2.0",
|
||||
"husky": "^8.0.3",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lint-staged": "^13.2.0",
|
||||
"markdown-it-emoji": "^2.0.2",
|
||||
"marked": "^4.3.0",
|
||||
"nyc": "^15.1.0",
|
||||
"prettier": "^2.8.7",
|
||||
"pretty": "^2.0.0",
|
||||
"rimraf": "^4.4.1",
|
||||
"sass": "^1.60.0",
|
||||
"vue": "^3.2.47"
|
||||
},
|
||||
"dependencies": {
|
||||
"@11ty/dependency-tree": "^2.0.1",
|
||||
"@11ty/eleventy-dev-server": "^1.0.4",
|
||||
"@11ty/eleventy-utils": "^1.0.1",
|
||||
"@11ty/lodash-custom": "^4.17.21",
|
||||
"@iarna/toml": "^2.2.5",
|
||||
"@sindresorhus/slugify": "^1.1.2",
|
||||
"bcp-47-normalize": "^1.1.1",
|
||||
"chokidar": "^3.5.3",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"debug": "^4.3.4",
|
||||
"dependency-graph": "^0.11.0",
|
||||
"ejs": "^3.1.9",
|
||||
"fast-glob": "^3.2.12",
|
||||
"graceful-fs": "^4.2.11",
|
||||
"gray-matter": "^4.0.3",
|
||||
"hamljs": "^0.6.2",
|
||||
"handlebars": "^4.7.7",
|
||||
"is-glob": "^4.0.3",
|
||||
"iso-639-1": "^2.1.15",
|
||||
"kleur": "^4.1.5",
|
||||
"liquidjs": "^10.7.0",
|
||||
"luxon": "^3.3.0",
|
||||
"markdown-it": "^13.0.1",
|
||||
"micromatch": "^4.0.5",
|
||||
"minimist": "^1.2.8",
|
||||
"moo": "^0.5.2",
|
||||
"multimatch": "^5.0.0",
|
||||
"mustache": "^4.2.0",
|
||||
"normalize-path": "^3.0.0",
|
||||
"nunjucks": "^3.2.3",
|
||||
"path-to-regexp": "^6.2.1",
|
||||
"please-upgrade-node": "^3.2.0",
|
||||
"posthtml": "^0.16.6",
|
||||
"posthtml-urls": "^1.0.0",
|
||||
"pug": "^3.0.2",
|
||||
"recursive-copy": "^2.0.14",
|
||||
"semver": "^7.3.8",
|
||||
"slugify": "^1.6.6"
|
||||
}
|
||||
}
|
52
node_modules/@11ty/eleventy/src/Benchmark.js
generated
vendored
Normal file
52
node_modules/@11ty/eleventy/src/Benchmark.js
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
const { performance } = require("perf_hooks");
|
||||
|
||||
class Benchmark {
|
||||
constructor() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
getNewTimestamp() {
|
||||
if (performance) {
|
||||
return performance.now();
|
||||
}
|
||||
return new Date().getTime();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.timeSpent = 0;
|
||||
this.timesCalled = 0;
|
||||
this.beforeTimers = [];
|
||||
}
|
||||
|
||||
incrementCount() {
|
||||
this.timesCalled++;
|
||||
}
|
||||
|
||||
// TODO(slightlyoff):
|
||||
// disable all of these hrtime requests when not benchmarking
|
||||
before() {
|
||||
this.timesCalled++;
|
||||
this.beforeTimers.push(this.getNewTimestamp());
|
||||
}
|
||||
|
||||
after() {
|
||||
if (!this.beforeTimers.length) {
|
||||
throw new Error("You called Benchmark after() without a before().");
|
||||
}
|
||||
|
||||
let before = this.beforeTimers.pop();
|
||||
if (!this.beforeTimers.length) {
|
||||
this.timeSpent += this.getNewTimestamp() - before;
|
||||
}
|
||||
}
|
||||
|
||||
getTimesCalled() {
|
||||
return this.timesCalled;
|
||||
}
|
||||
|
||||
getTotal() {
|
||||
return this.timeSpent;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Benchmark;
|
124
node_modules/@11ty/eleventy/src/BenchmarkGroup.js
generated
vendored
Normal file
124
node_modules/@11ty/eleventy/src/BenchmarkGroup.js
generated
vendored
Normal file
@ -0,0 +1,124 @@
|
||||
const ConsoleLogger = require("./Util/ConsoleLogger");
|
||||
const Benchmark = require("./Benchmark");
|
||||
const debugBenchmark = require("debug")("Eleventy:Benchmark");
|
||||
|
||||
class BenchmarkGroup {
|
||||
constructor() {
|
||||
this.benchmarks = {};
|
||||
// Warning: aggregate benchmarks automatically default to false via BenchmarkManager->getBenchmarkGroup
|
||||
this.isVerbose = true;
|
||||
this.logger = new ConsoleLogger(this.isVerbose);
|
||||
this.minimumThresholdMs = 0;
|
||||
this.minimumThresholdPercent = 8;
|
||||
}
|
||||
|
||||
setIsVerbose(isVerbose) {
|
||||
this.isVerbose = isVerbose;
|
||||
this.logger.isVerbose = isVerbose;
|
||||
}
|
||||
|
||||
reset() {
|
||||
for (var type in this.benchmarks) {
|
||||
this.benchmarks[type].reset();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO use addAsync everywhere instead
|
||||
add(type, callback) {
|
||||
let benchmark = (this.benchmarks[type] = new Benchmark());
|
||||
|
||||
return function (...args) {
|
||||
benchmark.before();
|
||||
let ret = callback.call(this, ...args);
|
||||
benchmark.after();
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
// callback must return a promise
|
||||
// async addAsync(type, callback) {
|
||||
// let benchmark = (this.benchmarks[type] = new Benchmark());
|
||||
|
||||
// benchmark.before();
|
||||
// // don’t await here.
|
||||
// let promise = callback.call(this);
|
||||
// promise.then(function() {
|
||||
// benchmark.after();
|
||||
// });
|
||||
// return promise;
|
||||
// }
|
||||
|
||||
setMinimumThresholdMs(minimumThresholdMs) {
|
||||
let val = parseInt(minimumThresholdMs, 10);
|
||||
if (isNaN(val)) {
|
||||
throw new Error("`setMinimumThresholdMs` expects a number argument.");
|
||||
}
|
||||
this.minimumThresholdMs = val;
|
||||
}
|
||||
|
||||
setMinimumThresholdPercent(minimumThresholdPercent) {
|
||||
let val = parseInt(minimumThresholdPercent, 10);
|
||||
if (isNaN(val)) {
|
||||
throw new Error(
|
||||
"`setMinimumThresholdPercent` expects a number argument."
|
||||
);
|
||||
}
|
||||
this.minimumThresholdPercent = val;
|
||||
}
|
||||
|
||||
has(type) {
|
||||
return !!this.benchmarks[type];
|
||||
}
|
||||
|
||||
get(type) {
|
||||
if (!this.benchmarks[type]) {
|
||||
this.benchmarks[type] = new Benchmark();
|
||||
}
|
||||
return this.benchmarks[type];
|
||||
}
|
||||
|
||||
padNumber(num, length) {
|
||||
if (("" + num).length >= length) {
|
||||
return num;
|
||||
}
|
||||
|
||||
let prefix = new Array(length + 1).join(" ");
|
||||
return (prefix + num).substr(-1 * length);
|
||||
}
|
||||
|
||||
finish(label, totalTimeSpent) {
|
||||
for (var type in this.benchmarks) {
|
||||
let bench = this.benchmarks[type];
|
||||
let isAbsoluteMinimumComparison = this.minimumThresholdMs > 0;
|
||||
let totalForBenchmark = bench.getTotal();
|
||||
let percent = Math.round((totalForBenchmark * 100) / totalTimeSpent);
|
||||
let callCount = bench.getTimesCalled();
|
||||
|
||||
let output = {
|
||||
ms: this.padNumber(totalForBenchmark.toFixed(0), 6),
|
||||
percent: this.padNumber(percent, 3),
|
||||
calls: this.padNumber(callCount, 5),
|
||||
};
|
||||
let str = `Benchmark ${output.ms}ms ${output.percent}% ${output.calls}× (${label}) ${type}`;
|
||||
|
||||
if (
|
||||
(isAbsoluteMinimumComparison &&
|
||||
totalForBenchmark >= this.minimumThresholdMs) ||
|
||||
percent > this.minimumThresholdPercent
|
||||
) {
|
||||
this.logger.warn(str);
|
||||
}
|
||||
|
||||
// Opt out of logging if low count (1× or 2×) or 0ms / 1%
|
||||
if (
|
||||
totalForBenchmark.toFixed(0) > 1 || // more than 1ms
|
||||
callCount > 2 || // more than 2×
|
||||
percent > 1 // more than 1%
|
||||
) {
|
||||
debugBenchmark(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BenchmarkGroup;
|
72
node_modules/@11ty/eleventy/src/BenchmarkManager.js
generated
vendored
Normal file
72
node_modules/@11ty/eleventy/src/BenchmarkManager.js
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
const BenchmarkGroup = require("./BenchmarkGroup");
|
||||
const { performance } = require("perf_hooks");
|
||||
|
||||
// TODO this should not be a singleton, it belongs in the config or somewhere on the Eleventy instance.
|
||||
|
||||
class BenchmarkManager {
|
||||
constructor() {
|
||||
this.benchmarkGroups = {};
|
||||
this.isVerbose = true;
|
||||
this.start = this.getNewTimestamp();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.start = this.getNewTimestamp();
|
||||
|
||||
for (var j in this.benchmarkGroups) {
|
||||
this.benchmarkGroups[j].reset();
|
||||
}
|
||||
}
|
||||
|
||||
getNewTimestamp() {
|
||||
if (performance) {
|
||||
return performance.now();
|
||||
}
|
||||
return new Date().getTime();
|
||||
}
|
||||
|
||||
setVerboseOutput(isVerbose) {
|
||||
this.isVerbose = !!isVerbose;
|
||||
}
|
||||
|
||||
hasBenchmarkGroup(name) {
|
||||
return name in this.benchmarkGroups;
|
||||
}
|
||||
|
||||
getBenchmarkGroup(name) {
|
||||
if (!this.benchmarkGroups[name]) {
|
||||
this.benchmarkGroups[name] = new BenchmarkGroup();
|
||||
|
||||
// Special behavior for aggregate benchmarks
|
||||
// so they don’t console.log every time
|
||||
if (name === "Aggregate") {
|
||||
this.benchmarkGroups[name].setIsVerbose(false);
|
||||
} else {
|
||||
this.benchmarkGroups[name].setIsVerbose(this.isVerbose);
|
||||
}
|
||||
}
|
||||
|
||||
return this.benchmarkGroups[name];
|
||||
}
|
||||
|
||||
getAll() {
|
||||
return this.benchmarkGroups;
|
||||
}
|
||||
|
||||
get(name) {
|
||||
if (name) {
|
||||
return this.getBenchmarkGroup(name);
|
||||
}
|
||||
|
||||
return this.getAll();
|
||||
}
|
||||
|
||||
finish() {
|
||||
let totalTimeSpentBenchmarking = this.getNewTimestamp() - this.start;
|
||||
for (var j in this.benchmarkGroups) {
|
||||
this.benchmarkGroups[j].finish(j, totalTimeSpentBenchmarking);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BenchmarkManager;
|
116
node_modules/@11ty/eleventy/src/ComputedData.js
generated
vendored
Normal file
116
node_modules/@11ty/eleventy/src/ComputedData.js
generated
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
const { set: lodashSet, get: lodashGet } = require("@11ty/lodash-custom");
|
||||
|
||||
const ComputedDataQueue = require("./ComputedDataQueue");
|
||||
const ComputedDataTemplateString = require("./ComputedDataTemplateString");
|
||||
const ComputedDataProxy = require("./ComputedDataProxy");
|
||||
|
||||
const debug = require("debug")("Eleventy:ComputedData");
|
||||
|
||||
class ComputedData {
|
||||
constructor(config) {
|
||||
this.computed = {};
|
||||
this.symbolParseFunctions = {};
|
||||
this.templateStringKeyLookup = {};
|
||||
this.computedKeys = new Set();
|
||||
this.declaredDependencies = {};
|
||||
this.queue = new ComputedDataQueue();
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
add(key, renderFn, declaredDependencies = [], symbolParseFn = undefined) {
|
||||
this.computedKeys.add(key);
|
||||
this.declaredDependencies[key] = declaredDependencies;
|
||||
|
||||
// bind config filters/JS functions
|
||||
if (typeof renderFn === "function") {
|
||||
let fns = {};
|
||||
// TODO bug? no access to non-universal config things?
|
||||
if (this.config) {
|
||||
fns = this.config.javascriptFunctions;
|
||||
}
|
||||
renderFn = renderFn.bind(fns);
|
||||
}
|
||||
|
||||
lodashSet(this.computed, key, renderFn);
|
||||
|
||||
if (symbolParseFn) {
|
||||
lodashSet(this.symbolParseFunctions, key, symbolParseFn);
|
||||
}
|
||||
}
|
||||
|
||||
addTemplateString(key, renderFn, declaredDependencies = [], symbolParseFn = undefined) {
|
||||
this.add(key, renderFn, declaredDependencies, symbolParseFn);
|
||||
this.templateStringKeyLookup[key] = true;
|
||||
}
|
||||
|
||||
async resolveVarOrder(data) {
|
||||
let proxyByTemplateString = new ComputedDataTemplateString(this.computedKeys);
|
||||
let proxyByProxy = new ComputedDataProxy(this.computedKeys);
|
||||
|
||||
for (let key of this.computedKeys) {
|
||||
let computed = lodashGet(this.computed, key);
|
||||
|
||||
if (typeof computed !== "function") {
|
||||
// add nodes for non functions (primitives like booleans, etc)
|
||||
// This will not handle template strings, as they are normalized to functions
|
||||
this.queue.addNode(key);
|
||||
} else {
|
||||
this.queue.uses(key, this.declaredDependencies[key]);
|
||||
|
||||
let symbolParseFn = lodashGet(this.symbolParseFunctions, key);
|
||||
let varsUsed = [];
|
||||
if (symbolParseFn) {
|
||||
// use the parseForSymbols function in the TemplateEngine
|
||||
varsUsed = symbolParseFn();
|
||||
} else if (symbolParseFn !== false) {
|
||||
// skip resolution is this is false (just use declaredDependencies)
|
||||
let isTemplateString = !!this.templateStringKeyLookup[key];
|
||||
let proxy = isTemplateString ? proxyByTemplateString : proxyByProxy;
|
||||
varsUsed = await proxy.findVarsUsed(computed, data);
|
||||
}
|
||||
|
||||
debug("%o accesses %o variables", key, varsUsed);
|
||||
let filteredVarsUsed = varsUsed.filter((varUsed) => {
|
||||
return (
|
||||
(varUsed !== key && this.computedKeys.has(varUsed)) ||
|
||||
varUsed.startsWith("collections.")
|
||||
);
|
||||
});
|
||||
this.queue.uses(key, filteredVarsUsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async _setupDataEntry(data, order) {
|
||||
debug("Computed data order of execution: %o", order);
|
||||
for (let key of order) {
|
||||
let computed = lodashGet(this.computed, key);
|
||||
|
||||
if (typeof computed === "function") {
|
||||
let ret = await computed(data);
|
||||
lodashSet(data, key, ret);
|
||||
} else if (computed !== undefined) {
|
||||
lodashSet(data, key, computed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async setupData(data, orderFilter) {
|
||||
await this.resolveVarOrder(data);
|
||||
|
||||
await this.processRemainingData(data, orderFilter);
|
||||
}
|
||||
|
||||
async processRemainingData(data, orderFilter) {
|
||||
// process all variables
|
||||
let order = this.queue.getOrder();
|
||||
if (orderFilter && typeof orderFilter === "function") {
|
||||
order = order.filter(orderFilter.bind(this.queue));
|
||||
}
|
||||
|
||||
await this._setupDataEntry(data, order);
|
||||
this.queue.markComputed(order);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ComputedData;
|
129
node_modules/@11ty/eleventy/src/ComputedDataProxy.js
generated
vendored
Normal file
129
node_modules/@11ty/eleventy/src/ComputedDataProxy.js
generated
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
const { set: lodashSet, get: lodashGet } = require("@11ty/lodash-custom");
|
||||
const { isPlainObject } = require("@11ty/eleventy-utils");
|
||||
|
||||
/* Calculates computed data using Proxies */
|
||||
class ComputedDataProxy {
|
||||
constructor(computedKeys) {
|
||||
if (Array.isArray(computedKeys)) {
|
||||
this.computedKeys = new Set(computedKeys);
|
||||
} else {
|
||||
this.computedKeys = computedKeys;
|
||||
}
|
||||
}
|
||||
|
||||
isArrayOrPlainObject(data) {
|
||||
return Array.isArray(data) || isPlainObject(data);
|
||||
}
|
||||
|
||||
getProxyData(data, keyRef) {
|
||||
// WARNING: SIDE EFFECTS
|
||||
// Set defaults for keys not already set on parent data
|
||||
|
||||
// TODO should make another effort to get rid of this,
|
||||
// See the ProxyWrap util for more proxy handlers that will likely fix this
|
||||
let undefinedValue = "__11TY_UNDEFINED__";
|
||||
if (this.computedKeys) {
|
||||
for (let key of this.computedKeys) {
|
||||
if (lodashGet(data, key, undefinedValue) === undefinedValue) {
|
||||
lodashSet(data, key, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let proxyData = this._getProxyData(data, keyRef);
|
||||
return proxyData;
|
||||
}
|
||||
|
||||
_getProxyForObject(dataObj, keyRef, parentKey = "") {
|
||||
return new Proxy(
|
||||
{},
|
||||
{
|
||||
get: (obj, key) => {
|
||||
if (typeof key !== "string") {
|
||||
return obj[key];
|
||||
}
|
||||
|
||||
let newKey = `${parentKey ? `${parentKey}.` : ""}${key}`;
|
||||
|
||||
// Issue #1137
|
||||
// Special case for Collections, always return an Array for collection keys
|
||||
// so they it works fine with Array methods like `filter`, `map`, etc
|
||||
if (newKey === "collections") {
|
||||
keyRef.add(newKey);
|
||||
return new Proxy(
|
||||
{},
|
||||
{
|
||||
get: (target, key) => {
|
||||
if (typeof key === "string") {
|
||||
keyRef.add(`collections.${key}`);
|
||||
return [];
|
||||
}
|
||||
return target[key];
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
let newData = this._getProxyData(dataObj[key], keyRef, newKey);
|
||||
if (!this.isArrayOrPlainObject(newData)) {
|
||||
keyRef.add(newKey);
|
||||
}
|
||||
return newData;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
_getProxyForArray(dataArr, keyRef, parentKey = "") {
|
||||
return new Proxy(new Array(dataArr.length), {
|
||||
get: (obj, key) => {
|
||||
if (Array.prototype.hasOwnProperty(key)) {
|
||||
// remove `filter`, `constructor`, `map`, etc
|
||||
keyRef.add(parentKey);
|
||||
return obj[key];
|
||||
}
|
||||
|
||||
// Hm, this needs to be better
|
||||
if (key === "then") {
|
||||
keyRef.add(parentKey);
|
||||
return;
|
||||
}
|
||||
|
||||
let newKey = `${parentKey}[${key}]`;
|
||||
let newData = this._getProxyData(dataArr[key], keyRef, newKey);
|
||||
if (!this.isArrayOrPlainObject(newData)) {
|
||||
keyRef.add(newKey);
|
||||
}
|
||||
return newData;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
_getProxyData(data, keyRef, parentKey = "") {
|
||||
if (isPlainObject(data)) {
|
||||
return this._getProxyForObject(data, keyRef, parentKey);
|
||||
} else if (Array.isArray(data)) {
|
||||
return this._getProxyForArray(data, keyRef, parentKey);
|
||||
}
|
||||
|
||||
// everything else!
|
||||
return data;
|
||||
}
|
||||
|
||||
async findVarsUsed(fn, data = {}) {
|
||||
let keyRef = new Set();
|
||||
|
||||
// careful, logging proxyData will mess with test results!
|
||||
let proxyData = this.getProxyData(data, keyRef);
|
||||
|
||||
// squelch console logs for this fake proxy data pass 😅
|
||||
// let savedLog = console.log;
|
||||
// console.log = () => {};
|
||||
await fn(proxyData);
|
||||
// console.log = savedLog;
|
||||
|
||||
return Array.from(keyRef);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ComputedDataProxy;
|
64
node_modules/@11ty/eleventy/src/ComputedDataQueue.js
generated
vendored
Normal file
64
node_modules/@11ty/eleventy/src/ComputedDataQueue.js
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
const DependencyGraph = require("dependency-graph").DepGraph;
|
||||
|
||||
/* Keeps track of the dependency graph between computed data variables
|
||||
* Removes keys from the graph when they are computed.
|
||||
*/
|
||||
class ComputedDataQueue {
|
||||
constructor() {
|
||||
this.graph = new DependencyGraph();
|
||||
}
|
||||
|
||||
getOrder() {
|
||||
return this.graph.overallOrder();
|
||||
}
|
||||
|
||||
getOrderFor(name) {
|
||||
return this.graph.dependenciesOf(name);
|
||||
}
|
||||
|
||||
getDependsOn(name) {
|
||||
return this.graph.dependantsOf(name);
|
||||
}
|
||||
|
||||
isUsesStartsWith(name, prefix) {
|
||||
if (name.startsWith(prefix)) {
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
this.graph.dependenciesOf(name).filter((entry) => {
|
||||
return entry.startsWith(prefix);
|
||||
}).length > 0
|
||||
);
|
||||
}
|
||||
|
||||
addNode(name) {
|
||||
if (!this.graph.hasNode(name)) {
|
||||
this.graph.addNode(name);
|
||||
}
|
||||
}
|
||||
|
||||
_uses(graph, name, varsUsed = []) {
|
||||
if (!graph.hasNode(name)) {
|
||||
graph.addNode(name);
|
||||
}
|
||||
|
||||
for (let varUsed of varsUsed) {
|
||||
if (!graph.hasNode(varUsed)) {
|
||||
graph.addNode(varUsed);
|
||||
}
|
||||
graph.addDependency(name, varUsed);
|
||||
}
|
||||
}
|
||||
|
||||
uses(name, varsUsed = []) {
|
||||
this._uses(this.graph, name, varsUsed);
|
||||
}
|
||||
|
||||
markComputed(varsComputed = []) {
|
||||
for (let varComputed of varsComputed) {
|
||||
this.graph.removeNode(varComputed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ComputedDataQueue;
|
68
node_modules/@11ty/eleventy/src/ComputedDataTemplateString.js
generated
vendored
Normal file
68
node_modules/@11ty/eleventy/src/ComputedDataTemplateString.js
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
const { set: lodashSet } = require("@11ty/lodash-custom");
|
||||
|
||||
const debug = require("debug")("Eleventy:ComputedDataTemplateString");
|
||||
|
||||
/* Calculates computed data in Template Strings.
|
||||
* Ideally we would use the Proxy approach but it doesn’t work
|
||||
* in some template languages that visit all available data even if
|
||||
* it isn’t used in the template (Nunjucks)
|
||||
*/
|
||||
class ComputedDataTemplateString {
|
||||
constructor(computedKeys) {
|
||||
if (Array.isArray(computedKeys)) {
|
||||
this.computedKeys = new Set(computedKeys);
|
||||
} else {
|
||||
this.computedKeys = computedKeys;
|
||||
}
|
||||
|
||||
// is this ¯\_(lisp)_/¯
|
||||
// must be strings that won’t be escaped by template languages
|
||||
this.prefix = "(((11ty(((";
|
||||
this.suffix = ")))11ty)))";
|
||||
}
|
||||
|
||||
getProxyData() {
|
||||
let proxyData = {};
|
||||
|
||||
// use these special strings as a workaround to check the rendered output
|
||||
// can’t use proxies here as some template languages trigger proxy for all
|
||||
// keys in data
|
||||
for (let key of this.computedKeys) {
|
||||
// TODO don’t allow to set eleventyComputed.page? other disallowed computed things?
|
||||
lodashSet(proxyData, key, this.prefix + key + this.suffix);
|
||||
}
|
||||
|
||||
return proxyData;
|
||||
}
|
||||
|
||||
findVarsInOutput(output = "") {
|
||||
let vars = new Set();
|
||||
let splits = output.split(this.prefix);
|
||||
for (let split of splits) {
|
||||
let varName = split.slice(0, split.indexOf(this.suffix) < 0 ? 0 : split.indexOf(this.suffix));
|
||||
if (varName) {
|
||||
vars.add(varName);
|
||||
}
|
||||
}
|
||||
return Array.from(vars);
|
||||
}
|
||||
|
||||
async findVarsUsed(fn) {
|
||||
let proxyData = this.getProxyData();
|
||||
let output;
|
||||
// Mitigation for #1061, errors with filters in the first pass shouldn’t fail the whole thing.
|
||||
try {
|
||||
output = await fn(proxyData);
|
||||
} catch (e) {
|
||||
debug("Computed Data first pass data resolution error: %o", e);
|
||||
}
|
||||
|
||||
// page.outputPath on serverless urls returns false.
|
||||
if (typeof output === "string") {
|
||||
return this.findVarsInOutput(output);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ComputedDataTemplateString;
|
1245
node_modules/@11ty/eleventy/src/Eleventy.js
generated
vendored
Normal file
1245
node_modules/@11ty/eleventy/src/Eleventy.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
23
node_modules/@11ty/eleventy/src/EleventyBaseError.js
generated
vendored
Normal file
23
node_modules/@11ty/eleventy/src/EleventyBaseError.js
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* This class serves as basis for all Eleventy-specific errors.
|
||||
*/
|
||||
class EleventyBaseError extends Error {
|
||||
/**
|
||||
* @param {string} message - The error message to display.
|
||||
* @param {Error} originalError - The original error caught.
|
||||
*/
|
||||
constructor(message, originalError) {
|
||||
super(message);
|
||||
|
||||
/** @type {string} - The error message to display. */
|
||||
this.name = this.constructor.name;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
|
||||
if (originalError) {
|
||||
/** @type {Error} - The original error caught. */
|
||||
this.originalError = originalError;
|
||||
}
|
||||
}
|
||||
}
|
||||
module.exports = EleventyBaseError;
|
3
node_modules/@11ty/eleventy/src/EleventyCommandCheckError.js
generated
vendored
Normal file
3
node_modules/@11ty/eleventy/src/EleventyCommandCheckError.js
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
const EleventyBaseError = require("./EleventyBaseError");
|
||||
class EleventyCommandCheckError extends EleventyBaseError {}
|
||||
module.exports = EleventyCommandCheckError;
|
121
node_modules/@11ty/eleventy/src/EleventyErrorHandler.js
generated
vendored
Normal file
121
node_modules/@11ty/eleventy/src/EleventyErrorHandler.js
generated
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
const ConsoleLogger = require("./Util/ConsoleLogger");
|
||||
const EleventyErrorUtil = require("./EleventyErrorUtil");
|
||||
const debug = require("debug")("Eleventy:EleventyErrorHandler");
|
||||
|
||||
class EleventyErrorHandler {
|
||||
constructor() {
|
||||
this._isVerbose = true;
|
||||
}
|
||||
|
||||
get isVerbose() {
|
||||
return this._isVerbose;
|
||||
}
|
||||
|
||||
set isVerbose(verbose) {
|
||||
this._isVerbose = !!verbose;
|
||||
this.logger.isVerbose = !!verbose;
|
||||
}
|
||||
|
||||
get logger() {
|
||||
if (!this._logger) {
|
||||
this._logger = new ConsoleLogger();
|
||||
this._logger.isVerbose = this.isVerbose;
|
||||
}
|
||||
|
||||
return this._logger;
|
||||
}
|
||||
|
||||
set logger(logger) {
|
||||
this._logger = logger;
|
||||
}
|
||||
|
||||
warn(e, msg) {
|
||||
if (msg) {
|
||||
this.initialMessage(msg, "warn", "yellow");
|
||||
}
|
||||
this.log(e, "warn");
|
||||
}
|
||||
|
||||
fatal(e, msg) {
|
||||
this.error(e, msg);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
|
||||
error(e, msg) {
|
||||
if (msg) {
|
||||
this.initialMessage(msg, "error", "red", true);
|
||||
}
|
||||
this.log(e, "error", undefined, true);
|
||||
}
|
||||
|
||||
//https://nodejs.org/api/process.html
|
||||
log(e, type = "log", chalkColor = "", forceToConsole = false) {
|
||||
let errorCount = 0;
|
||||
let errorCountRef = e;
|
||||
while (errorCountRef) {
|
||||
errorCount++;
|
||||
errorCountRef = errorCountRef.originalError;
|
||||
}
|
||||
|
||||
let ref = e;
|
||||
let index = 1;
|
||||
while (ref) {
|
||||
let nextRef = ref.originalError;
|
||||
if (!nextRef && EleventyErrorUtil.hasEmbeddedError(ref.message)) {
|
||||
nextRef = EleventyErrorUtil.deconvertErrorToObject(ref);
|
||||
}
|
||||
|
||||
this.logger.message(
|
||||
`${errorCount > 1 ? `${index}. ` : ""}${(
|
||||
EleventyErrorUtil.cleanMessage(ref.message) ||
|
||||
"(No error message provided)"
|
||||
).trim()} (via ${ref.name})`,
|
||||
type,
|
||||
chalkColor,
|
||||
forceToConsole
|
||||
);
|
||||
|
||||
if (process.env.DEBUG) {
|
||||
debug(`(${type} stack): ${ref.stack}`);
|
||||
} else if (!nextRef) {
|
||||
// last error in the loop
|
||||
let prefix = " ";
|
||||
|
||||
// remove duplicate error messages if the stack contains the original message output above
|
||||
let stackStr = ref.stack || "";
|
||||
if (e.removeDuplicateErrorStringFromOutput) {
|
||||
stackStr = stackStr.replace(
|
||||
`${ref.name}: ${ref.message}`,
|
||||
"(Repeated output has been truncated…)"
|
||||
);
|
||||
}
|
||||
this.logger.message(
|
||||
"\nOriginal error stack trace: " + stackStr,
|
||||
type,
|
||||
chalkColor,
|
||||
forceToConsole
|
||||
);
|
||||
}
|
||||
ref = nextRef;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
initialMessage(
|
||||
message,
|
||||
type = "log",
|
||||
chalkColor = "blue",
|
||||
forceToConsole = false
|
||||
) {
|
||||
if (message) {
|
||||
this.logger.message(
|
||||
message + ":" + (process.env.DEBUG ? "" : " (more in DEBUG output)"),
|
||||
type,
|
||||
chalkColor,
|
||||
forceToConsole
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyErrorHandler;
|
80
node_modules/@11ty/eleventy/src/EleventyErrorUtil.js
generated
vendored
Normal file
80
node_modules/@11ty/eleventy/src/EleventyErrorUtil.js
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
const TemplateContentPrematureUseError = require("./Errors/TemplateContentPrematureUseError");
|
||||
|
||||
/* Hack to workaround the variety of error handling schemes in template languages */
|
||||
class EleventyErrorUtil {
|
||||
static get prefix() {
|
||||
return ">>>>>11ty>>>>>";
|
||||
}
|
||||
static get suffix() {
|
||||
return "<<<<<11ty<<<<<";
|
||||
}
|
||||
|
||||
static hasEmbeddedError(msg) {
|
||||
if (!msg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
msg.indexOf(EleventyErrorUtil.prefix) > -1 &&
|
||||
msg.indexOf(EleventyErrorUtil.suffix) > -1
|
||||
);
|
||||
}
|
||||
|
||||
static cleanMessage(msg) {
|
||||
if (!msg) {
|
||||
return "";
|
||||
}
|
||||
if (!EleventyErrorUtil.hasEmbeddedError(msg)) {
|
||||
return "" + msg;
|
||||
}
|
||||
|
||||
return msg.slice(
|
||||
0,
|
||||
msg.indexOf(EleventyErrorUtil.prefix) < 0
|
||||
? 0
|
||||
: msg.indexOf(EleventyErrorUtil.prefix)
|
||||
);
|
||||
}
|
||||
|
||||
static deconvertErrorToObject(error) {
|
||||
if (!error || !error.message) {
|
||||
throw new Error(`Could not convert error object from: ${error}`);
|
||||
}
|
||||
if (!EleventyErrorUtil.hasEmbeddedError(error.message)) {
|
||||
return error;
|
||||
}
|
||||
|
||||
let msg = error.message;
|
||||
let objectString = msg.substring(
|
||||
msg.indexOf(EleventyErrorUtil.prefix) + EleventyErrorUtil.prefix.length,
|
||||
msg.lastIndexOf(EleventyErrorUtil.suffix)
|
||||
);
|
||||
let obj = JSON.parse(objectString);
|
||||
obj.name = error.name;
|
||||
return obj;
|
||||
}
|
||||
|
||||
// pass an error through a random template engine’s error handling unscathed
|
||||
static convertErrorToString(error) {
|
||||
return (
|
||||
EleventyErrorUtil.prefix +
|
||||
JSON.stringify({ message: error.message, stack: error.stack }) +
|
||||
EleventyErrorUtil.suffix
|
||||
);
|
||||
}
|
||||
|
||||
static isPrematureTemplateContentError(e) {
|
||||
// TODO the rest of the template engines
|
||||
return (
|
||||
e instanceof TemplateContentPrematureUseError ||
|
||||
(e.originalError &&
|
||||
(e.originalError.name === "RenderError" ||
|
||||
e.originalError.name === "UndefinedVariableError") &&
|
||||
e.originalError.originalError instanceof
|
||||
TemplateContentPrematureUseError) || // Liquid
|
||||
(e.message || "").indexOf("TemplateContentPrematureUseError") > -1
|
||||
); // Nunjucks
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyErrorUtil;
|
268
node_modules/@11ty/eleventy/src/EleventyExtensionMap.js
generated
vendored
Normal file
268
node_modules/@11ty/eleventy/src/EleventyExtensionMap.js
generated
vendored
Normal file
@ -0,0 +1,268 @@
|
||||
const { TemplatePath } = require("@11ty/eleventy-utils");
|
||||
|
||||
const TemplateEngineManager = require("./TemplateEngineManager");
|
||||
const TemplateConfig = require("./TemplateConfig");
|
||||
const EleventyBaseError = require("./EleventyBaseError");
|
||||
|
||||
class EleventyExtensionMapConfigError extends EleventyBaseError {}
|
||||
|
||||
class EleventyExtensionMap {
|
||||
constructor(formatKeys, config) {
|
||||
if (!config) {
|
||||
throw new EleventyExtensionMapConfigError("Missing `config` argument.");
|
||||
}
|
||||
if (config instanceof TemplateConfig) {
|
||||
this.eleventyConfig = config;
|
||||
}
|
||||
this._config = config;
|
||||
|
||||
this.formatKeys = formatKeys;
|
||||
|
||||
this.setFormats(formatKeys);
|
||||
|
||||
this._spiderJsDepsCache = {};
|
||||
}
|
||||
|
||||
setFormats(formatKeys = []) {
|
||||
this.unfilteredFormatKeys = formatKeys.map(function (key) {
|
||||
return key.trim().toLowerCase();
|
||||
});
|
||||
|
||||
this.validTemplateLanguageKeys = this.unfilteredFormatKeys.filter((key) =>
|
||||
this.hasExtension(key)
|
||||
);
|
||||
|
||||
this.passthroughCopyKeys = this.unfilteredFormatKeys.filter((key) => !this.hasExtension(key));
|
||||
}
|
||||
|
||||
set config(cfg) {
|
||||
this._config = cfg;
|
||||
}
|
||||
|
||||
get config() {
|
||||
if (this._config instanceof TemplateConfig) {
|
||||
return this._config.getConfig();
|
||||
}
|
||||
return this._config;
|
||||
}
|
||||
|
||||
get engineManager() {
|
||||
if (!this._engineManager) {
|
||||
this._engineManager = new TemplateEngineManager(this.eleventyConfig);
|
||||
}
|
||||
|
||||
return this._engineManager;
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.engineManager.reset();
|
||||
}
|
||||
|
||||
/* Used for layout path resolution */
|
||||
getFileList(path, dir) {
|
||||
if (!path) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let files = [];
|
||||
this.validTemplateLanguageKeys.forEach(
|
||||
function (key) {
|
||||
this.getExtensionsFromKey(key).forEach(function (extension) {
|
||||
files.push((dir ? dir + "/" : "") + path + "." + extension);
|
||||
});
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
// Warning: this would false positive on an include, but is only used
|
||||
// on paths found from the file system glob search.
|
||||
// TODO: Method name might just need to be renamed to something more accurate.
|
||||
isFullTemplateFilePath(path) {
|
||||
for (let extension of this.validTemplateLanguageKeys) {
|
||||
if (path.endsWith(`.${extension}`)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getCustomExtensionEntry(extension) {
|
||||
if (!this.config.extensionMap) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let entry of this.config.extensionMap) {
|
||||
if (entry.extension === extension) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getValidExtensionsForPath(path) {
|
||||
let extensions = new Set();
|
||||
for (let extension in this.extensionToKeyMap) {
|
||||
if (path.endsWith(`.${extension}`)) {
|
||||
extensions.add(extension);
|
||||
}
|
||||
}
|
||||
|
||||
// if multiple extensions are valid, sort from longest to shortest
|
||||
// e.g. .11ty.js and .js
|
||||
let sorted = Array.from(extensions)
|
||||
.filter((extension) => this.validTemplateLanguageKeys.includes(extension))
|
||||
.sort((a, b) => b.length - a.length);
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
shouldSpiderJavaScriptDependencies(path) {
|
||||
let extensions = this.getValidExtensionsForPath(path);
|
||||
for (let extension of extensions) {
|
||||
if (extension in this._spiderJsDepsCache) {
|
||||
return this._spiderJsDepsCache[extension];
|
||||
}
|
||||
|
||||
let cls = this.engineManager.getEngineClassByExtension(extension);
|
||||
if (cls) {
|
||||
let entry = this.getCustomExtensionEntry(extension);
|
||||
let shouldSpider = cls.shouldSpiderJavaScriptDependencies(entry);
|
||||
this._spiderJsDepsCache[extension] = shouldSpider;
|
||||
return shouldSpider;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
getPassthroughCopyGlobs(inputDir) {
|
||||
return this._getGlobs(this.passthroughCopyKeys, inputDir);
|
||||
}
|
||||
|
||||
getValidGlobs(inputDir) {
|
||||
return this._getGlobs(this.validTemplateLanguageKeys, inputDir);
|
||||
}
|
||||
|
||||
getGlobs(inputDir) {
|
||||
return this._getGlobs(this.unfilteredFormatKeys, inputDir);
|
||||
}
|
||||
|
||||
_getGlobs(formatKeys, inputDir) {
|
||||
let dir = TemplatePath.convertToRecursiveGlobSync(inputDir);
|
||||
let extensions = [];
|
||||
for (let key of formatKeys) {
|
||||
if (this.hasExtension(key)) {
|
||||
for (let extension of this.getExtensionsFromKey(key)) {
|
||||
extensions.push(extension);
|
||||
}
|
||||
} else {
|
||||
extensions.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
let globs = [];
|
||||
if (extensions.length === 1) {
|
||||
globs.push(`${dir}/*.${extensions[0]}`);
|
||||
} else if (extensions.length > 1) {
|
||||
globs.push(`${dir}/*.{${extensions.join(",")}}`);
|
||||
}
|
||||
|
||||
return globs;
|
||||
}
|
||||
|
||||
hasExtension(key) {
|
||||
for (var extension in this.extensionToKeyMap) {
|
||||
if (this.extensionToKeyMap[extension] === key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getExtensionsFromKey(key) {
|
||||
let extensions = [];
|
||||
for (var extension in this.extensionToKeyMap) {
|
||||
if (this.extensionToKeyMap[extension] === key) {
|
||||
extensions.push(extension);
|
||||
}
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
// Only `addExtension` configuration API extensions
|
||||
getExtensionEntriesFromKey(key) {
|
||||
let entries = [];
|
||||
if ("extensionMap" in this.config) {
|
||||
for (let entry of this.config.extensionMap) {
|
||||
if (entry.key === key) {
|
||||
entries.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
hasEngine(pathOrKey) {
|
||||
return !!this.getKey(pathOrKey);
|
||||
}
|
||||
|
||||
getKey(pathOrKey) {
|
||||
pathOrKey = (pathOrKey || "").toLowerCase();
|
||||
|
||||
for (var extension in this.extensionToKeyMap) {
|
||||
let key = this.extensionToKeyMap[extension];
|
||||
if (pathOrKey === extension) {
|
||||
return key;
|
||||
} else if (pathOrKey.endsWith("." + extension)) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removeTemplateExtension(path) {
|
||||
for (var extension in this.extensionToKeyMap) {
|
||||
if (path === extension || path.endsWith("." + extension)) {
|
||||
return path.slice(
|
||||
0,
|
||||
path.length - 1 - extension.length < 0 ? 0 : path.length - 1 - extension.length
|
||||
);
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
// keys are file extensions
|
||||
// values are template language keys
|
||||
get extensionToKeyMap() {
|
||||
if (!this._extensionToKeyMap) {
|
||||
this._extensionToKeyMap = {
|
||||
ejs: "ejs",
|
||||
md: "md",
|
||||
html: "html",
|
||||
hbs: "hbs",
|
||||
mustache: "mustache",
|
||||
haml: "haml",
|
||||
pug: "pug",
|
||||
njk: "njk",
|
||||
liquid: "liquid",
|
||||
"11ty.js": "11ty.js",
|
||||
"11ty.cjs": "11ty.js",
|
||||
};
|
||||
|
||||
if ("extensionMap" in this.config) {
|
||||
for (let entry of this.config.extensionMap) {
|
||||
this._extensionToKeyMap[entry.extension] = entry.key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this._extensionToKeyMap;
|
||||
}
|
||||
|
||||
getReadableFileExtensions() {
|
||||
return Object.keys(this.extensionToKeyMap).join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyExtensionMap;
|
463
node_modules/@11ty/eleventy/src/EleventyFiles.js
generated
vendored
Normal file
463
node_modules/@11ty/eleventy/src/EleventyFiles.js
generated
vendored
Normal file
@ -0,0 +1,463 @@
|
||||
const fs = require("fs");
|
||||
|
||||
const { TemplatePath } = require("@11ty/eleventy-utils");
|
||||
|
||||
const EleventyExtensionMap = require("./EleventyExtensionMap");
|
||||
const TemplateData = require("./TemplateData");
|
||||
const TemplateGlob = require("./TemplateGlob");
|
||||
const TemplatePassthroughManager = require("./TemplatePassthroughManager");
|
||||
const EleventyBaseError = require("./EleventyBaseError");
|
||||
const checkPassthroughCopyBehavior = require("./Util/PassthroughCopyBehaviorCheck");
|
||||
|
||||
class EleventyFilesError extends EleventyBaseError {}
|
||||
|
||||
const debug = require("debug")("Eleventy:EleventyFiles");
|
||||
// const debugDev = require("debug")("Dev:Eleventy:EleventyFiles");
|
||||
|
||||
class EleventyFiles {
|
||||
constructor(input, outputDir, formats, eleventyConfig) {
|
||||
if (!eleventyConfig) {
|
||||
throw new EleventyFilesError("Missing `eleventyConfig`` argument.");
|
||||
}
|
||||
|
||||
this.eleventyConfig = eleventyConfig;
|
||||
this.config = eleventyConfig.getConfig();
|
||||
this.aggregateBench = this.config.benchmarkManager.get("Aggregate");
|
||||
|
||||
this.input = input;
|
||||
this.inputDir = TemplatePath.getDir(this.input);
|
||||
this.outputDir = outputDir;
|
||||
|
||||
this.initConfig();
|
||||
|
||||
this.formats = formats;
|
||||
this.eleventyIgnoreContent = false;
|
||||
|
||||
// init has not yet been called()
|
||||
this.alreadyInit = false;
|
||||
}
|
||||
|
||||
setFileSystemSearch(fileSystemSearch) {
|
||||
this.fileSystemSearch = fileSystemSearch;
|
||||
}
|
||||
|
||||
/* Overrides this.input and this.inputDir,
|
||||
* Useful when input is a file and inputDir is not its direct parent */
|
||||
setInput(inputDir, input) {
|
||||
this.inputDir = inputDir;
|
||||
this.input = input;
|
||||
|
||||
this.initConfig();
|
||||
|
||||
if (this.alreadyInit) {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
|
||||
initConfig() {
|
||||
this.includesDir = TemplatePath.join(this.inputDir, this.config.dir.includes);
|
||||
|
||||
if ("layouts" in this.config.dir) {
|
||||
this.layoutsDir = TemplatePath.join(this.inputDir, this.config.dir.layouts);
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
this.alreadyInit = true;
|
||||
|
||||
// Input is a directory
|
||||
if (this.input === this.inputDir) {
|
||||
this.templateGlobs = this.extensionMap.getGlobs(this.inputDir);
|
||||
} else {
|
||||
// input is not a directory
|
||||
this.templateGlobs = TemplateGlob.map([this.input]);
|
||||
}
|
||||
|
||||
this.initPassthroughManager();
|
||||
this.setupGlobs();
|
||||
}
|
||||
|
||||
get validTemplateGlobs() {
|
||||
if (!this._validTemplateGlobs) {
|
||||
let globs;
|
||||
// Input is a directory
|
||||
if (this.input === this.inputDir) {
|
||||
globs = this.extensionMap.getValidGlobs(this.inputDir);
|
||||
} else {
|
||||
globs = this.templateGlobs;
|
||||
}
|
||||
this._validTemplateGlobs = globs;
|
||||
}
|
||||
return this._validTemplateGlobs;
|
||||
}
|
||||
|
||||
get passthroughGlobs() {
|
||||
let paths = new Set();
|
||||
// stuff added in addPassthroughCopy()
|
||||
for (let path of this.passthroughManager.getConfigPathGlobs()) {
|
||||
paths.add(path);
|
||||
}
|
||||
// non-template language extensions
|
||||
for (let path of this.extensionMap.getPassthroughCopyGlobs(this.inputDir)) {
|
||||
paths.add(path);
|
||||
}
|
||||
return Array.from(paths);
|
||||
}
|
||||
|
||||
restart() {
|
||||
this.passthroughManager.reset();
|
||||
this.setupGlobs();
|
||||
this._glob = null;
|
||||
}
|
||||
|
||||
/* For testing */
|
||||
_setConfig(config) {
|
||||
if (!config.ignores) {
|
||||
config.ignores = new Set();
|
||||
config.ignores.add("**/node_modules/**");
|
||||
}
|
||||
this.config = config;
|
||||
this.initConfig();
|
||||
}
|
||||
|
||||
/* Set command root for local project paths */
|
||||
// This is only used by tests
|
||||
_setLocalPathRoot(dir) {
|
||||
this.localPathRoot = dir;
|
||||
}
|
||||
|
||||
set extensionMap(extensionMap) {
|
||||
this._extensionMap = extensionMap;
|
||||
}
|
||||
|
||||
get extensionMap() {
|
||||
// for tests
|
||||
if (!this._extensionMap) {
|
||||
this._extensionMap = new EleventyExtensionMap(this.formats, this.eleventyConfig);
|
||||
this._extensionMap.config = this.config;
|
||||
}
|
||||
return this._extensionMap;
|
||||
}
|
||||
|
||||
setRunMode(runMode) {
|
||||
this.runMode = runMode;
|
||||
}
|
||||
|
||||
initPassthroughManager() {
|
||||
let mgr = new TemplatePassthroughManager(this.eleventyConfig);
|
||||
mgr.setInputDir(this.inputDir);
|
||||
mgr.setOutputDir(this.outputDir);
|
||||
mgr.setRunMode(this.runMode);
|
||||
mgr.extensionMap = this.extensionMap;
|
||||
mgr.setFileSystemSearch(this.fileSystemSearch);
|
||||
this.passthroughManager = mgr;
|
||||
}
|
||||
|
||||
getPassthroughManager() {
|
||||
return this.passthroughManager;
|
||||
}
|
||||
|
||||
setPassthroughManager(mgr) {
|
||||
mgr.extensionMap = this.extensionMap;
|
||||
this.passthroughManager = mgr;
|
||||
}
|
||||
|
||||
set templateData(templateData) {
|
||||
this._templateData = templateData;
|
||||
}
|
||||
|
||||
get templateData() {
|
||||
if (!this._templateData) {
|
||||
this._templateData = new TemplateData(this.inputDir, this.eleventyConfig);
|
||||
}
|
||||
return this._templateData;
|
||||
}
|
||||
|
||||
getDataDir() {
|
||||
let data = this.templateData;
|
||||
|
||||
return data.getDataDir();
|
||||
}
|
||||
|
||||
setupGlobs() {
|
||||
this.fileIgnores = this.getIgnores();
|
||||
this.extraIgnores = this._getIncludesAndDataDirs();
|
||||
this.uniqueIgnores = this.getIgnoreGlobs();
|
||||
|
||||
// Conditional added for tests that don’t have a config
|
||||
if (this.config && this.config.events) {
|
||||
this.config.events.emit("eleventy.ignores", this.uniqueIgnores);
|
||||
}
|
||||
|
||||
this.normalizedTemplateGlobs = this.templateGlobs;
|
||||
}
|
||||
|
||||
getIgnoreGlobs() {
|
||||
let uniqueIgnores = new Set();
|
||||
for (let ignore of this.fileIgnores) {
|
||||
uniqueIgnores.add(ignore);
|
||||
}
|
||||
for (let ignore of this.extraIgnores) {
|
||||
uniqueIgnores.add(ignore);
|
||||
}
|
||||
// Placing the config ignores last here is important to the tests
|
||||
for (let ignore of this.config.ignores) {
|
||||
uniqueIgnores.add(TemplateGlob.normalizePath(this.localPathRoot || ".", ignore));
|
||||
}
|
||||
return Array.from(uniqueIgnores);
|
||||
}
|
||||
|
||||
static getFileIgnores(ignoreFiles) {
|
||||
if (!Array.isArray(ignoreFiles)) {
|
||||
ignoreFiles = [ignoreFiles];
|
||||
}
|
||||
|
||||
let ignores = [];
|
||||
for (let ignorePath of ignoreFiles) {
|
||||
ignorePath = TemplatePath.normalize(ignorePath);
|
||||
|
||||
let dir = TemplatePath.getDirFromFilePath(ignorePath);
|
||||
|
||||
if (fs.existsSync(ignorePath) && fs.statSync(ignorePath).size > 0) {
|
||||
let ignoreContent = fs.readFileSync(ignorePath, "utf8");
|
||||
|
||||
ignores = ignores.concat(EleventyFiles.normalizeIgnoreContent(dir, ignoreContent));
|
||||
}
|
||||
}
|
||||
|
||||
ignores.forEach((path) => debug(`${ignoreFiles} ignoring: ${path}`));
|
||||
|
||||
return ignores;
|
||||
}
|
||||
|
||||
static normalizeIgnoreContent(dir, ignoreContent) {
|
||||
let ignores = [];
|
||||
|
||||
if (ignoreContent) {
|
||||
ignores = ignoreContent
|
||||
.split("\n")
|
||||
.map((line) => {
|
||||
return line.trim();
|
||||
})
|
||||
.filter((line) => {
|
||||
if (line.charAt(0) === "!") {
|
||||
debug(
|
||||
">>> When processing .gitignore/.eleventyignore, Eleventy does not currently support negative patterns but encountered one:"
|
||||
);
|
||||
debug(">>>", line);
|
||||
debug("Follow along at https://github.com/11ty/eleventy/issues/693 to track support.");
|
||||
}
|
||||
|
||||
// empty lines or comments get filtered out
|
||||
return line.length > 0 && line.charAt(0) !== "#" && line.charAt(0) !== "!";
|
||||
})
|
||||
.map((line) => {
|
||||
let path = TemplateGlob.normalizePath(dir, "/", line);
|
||||
path = TemplatePath.addLeadingDotSlash(TemplatePath.relativePath(path));
|
||||
|
||||
try {
|
||||
// Note these folders must exist to get /** suffix
|
||||
let stat = fs.statSync(path);
|
||||
if (stat.isDirectory()) {
|
||||
return path + "/**";
|
||||
}
|
||||
return path;
|
||||
} catch (e) {
|
||||
return path;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return ignores;
|
||||
}
|
||||
|
||||
setEleventyIgnoreContent(content) {
|
||||
this.eleventyIgnoreContent = content;
|
||||
}
|
||||
|
||||
getIgnores() {
|
||||
let files = new Set();
|
||||
|
||||
for (let ignore of EleventyFiles.getFileIgnores(this.getIgnoreFiles())) {
|
||||
files.add(ignore);
|
||||
}
|
||||
|
||||
// testing API
|
||||
if (this.eleventyIgnoreContent !== false) {
|
||||
files.add(this.eleventyIgnoreContent);
|
||||
}
|
||||
|
||||
// ignore output dir unless that would exclude all input
|
||||
if (!TemplatePath.startsWithSubPath(this.inputDir, this.outputDir)) {
|
||||
files.add(TemplateGlob.map(this.outputDir + "/**"));
|
||||
}
|
||||
|
||||
return Array.from(files);
|
||||
}
|
||||
|
||||
getIgnoreFiles() {
|
||||
let ignoreFiles = [];
|
||||
let rootDirectory = this.localPathRoot || ".";
|
||||
|
||||
if (this.config.useGitIgnore) {
|
||||
ignoreFiles.push(TemplatePath.join(rootDirectory, ".gitignore"));
|
||||
}
|
||||
|
||||
if (this.eleventyIgnoreContent === false) {
|
||||
let absoluteInputDir = TemplatePath.absolutePath(this.inputDir);
|
||||
ignoreFiles.push(TemplatePath.join(rootDirectory, ".eleventyignore"));
|
||||
if (rootDirectory !== absoluteInputDir) {
|
||||
ignoreFiles.push(TemplatePath.join(this.inputDir, ".eleventyignore"));
|
||||
}
|
||||
}
|
||||
|
||||
return ignoreFiles;
|
||||
}
|
||||
|
||||
getIncludesDir() {
|
||||
return this.includesDir;
|
||||
}
|
||||
|
||||
getLayoutsDir() {
|
||||
return this.layoutsDir;
|
||||
}
|
||||
|
||||
getFileGlobs() {
|
||||
return this.normalizedTemplateGlobs;
|
||||
}
|
||||
|
||||
getRawFiles() {
|
||||
return this.templateGlobs;
|
||||
}
|
||||
|
||||
getWatchPathCache() {
|
||||
// Issue #1325: make sure passthrough copy files are not included here
|
||||
if (!this.pathCache) {
|
||||
throw new Error("Watching requires `.getFiles()` to be called first in EleventyFiles");
|
||||
}
|
||||
|
||||
// Filter out the passthrough copy paths.
|
||||
return this.pathCache.filter((path) => {
|
||||
return (
|
||||
this.extensionMap.isFullTemplateFilePath(path) &&
|
||||
this.extensionMap.shouldSpiderJavaScriptDependencies(path)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
_globSearch() {
|
||||
let globs = this.getFileGlobs();
|
||||
|
||||
// returns a promise
|
||||
debug("Searching for: %o", globs);
|
||||
return this.fileSystemSearch.search("templates", globs, {
|
||||
ignore: this.uniqueIgnores,
|
||||
});
|
||||
}
|
||||
|
||||
async getFiles() {
|
||||
let bench = this.aggregateBench.get("Searching the file system (templates)");
|
||||
bench.before();
|
||||
let globResults = await this._globSearch();
|
||||
let paths = TemplatePath.addLeadingDotSlashArray(globResults);
|
||||
bench.after();
|
||||
|
||||
// Note 2.0.0-canary.19 removed a `filter` option for custom template syntax here that was unpublished and unused.
|
||||
|
||||
this.pathCache = paths;
|
||||
return paths;
|
||||
}
|
||||
|
||||
// Assumption here that filePath is not a passthrough copy file
|
||||
isFullTemplateFile(paths, filePath) {
|
||||
if (!filePath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let path of paths) {
|
||||
if (path === filePath) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* For `eleventy --watch` */
|
||||
getGlobWatcherFiles() {
|
||||
// TODO improvement: tie the includes and data to specific file extensions (currently using `**`)
|
||||
let directoryGlobs = this._getIncludesAndDataDirs();
|
||||
|
||||
if (checkPassthroughCopyBehavior(this.config, this.runMode)) {
|
||||
return this.validTemplateGlobs.concat(directoryGlobs);
|
||||
}
|
||||
|
||||
// Revert to old passthroughcopy copy files behavior
|
||||
return this.validTemplateGlobs.concat(this.passthroughGlobs).concat(directoryGlobs);
|
||||
}
|
||||
|
||||
/* For `eleventy --watch` */
|
||||
getGlobWatcherFilesForPassthroughCopy() {
|
||||
return this.passthroughGlobs;
|
||||
}
|
||||
|
||||
/* For `eleventy --watch` */
|
||||
async getGlobWatcherTemplateDataFiles() {
|
||||
let templateData = this.templateData;
|
||||
return await templateData.getTemplateDataFileGlob();
|
||||
}
|
||||
|
||||
/* For `eleventy --watch` */
|
||||
// TODO this isn’t great but reduces complexity avoiding using TemplateData:getLocalDataPaths for each template in the cache
|
||||
async getWatcherTemplateJavaScriptDataFiles() {
|
||||
let globs = await this.templateData.getTemplateJavaScriptDataFileGlob();
|
||||
let bench = this.aggregateBench.get("Searching the file system (watching)");
|
||||
bench.before();
|
||||
let results = TemplatePath.addLeadingDotSlashArray(
|
||||
await this.fileSystemSearch.search("js-dependencies", globs, {
|
||||
ignore: ["**/node_modules/**"],
|
||||
})
|
||||
);
|
||||
bench.after();
|
||||
return results;
|
||||
}
|
||||
|
||||
/* Ignored by `eleventy --watch` */
|
||||
getGlobWatcherIgnores() {
|
||||
// convert to format without ! since they are passed in as a separate argument to glob watcher
|
||||
let entries = new Set(
|
||||
this.fileIgnores.map((ignore) => TemplatePath.stripLeadingDotSlash(ignore))
|
||||
);
|
||||
|
||||
for (let ignore of this.config.watchIgnores) {
|
||||
entries.add(TemplateGlob.normalizePath(this.localPathRoot || ".", ignore));
|
||||
}
|
||||
|
||||
// de-duplicated
|
||||
return Array.from(entries);
|
||||
}
|
||||
|
||||
_getIncludesAndDataDirs() {
|
||||
let files = [];
|
||||
// we want this to fail on "" because we don’t want to ignore the
|
||||
// entire input directory when using ""
|
||||
if (this.config.dir.includes) {
|
||||
files = files.concat(TemplateGlob.map(this.includesDir + "/**"));
|
||||
}
|
||||
|
||||
// we want this to fail on "" because we don’t want to ignore the
|
||||
// entire input directory when using ""
|
||||
if (this.config.dir.layouts) {
|
||||
files = files.concat(TemplateGlob.map(this.layoutsDir + "/**"));
|
||||
}
|
||||
|
||||
if (this.config.dir.data && this.config.dir.data !== ".") {
|
||||
let dataDir = this.getDataDir();
|
||||
files = files.concat(TemplateGlob.map(dataDir + "/**"));
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyFiles;
|
259
node_modules/@11ty/eleventy/src/EleventyServe.js
generated
vendored
Normal file
259
node_modules/@11ty/eleventy/src/EleventyServe.js
generated
vendored
Normal file
@ -0,0 +1,259 @@
|
||||
const { TemplatePath } = require("@11ty/eleventy-utils");
|
||||
|
||||
const EleventyBaseError = require("./EleventyBaseError");
|
||||
const ConsoleLogger = require("./Util/ConsoleLogger");
|
||||
const PathPrefixer = require("./Util/PathPrefixer");
|
||||
const merge = require("./Util/Merge");
|
||||
const checkPassthroughCopyBehavior = require("./Util/PassthroughCopyBehaviorCheck");
|
||||
|
||||
const debug = require("debug")("EleventyServe");
|
||||
|
||||
class EleventyServeConfigError extends EleventyBaseError {}
|
||||
|
||||
const DEFAULT_SERVER_OPTIONS = {
|
||||
module: "@11ty/eleventy-dev-server",
|
||||
port: 8080,
|
||||
// pathPrefix: "/",
|
||||
// setup: function() {},
|
||||
// logger: { info: function() {}, error: function() {} }
|
||||
};
|
||||
|
||||
class EleventyServe {
|
||||
constructor() {
|
||||
this.logger = new ConsoleLogger(true);
|
||||
this._initOptionsFetched = false;
|
||||
this._aliases = undefined;
|
||||
this._watchedFiles = new Set();
|
||||
}
|
||||
|
||||
get config() {
|
||||
if (!this._config) {
|
||||
throw new EleventyServeConfigError("You need to set the config property on EleventyServe.");
|
||||
}
|
||||
|
||||
return this._config;
|
||||
}
|
||||
|
||||
set config(config) {
|
||||
this._options = null;
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
setAliases(aliases) {
|
||||
this._aliases = aliases;
|
||||
|
||||
if (this._server && "setAliases" in this._server) {
|
||||
this._server.setAliases(aliases);
|
||||
}
|
||||
}
|
||||
|
||||
get eleventyConfig() {
|
||||
if (!this._eleventyConfig) {
|
||||
throw new EleventyServeConfigError(
|
||||
"You need to set the eleventyConfig property on EleventyServe."
|
||||
);
|
||||
}
|
||||
|
||||
return this._eleventyConfig;
|
||||
}
|
||||
|
||||
set eleventyConfig(config) {
|
||||
this._eleventyConfig = config;
|
||||
if (checkPassthroughCopyBehavior(this._eleventyConfig.userConfig, "serve")) {
|
||||
this._eleventyConfig.userConfig.events.on("eleventy.passthrough", ({ map }) => {
|
||||
// for-free passthrough copy
|
||||
this.setAliases(map);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async setOutputDir(outputDir) {
|
||||
// TODO check if this is different and if so, restart server (if already running)
|
||||
// This applies if you change the output directory in your config file during watch/serve
|
||||
this.outputDir = outputDir;
|
||||
}
|
||||
|
||||
getServerModule(name) {
|
||||
try {
|
||||
if (!name || name === DEFAULT_SERVER_OPTIONS.module) {
|
||||
return require(DEFAULT_SERVER_OPTIONS.module);
|
||||
}
|
||||
|
||||
// Look for peer dep in local project
|
||||
let projectNodeModulesPath = TemplatePath.absolutePath("./node_modules/");
|
||||
let serverPath = TemplatePath.absolutePath(projectNodeModulesPath, name);
|
||||
|
||||
// No references outside of the project node_modules are allowed
|
||||
if (!serverPath.startsWith(projectNodeModulesPath)) {
|
||||
throw new Error("Invalid node_modules name for Eleventy server instance, received:" + name);
|
||||
}
|
||||
|
||||
let module = require(serverPath);
|
||||
|
||||
if (!("getServer" in module)) {
|
||||
throw new Error(
|
||||
`Eleventy server module requires a \`getServer\` static method. Could not find one on module: \`${name}\``
|
||||
);
|
||||
}
|
||||
|
||||
let serverPackageJsonPath = TemplatePath.absolutePath(serverPath, "package.json");
|
||||
|
||||
let serverPackageJson = require(serverPackageJsonPath);
|
||||
if (serverPackageJson["11ty"] && serverPackageJson["11ty"].compatibility) {
|
||||
try {
|
||||
this.eleventyConfig.userConfig.versionCheck(serverPackageJson["11ty"].compatibility);
|
||||
} catch (e) {
|
||||
this.logger.warn(`Warning: \`${name}\` Plugin Compatibility: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
return module;
|
||||
} catch (e) {
|
||||
this.logger.error(
|
||||
"There was an error with your custom Eleventy server. We’re using the default server instead.\n" +
|
||||
e.message
|
||||
);
|
||||
debug("Eleventy server error %o", e);
|
||||
return require(DEFAULT_SERVER_OPTIONS.module);
|
||||
}
|
||||
}
|
||||
|
||||
get options() {
|
||||
if (this._options) {
|
||||
return this._options;
|
||||
}
|
||||
|
||||
this._options = Object.assign(
|
||||
{
|
||||
pathPrefix: PathPrefixer.normalizePathPrefix(this.config.pathPrefix),
|
||||
logger: this.logger,
|
||||
},
|
||||
DEFAULT_SERVER_OPTIONS,
|
||||
this.config.serverOptions
|
||||
);
|
||||
|
||||
// TODO improve by sorting keys here
|
||||
this._savedConfigOptions = JSON.stringify(this.config.serverOptions);
|
||||
|
||||
if (!this._initOptionsFetched && this.getSetupCallback()) {
|
||||
throw new Error(
|
||||
"Init options have not yet been fetched in the setup callback. This probably means that `init()` has not yet been called."
|
||||
);
|
||||
}
|
||||
|
||||
return this._options;
|
||||
}
|
||||
|
||||
get server() {
|
||||
if (this._server) {
|
||||
return this._server;
|
||||
}
|
||||
|
||||
let serverModule = this.getServerModule(this.options.module);
|
||||
|
||||
// Static method `getServer` was already checked in `getServerModule`
|
||||
this._server = serverModule.getServer("eleventy-server", this.outputDir, this.options);
|
||||
|
||||
this.setAliases(this._aliases);
|
||||
|
||||
return this._server;
|
||||
}
|
||||
|
||||
set server(val) {
|
||||
this._server = val;
|
||||
}
|
||||
|
||||
getSetupCallback() {
|
||||
let setupCallback = this.config.serverOptions.setup;
|
||||
if (setupCallback && typeof setupCallback === "function") {
|
||||
return setupCallback;
|
||||
}
|
||||
}
|
||||
|
||||
async init() {
|
||||
if (!this._initPromise) {
|
||||
this._initPromise = new Promise(async (resolve) => {
|
||||
let setupCallback = this.getSetupCallback();
|
||||
if (setupCallback) {
|
||||
let opts = await setupCallback();
|
||||
this._initOptionsFetched = true;
|
||||
|
||||
if (opts) {
|
||||
merge(this.options, opts);
|
||||
}
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
return this._initPromise;
|
||||
}
|
||||
|
||||
// Port comes in here from --port on the command line
|
||||
async serve(port) {
|
||||
this._commandLinePort = port;
|
||||
|
||||
await this.init();
|
||||
|
||||
this.server.serve(port || this.options.port);
|
||||
}
|
||||
|
||||
async close() {
|
||||
if (this._server) {
|
||||
await this.server.close();
|
||||
|
||||
this.server = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async sendError({ error }) {
|
||||
if (this._server) {
|
||||
await this.server.sendError({
|
||||
error,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Restart the server entirely
|
||||
// We don’t want to use a native `restart` method (e.g. restart() in Vite) so that
|
||||
// we can correctly handle a `module` property change (changing the server type)
|
||||
async restart() {
|
||||
await this.close();
|
||||
|
||||
// saved --port in `serve()`
|
||||
await this.serve(this._commandLinePort);
|
||||
|
||||
// rewatch the saved watched files (passthrough copy)
|
||||
if ("watchFiles" in this.server) {
|
||||
this.server.watchFiles(this._watchedFiles);
|
||||
}
|
||||
}
|
||||
|
||||
// checkPassthroughCopyBehavior check is called upstream in Eleventy.js
|
||||
// TODO globs are not removed from watcher
|
||||
watchPassthroughCopy(globs) {
|
||||
this._watchedFiles = globs;
|
||||
|
||||
if ("watchFiles" in this.server) {
|
||||
this.server.watchFiles(globs);
|
||||
}
|
||||
}
|
||||
|
||||
// Live reload the server
|
||||
async reload(reloadEvent = {}) {
|
||||
if (!this._server) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Restart the server if the options have changed
|
||||
if (JSON.stringify(this.config.serverOptions) !== this._savedConfigOptions) {
|
||||
debug("Server options changed, we’re restarting the server");
|
||||
await this.restart();
|
||||
} else {
|
||||
await this.server.reload(reloadEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyServe;
|
5
node_modules/@11ty/eleventy/src/EleventyShortcodeError.js
generated
vendored
Normal file
5
node_modules/@11ty/eleventy/src/EleventyShortcodeError.js
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
const EleventyBaseError = require("./EleventyBaseError");
|
||||
|
||||
class EleventyShortcodeError extends EleventyBaseError {}
|
||||
|
||||
module.exports = EleventyShortcodeError;
|
128
node_modules/@11ty/eleventy/src/EleventyWatch.js
generated
vendored
Executable file
128
node_modules/@11ty/eleventy/src/EleventyWatch.js
generated
vendored
Executable file
@ -0,0 +1,128 @@
|
||||
const { TemplatePath } = require("@11ty/eleventy-utils");
|
||||
const PathNormalizer = require("./Util/PathNormalizer.js");
|
||||
|
||||
/* Decides when to watch and in what mode to watch
|
||||
* Incremental builds don’t batch changes, they queue.
|
||||
* Nonincremental builds batch.
|
||||
*/
|
||||
|
||||
class EleventyWatch {
|
||||
constructor() {
|
||||
this.incremental = false;
|
||||
this.isActive = false;
|
||||
this.activeQueue = [];
|
||||
}
|
||||
|
||||
isBuildRunning() {
|
||||
return this.isActive;
|
||||
}
|
||||
|
||||
setBuildRunning() {
|
||||
this.isActive = true;
|
||||
|
||||
// pop waiting queue into the active queue
|
||||
this.activeQueue = this.popNextActiveQueue();
|
||||
}
|
||||
|
||||
setBuildFinished() {
|
||||
this.isActive = false;
|
||||
this.activeQueue = [];
|
||||
}
|
||||
|
||||
getIncrementalFile() {
|
||||
if (this.incremental) {
|
||||
return this.activeQueue.length ? this.activeQueue[0] : false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Returns the changed files currently being operated on in the current `watch` build
|
||||
* Works with or without incremental (though in incremental only one file per time will be processed)
|
||||
*/
|
||||
getActiveQueue() {
|
||||
if (!this.isActive) {
|
||||
return [];
|
||||
} else if (this.incremental) {
|
||||
return [this.activeQueue[0]];
|
||||
}
|
||||
|
||||
return this.activeQueue;
|
||||
}
|
||||
|
||||
_queueMatches(file) {
|
||||
let filterCallback;
|
||||
if (typeof file === "function") {
|
||||
filterCallback = file;
|
||||
} else {
|
||||
filterCallback = (path) => path === file;
|
||||
}
|
||||
|
||||
return this.activeQueue.filter(filterCallback);
|
||||
}
|
||||
|
||||
hasAllQueueFiles(file) {
|
||||
return (
|
||||
this.activeQueue.length > 0 && this.activeQueue.length === this._queueMatches(file).length
|
||||
);
|
||||
}
|
||||
|
||||
hasQueuedFile(file) {
|
||||
if (file) {
|
||||
return this._queueMatches(file).length > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
hasQueuedFiles(files) {
|
||||
for (const file of files) {
|
||||
if (this.hasQueuedFile(file)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
get pendingQueue() {
|
||||
if (!this._queue) {
|
||||
this._queue = [];
|
||||
}
|
||||
return this._queue;
|
||||
}
|
||||
|
||||
set pendingQueue(value) {
|
||||
this._queue = value;
|
||||
}
|
||||
|
||||
addToPendingQueue(path) {
|
||||
if (path) {
|
||||
path = PathNormalizer.normalizeSeperator(TemplatePath.addLeadingDotSlash(path));
|
||||
this.pendingQueue.push(path);
|
||||
}
|
||||
}
|
||||
|
||||
getPendingQueueSize() {
|
||||
return this.pendingQueue.length;
|
||||
}
|
||||
|
||||
getPendingQueue() {
|
||||
return this.pendingQueue;
|
||||
}
|
||||
|
||||
getActiveQueueSize() {
|
||||
return this.activeQueue.length;
|
||||
}
|
||||
|
||||
// returns array
|
||||
popNextActiveQueue() {
|
||||
if (this.incremental) {
|
||||
return this.pendingQueue.length ? [this.pendingQueue.shift()] : [];
|
||||
}
|
||||
|
||||
let ret = this.pendingQueue.slice();
|
||||
this.pendingQueue = [];
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyWatch;
|
155
node_modules/@11ty/eleventy/src/EleventyWatchTargets.js
generated
vendored
Normal file
155
node_modules/@11ty/eleventy/src/EleventyWatchTargets.js
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
const { TemplatePath } = require("@11ty/eleventy-utils");
|
||||
const { DepGraph } = require("dependency-graph");
|
||||
|
||||
const deleteRequireCache = require("./Util/DeleteRequireCache");
|
||||
const JavaScriptDependencies = require("./Util/JavaScriptDependencies");
|
||||
|
||||
class EleventyWatchTargets {
|
||||
constructor() {
|
||||
this.targets = new Set();
|
||||
this.dependencies = new Set();
|
||||
this.newTargets = new Set();
|
||||
this._watchJavaScriptDependencies = true;
|
||||
|
||||
this.graph = new DepGraph();
|
||||
}
|
||||
|
||||
set watchJavaScriptDependencies(watch) {
|
||||
this._watchJavaScriptDependencies = !!watch;
|
||||
}
|
||||
|
||||
get watchJavaScriptDependencies() {
|
||||
return this._watchJavaScriptDependencies;
|
||||
}
|
||||
|
||||
isJavaScriptDependency(path) {
|
||||
return this.dependencies.has(path);
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.newTargets = new Set();
|
||||
}
|
||||
|
||||
isWatched(target) {
|
||||
return this.targets.has(target);
|
||||
}
|
||||
|
||||
addToDependencyGraph(parent, deps) {
|
||||
if (!this.graph.hasNode(parent)) {
|
||||
this.graph.addNode(parent);
|
||||
}
|
||||
for (let dep of deps) {
|
||||
if (!this.graph.hasNode(dep)) {
|
||||
this.graph.addNode(dep);
|
||||
}
|
||||
this.graph.addDependency(parent, dep);
|
||||
}
|
||||
}
|
||||
|
||||
uses(parent, dep) {
|
||||
return this.getDependenciesOf(parent).includes(dep);
|
||||
}
|
||||
|
||||
getDependenciesOf(parent) {
|
||||
if (!this.graph.hasNode(parent)) {
|
||||
return [];
|
||||
}
|
||||
return this.graph.dependenciesOf(parent);
|
||||
}
|
||||
|
||||
getDependantsOf(child) {
|
||||
if (!this.graph.hasNode(child)) {
|
||||
return [];
|
||||
}
|
||||
return this.graph.dependantsOf(child);
|
||||
}
|
||||
|
||||
addRaw(targets, isDependency) {
|
||||
for (let target of targets) {
|
||||
let path = TemplatePath.addLeadingDotSlash(target);
|
||||
if (!this.isWatched(path)) {
|
||||
this.newTargets.add(path);
|
||||
}
|
||||
|
||||
this.targets.add(path);
|
||||
|
||||
if (isDependency) {
|
||||
this.dependencies.add(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static normalize(targets) {
|
||||
if (!targets) {
|
||||
return [];
|
||||
} else if (Array.isArray(targets)) {
|
||||
return targets;
|
||||
}
|
||||
|
||||
return [targets];
|
||||
}
|
||||
|
||||
// add only a target
|
||||
add(targets) {
|
||||
this.addRaw(EleventyWatchTargets.normalize(targets));
|
||||
}
|
||||
|
||||
static normalizeToGlobs(targets) {
|
||||
return EleventyWatchTargets.normalize(targets).map((entry) =>
|
||||
TemplatePath.convertToRecursiveGlobSync(entry)
|
||||
);
|
||||
}
|
||||
|
||||
addAndMakeGlob(targets) {
|
||||
this.addRaw(EleventyWatchTargets.normalizeToGlobs(targets));
|
||||
}
|
||||
|
||||
// add only a target’s dependencies
|
||||
addDependencies(targets, filterCallback) {
|
||||
if (!this.watchJavaScriptDependencies) {
|
||||
return;
|
||||
}
|
||||
|
||||
targets = EleventyWatchTargets.normalize(targets);
|
||||
let deps = JavaScriptDependencies.getDependencies(targets);
|
||||
if (filterCallback) {
|
||||
deps = deps.filter(filterCallback);
|
||||
}
|
||||
|
||||
for (let target of targets) {
|
||||
this.addToDependencyGraph(target, deps);
|
||||
}
|
||||
this.addRaw(deps, true);
|
||||
}
|
||||
|
||||
setWriter(templateWriter) {
|
||||
this.writer = templateWriter;
|
||||
}
|
||||
|
||||
clearRequireCacheFor(filePathArray) {
|
||||
for (const filePath of filePathArray) {
|
||||
deleteRequireCache(filePath);
|
||||
|
||||
// Delete from require cache so that updates to the module are re-required
|
||||
let importsTheChangedFile = this.getDependantsOf(filePath);
|
||||
for (let dep of importsTheChangedFile) {
|
||||
deleteRequireCache(dep);
|
||||
}
|
||||
|
||||
let isImportedInTheChangedFile = this.getDependenciesOf(filePath);
|
||||
for (let dep of isImportedInTheChangedFile) {
|
||||
deleteRequireCache(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getNewTargetsSinceLastReset() {
|
||||
return Array.from(this.newTargets);
|
||||
}
|
||||
|
||||
getTargets() {
|
||||
return Array.from(this.targets);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyWatchTargets;
|
299
node_modules/@11ty/eleventy/src/Engines/Custom.js
generated
vendored
Normal file
299
node_modules/@11ty/eleventy/src/Engines/Custom.js
generated
vendored
Normal file
@ -0,0 +1,299 @@
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
const getJavaScriptData = require("../Util/GetJavaScriptData");
|
||||
const eventBus = require("../EventBus.js");
|
||||
|
||||
let lastModifiedFile = undefined;
|
||||
eventBus.on("eleventy.resourceModified", (path) => {
|
||||
lastModifiedFile = path;
|
||||
});
|
||||
|
||||
class CustomEngine extends TemplateEngine {
|
||||
constructor(name, dirs, config) {
|
||||
super(name, dirs, config);
|
||||
|
||||
this.entry = this.getExtensionMapEntry();
|
||||
this.needsInit =
|
||||
"init" in this.entry && typeof this.entry.init === "function";
|
||||
|
||||
this._defaultEngine = undefined;
|
||||
|
||||
// Enable cacheability for this template
|
||||
if (this.entry.compileOptions && "cache" in this.entry.compileOptions) {
|
||||
this.cacheable = this.entry.compileOptions.cache;
|
||||
} else if (this.needsToReadFileContents()) {
|
||||
this.cacheable = true;
|
||||
}
|
||||
}
|
||||
|
||||
getExtensionMapEntry() {
|
||||
if ("extensionMap" in this.config) {
|
||||
// Iterates over only the user config `addExtension` entries
|
||||
for (let entry of this.config.extensionMap) {
|
||||
if (entry.key.toLowerCase() === this.name.toLowerCase()) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw Error(
|
||||
`Could not find a custom extension for ${this.name}. Did you add it to your config file?`
|
||||
);
|
||||
}
|
||||
|
||||
setDefaultEngine(defaultEngine) {
|
||||
this._defaultEngine = defaultEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
needsToReadFileContents() {
|
||||
if ("read" in this.entry) {
|
||||
return this.entry.read;
|
||||
}
|
||||
|
||||
// Handle aliases to `11ty.js` templates, avoid reading files in the alias, see #2279
|
||||
// Here, we are short circuiting fallback to defaultRenderer, does not account for compile
|
||||
// functions that call defaultRenderer explicitly
|
||||
if (
|
||||
this._defaultEngine &&
|
||||
"needsToReadFileContents" in this._defaultEngine
|
||||
) {
|
||||
return this._defaultEngine.needsToReadFileContents();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we init from multiple places, wait for the first init to finish before continuing on.
|
||||
async _runningInit() {
|
||||
if (this.needsInit) {
|
||||
if (!this._initing) {
|
||||
this._initBench = this.benchmarks.aggregate.get(
|
||||
`Engine (${this.name}) Init`
|
||||
);
|
||||
this._initBench.before();
|
||||
this._initing = this.entry.init.bind({
|
||||
config: this.config,
|
||||
bench: this.benchmarks.aggregate,
|
||||
})();
|
||||
}
|
||||
await this._initing;
|
||||
this.needsInit = false;
|
||||
|
||||
if (this._initBench) {
|
||||
this._initBench.after();
|
||||
this._initBench = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async getExtraDataFromFile(inputPath) {
|
||||
if (this.entry.getData === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!("getData" in this.entry)) {
|
||||
// Handle aliases to `11ty.js` templates, use upstream default engine data fetch, see #2279
|
||||
if (
|
||||
this._defaultEngine &&
|
||||
"getExtraDataFromFile" in this._defaultEngine
|
||||
) {
|
||||
return this._defaultEngine.getExtraDataFromFile(inputPath);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await this._runningInit();
|
||||
|
||||
if (typeof this.entry.getData === "function") {
|
||||
let dataBench = this.benchmarks.aggregate.get(
|
||||
`Engine (${this.name}) Get Data From File (Function)`
|
||||
);
|
||||
dataBench.before();
|
||||
let data = this.entry.getData(inputPath);
|
||||
dataBench.after();
|
||||
return data;
|
||||
}
|
||||
|
||||
// if getData is not false or a function then `getInstanceFromInputPath` must exist
|
||||
if (!("getInstanceFromInputPath" in this.entry)) {
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
`getInstanceFromInputPath callback missing from ${this.name} template engine plugin.`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
let keys = new Set();
|
||||
if (this.entry.getData === true) {
|
||||
keys.add("data");
|
||||
} else if (Array.isArray(this.entry.getData)) {
|
||||
for (let key of this.entry.getData) {
|
||||
keys.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
let dataBench = this.benchmarks.aggregate.get(
|
||||
`Engine (${this.name}) Get Data From File`
|
||||
);
|
||||
dataBench.before();
|
||||
|
||||
let inst = await this.entry.getInstanceFromInputPath(inputPath);
|
||||
// override keys set at the plugin level in the individual template
|
||||
if (inst.eleventyDataKey) {
|
||||
keys = new Set(inst.eleventyDataKey);
|
||||
}
|
||||
|
||||
let mixins;
|
||||
if (this.config) {
|
||||
// Object.assign usage: see TemplateRenderCustomTest.js: `JavaScript functions should not be mutable but not *that* mutable`
|
||||
mixins = Object.assign({}, this.config.javascriptFunctions);
|
||||
}
|
||||
|
||||
let promises = [];
|
||||
for (let key of keys) {
|
||||
promises.push(
|
||||
getJavaScriptData(inst, inputPath, key, {
|
||||
mixins,
|
||||
isObjectRequired: key === "data",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
let results = await Promise.all(promises);
|
||||
let data = {};
|
||||
for (let result of results) {
|
||||
Object.assign(data, result);
|
||||
}
|
||||
dataBench.after();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async compile(str, inputPath, ...args) {
|
||||
await this._runningInit();
|
||||
let defaultRenderer;
|
||||
if (this._defaultEngine) {
|
||||
defaultRenderer = async (data) => {
|
||||
const render = await this._defaultEngine.compile(
|
||||
str,
|
||||
inputPath,
|
||||
...args
|
||||
);
|
||||
return render(data);
|
||||
};
|
||||
}
|
||||
|
||||
// Fall back to default compiler if the user does not provide their own
|
||||
if (!this.entry.compile && defaultRenderer) {
|
||||
return defaultRenderer;
|
||||
}
|
||||
|
||||
// TODO generalize this (look at JavaScript.js)
|
||||
let fn = this.entry.compile.bind({
|
||||
config: this.config,
|
||||
addDependencies: (from, toArray = []) => {
|
||||
this.config.uses.addDependency(from, toArray);
|
||||
},
|
||||
defaultRenderer, // bind defaultRenderer to compile function
|
||||
})(str, inputPath);
|
||||
|
||||
// Support `undefined` to skip compile/render
|
||||
if (fn) {
|
||||
// Bind defaultRenderer to render function
|
||||
if ("then" in fn && typeof fn.then === "function") {
|
||||
// Promise, wait to bind
|
||||
return fn.then((fn) => {
|
||||
if (typeof fn === "function") {
|
||||
return fn.bind({ defaultRenderer });
|
||||
}
|
||||
return fn;
|
||||
});
|
||||
} else if ("bind" in fn && typeof fn.bind === "function") {
|
||||
return fn.bind({ defaultRenderer });
|
||||
}
|
||||
}
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
get defaultTemplateFileExtension() {
|
||||
return this.entry.outputFileExtension;
|
||||
}
|
||||
|
||||
hasDependencies(inputPath) {
|
||||
if (this.config.uses.getDependencies(inputPath) === false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
isFileRelevantTo(inputPath, comparisonFile, includeLayouts) {
|
||||
return this.config.uses.isFileRelevantTo(
|
||||
inputPath,
|
||||
comparisonFile,
|
||||
includeLayouts
|
||||
);
|
||||
}
|
||||
|
||||
getCompileCacheKey(str, inputPath) {
|
||||
// Return this separately so we know whether or not to use the cached version
|
||||
// but still return a key to cache this new render for next time
|
||||
let useCache = !this.isFileRelevantTo(inputPath, lastModifiedFile, false);
|
||||
|
||||
if (
|
||||
this.entry.compileOptions &&
|
||||
"getCacheKey" in this.entry.compileOptions
|
||||
) {
|
||||
if (typeof this.entry.compileOptions.getCacheKey !== "function") {
|
||||
throw new Error(
|
||||
`\`compileOptions.getCacheKey\` must be a function in addExtension for the ${this.name} type`
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
useCache,
|
||||
key: this.entry.compileOptions.getCacheKey(str, inputPath),
|
||||
};
|
||||
}
|
||||
|
||||
let { key } = super.getCompileCacheKey(str, inputPath);
|
||||
return {
|
||||
useCache,
|
||||
key,
|
||||
};
|
||||
}
|
||||
|
||||
permalinkNeedsCompilation(str) {
|
||||
if (this.entry.compileOptions && "permalink" in this.entry.compileOptions) {
|
||||
let p = this.entry.compileOptions.permalink;
|
||||
if (p === "raw") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// permalink: false is aliased to permalink: () => false
|
||||
if (p === false) {
|
||||
return () => false;
|
||||
}
|
||||
|
||||
return this.entry.compileOptions.permalink;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static shouldSpiderJavaScriptDependencies(entry) {
|
||||
if (
|
||||
entry.compileOptions &&
|
||||
"spiderJavaScriptDependencies" in entry.compileOptions
|
||||
) {
|
||||
return entry.compileOptions.spiderJavaScriptDependencies;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CustomEngine;
|
55
node_modules/@11ty/eleventy/src/Engines/Ejs.js
generated
vendored
Normal file
55
node_modules/@11ty/eleventy/src/Engines/Ejs.js
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
const ejsLib = require("ejs");
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
|
||||
class Ejs extends TemplateEngine {
|
||||
constructor(name, dirs, config) {
|
||||
super(name, dirs, config);
|
||||
|
||||
this.ejsOptions = {};
|
||||
|
||||
this.setLibrary(this.config.libraryOverrides.ejs);
|
||||
this.setEjsOptions(this.config.ejsOptions);
|
||||
}
|
||||
|
||||
setLibrary(lib) {
|
||||
this.ejsLib = lib || ejsLib;
|
||||
this.setEngineLib(this.ejsLib);
|
||||
}
|
||||
|
||||
getEngine() {
|
||||
return this.ejsLib;
|
||||
}
|
||||
|
||||
setEjsOptions(options) {
|
||||
this.ejsOptions = options;
|
||||
}
|
||||
|
||||
getEjsOptions() {
|
||||
let includesDir = super.getIncludesDir();
|
||||
|
||||
return Object.assign(
|
||||
{
|
||||
root: "./" + includesDir,
|
||||
compileDebug: true,
|
||||
filename: "./" + includesDir,
|
||||
},
|
||||
this.ejsOptions || {}
|
||||
);
|
||||
}
|
||||
|
||||
async compile(str, inputPath) {
|
||||
let options = this.getEjsOptions();
|
||||
|
||||
if (inputPath && inputPath !== "ejs" && inputPath !== "md") {
|
||||
options.filename = inputPath;
|
||||
}
|
||||
|
||||
let fn = this.ejsLib.compile(str, options);
|
||||
|
||||
return function (data) {
|
||||
return fn(data);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Ejs;
|
21
node_modules/@11ty/eleventy/src/Engines/Haml.js
generated
vendored
Normal file
21
node_modules/@11ty/eleventy/src/Engines/Haml.js
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
const HamlLib = require("hamljs");
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
|
||||
class Haml extends TemplateEngine {
|
||||
constructor(name, dirs, config) {
|
||||
super(name, dirs, config);
|
||||
|
||||
this.setLibrary(this.config.libraryOverrides.haml);
|
||||
}
|
||||
|
||||
setLibrary(lib) {
|
||||
this.hamlLib = lib || HamlLib;
|
||||
this.setEngineLib(lib);
|
||||
}
|
||||
|
||||
async compile(str) {
|
||||
return this.hamlLib.compile(str);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Haml;
|
73
node_modules/@11ty/eleventy/src/Engines/Handlebars.js
generated
vendored
Normal file
73
node_modules/@11ty/eleventy/src/Engines/Handlebars.js
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
const HandlebarsLib = require("handlebars");
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
|
||||
class Handlebars extends TemplateEngine {
|
||||
constructor(name, dirs, config) {
|
||||
super(name, dirs, config);
|
||||
|
||||
this.setLibrary(this.config.libraryOverrides.hbs);
|
||||
}
|
||||
|
||||
setLibrary(lib) {
|
||||
this.handlebarsLib = lib || HandlebarsLib;
|
||||
this.setEngineLib(this.handlebarsLib);
|
||||
|
||||
// TODO these all go to the same place (addHelper), add warnings for overwrites
|
||||
this.addHelpers(this.config.handlebarsHelpers);
|
||||
this.addShortcodes(this.config.handlebarsShortcodes);
|
||||
this.addPairedShortcodes(this.config.handlebarsPairedShortcodes);
|
||||
}
|
||||
|
||||
addHelper(name, callback) {
|
||||
this.handlebarsLib.registerHelper(name, callback);
|
||||
}
|
||||
|
||||
addHelpers(helpers) {
|
||||
for (let name in helpers) {
|
||||
// We don’t need to wrap helpers for `page` or `eleventy`, this is provided for free by Handlebars
|
||||
this.addHelper(name, helpers[name]);
|
||||
}
|
||||
}
|
||||
|
||||
addShortcodes(shortcodes) {
|
||||
for (let name in shortcodes) {
|
||||
this.addHelper(name, shortcodes[name]);
|
||||
}
|
||||
}
|
||||
|
||||
addPairedShortcodes(shortcodes) {
|
||||
for (let name in shortcodes) {
|
||||
let callback = shortcodes[name];
|
||||
this.addHelper(name, function (...args) {
|
||||
let options = args[args.length - 1];
|
||||
let content = "";
|
||||
if (options && options.fn) {
|
||||
content = options.fn(this);
|
||||
}
|
||||
|
||||
return callback.call(this, content, ...args);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
async cachePartialFiles() {
|
||||
let ret = await super.cachePartialFiles();
|
||||
this.handlebarsLib.registerPartial(ret.partials);
|
||||
return ret;
|
||||
}
|
||||
|
||||
async compile(str) {
|
||||
// Ensure partials are cached and registered.
|
||||
await this.getPartials();
|
||||
|
||||
let fn = this.handlebarsLib.compile(str);
|
||||
return function (data) {
|
||||
return fn(data);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Handlebars;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user