From 0d18cc17eca2a26f9d321d5630795e60b25eb57b Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Mon, 14 Sep 2020 10:14:12 -0400
Subject: [PATCH 01/75] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20Remove=20suppo?=
=?UTF-8?q?rt=20for=20hooks=20in=20'route.js'=20files?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
package.json | 2 +-
src/Elder.ts | 17 +----------------
src/utils/validations.ts | 5 -----
3 files changed, 2 insertions(+), 22 deletions(-)
diff --git a/package.json b/package.json
index c627113d..4f2f0c1d 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,7 @@
"devDependencies": {
"@types/fs-extra": "^9.0.1",
"@types/jest": "^26.0.12",
- "@types/node": "^14.6.2",
+ "@types/node": "^14.10.1",
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"cz-conventional-changelog": "^3.3.0",
diff --git a/src/Elder.ts b/src/Elder.ts
index 66b02ff6..64a0c112 100644
--- a/src/Elder.ts
+++ b/src/Elder.ts
@@ -253,7 +253,6 @@ class Elder {
// add meta to routes and collect hooks from routes
const userRoutesJsFile = routes(this.settings);
- const routeHooks: Array = [];
const userRoutes = Object.keys(userRoutesJsFile);
userRoutes.forEach((routeName) => {
@@ -264,20 +263,6 @@ class Elder {
addedBy: 'routejs',
},
};
- const processedRoute = userRoutesJsFile[routeName];
-
- if (processedRoute.hooks && Array.isArray(processedRoute.hooks)) {
- processedRoute.hooks.forEach((hook) => {
- const hookWithMeta: HookOptions = {
- ...hook,
- $$meta: {
- type: 'route',
- addedBy: routeName,
- },
- };
- routeHooks.push(hookWithMeta);
- });
- }
});
// plugins should never overwrite user routes.
@@ -353,7 +338,7 @@ class Elder {
const allSupportedHooks = hookInterface;
- this.hooks = [...elderJsHooks, ...pluginHooks, ...routeHooks, ...hooksJs]
+ this.hooks = [...elderJsHooks, ...pluginHooks, ...hooksJs]
.map((hook) => validateHook(hook))
.filter((Boolean as any) as ExcludesFalse);
diff --git a/src/utils/validations.ts b/src/utils/validations.ts
index 7024b357..a57fae61 100644
--- a/src/utils/validations.ts
+++ b/src/utils/validations.ts
@@ -143,11 +143,6 @@ const routeSchema = yup.object({
.label(
'Sync function that turns request objects from the all() function into permalinks which are relative to the site root',
),
- hooks: yup
- .array()
- .notRequired()
- .default([])
- .label('An array of hooks. NOTE/TODO: These run on all routes, not just the one defined on.'),
});
const pluginSchema = yup.object({
From 22b6b4c47d9d1ce58f5de623ebd115413fc31970 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Mon, 14 Sep 2020 10:18:26 -0400
Subject: [PATCH 02/75] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Add=20'data'=20val?=
=?UTF-8?q?idation=20to=20the=20route=20validation?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/utils/validations.ts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/utils/validations.ts b/src/utils/validations.ts
index a57fae61..0a0f9161 100644
--- a/src/utils/validations.ts
+++ b/src/utils/validations.ts
@@ -143,6 +143,12 @@ const routeSchema = yup.object({
.label(
'Sync function that turns request objects from the all() function into permalinks which are relative to the site root',
),
+ data: yup
+ .mixed()
+ .required()
+ .label(
+ `Async/sync function that returns a JS object. Can also be a plain JS object. Important: If this is a function it is passed a '{data}' parameter. This parameter should be mutated and returned to pick up any data populated via hooks or plugins.`,
+ ),
});
const pluginSchema = yup.object({
From 50a0bb65f5ac8ec59b9bd3299fec4cea26b063f4 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Mon, 14 Sep 2020 10:21:16 -0400
Subject: [PATCH 03/75] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Useful=20error=20w?=
=?UTF-8?q?hen=20request.route=20is=20not=20defined?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Elder.ts | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/src/Elder.ts b/src/Elder.ts
index 64a0c112..d7824b7e 100644
--- a/src/Elder.ts
+++ b/src/Elder.ts
@@ -415,12 +415,21 @@ class Elder {
await this.runHook('allRequests', this);
- // TODO: We should validate that all requests have a request.route = '';
- // sometimes the request object returned by the allRequests hook may not have it set.
-
await asyncForEach(this.allRequests, async (request) => {
if (!this.routes[request.route] || !this.routes[request.route].permalink) {
- console.error(`request missing permalink, please create an issue. ${request}`);
+ if (!request.route) {
+ console.error(
+ `Request is missing a 'route' key. This usually happens when request objects have been added to the allRequests array via a hook or plugin. ${JSON.stringify(
+ request,
+ )}`,
+ );
+ } else {
+ console.error(
+ `Request missing permalink but has request.route defined. This shouldn't be an Elder.js issue but if you believe it could be please create an issue. ${JSON.stringify(
+ request,
+ )}`,
+ );
+ }
}
if (context === 'server') {
request.type = 'server';
From a1315e9a64de6098723d59089969eb1dfa275401 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Mon, 14 Sep 2020 10:24:10 -0400
Subject: [PATCH 04/75] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20remove=20link(?=
=?UTF-8?q?)=20from=20templates?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/utils/svelteComponent.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/utils/svelteComponent.ts b/src/utils/svelteComponent.ts
index c3dab666..02e6ae19 100644
--- a/src/utils/svelteComponent.ts
+++ b/src/utils/svelteComponent.ts
@@ -50,7 +50,7 @@ const svelteComponent = (componentName) => ({ page, props, hydrateOptions }: Com
const { render, clientSrc } = componentCache[cleanComponentName];
try {
- const { css, html: htmlOutput, head } = render({ ...props, link: page.helpers.permalinks });
+ const { css, html: htmlOutput, head } = render(props);
if (css && css.code && css.code.length > 0 && page.cssStack) {
page.cssStack.push({ source: componentName, priority: 50, string: css.code });
From 9a1aab90636f2a5f513c13bb40d97d7fbc0d7911 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Mon, 14 Sep 2020 11:39:10 -0400
Subject: [PATCH 05/75] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20remove=20custo?=
=?UTF-8?q?mProps=20from=20Elder.js?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Elder.ts | 7 +-
.../__snapshots__/Elder.spec.ts.snap | 84 ++-----------------
src/hookInterface/hookEntityDefinitions.ts | 1 -
src/hookInterface/hookInterface.ts | 22 ++---
src/hookInterface/types.ts | 1 -
src/utils/Page.ts | 19 +----
src/utils/__tests__/Page.spec.ts | 3 +-
.../__tests__/__snapshots__/Page.spec.ts.snap | 2 -
.../__snapshots__/validations.spec.ts.snap | 19 ++---
src/utils/__tests__/validations.spec.ts | 1 +
src/utils/prepareRunHook.ts | 14 +---
src/utils/prepareServer.ts | 2 -
src/utils/validations.ts | 3 +-
src/workerBuild.ts | 2 -
14 files changed, 26 insertions(+), 154 deletions(-)
diff --git a/src/Elder.ts b/src/Elder.ts
index d7824b7e..df170fcb 100644
--- a/src/Elder.ts
+++ b/src/Elder.ts
@@ -56,8 +56,6 @@ class Elder {
hookInterface: any;
- customProps: any;
-
query: QueryOptions;
allRequests: Array;
@@ -346,11 +344,8 @@ class Elder {
this.hooks = this.hooks.filter((h) => !this.settings.hooks.disable.includes(h.name));
}
- // TODO: plugins should be able to register their own hooks?
-
this.data = {};
this.hookInterface = allSupportedHooks;
- this.customProps = {};
this.query = {};
this.allRequests = [];
@@ -375,7 +370,7 @@ class Elder {
});
this.runHook('customizeHooks', this).then(async () => {
- // we now have customProps and a new hookInterface.
+ // we now have any customizations to the hookInterface.
this.runHook = prepareRunHook({
hooks: this.hooks,
allSupportedHooks: this.hookInterface,
diff --git a/src/__tests__/__snapshots__/Elder.spec.ts.snap b/src/__tests__/__snapshots__/Elder.spec.ts.snap
index 9055187e..b55db317 100644
--- a/src/__tests__/__snapshots__/Elder.spec.ts.snap
+++ b/src/__tests__/__snapshots__/Elder.spec.ts.snap
@@ -4,7 +4,6 @@ exports[`#Elder hookSrcFile not found 1`] = `
Elder {
"allRequests": Array [],
"bootstrapComplete": Promise {},
- "customProps": Object {},
"data": Object {},
"errors": Array [],
"helpers": Object {
@@ -18,22 +17,20 @@ Elder {
"hookInterface": Array [
Object {
"advanced": true,
- "context": "Run before collecting all hooks.",
+ "context": "Used to modify what hooks can mutate which properties all hooks.",
"experimental": true,
"hook": "customizeHooks",
"location": "Elder.ts",
"mutable": Array [
"hookInterface",
- "customProps",
"errors",
],
"props": Array [
"hookInterface",
- "customProps",
"errors",
],
"use": "
This hook receives the hookInterface.ts file which defines all hook interactions. You can customize all 'props' and 'mutable' of
- all hooks by using this hook. This is a power user hook and would often be used in conjunction with customProps.
",
+ all hooks by using this hook. This is a power user hook and unless you know Elder.js internals don't mess with it.
",
},
Object {
"advanced": false,
@@ -64,7 +61,7 @@ Elder {
",
},
Object {
- "advanced": true,
+ "advanced": false,
"context": "allRequests which represents all of the request objects have been collected from route and plugins. This makes the 'allRequests' array mutable.",
"experimental": false,
"hook": "allRequests",
@@ -134,29 +131,6 @@ Elder {
Anything you'd use an Express 'req' or 'next' for you can do and customize other parts of the Elder.js on this hook.
",
},
- Object {
- "advanced": true,
- "context": "This hook is run just after a Page.ts object is created for a request. Page.ts objects are the main object used during page generation.",
- "experimental": true,
- "hook": "modifyCustomProps",
- "location": "Page.ts",
- "mutable": Array [
- "customProps",
- "request",
- "errors",
- "helpers",
- "query",
- ],
- "props": Array [
- "customProps",
- "request",
- "errors",
- "helpers",
- "query",
- "settings",
- ],
- "use": "
This hook is often used in conjunction with the 'customizeHooks' hook to modify 'customProps' based on the request. This is very much a power user hook.
This hook receives the hookInterface.ts file which defines all hook interactions. You can customize all 'props' and 'mutable' of
- all hooks by using this hook. This is a power user hook and would often be used in conjunction with customProps.
",
+ all hooks by using this hook. This is a power user hook and unless you know Elder.js internals don't mess with it.",
},
Object {
"advanced": false,
@@ -668,7 +629,7 @@ Elder {
",
},
Object {
- "advanced": true,
+ "advanced": false,
"context": "allRequests which represents all of the request objects have been collected from route and plugins. This makes the 'allRequests' array mutable.",
"experimental": false,
"hook": "allRequests",
@@ -738,29 +699,6 @@ Elder {
Anything you'd use an Express 'req' or 'next' for you can do and customize other parts of the Elder.js on this hook.
",
},
- Object {
- "advanced": true,
- "context": "This hook is run just after a Page.ts object is created for a request. Page.ts objects are the main object used during page generation.",
- "experimental": true,
- "hook": "modifyCustomProps",
- "location": "Page.ts",
- "mutable": Array [
- "customProps",
- "request",
- "errors",
- "helpers",
- "query",
- ],
- "props": Array [
- "customProps",
- "request",
- "errors",
- "helpers",
- "query",
- "settings",
- ],
- "use": "
This hook is often used in conjunction with the 'customizeHooks' hook to modify 'customProps' based on the request. This is very much a power user hook.
",
- },
Object {
"advanced": false,
"context": "This is executed at the beginning the request object being processed.",
@@ -1133,16 +1071,6 @@ Elder {
"name": "test hook 3",
"run": [Function],
},
- Object {
- "$$meta": Object {
- "addedBy": "route-a",
- "type": "route",
- },
- "description": "test",
- "hook": "routeHook",
- "name": "route hook",
- "run": [MockFunction],
- },
Object {
"$$meta": Object {
"addedBy": "hooks.js",
diff --git a/src/hookInterface/hookEntityDefinitions.ts b/src/hookInterface/hookEntityDefinitions.ts
index 5931d794..4ab8398d 100644
--- a/src/hookInterface/hookEntityDefinitions.ts
+++ b/src/hookInterface/hookEntityDefinitions.ts
@@ -3,7 +3,6 @@ const hookEntityDefinitions = {
allRequests: `Every request object collected from all routes during bootstrap. It is important to note that 'allRequests' will be different at the 'request' hook during a build because the requests are split between different processes during build time using the allRequests object.`,
hookInterface:
'The hook interface is what defines the "contract" for each hook. It includes what properties the hook has access to and which of those properties can be mutated.',
- customProps: 'An object that represents any custom props added during the "customizeHook" hook',
errors: 'An array of errors collected during the build process.',
helpers:
'An object of helpers loaded from `./src/helpers/index.js` in addition to the Elder.js provided helper functions.',
diff --git a/src/hookInterface/hookInterface.ts b/src/hookInterface/hookInterface.ts
index bb20cc75..111fbd20 100644
--- a/src/hookInterface/hookInterface.ts
+++ b/src/hookInterface/hookInterface.ts
@@ -6,11 +6,11 @@ import type { HookInterface } from './types';
export const hookInterface: Array = [
{
hook: 'customizeHooks',
- props: ['hookInterface', 'customProps', 'errors'],
- mutable: ['hookInterface', 'customProps', 'errors'],
- context: 'Run before collecting all hooks.',
+ props: ['hookInterface', 'errors'],
+ mutable: ['hookInterface', 'errors'],
+ context: 'Used to modify what hooks can mutate which properties all hooks.',
use: `
This hook receives the hookInterface.ts file which defines all hook interactions. You can customize all 'props' and 'mutable' of
- all hooks by using this hook. This is a power user hook and would often be used in conjunction with customProps.
`,
+ all hooks by using this hook. This is a power user hook and unless you know Elder.js internals don't mess with it.`,
location: 'Elder.ts',
experimental: true,
advanced: true,
@@ -44,7 +44,7 @@ export const hookInterface: Array = [
NOTE: If you are modifying 'allRequests' you must set 'request.route' key for each request.
`,
location: 'Elder.ts',
experimental: false,
- advanced: true,
+ advanced: false,
},
// above this is Elder.js
@@ -94,18 +94,6 @@ export const hookInterface: Array = [
advanced: true,
},
- {
- hook: 'modifyCustomProps',
- props: ['customProps', 'request', 'errors', 'helpers', 'query', 'settings'],
- mutable: ['customProps', 'request', 'errors', 'helpers', 'query'],
- context:
- 'This hook is run just after a Page.ts object is created for a request. Page.ts objects are the main object used during page generation.',
- use: `
This hook is often used in conjunction with the 'customizeHooks' hook to modify 'customProps' based on the request. This is very much a power user hook.
`,
- location: 'Page.ts',
- experimental: true,
- advanced: true,
- },
-
{
hook: 'request',
props: ['helpers', 'data', 'settings', 'request', 'allRequests', 'query', 'errors', 'routes', 'route'],
diff --git a/src/hookInterface/types.ts b/src/hookInterface/types.ts
index 43988a0d..b55a285e 100644
--- a/src/hookInterface/types.ts
+++ b/src/hookInterface/types.ts
@@ -3,7 +3,6 @@ export type Hook =
| 'bootstrap'
| 'allRequests'
| 'middleware'
- | 'modifyCustomProps'
| 'request'
| 'data'
| 'stacks'
diff --git a/src/utils/Page.ts b/src/utils/Page.ts
index dd3cdc4f..9bd35603 100644
--- a/src/utils/Page.ts
+++ b/src/utils/Page.ts
@@ -142,8 +142,6 @@ class Page {
perf: any;
- customProps: any;
-
htmlString: string;
headStack: Stack;
@@ -158,19 +156,7 @@ class Page {
footerStack: Stack;
- constructor({
- request,
- settings,
- query,
- helpers,
- data,
- route,
- runHook,
- allRequests,
- routes,
- errors,
- customProps = {},
- }) {
+ constructor({ request, settings, query, helpers, data, route, runHook, allRequests, routes, errors }) {
this.uid = getUniqueId();
perf(this);
this.perf.start('page');
@@ -185,7 +171,6 @@ class Page {
this.query = query;
this.errors = [...errors];
this.routes = routes;
- this.customProps = customProps;
this.htmlString = '';
this.headStack = [];
@@ -197,8 +182,6 @@ class Page {
this.processStack = prepareProcessStack(this);
- this.runHook('modifyCustomProps', this);
-
this.perf.end('constructor');
this.perf.start('initToBuildGap');
diff --git a/src/utils/__tests__/Page.spec.ts b/src/utils/__tests__/Page.spec.ts
index be9a71e5..e5703223 100644
--- a/src/utils/__tests__/Page.spec.ts
+++ b/src/utils/__tests__/Page.spec.ts
@@ -221,9 +221,8 @@ describe('#Page', () => {
it('initialize and build', async () => {
const page = new Page(pageInput);
expect(page).toMatchSnapshot();
- expect(hooks).toEqual(['modifyCustomProps']);
await page.build();
- expect(hooks).toEqual(['modifyCustomProps', 'request', 'data', 'stacks', 'head', 'html', 'requestComplete']);
+ expect(hooks).toEqual(['request', 'data', 'stacks', 'head', 'html', 'requestComplete']);
expect(page).toMatchSnapshot();
const htmlString = await page.html();
expect(htmlString.trim()).toEqual(expectedOutput);
diff --git a/src/utils/__tests__/__snapshots__/Page.spec.ts.snap b/src/utils/__tests__/__snapshots__/Page.spec.ts.snap
index 269060ba..8c50c657 100644
--- a/src/utils/__tests__/__snapshots__/Page.spec.ts.snap
+++ b/src/utils/__tests__/__snapshots__/Page.spec.ts.snap
@@ -29,7 +29,6 @@ Page {
"beforeHydrateStack": Array [],
"cssStack": Array [],
"customJsStack": Array [],
- "customProps": Object {},
"data": Object {},
"errors": Array [],
"footerStack": Array [],
@@ -244,7 +243,6 @@ Page {
"customJsStack": Array [
"customJsStack",
],
- "customProps": Object {},
"data": Object {
"worldPopulation": 7805564950,
},
diff --git a/src/utils/__tests__/__snapshots__/validations.spec.ts.snap b/src/utils/__tests__/__snapshots__/validations.spec.ts.snap
index 2d62d34b..b00d32b0 100644
--- a/src/utils/__tests__/__snapshots__/validations.spec.ts.snap
+++ b/src/utils/__tests__/__snapshots__/validations.spec.ts.snap
@@ -1368,7 +1368,7 @@ ObjectSchema {
"_exclusive": Object {},
"_mutate": undefined,
"_nodes": Array [
- "hooks",
+ "data",
"permalink",
"all",
"template",
@@ -1414,34 +1414,31 @@ ObjectSchema {
"transforms": Array [],
"type": "mixed",
},
- "hooks": ArraySchema {
+ "data": SchemaType {
"_blacklist": RefSet {
"list": Set {},
"refs": Map {},
},
"_conditions": Array [],
- "_default": Array [],
+ "_default": Object {},
"_deps": Array [],
"_exclusive": Object {},
- "_label": "An array of hooks. NOTE/TODO: These run on all routes, not just the one defined on.",
+ "_label": "Async/sync function that returns a JS object. Can also be a plain JS object. Important: If this is a function it is passed a '{data}' parameter. This parameter should be mutated and returned to pick up any data populated via hooks or plugins.",
"_mutate": undefined,
+ "_nullable": true,
"_options": Object {
"abortEarly": true,
"recursive": true,
},
- "_subType": undefined,
- "_type": "array",
+ "_type": "mixed",
"_typeError": [Function],
"_whitelist": RefSet {
"list": Set {},
"refs": Map {},
},
- "innerType": undefined,
"tests": Array [],
- "transforms": Array [
- [Function],
- ],
- "type": "array",
+ "transforms": Array [],
+ "type": "mixed",
},
"permalink": SchemaType {
"_blacklist": RefSet {
diff --git a/src/utils/__tests__/validations.spec.ts b/src/utils/__tests__/validations.spec.ts
index 6b69a209..bfecfa7e 100644
--- a/src/utils/__tests__/validations.spec.ts
+++ b/src/utils/__tests__/validations.spec.ts
@@ -82,6 +82,7 @@ describe('#validations', () => {
all: jest.fn(),
permalink: jest.fn(),
hooks: [],
+ data: {},
};
expect(validateRoute(validRoute, 'Home')).toEqual(validRoute);
// works with valid hook
diff --git a/src/utils/prepareRunHook.ts b/src/utils/prepareRunHook.ts
index 8831502d..ff22ba05 100644
--- a/src/utils/prepareRunHook.ts
+++ b/src/utils/prepareRunHook.ts
@@ -11,7 +11,6 @@ function prepareRunHook({ hooks, allSupportedHooks, settings }) {
throw new Error(`Hook ${hookName} not defined in hookInterface or via plugins.`);
}
- const customPropKeys = [];
const hookProps = hookDefinition.props.reduce((out, cv) => {
if (Object.hasOwnProperty.call(props, cv)) {
if (!hookDefinition.mutable.includes(cv)) {
@@ -19,13 +18,6 @@ function prepareRunHook({ hooks, allSupportedHooks, settings }) {
} else {
out[cv] = props[cv];
}
- } else if (typeof props.customProps === 'object' && props.customProps[cv]) {
- if (!hookDefinition.mutable.includes(cv)) {
- out[cv] = createReadOnlyProxy(props.customProps[cv], cv, hookName);
- } else {
- out[cv] = props.customProps[cv];
- }
- customPropKeys.push(cv);
} else {
console.error(
`Hook named '${hookName}' cannot be run because prop ${cv} is not in scope to pass to the hook. Hook contract broken.`,
@@ -81,11 +73,7 @@ function prepareRunHook({ hooks, allSupportedHooks, settings }) {
) {
hookDefinition.mutable.forEach((key) => {
if ({}.hasOwnProperty.call(hookOutput, key)) {
- if (customPropKeys.includes(key)) {
- props.customProps[key] = hookOutput[key];
- } else {
- props[key] = hookOutput[key];
- }
+ props[key] = hookOutput[key];
}
});
}
diff --git a/src/utils/prepareServer.ts b/src/utils/prepareServer.ts
index efd5efa6..f5bc282a 100644
--- a/src/utils/prepareServer.ts
+++ b/src/utils/prepareServer.ts
@@ -13,7 +13,6 @@ function prepareServer({ bootstrapComplete }) {
allRequests,
runHook,
errors,
- customProps,
} = await bootstrapComplete;
if (req.path) {
@@ -49,7 +48,6 @@ function prepareServer({ bootstrapComplete }) {
allRequests,
routes,
errors,
- customProps,
};
await runHook('middleware', { ...forPage, req, next, res });
diff --git a/src/utils/validations.ts b/src/utils/validations.ts
index 0a0f9161..9f19a2f7 100644
--- a/src/utils/validations.ts
+++ b/src/utils/validations.ts
@@ -145,7 +145,8 @@ const routeSchema = yup.object({
),
data: yup
.mixed()
- .required()
+ .notRequired()
+ .default({})
.label(
`Async/sync function that returns a JS object. Can also be a plain JS object. Important: If this is a function it is passed a '{data}' parameter. This parameter should be mutated and returned to pick up any data populated via hooks or plugins.`,
),
diff --git a/src/workerBuild.ts b/src/workerBuild.ts
index a7bc4f96..1b3ef2ac 100644
--- a/src/workerBuild.ts
+++ b/src/workerBuild.ts
@@ -9,7 +9,6 @@ async function workerBuild({ bootstrapComplete, workerRequests }) {
runHook,
routes: workerRoutes,
errors,
- customProps,
allRequests,
} = await bootstrapComplete;
@@ -37,7 +36,6 @@ async function workerBuild({ bootstrapComplete, workerRequests }) {
runHook,
routes: workerRoutes,
errors,
- customProps,
});
const { errors: buildErrors, timings } = await page.build();
i += 1;
From e77877bba208b18841f94cb64be59f6f615ca70d Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Mon, 14 Sep 2020 13:05:38 -0400
Subject: [PATCH 06/75] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20compileHtml=20hook?=
=?UTF-8?q?=20to=20give=20complete=20control=20over=20html?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
package-lock.json | 8 +--
.../__snapshots__/Elder.spec.ts.snap | 72 +++++++++++++++++--
.../__snapshots__/hooks.spec.ts.snap | 7 ++
src/__tests__/hooks.spec.ts | 28 ++++++--
src/hookInterface/hookInterface.ts | 15 +++-
src/hookInterface/types.ts | 3 +-
src/hooks.ts | 12 ++++
src/utils/Page.ts | 43 +++++------
src/utils/__tests__/Page.spec.ts | 26 +------
.../__tests__/__snapshots__/Page.spec.ts.snap | 53 ++++----------
.../__snapshots__/validations.spec.ts.snap | 1 -
src/utils/__tests__/prepareRunHook.spec.ts | 20 ------
12 files changed, 163 insertions(+), 125 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 395a810c..7261b8e3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.4",
+ "version": "0.1.5",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -1590,9 +1590,9 @@
"dev": true
},
"@types/node": {
- "version": "14.6.2",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.2.tgz",
- "integrity": "sha512-onlIwbaeqvZyniGPfdw/TEhKIh79pz66L1q06WUQqJLnAb6wbjvOtepLYTGHTqzdXgBYIE3ZdmqHDGsRsbBz7A==",
+ "version": "14.10.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.1.tgz",
+ "integrity": "sha512-aYNbO+FZ/3KGeQCEkNhHFRIzBOUgc7QvcVNKXbfnhDkSfwUv91JsQQa10rDgKSTSLkXZ1UIyPe4FJJNVgw1xWQ==",
"dev": true
},
"@types/normalize-package-data": {
diff --git a/src/__tests__/__snapshots__/Elder.spec.ts.snap b/src/__tests__/__snapshots__/Elder.spec.ts.snap
index b55db317..5b742558 100644
--- a/src/__tests__/__snapshots__/Elder.spec.ts.snap
+++ b/src/__tests__/__snapshots__/Elder.spec.ts.snap
@@ -104,7 +104,6 @@ Elder {
"settings",
"allRequests",
"routes",
- "customProps",
"req",
"next",
"res",
@@ -119,7 +118,6 @@ Elder {
"settings",
"allRequests",
"routes",
- "customProps",
"req",
"next",
"res",
@@ -268,9 +266,30 @@ Elder {
"query",
"errors",
],
- "use": "
This hook's headSting represents everything that will be written to <head> tag excluding CSS (those are managed on the style hook).
+ "use": "
This hook's headSting represents everything that will be written to <head> tag.
There are many possible SEO uses to this hook, especially for plugins. That said, we recommend users who want to set common SEO elements such as tags <title> and meta descriptions programatically to do it from within Svelte templates using the <svelte:head></svelte:head> tag. Chances are you won't need this field unless you're a power user and need access to the raw head.
",
},
+ Object {
+ "advanced": true,
+ "context": "This is where Elder.js merges the html from the Svelte layout with stacks and wraps it in an tag.",
+ "experimental": false,
+ "hook": "compileHtml",
+ "location": "Page.ts",
+ "mutable": Array [
+ "errors",
+ "htmlString",
+ ],
+ "props": Array [
+ "helpers",
+ "data",
+ "request",
+ "headString",
+ "footerString",
+ "layoutHtml",
+ "htmlString",
+ ],
+ "use": "
This stack should only be used when you need to have full control over the <html> document. Make sure if you use this to add 'elderCompileHtml' to the 'hooks.disable' array in your elder.config.js or your template will be overwritten.
",
+ },
Object {
"advanced": false,
"context": "Executed when all of the html has been compiled.",
@@ -418,6 +437,17 @@ Elder {
"priority": 1,
"run": [Function],
},
+ Object {
+ "$$meta": Object {
+ "addedBy": "elder.js",
+ "type": "internal",
+ },
+ "description": "Creates an HTML string out of the Svelte layout and stacks.",
+ "hook": "compileHtml",
+ "name": "elderCompileHtml",
+ "priority": 100,
+ "run": [Function],
+ },
Object {
"$$meta": Object {
"addedBy": "elder.js",
@@ -672,7 +702,6 @@ Elder {
"settings",
"allRequests",
"routes",
- "customProps",
"req",
"next",
"res",
@@ -687,7 +716,6 @@ Elder {
"settings",
"allRequests",
"routes",
- "customProps",
"req",
"next",
"res",
@@ -836,9 +864,30 @@ Elder {
"query",
"errors",
],
- "use": "
This hook's headSting represents everything that will be written to <head> tag excluding CSS (those are managed on the style hook).
+ "use": "
This hook's headSting represents everything that will be written to <head> tag.
There are many possible SEO uses to this hook, especially for plugins. That said, we recommend users who want to set common SEO elements such as tags <title> and meta descriptions programatically to do it from within Svelte templates using the <svelte:head></svelte:head> tag. Chances are you won't need this field unless you're a power user and need access to the raw head.
",
},
+ Object {
+ "advanced": true,
+ "context": "This is where Elder.js merges the html from the Svelte layout with stacks and wraps it in an tag.",
+ "experimental": false,
+ "hook": "compileHtml",
+ "location": "Page.ts",
+ "mutable": Array [
+ "errors",
+ "htmlString",
+ ],
+ "props": Array [
+ "helpers",
+ "data",
+ "request",
+ "headString",
+ "footerString",
+ "layoutHtml",
+ "htmlString",
+ ],
+ "use": "
This stack should only be used when you need to have full control over the <html> document. Make sure if you use this to add 'elderCompileHtml' to the 'hooks.disable' array in your elder.config.js or your template will be overwritten.
This hook's headSting represents everything that will be written to <head> tag excluding CSS (those are managed on the style hook).
+ use: `
This hook's headSting represents everything that will be written to <head> tag.
There are many possible SEO uses to this hook, especially for plugins. That said, we recommend users who want to set common SEO elements such as tags <title> and meta descriptions programatically to do it from within Svelte templates using the <svelte:head></svelte:head> tag. Chances are you won't need this field unless you're a power user and need access to the raw head.
`,
location: 'Page.ts',
experimental: false,
advanced: true,
},
+ {
+ hook: 'compileHtml',
+ props: ['helpers', 'data', 'request', 'headString', 'footerString', 'layoutHtml', 'htmlString'],
+ mutable: ['errors', 'htmlString'],
+ context: 'This is where Elder.js merges the html from the Svelte layout with stacks and wraps it in an tag.',
+ use: `
This hook should only be used when you need to have full control over the <html> document. Make sure if you use this to add 'elderCompileHtml' to the 'hooks.disable' array in your elder.config.js or your template will be overwritten.
`,
+ // css: '.test{}',
+ // js: '',
+ // head: '',
+ // };
+ // },
+ // },
+ ];
+
if (context === 'server') {
this.server = prepareServer({ bootstrapComplete: this.bootstrapComplete });
}
diff --git a/src/hookInterface/hookInterface.ts b/src/hookInterface/hookInterface.ts
index 4ad5f33d..4b0c1b16 100644
--- a/src/hookInterface/hookInterface.ts
+++ b/src/hookInterface/hookInterface.ts
@@ -154,6 +154,29 @@ export const hookInterface: Array = [
advanced: true,
},
+ {
+ hook: 'shortcodes',
+ props: [
+ 'helpers',
+ 'data',
+ 'settings',
+ 'request',
+ 'query',
+ 'errors',
+ 'cssStack',
+ 'headStack',
+ 'customJsStack',
+ 'routeHtml',
+ 'shortcodes',
+ ],
+ mutable: ['errors', 'routeHtml', 'cssStack', 'headStack', 'customJsStack'],
+ context: `Executed after the route's html has been compiled, but before the layout html has been compiled.`,
+ use: `
Elder.js uses this hook to process shortcodes. The vast majority of users won't need to use this hook, but if you'd like to disable shortcodes completely, you can add 'elderProcessShortcodes' to hooks.disable in your elder.config.js file.
`,
- // css: '.test{}',
- // js: '',
- // head: '',
- // };
- // },
- // },
];
if (context === 'server') {
diff --git a/src/hookInterface/hookInterface.ts b/src/hookInterface/hookInterface.ts
index 4b0c1b16..f761f26e 100644
--- a/src/hookInterface/hookInterface.ts
+++ b/src/hookInterface/hookInterface.ts
@@ -171,7 +171,8 @@ export const hookInterface: Array = [
],
mutable: ['errors', 'routeHtml', 'cssStack', 'headStack', 'customJsStack'],
context: `Executed after the route's html has been compiled, but before the layout html has been compiled.`,
- use: `
Elder.js uses this hook to process shortcodes. The vast majority of users won't need to use this hook, but if you'd like to disable shortcodes completely, you can add 'elderProcessShortcodes' to hooks.disable in your elder.config.js file.
`,
+ use: `
Elder.js uses this hook to process shortcodes. The vast majority of users won't need to use this hook, but if you were so inclined you could write your own shortcode parser or if you'd like to disable shortcodes completely, you can add 'elderProcessShortcodes' to hooks.disable in your elder.config.js file.
+
NOTE: Don't use this hook for anything besides shortcodes.
`,
location: 'Page.ts',
experimental: false,
advanced: true,
diff --git a/src/utils/prepareShortcodeParser.ts b/src/utils/prepareShortcodeParser.ts
index 38c79ffb..630bae13 100644
--- a/src/utils/prepareShortcodeParser.ts
+++ b/src/utils/prepareShortcodeParser.ts
@@ -1,5 +1,4 @@
const ShortcodeParser = require('@elderjs/shortcodes');
-const { ShortcodeResponse } = require('./types');
function prepareShortcodeParser({
shortcodes,
@@ -24,11 +23,7 @@ function prepareShortcodeParser({
);
shortcodeParser.add(shortcode.shortcode, async (props, content) => {
- // todo, async?
-
- console.log(shortcode.shortcode, props, content);
-
- // plugin?
+ // todo: plugin?
const { html, css, js, head } = await shortcode.run({
props,
content,
@@ -36,6 +31,7 @@ function prepareShortcodeParser({
request,
query,
helpers,
+ settings,
});
if (css) {
From 88cdbd08287223deeda02e50bc9bee5a669348c6 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Tue, 15 Sep 2020 15:01:47 -0400
Subject: [PATCH 10/75] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Validate=20shortco?=
=?UTF-8?q?des=20from=20Elder,=20Plugins,=20and=20Config?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
package-lock.json | 6 ++--
package.json | 2 +-
src/Elder.ts | 55 ++++++++++-------------------
src/shortcodes.ts | 23 ++++++++++++
src/utils/getConfig.ts | 8 ++++-
src/utils/index.ts | 3 +-
src/utils/prepareShortcodeParser.ts | 1 +
src/utils/types.ts | 12 ++++++-
src/utils/validations.ts | 23 +++++++++++-
9 files changed, 88 insertions(+), 45 deletions(-)
create mode 100644 src/shortcodes.ts
diff --git a/package-lock.json b/package-lock.json
index ef5db6d6..68c13073 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -511,9 +511,9 @@
"optional": true
},
"@elderjs/shortcodes": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/@elderjs/shortcodes/-/shortcodes-1.0.5.tgz",
- "integrity": "sha512-5NofJ/1OuKNEUPYYrnTkNHMjMZarw7XG6d5NqXavyraxTEA48bVrY3hH5bxYQipMhxRJHNkF6QSQjmwpLAE0kQ=="
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@elderjs/shortcodes/-/shortcodes-1.0.6.tgz",
+ "integrity": "sha512-8n6FpnCbr4RnJYQDs7869zeywYXNyVtZnA5E4fHYWp2/fJX3OlDp7eYfMj6AnoE+E3Ehs5LVn9uT+rqUXcA0pQ=="
},
"@eslint/eslintrc": {
"version": "0.1.0",
diff --git a/package.json b/package.json
index d36c2106..20769e50 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,7 @@
"glob": "^7.1.6",
"intersection-observer": "^0.11.0",
"lodash.defaultsdeep": "^4.6.1",
- "@elderjs/shortcodes": "^1.0.5",
+ "@elderjs/shortcodes": "^1.0.6",
"nanoid": "^3.1.12",
"systemjs": "^6.5.0",
"yup": "^0.29.3"
diff --git a/src/Elder.ts b/src/Elder.ts
index 5534f19d..ed80153c 100644
--- a/src/Elder.ts
+++ b/src/Elder.ts
@@ -17,6 +17,7 @@ import {
validateHook,
validateRoute,
validatePlugin,
+ validateShortcode,
permalinks,
asyncForEach,
getHashedSvelteComponents,
@@ -37,6 +38,7 @@ import {
import createReadOnlyProxy from './utils/createReadOnlyProxy';
import workerBuild from './workerBuild';
import { inlineSvelteComponent } from './partialHydration/inlineSvelteComponent';
+import elderJsShortcodes from './shortcodes';
const getElderConfig = getConfig;
@@ -106,7 +108,7 @@ class Elder {
*/
let pluginRoutes: RoutesOptions = {};
const pluginHooks: Array = [];
-
+ const pluginShortcodes: ShortcodeDefs = [];
const pluginNames = Object.keys(this.settings.plugins);
for (let i = 0; i < pluginNames.length; i += 1) {
@@ -157,8 +159,6 @@ class Elder {
if (!validatedPlugin) return;
plugin = validatedPlugin;
- // TODO: Collect plugin, shortcodes here.
-
// clean props the plugin shouldn't be able to change between hook... specifically their hooks;
let { hooks: pluginHooksArray } = plugin;
@@ -177,10 +177,6 @@ class Elder {
// pass the plugin definition into the closure of every hook.
let pluginDefinition = sanitizedPlugin;
- // TODO: In a future release add in specific helpers to allow plugins to implement the
- // same hook signature as we use on plugin.helpers; Plugin defined hooks will basically "shadow"
- // system hooks.
-
// eslint-disable-next-line no-param-reassign
payload.plugin = pluginDefinition;
@@ -251,6 +247,14 @@ class Elder {
pluginRoutes = { ...pluginRoutes, ...sanitizedRoute };
});
}
+
+ plugin.shortcodes.forEach((shortcode) => {
+ shortcode.$$meta = {
+ type: 'plugin',
+ addedBy: pluginName,
+ };
+ pluginShortcodes.push(shortcode);
+ });
}
// add meta to routes and collect hooks from routes
@@ -331,6 +335,7 @@ class Elder {
}
}
+ // validate hooks
const elderJsHooks: Array = internalHooks.map((hook) => ({
...hook,
$$meta: {
@@ -339,8 +344,6 @@ class Elder {
},
}));
- const allSupportedHooks = hookInterface;
-
this.hooks = [...elderJsHooks, ...pluginHooks, ...hooksJs]
.map((hook) => validateHook(hook))
.filter((Boolean as any) as ExcludesFalse);
@@ -349,8 +352,13 @@ class Elder {
this.hooks = this.hooks.filter((h) => !this.settings.hooks.disable.includes(h.name));
}
+ // validate shortcodes
+ this.shortcodes = [...elderJsShortcodes, ...pluginShortcodes, ...config.shortcodes.customShortcodes]
+ .map((shortcode) => validateShortcode(shortcode))
+ .filter((Boolean as any) as ExcludesFalse);
+
this.data = {};
- this.hookInterface = allSupportedHooks;
+ this.hookInterface = hookInterface;
this.query = {};
this.allRequests = [];
@@ -362,33 +370,6 @@ class Elder {
inlineSvelteComponent,
};
- this.shortcodes = [
- {
- shortcode: 'svelteComponent',
- run: async ({ props, helpers }) => {
- if (!props.name) throw new Error(`svelteComponent shortcode requires a name="" property.`);
- return {
- html: helpers.inlineSvelteComponent({
- name: props.name,
- props: props.props || {},
- options: props.options || {},
- }),
- };
- },
- },
- {
- shortcode: 'box',
- run: async ({ content }) => {
- return {
- html: `
This hook receives the hookInterface.ts file which defines all hook interactions. You can customize all 'props' and 'mutable' of
- all hooks by using this hook. This is a power user hook and unless you know Elder.js internals don't mess with it.
Often used to populate the empty query object with a database or API connection as query is passed to the all() function which is used to generate request objects.
-
Internally used to automatically populate the helpers object with the helpers found in './src/helpers/index.js'.
-
Can be used to set information on the data object that is needed throughout the entire lifecycle. (sitewide settings)
-
",
- },
- Object {
- "advanced": false,
- "context": "allRequests which represents all of the request objects have been collected from route and plugins. This makes the 'allRequests' array mutable.",
- "experimental": false,
- "hook": "allRequests",
- "location": "Elder.ts",
- "mutable": Array [
- "errors",
- "allRequests",
- ],
- "props": Array [
- "helpers",
- "data",
- "settings",
- "allRequests",
- "routes",
- "query",
- "errors",
- ],
- "use": "
The main use here is to allow users to adjust the requests that Elder.js is aware of.
-
-
This could be used for incremental builds. By filtering and overwriting the allRequests array building just a single route or even a single request is doable.
-
This hook is used by elderjs-plugin-random to register temporary requests that it later intercepts to redirect to a random page of a route.
-
This hook is used by elderjs-plugin-markdown to register processed markdown files and their slugs Elder.js
-
-
-
NOTE: If you are modifying 'allRequests' you must set 'request.route' key for each request.
",
- },
- Object {
- "advanced": true,
- "context": "Fired upon a request that originates from the express/polka middleware version of Elder.js. The hook has access to \\"req\\" and \\"next\\" common in express like middleware.",
- "experimental": true,
- "hook": "middleware",
- "location": "prepareServer.ts",
- "mutable": Array [
- "errors",
- "request",
- "query",
- "helpers",
- "data",
- "route",
- "settings",
- "allRequests",
- "routes",
- "req",
- "next",
- "res",
- ],
- "props": Array [
- "errors",
- "request",
- "query",
- "helpers",
- "data",
- "route",
- "settings",
- "allRequests",
- "routes",
- "req",
- "next",
- "res",
- ],
- "use": "
If you're looking to use Elder.js with express/polka to build a server rendered website, then you'll be interested in this hook as it includes the familiar 'req' and 'next' objects as often used in Express middleware.
-
-
This hook could be used to set user or session information stored on the 'req' prop anywhere it is needed such as on the Elder.js 'request' object or 'data' object.
-
If you're looking to pass in details about the query string deeper into your application, you could use this hook to do so.
-
Anything you'd use an Express 'req' or 'next' for you can do and customize other parts of the Elder.js on this hook.
This hook is mainly used by plugins/hooks to offer functionality at the route level that is dependent on the route's \\"data\\" function has returning but isn't suitable to live in multiple data function across many routes due to code duplication.
-
Examples of things we (ElderGuide.com) have done or have seen users do:
-
-
LD+JSON: Plugins/hooks that add LD+JSON may need the a route's \\"data\\" function to be executed before they have the data needed to run.
-
Breadcrumbs: Plugins/hooks that add breadcrumbs may be dependent on the \\"data\\" function of a route.
-
Table Of Contents: Plugins/hooks that automatically generate a table of contents will be dependent on data from a route's data function.
-
Reference Plugins: Plugins/hooks that collect references from content and add them to the footer of the page content.
-
Last Updated Data: Determining the last updated date for a page is often better to do in a central place instead of in many \\"data\\" functions.
-
-
Stacks are made available here so that strings can be added to the head or footer of the page easily.
Elder.js uses 'stacks' to manage it's string concatenation. If you are unfamiliar, stacks are basically an array of strings, with a priority, and some meta data. This hook let's you manipulate or view the stacks before they are written to the page and is designed for use by plugins.
-
This hook will mainly be used when you need to add arbitrary strings to the footer. In most cases, users should be using <svelte:head></svelte:head> to add content to the head.
-
-
headStack: Internally all content used in are added to the head stack. If you were looking to add ld+json to the page, you could do it here. If you're looking to write <title> tags, we recommend doing it within Svelte templates unless you are writing a plugin in which case you may want to also look at the 'head' hook.
-
cssStack: The 'cssStack' represents all of the css strings emitted by the SSR Svelte components. Plugins can add css here (such as critical path CSS), but we recommend users add them directly in Svelte files. Note: Do not wrap strings added to the stack in <style>.
-
beforeHydrateStack: default this stack includes a polyfill for intersection observer and systemjs for loading svelte. This stack is not run unless there are Svelte components to be hydrated.
-
hydrateStack: the hydrateStack contains strings which represent all of the root svelte components which will be hydrated.
-
customJsStack: Used to add custom JS to the site. This is done after the Svelte components are written to the page.
-
footerStack: the footerStack which is an array of html or html friendly strings that will be written to the footer. This is generally the ideal place for plugins to add Analytics scripts as it fires after all other JS.
This hook's headSting represents everything that will be written to <head> tag.
-
There are many possible SEO uses to this hook, especially for plugins. That said, we recommend users who want to set common SEO elements such as tags <title> and meta descriptions programatically to do it from within Svelte templates using the <svelte:head></svelte:head> tag. Chances are you won't need this field unless you're a power user and need access to the raw head.
",
- },
- Object {
- "advanced": true,
- "context": "This is where Elder.js merges the html from the Svelte layout with stacks and wraps it in an tag.",
- "experimental": false,
- "hook": "compileHtml",
- "location": "Page.ts",
- "mutable": Array [
- "errors",
- "htmlString",
- ],
- "props": Array [
- "helpers",
- "data",
- "request",
- "headString",
- "footerString",
- "layoutHtml",
- "htmlString",
- ],
- "use": "
This stack should only be used when you need to have full control over the <html> document. Make sure if you use this to add 'elderCompileHtml' to the 'hooks.disable' array in your elder.config.js or your template will be overwritten.
",
- },
- Object {
- "advanced": false,
- "context": "Executed when all of the html has been compiled.",
- "experimental": false,
- "hook": "html",
- "location": "Page.ts",
- "mutable": Array [
- "errors",
- "htmlString",
- ],
- "props": Array [
- "helpers",
- "data",
- "settings",
- "request",
- "htmlString",
- "query",
- "errors",
- ],
- "use": "
This hook receives the full html of the document. With great power comes great responsibility.
-
-
Can be used to compress the html/css/js.
-
Could be used to programmatically extract h2/h3 tags and build/inject a table of contents with something like Cheeriojs.
-
If you need to modify the final html output, here is where you can do it.
This hook is triggered on an individual 'request object' completing whether Elder.js is being used in the \\"build\\" or a \\"server\\" mode.
-
-
Internally, Elder.js uses this hook to write html to the \\"public folder\\".
-
Useful for uploading static html to s3 or another source.
-
Could also be used to write the output of a route's \\"data\\" function file to help with client site routing if you were so inclined.
-
This hook may also be used by plugins to clean up any request specific 'state' they have stored.
-
By default Elder.js adds a hook here to all server requests that outputs how long the request took to generate. If you want to see detailed output from this hook set debug.speed = true in your config file.
-
",
- },
- Object {
- "advanced": false,
- "context": "Executed only if the script has encountered errors and they are pushed to the errors array.",
- "experimental": false,
- "hook": "error",
- "location": "Page.ts, build.ts",
- "mutable": Array [],
- "props": Array [
- "helpers",
- "data",
- "settings",
- "request",
- "query",
- "errors",
- ],
- "use": "
As the script encounters errors, they are collected and presented on this hook at the end of a request and the end of an entire build.
Contains whether the build was successful. If not it contains errors for the entire build. Also includes
- average performance details, and a granular performance object. Could be used to fire off additional scripts such as generating a sitemap or copying asset files to the public folder.
-
Plugins: Because builds are split across processes, a plugin doesn't not have a shared memory space across all processes.
This hook receives the hookInterface.ts file which defines all hook interactions. You can customize all 'props' and 'mutable' of
- all hooks by using this hook. This is a power user hook and unless you know Elder.js internals don't mess with it.
Often used to populate the empty query object with a database or API connection as query is passed to the all() function which is used to generate request objects.
-
Internally used to automatically populate the helpers object with the helpers found in './src/helpers/index.js'.
-
Can be used to set information on the data object that is needed throughout the entire lifecycle. (sitewide settings)
-
",
- },
- Object {
- "advanced": false,
- "context": "allRequests which represents all of the request objects have been collected from route and plugins. This makes the 'allRequests' array mutable.",
- "experimental": false,
- "hook": "allRequests",
- "location": "Elder.ts",
- "mutable": Array [
- "errors",
- "allRequests",
- ],
- "props": Array [
- "helpers",
- "data",
- "settings",
- "allRequests",
- "routes",
- "query",
- "errors",
- ],
- "use": "
The main use here is to allow users to adjust the requests that Elder.js is aware of.
-
-
This could be used for incremental builds. By filtering and overwriting the allRequests array building just a single route or even a single request is doable.
-
This hook is used by elderjs-plugin-random to register temporary requests that it later intercepts to redirect to a random page of a route.
-
This hook is used by elderjs-plugin-markdown to register processed markdown files and their slugs Elder.js
-
-
-
NOTE: If you are modifying 'allRequests' you must set 'request.route' key for each request.
",
- },
- Object {
- "advanced": true,
- "context": "Fired upon a request that originates from the express/polka middleware version of Elder.js. The hook has access to \\"req\\" and \\"next\\" common in express like middleware.",
- "experimental": true,
- "hook": "middleware",
- "location": "prepareServer.ts",
- "mutable": Array [
- "errors",
- "request",
- "query",
- "helpers",
- "data",
- "route",
- "settings",
- "allRequests",
- "routes",
- "req",
- "next",
- "res",
- ],
- "props": Array [
- "errors",
- "request",
- "query",
- "helpers",
- "data",
- "route",
- "settings",
- "allRequests",
- "routes",
- "req",
- "next",
- "res",
- ],
- "use": "
If you're looking to use Elder.js with express/polka to build a server rendered website, then you'll be interested in this hook as it includes the familiar 'req' and 'next' objects as often used in Express middleware.
-
-
This hook could be used to set user or session information stored on the 'req' prop anywhere it is needed such as on the Elder.js 'request' object or 'data' object.
-
If you're looking to pass in details about the query string deeper into your application, you could use this hook to do so.
-
Anything you'd use an Express 'req' or 'next' for you can do and customize other parts of the Elder.js on this hook.
This hook is mainly used by plugins/hooks to offer functionality at the route level that is dependent on the route's \\"data\\" function has returning but isn't suitable to live in multiple data function across many routes due to code duplication.
-
Examples of things we (ElderGuide.com) have done or have seen users do:
-
-
LD+JSON: Plugins/hooks that add LD+JSON may need the a route's \\"data\\" function to be executed before they have the data needed to run.
-
Breadcrumbs: Plugins/hooks that add breadcrumbs may be dependent on the \\"data\\" function of a route.
-
Table Of Contents: Plugins/hooks that automatically generate a table of contents will be dependent on data from a route's data function.
-
Reference Plugins: Plugins/hooks that collect references from content and add them to the footer of the page content.
-
Last Updated Data: Determining the last updated date for a page is often better to do in a central place instead of in many \\"data\\" functions.
-
-
Stacks are made available here so that strings can be added to the head or footer of the page easily.
Elder.js uses 'stacks' to manage it's string concatenation. If you are unfamiliar, stacks are basically an array of strings, with a priority, and some meta data. This hook let's you manipulate or view the stacks before they are written to the page and is designed for use by plugins.
-
This hook will mainly be used when you need to add arbitrary strings to the footer. In most cases, users should be using <svelte:head></svelte:head> to add content to the head.
-
-
headStack: Internally all content used in are added to the head stack. If you were looking to add ld+json to the page, you could do it here. If you're looking to write <title> tags, we recommend doing it within Svelte templates unless you are writing a plugin in which case you may want to also look at the 'head' hook.
-
cssStack: The 'cssStack' represents all of the css strings emitted by the SSR Svelte components. Plugins can add css here (such as critical path CSS), but we recommend users add them directly in Svelte files. Note: Do not wrap strings added to the stack in <style>.
-
beforeHydrateStack: default this stack includes a polyfill for intersection observer and systemjs for loading svelte. This stack is not run unless there are Svelte components to be hydrated.
-
hydrateStack: the hydrateStack contains strings which represent all of the root svelte components which will be hydrated.
-
customJsStack: Used to add custom JS to the site. This is done after the Svelte components are written to the page.
-
footerStack: the footerStack which is an array of html or html friendly strings that will be written to the footer. This is generally the ideal place for plugins to add Analytics scripts as it fires after all other JS.
This hook's headSting represents everything that will be written to <head> tag.
-
There are many possible SEO uses to this hook, especially for plugins. That said, we recommend users who want to set common SEO elements such as tags <title> and meta descriptions programatically to do it from within Svelte templates using the <svelte:head></svelte:head> tag. Chances are you won't need this field unless you're a power user and need access to the raw head.
",
- },
- Object {
- "advanced": true,
- "context": "This is where Elder.js merges the html from the Svelte layout with stacks and wraps it in an tag.",
- "experimental": false,
- "hook": "compileHtml",
- "location": "Page.ts",
- "mutable": Array [
- "errors",
- "htmlString",
- ],
- "props": Array [
- "helpers",
- "data",
- "request",
- "headString",
- "footerString",
- "layoutHtml",
- "htmlString",
- ],
- "use": "
This stack should only be used when you need to have full control over the <html> document. Make sure if you use this to add 'elderCompileHtml' to the 'hooks.disable' array in your elder.config.js or your template will be overwritten.
",
- },
- Object {
- "advanced": false,
- "context": "Executed when all of the html has been compiled.",
- "experimental": false,
- "hook": "html",
- "location": "Page.ts",
- "mutable": Array [
- "errors",
- "htmlString",
- ],
- "props": Array [
- "helpers",
- "data",
- "settings",
- "request",
- "htmlString",
- "query",
- "errors",
- ],
- "use": "
This hook receives the full html of the document. With great power comes great responsibility.
-
-
Can be used to compress the html/css/js.
-
Could be used to programmatically extract h2/h3 tags and build/inject a table of contents with something like Cheeriojs.
-
If you need to modify the final html output, here is where you can do it.
This hook is triggered on an individual 'request object' completing whether Elder.js is being used in the \\"build\\" or a \\"server\\" mode.
-
-
Internally, Elder.js uses this hook to write html to the \\"public folder\\".
-
Useful for uploading static html to s3 or another source.
-
Could also be used to write the output of a route's \\"data\\" function file to help with client site routing if you were so inclined.
-
This hook may also be used by plugins to clean up any request specific 'state' they have stored.
-
By default Elder.js adds a hook here to all server requests that outputs how long the request took to generate. If you want to see detailed output from this hook set debug.speed = true in your config file.
-
",
- },
- Object {
- "advanced": false,
- "context": "Executed only if the script has encountered errors and they are pushed to the errors array.",
- "experimental": false,
- "hook": "error",
- "location": "Page.ts, build.ts",
- "mutable": Array [],
- "props": Array [
- "helpers",
- "data",
- "settings",
- "request",
- "query",
- "errors",
- ],
- "use": "
As the script encounters errors, they are collected and presented on this hook at the end of a request and the end of an entire build.
Contains whether the build was successful. If not it contains errors for the entire build. Also includes
- average performance details, and a granular performance object. Could be used to fire off additional scripts such as generating a sitemap or copying asset files to the public folder.
-
Plugins: Because builds are split across processes, a plugin doesn't not have a shared memory space across all processes.
This hook receives the hookInterface.ts file which defines all hook interactions. You can customize all 'props' and 'mutable' of
+ all hooks by using this hook. This is a power user hook and unless you know Elder.js internals don't mess with it.
Often used to populate the empty query object with a database or API connection as query is passed to the all() function which is used to generate request objects.
+
Internally used to automatically populate the helpers object with the helpers found in './src/helpers/index.js'.
+
Can be used to set information on the data object that is needed throughout the entire lifecycle. (sitewide settings)
+
",
+ },
+ Object {
+ "advanced": false,
+ "context": "allRequests which represents all of the request objects have been collected from route and plugins. This makes the 'allRequests' array mutable.",
+ "experimental": false,
+ "hook": "allRequests",
+ "location": "Elder.ts",
+ "mutable": Array [
+ "errors",
+ "allRequests",
+ ],
+ "props": Array [
+ "helpers",
+ "data",
+ "settings",
+ "allRequests",
+ "routes",
+ "query",
+ "errors",
+ ],
+ "use": "
The main use here is to allow users to adjust the requests that Elder.js is aware of.
+
+
This could be used for incremental builds. By filtering and overwriting the allRequests array building just a single route or even a single request is doable.
+
This hook is used by elderjs-plugin-random to register temporary requests that it later intercepts to redirect to a random page of a route.
+
This hook is used by elderjs-plugin-markdown to register processed markdown files and their slugs Elder.js
+
+
+
NOTE: If you are modifying 'allRequests' you must set 'request.route' key for each request.
",
+ },
+ Object {
+ "advanced": true,
+ "context": "Fired upon a request that originates from the express/polka middleware version of Elder.js. The hook has access to \\"req\\" and \\"next\\" common in express like middleware.",
+ "experimental": true,
+ "hook": "middleware",
+ "location": "prepareServer.ts",
+ "mutable": Array [
+ "errors",
+ "request",
+ "query",
+ "helpers",
+ "data",
+ "route",
+ "settings",
+ "allRequests",
+ "routes",
+ "req",
+ "next",
+ "res",
+ ],
+ "props": Array [
+ "errors",
+ "request",
+ "query",
+ "helpers",
+ "data",
+ "route",
+ "settings",
+ "allRequests",
+ "routes",
+ "req",
+ "next",
+ "res",
+ ],
+ "use": "
If you're looking to use Elder.js with express/polka to build a server rendered website, then you'll be interested in this hook as it includes the familiar 'req' and 'next' objects as often used in Express middleware.
+
+
This hook could be used to set user or session information stored on the 'req' prop anywhere it is needed such as on the Elder.js 'request' object or 'data' object.
+
If you're looking to pass in details about the query string deeper into your application, you could use this hook to do so.
+
Anything you'd use an Express 'req' or 'next' for you can do and customize other parts of the Elder.js on this hook.
This hook is mainly used by plugins/hooks to offer functionality at the route level that is dependent on the route's \\"data\\" function has returning but isn't suitable to live in multiple data function across many routes due to code duplication.
+
Examples of things we (ElderGuide.com) have done or have seen users do:
+
+
LD+JSON: Plugins/hooks that add LD+JSON may need the a route's \\"data\\" function to be executed before they have the data needed to run.
+
Breadcrumbs: Plugins/hooks that add breadcrumbs may be dependent on the \\"data\\" function of a route.
+
Table Of Contents: Plugins/hooks that automatically generate a table of contents will be dependent on data from a route's data function.
+
Reference Plugins: Plugins/hooks that collect references from content and add them to the footer of the page content.
+
Last Updated Data: Determining the last updated date for a page is often better to do in a central place instead of in many \\"data\\" functions.
+
+
Stacks are made available here so that strings can be added to the head or footer of the page easily.
+ ",
+ },
+ Object {
+ "advanced": true,
+ "context": "Executed after the route's html has been compiled, but before the layout html has been compiled.",
+ "experimental": false,
+ "hook": "shortcodes",
+ "location": "Page.ts",
+ "mutable": Array [
+ "errors",
+ "routeHtml",
+ "cssStack",
+ "headStack",
+ "customJsStack",
+ ],
+ "props": Array [
+ "helpers",
+ "data",
+ "settings",
+ "request",
+ "query",
+ "errors",
+ "cssStack",
+ "headStack",
+ "customJsStack",
+ "routeHtml",
+ "shortcodes",
+ "allRequests",
+ ],
+ "use": "
Elder.js uses this hook to process shortcodes. The vast majority of users won't need to use this hook, but if you were so inclined you could write your own shortcode parser or if you'd like to disable shortcodes completely, you can add 'elderProcessShortcodes' to hooks.disable in your elder.config.js file.
+
NOTE: Don't use this hook for anything besides shortcodes.
Elder.js uses 'stacks' to manage it's string concatenation. If you are unfamiliar, stacks are basically an array of strings, with a priority, and some meta data. This hook let's you manipulate or view the stacks before they are written to the page and is designed for use by plugins.
+
This hook will mainly be used when you need to add arbitrary strings to the footer. In most cases, users should be using <svelte:head></svelte:head> to add content to the head.
+
+
headStack: Internally all content used in are added to the head stack. If you were looking to add ld+json to the page, you could do it here. If you're looking to write <title> tags, we recommend doing it within Svelte templates unless you are writing a plugin in which case you may want to also look at the 'head' hook.
+
cssStack: The 'cssStack' represents all of the css strings emitted by the SSR Svelte components. Plugins can add css here (such as critical path CSS), but we recommend users add them directly in Svelte files. Note: Do not wrap strings added to the stack in <style>.
+
beforeHydrateStack: default this stack includes a polyfill for intersection observer and systemjs for loading svelte. This stack is not run unless there are Svelte components to be hydrated.
+
hydrateStack: the hydrateStack contains strings which represent all of the root svelte components which will be hydrated.
+
customJsStack: Used to add custom JS to the site. This is done after the Svelte components are written to the page.
+
footerStack: the footerStack which is an array of html or html friendly strings that will be written to the footer. This is generally the ideal place for plugins to add Analytics scripts as it fires after all other JS.
This hook's headSting represents everything that will be written to <head> tag.
+
There are many possible SEO uses to this hook, especially for plugins. That said, we recommend users who want to set common SEO elements such as tags <title> and meta descriptions programatically to do it from within Svelte templates using the <svelte:head></svelte:head> tag. Chances are you won't need this field unless you're a power user and need access to the raw head.
",
+ },
+ Object {
+ "advanced": true,
+ "context": "This is where Elder.js merges the html from the Svelte layout with stacks and wraps it in an tag.",
+ "experimental": false,
+ "hook": "compileHtml",
+ "location": "Page.ts",
+ "mutable": Array [
+ "errors",
+ "htmlString",
+ ],
+ "props": Array [
+ "helpers",
+ "data",
+ "request",
+ "headString",
+ "footerString",
+ "layoutHtml",
+ "htmlString",
+ ],
+ "use": "
This hook should only be used when you need to have full control over the <html> document. Make sure if you use this to add 'elderCompileHtml' to the 'hooks.disable' array in your elder.config.js or your template will be overwritten.
",
+ },
+ Object {
+ "advanced": false,
+ "context": "Executed when all of the html has been compiled.",
+ "experimental": false,
+ "hook": "html",
+ "location": "Page.ts",
+ "mutable": Array [
+ "errors",
+ "htmlString",
+ ],
+ "props": Array [
+ "helpers",
+ "data",
+ "settings",
+ "request",
+ "htmlString",
+ "query",
+ "errors",
+ ],
+ "use": "
This hook receives the full html of the document. With great power comes great responsibility.
+
+
Can be used to compress the html/css/js.
+
Could be used to programmatically extract h2/h3 tags and build/inject a table of contents with something like Cheeriojs.
+
If you need to modify the final html output, here is where you can do it.
This hook is triggered on an individual 'request object' completing whether Elder.js is being used in the \\"build\\" or a \\"server\\" mode.
+
+
Internally, Elder.js uses this hook to write html to the \\"public folder\\".
+
Useful for uploading static html to s3 or another source.
+
Could also be used to write the output of a route's \\"data\\" function file to help with client site routing if you were so inclined.
+
This hook may also be used by plugins to clean up any request specific 'state' they have stored.
+
By default Elder.js adds a hook here to all server requests that outputs how long the request took to generate. If you want to see detailed output from this hook set debug.speed = true in your config file.
+
",
+ },
+ Object {
+ "advanced": false,
+ "context": "Executed only if the script has encountered errors and they are pushed to the errors array.",
+ "experimental": false,
+ "hook": "error",
+ "location": "Page.ts, build.ts",
+ "mutable": Array [],
+ "props": Array [
+ "helpers",
+ "data",
+ "settings",
+ "request",
+ "query",
+ "errors",
+ ],
+ "use": "
As the script encounters errors, they are collected and presented on this hook at the end of a request and the end of an entire build.
Contains whether the build was successful. If not it contains errors for the entire build. Also includes
+ average performance details, and a granular performance object. Could be used to fire off additional scripts such as generating a sitemap or copying asset files to the public folder.
+
Plugins: Because builds are split across processes, a plugin doesn't not have a shared memory space across all processes.
This hook receives the hookInterface.ts file which defines all hook interactions. You can customize all 'props' and 'mutable' of
+ all hooks by using this hook. This is a power user hook and unless you know Elder.js internals don't mess with it.
Often used to populate the empty query object with a database or API connection as query is passed to the all() function which is used to generate request objects.
+
Internally used to automatically populate the helpers object with the helpers found in './src/helpers/index.js'.
+
Can be used to set information on the data object that is needed throughout the entire lifecycle. (sitewide settings)
+
",
+ },
+ Object {
+ "advanced": false,
+ "context": "allRequests which represents all of the request objects have been collected from route and plugins. This makes the 'allRequests' array mutable.",
+ "experimental": false,
+ "hook": "allRequests",
+ "location": "Elder.ts",
+ "mutable": Array [
+ "errors",
+ "allRequests",
+ ],
+ "props": Array [
+ "helpers",
+ "data",
+ "settings",
+ "allRequests",
+ "routes",
+ "query",
+ "errors",
+ ],
+ "use": "
The main use here is to allow users to adjust the requests that Elder.js is aware of.
+
+
This could be used for incremental builds. By filtering and overwriting the allRequests array building just a single route or even a single request is doable.
+
This hook is used by elderjs-plugin-random to register temporary requests that it later intercepts to redirect to a random page of a route.
+
This hook is used by elderjs-plugin-markdown to register processed markdown files and their slugs Elder.js
+
+
+
NOTE: If you are modifying 'allRequests' you must set 'request.route' key for each request.
",
+ },
+ Object {
+ "advanced": true,
+ "context": "Fired upon a request that originates from the express/polka middleware version of Elder.js. The hook has access to \\"req\\" and \\"next\\" common in express like middleware.",
+ "experimental": true,
+ "hook": "middleware",
+ "location": "prepareServer.ts",
+ "mutable": Array [
+ "errors",
+ "request",
+ "query",
+ "helpers",
+ "data",
+ "route",
+ "settings",
+ "allRequests",
+ "routes",
+ "req",
+ "next",
+ "res",
+ ],
+ "props": Array [
+ "errors",
+ "request",
+ "query",
+ "helpers",
+ "data",
+ "route",
+ "settings",
+ "allRequests",
+ "routes",
+ "req",
+ "next",
+ "res",
+ ],
+ "use": "
If you're looking to use Elder.js with express/polka to build a server rendered website, then you'll be interested in this hook as it includes the familiar 'req' and 'next' objects as often used in Express middleware.
+
+
This hook could be used to set user or session information stored on the 'req' prop anywhere it is needed such as on the Elder.js 'request' object or 'data' object.
+
If you're looking to pass in details about the query string deeper into your application, you could use this hook to do so.
+
Anything you'd use an Express 'req' or 'next' for you can do and customize other parts of the Elder.js on this hook.
This hook is mainly used by plugins/hooks to offer functionality at the route level that is dependent on the route's \\"data\\" function has returning but isn't suitable to live in multiple data function across many routes due to code duplication.
+
Examples of things we (ElderGuide.com) have done or have seen users do:
+
+
LD+JSON: Plugins/hooks that add LD+JSON may need the a route's \\"data\\" function to be executed before they have the data needed to run.
+
Breadcrumbs: Plugins/hooks that add breadcrumbs may be dependent on the \\"data\\" function of a route.
+
Table Of Contents: Plugins/hooks that automatically generate a table of contents will be dependent on data from a route's data function.
+
Reference Plugins: Plugins/hooks that collect references from content and add them to the footer of the page content.
+
Last Updated Data: Determining the last updated date for a page is often better to do in a central place instead of in many \\"data\\" functions.
+
+
Stacks are made available here so that strings can be added to the head or footer of the page easily.
+ ",
+ },
+ Object {
+ "advanced": true,
+ "context": "Executed after the route's html has been compiled, but before the layout html has been compiled.",
+ "experimental": false,
+ "hook": "shortcodes",
+ "location": "Page.ts",
+ "mutable": Array [
+ "errors",
+ "routeHtml",
+ "cssStack",
+ "headStack",
+ "customJsStack",
+ ],
+ "props": Array [
+ "helpers",
+ "data",
+ "settings",
+ "request",
+ "query",
+ "errors",
+ "cssStack",
+ "headStack",
+ "customJsStack",
+ "routeHtml",
+ "shortcodes",
+ "allRequests",
+ ],
+ "use": "
Elder.js uses this hook to process shortcodes. The vast majority of users won't need to use this hook, but if you were so inclined you could write your own shortcode parser or if you'd like to disable shortcodes completely, you can add 'elderProcessShortcodes' to hooks.disable in your elder.config.js file.
+
NOTE: Don't use this hook for anything besides shortcodes.
Elder.js uses 'stacks' to manage it's string concatenation. If you are unfamiliar, stacks are basically an array of strings, with a priority, and some meta data. This hook let's you manipulate or view the stacks before they are written to the page and is designed for use by plugins.
+
This hook will mainly be used when you need to add arbitrary strings to the footer. In most cases, users should be using <svelte:head></svelte:head> to add content to the head.
+
+
headStack: Internally all content used in are added to the head stack. If you were looking to add ld+json to the page, you could do it here. If you're looking to write <title> tags, we recommend doing it within Svelte templates unless you are writing a plugin in which case you may want to also look at the 'head' hook.
+
cssStack: The 'cssStack' represents all of the css strings emitted by the SSR Svelte components. Plugins can add css here (such as critical path CSS), but we recommend users add them directly in Svelte files. Note: Do not wrap strings added to the stack in <style>.
+
beforeHydrateStack: default this stack includes a polyfill for intersection observer and systemjs for loading svelte. This stack is not run unless there are Svelte components to be hydrated.
+
hydrateStack: the hydrateStack contains strings which represent all of the root svelte components which will be hydrated.
+
customJsStack: Used to add custom JS to the site. This is done after the Svelte components are written to the page.
+
footerStack: the footerStack which is an array of html or html friendly strings that will be written to the footer. This is generally the ideal place for plugins to add Analytics scripts as it fires after all other JS.
This hook's headSting represents everything that will be written to <head> tag.
+
There are many possible SEO uses to this hook, especially for plugins. That said, we recommend users who want to set common SEO elements such as tags <title> and meta descriptions programatically to do it from within Svelte templates using the <svelte:head></svelte:head> tag. Chances are you won't need this field unless you're a power user and need access to the raw head.
",
+ },
+ Object {
+ "advanced": true,
+ "context": "This is where Elder.js merges the html from the Svelte layout with stacks and wraps it in an tag.",
+ "experimental": false,
+ "hook": "compileHtml",
+ "location": "Page.ts",
+ "mutable": Array [
+ "errors",
+ "htmlString",
+ ],
+ "props": Array [
+ "helpers",
+ "data",
+ "request",
+ "headString",
+ "footerString",
+ "layoutHtml",
+ "htmlString",
+ ],
+ "use": "
This hook should only be used when you need to have full control over the <html> document. Make sure if you use this to add 'elderCompileHtml' to the 'hooks.disable' array in your elder.config.js or your template will be overwritten.
",
+ },
+ Object {
+ "advanced": false,
+ "context": "Executed when all of the html has been compiled.",
+ "experimental": false,
+ "hook": "html",
+ "location": "Page.ts",
+ "mutable": Array [
+ "errors",
+ "htmlString",
+ ],
+ "props": Array [
+ "helpers",
+ "data",
+ "settings",
+ "request",
+ "htmlString",
+ "query",
+ "errors",
+ ],
+ "use": "
This hook receives the full html of the document. With great power comes great responsibility.
+
+
Can be used to compress the html/css/js.
+
Could be used to programmatically extract h2/h3 tags and build/inject a table of contents with something like Cheeriojs.
+
If you need to modify the final html output, here is where you can do it.
This hook is triggered on an individual 'request object' completing whether Elder.js is being used in the \\"build\\" or a \\"server\\" mode.
+
+
Internally, Elder.js uses this hook to write html to the \\"public folder\\".
+
Useful for uploading static html to s3 or another source.
+
Could also be used to write the output of a route's \\"data\\" function file to help with client site routing if you were so inclined.
+
This hook may also be used by plugins to clean up any request specific 'state' they have stored.
+
By default Elder.js adds a hook here to all server requests that outputs how long the request took to generate. If you want to see detailed output from this hook set debug.speed = true in your config file.
+
",
+ },
+ Object {
+ "advanced": false,
+ "context": "Executed only if the script has encountered errors and they are pushed to the errors array.",
+ "experimental": false,
+ "hook": "error",
+ "location": "Page.ts, build.ts",
+ "mutable": Array [],
+ "props": Array [
+ "helpers",
+ "data",
+ "settings",
+ "request",
+ "query",
+ "errors",
+ ],
+ "use": "
As the script encounters errors, they are collected and presented on this hook at the end of a request and the end of an entire build.
Contains whether the build was successful. If not it contains errors for the entire build. Also includes
+ average performance details, and a granular performance object. Could be used to fire off additional scripts such as generating a sitemap or copying asset files to the public folder.
+
Plugins: Because builds are split across processes, a plugin doesn't not have a shared memory space across all processes.
Anything you'd use an Express 'req' or 'next' for you can do and customize other parts of the Elder.js on this hook.
`,
location: 'prepareServer.ts',
- experimental: true,
+ experimental: false,
advanced: true,
},
@@ -166,11 +166,11 @@ export const hookInterface: Array = [
'cssStack',
'headStack',
'customJsStack',
- 'routeHtml',
+ 'templateHtml',
'shortcodes',
'allRequests',
],
- mutable: ['errors', 'routeHtml', 'cssStack', 'headStack', 'customJsStack'],
+ mutable: ['errors', 'templateHtml', 'cssStack', 'headStack', 'customJsStack'],
context: `Executed after the route's html has been compiled, but before the layout html has been compiled.`,
use: `
Elder.js uses this hook to process shortcodes. The vast majority of users won't need to use this hook, but if you were so inclined you could write your own shortcode parser or if you'd like to disable shortcodes completely, you can add 'elderProcessShortcodes' to hooks.disable in your elder.config.js file.
NOTE: Don't use this hook for anything besides shortcodes.
`,
diff --git a/src/hooks.ts b/src/hooks.ts
index 9f1be598..41b872cc 100644
--- a/src/hooks.ts
+++ b/src/hooks.ts
@@ -44,7 +44,7 @@ const hooks: Array = [
cssStack,
headStack,
customJsStack,
- routeHtml,
+ templateHtml,
shortcodes,
allRequests,
}) => {
@@ -61,10 +61,10 @@ const hooks: Array = [
allRequests,
});
- const html = await ShortcodeParser.parse(routeHtml);
+ const html = await ShortcodeParser.parse(templateHtml);
return {
- routeHtml: html,
+ templateHtml: html,
headStack,
cssStack,
customJsStack,
diff --git a/src/utils/Page.ts b/src/utils/Page.ts
index 9845f373..9a021746 100644
--- a/src/utils/Page.ts
+++ b/src/utils/Page.ts
@@ -38,7 +38,7 @@ const buildPage = async (page) => {
// start building templates
page.perf.start('html.template');
- page.routeHtml = page.route.templateComponent({
+ page.templateHtml = page.route.templateComponent({
page,
props: {
data: page.data,
@@ -59,7 +59,7 @@ const buildPage = async (page) => {
helpers: page.helpers,
settings: createReadOnlyProxy(page.settings, 'settings', `${page.request.route}: Svelte Layout`),
request: createReadOnlyProxy(page.request, 'request', `${page.request.route}: Svelte Layout`),
- routeHtml: page.routeHtml,
+ templateHtml: page.templateHtml,
},
});
page.perf.end('html.layout');
@@ -139,7 +139,7 @@ class Page {
layoutHtml: string;
- routeHtml: string;
+ templateHtml: string;
cssString: string;
diff --git a/src/utils/__tests__/__snapshots__/Page.spec.ts.snap b/src/utils/__tests__/__snapshots__/Page.spec.ts.snap
index cc2cd761..3bbf7734 100644
--- a/src/utils/__tests__/__snapshots__/Page.spec.ts.snap
+++ b/src/utils/__tests__/__snapshots__/Page.spec.ts.snap
@@ -443,7 +443,6 @@ Page {
},
"type": "build",
},
- "routeHtml": undefined,
"settings": Object {
"$$internal": Object {
"hashedComponents": Object {
@@ -494,6 +493,7 @@ Page {
"typescript": false,
"worker": true,
},
+ "templateHtml": undefined,
},
},
],
@@ -593,7 +593,6 @@ Page {
],
},
},
- "routeHtml": undefined,
"routes": Object {
"content": Object {
"$$meta": Object {
@@ -672,6 +671,7 @@ Page {
},
"shortcodes": Array [],
"styleTag": "",
+ "templateHtml": undefined,
"timings": Array [],
"uid": "xxxxxxxxxx",
}
diff --git a/src/utils/__tests__/hookEntityDefinitions.spec.ts b/src/utils/__tests__/hookEntityDefinitions.spec.ts
new file mode 100644
index 00000000..c7f202d7
--- /dev/null
+++ b/src/utils/__tests__/hookEntityDefinitions.spec.ts
@@ -0,0 +1,8 @@
+import { hookEntityDefinitions } from '../../hookInterface/hookEntityDefinitions';
+import hookInterface from '../../hookInterface/hookInterface';
+
+test('#hookEntityDefinitions', async () => {
+ const entities = [...new Set(hookInterface.reduce((out, hook) => [...out, ...hook.props, ...hook.mutable], []))];
+ const definitions = Object.keys(hookEntityDefinitions);
+ entities.forEach((entity) => expect(definitions).toContain(entity));
+});
From ddfd78acf8d9ad3581c595d60c8915f4562f675e Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Fri, 18 Sep 2020 13:52:41 -0400
Subject: [PATCH 47/75] 0.1.6-next.6
---
package-lock.json | 2 +-
package.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 2d7c936e..c01e0f2a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.6-next.5",
+ "version": "0.1.6-next.6",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index 36918e2a..8e78e610 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.6-next.5",
+ "version": "0.1.6-next.6",
"main": "./build/index.js",
"types": "./build/index.d.ts",
"engineStrict": true,
From 7b591cd28967a0c6e45919210e4f4c42b45211a6 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Fri, 18 Sep 2020 15:58:36 -0400
Subject: [PATCH 48/75] =?UTF-8?q?fix:=20=F0=9F=90=9B=20change=20siteUrl=20?=
=?UTF-8?q?to=20origin?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../__snapshots__/validations.spec.ts.snap | 56 ++++++++--------
src/utils/__tests__/validations.spec.ts | 2 +-
src/utils/validations.ts | 66 +------------------
3 files changed, 30 insertions(+), 94 deletions(-)
diff --git a/src/utils/__tests__/__snapshots__/validations.spec.ts.snap b/src/utils/__tests__/__snapshots__/validations.spec.ts.snap
index e372d036..f755fecd 100644
--- a/src/utils/__tests__/__snapshots__/validations.spec.ts.snap
+++ b/src/utils/__tests__/__snapshots__/validations.spec.ts.snap
@@ -22,7 +22,7 @@ ObjectSchema {
"srcDir",
"distDir",
"rootDir",
- "siteUrl",
+ "origin",
],
"_options": Object {
"abortEarly": true,
@@ -430,6 +430,33 @@ ObjectSchema {
],
"type": "object",
},
+ "origin": StringSchema {
+ "_blacklist": RefSet {
+ "list": Set {},
+ "refs": Map {},
+ },
+ "_conditions": Array [],
+ "_default": "",
+ "_deps": Array [],
+ "_exclusive": Object {},
+ "_label": "The domain your site is hosted on. https://yourdomain.com.",
+ "_mutate": undefined,
+ "_options": Object {
+ "abortEarly": true,
+ "recursive": true,
+ },
+ "_type": "string",
+ "_typeError": [Function],
+ "_whitelist": RefSet {
+ "list": Set {},
+ "refs": Map {},
+ },
+ "tests": Array [],
+ "transforms": Array [
+ [Function],
+ ],
+ "type": "string",
+ },
"plugins": ObjectSchema {
"_blacklist": RefSet {
"list": Set {},
@@ -634,33 +661,6 @@ ObjectSchema {
],
"type": "object",
},
- "siteUrl": StringSchema {
- "_blacklist": RefSet {
- "list": Set {},
- "refs": Map {},
- },
- "_conditions": Array [],
- "_default": "",
- "_deps": Array [],
- "_exclusive": Object {},
- "_label": "The domain your site is hosted on. https://yourdomain.com.",
- "_mutate": undefined,
- "_options": Object {
- "abortEarly": true,
- "recursive": true,
- },
- "_type": "string",
- "_typeError": [Function],
- "_whitelist": RefSet {
- "list": Set {},
- "refs": Map {},
- },
- "tests": Array [],
- "transforms": Array [
- [Function],
- ],
- "type": "string",
- },
"srcDir": StringSchema {
"_blacklist": RefSet {
"list": Set {},
diff --git a/src/utils/__tests__/validations.spec.ts b/src/utils/__tests__/validations.spec.ts
index 868aa775..a21a8536 100644
--- a/src/utils/__tests__/validations.spec.ts
+++ b/src/utils/__tests__/validations.spec.ts
@@ -39,7 +39,7 @@ describe('#validations', () => {
hooks: {
disable: [],
},
- siteUrl: '',
+ origin: '',
plugins: {},
server: {
prefix: '',
diff --git a/src/utils/validations.ts b/src/utils/validations.ts
index 979ff96e..f6a5affa 100644
--- a/src/utils/validations.ts
+++ b/src/utils/validations.ts
@@ -18,7 +18,7 @@ const shortcodeSchema = yup.object({
});
const configSchema = yup.object({
- siteUrl: yup.string().notRequired().default('').label(`The domain your site is hosted on. https://yourdomain.com.`),
+ origin: yup.string().notRequired().default('').label(`The domain your site is hosted on. https://yourdomain.com.`),
rootDir: yup.string().notRequired().default('process.cwd()').label('Here your package.json lives.'),
distDir: yup
.string()
@@ -32,70 +32,6 @@ const configSchema = yup.object({
.label(
"Where Elder.js should find it's expected file structure. If you are using a build step such as typescript on your project, you may need to edit this. ",
),
- // locations: yup
- // .object({
- // // assets: yup
- // // .string()
- // // .notRequired()
- // // .default('./public/dist/static/')
- // // .label(
- // // 'Where your site\'s assets files should be written to if you are using the Elder.js template. (Include ./public/)"',
- // // ),
- // // public: yup
- // // .string()
- // // .notRequired()
- // // .default('./public/')
- // // .label(
- // // 'Where should files be written? This represents the "root" of your site and where your html will be built.',
- // // ),
- // svelte: yup
- // .object()
- // .shape({
- // ssrComponents: yup
- // .string()
- // .notRequired()
- // .default('./___ELDER___/compiled/')
- // .label('Location where should SSR components be stored.'),
- // clientComponents: yup
- // .string()
- // .notRequired()
- // .default('./public/dist/svelte/')
- // .label(
- // 'Location where Svelte components that are bundled for the client should be saved. (Include ./public/)',
- // ),
- // })
- // .notRequired(),
- // systemJs: yup
- // .string()
- // .notRequired()
- // .default('/dist/static/s.min.js')
- // .label(
- // 'If you are using the recommended Elder.js rollup file it is using Systemjs. This defines is where the systemjs file will be found on your site. (exclude /public/)',
- // ),
- // srcFolder: yup
- // .string()
- // .notRequired()
- // .default('./src/')
- // .label('Elder.js and plugins use this to resolve where things should be in the expected file structure.'),
-
- // buildFolder: yup
- // .string()
- // .notRequired()
- // .default('')
- // .label(
- // `If Elder.js doesn't find the files it is looking for in the src folder, it will look in the build folder. (used for typescript)`,
- // ),
-
- // intersectionObserverPoly: yup
- // .string()
- // .notRequired()
- // .default('/dist/static/intersection-observer.js')
- // .label(
- // 'Elder.js uses a poly fill for the intersection observer. This is where it will be found on your site. (exclude /public/)',
- // ),
- // })
- // .notRequired()
- // .label('Where various files are written and read from.'),
debug: yup
.object()
.shape({
From dda2f79d1991816a73430010c5ea445237ca8426 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Fri, 18 Sep 2020 15:58:57 -0400
Subject: [PATCH 49/75] 0.1.6-next.7
---
package-lock.json | 2 +-
package.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index c01e0f2a..c0e7eb0f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.6-next.6",
+ "version": "0.1.6-next.7",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index 8e78e610..c529c373 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.6-next.6",
+ "version": "0.1.6-next.7",
"main": "./build/index.js",
"types": "./build/index.d.ts",
"engineStrict": true,
From 58b40ad8998a960b049d2609d796e4c4607238c5 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Mon, 21 Sep 2020 10:25:49 -0400
Subject: [PATCH 50/75] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20allRequests?=
=?UTF-8?q?=20to=20buildComplete?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/hookInterface/hookInterface.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/hookInterface/hookInterface.ts b/src/hookInterface/hookInterface.ts
index 1f2b4039..3bb1d7f5 100644
--- a/src/hookInterface/hookInterface.ts
+++ b/src/hookInterface/hookInterface.ts
@@ -282,7 +282,7 @@ export const hookInterface: Array = [
{
hook: 'buildComplete',
- props: ['helpers', 'data', 'settings', 'timings', 'query', 'errors', 'routes'],
+ props: ['helpers', 'data', 'settings', 'timings', 'query', 'errors', 'routes', 'allRequests'],
mutable: [],
context: 'Executed after a build is complete',
use: `
Contains whether the build was successful. If not it contains errors for the entire build. Also includes
From b8baaec1c95e27a5755847256787ed9e5001d28f Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Mon, 21 Sep 2020 10:59:28 -0400
Subject: [PATCH 51/75] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20partialHydration?=
=?UTF-8?q?=20error=20for=20non-self=20closing=20tags?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../__tests__/partialHydration.spec.ts | 24 +++++++++++++++++++
src/partialHydration/partialHydration.ts | 13 ++++++++++
2 files changed, 37 insertions(+)
diff --git a/src/partialHydration/__tests__/partialHydration.spec.ts b/src/partialHydration/__tests__/partialHydration.spec.ts
index 1bdd3b60..41ed0f6e 100644
--- a/src/partialHydration/__tests__/partialHydration.spec.ts
+++ b/src/partialHydration/__tests__/partialHydration.spec.ts
@@ -39,4 +39,28 @@ test('#partialHydration', async () => {
})
).code,
).toEqual(`Contains whether the build was successful. If not it contains errors for the entire build. Also includes
average performance details, and a granular performance object. Could be used to fire off additional scripts such as generating a sitemap or copying asset files to the public folder.
Contains whether the build was successful. If not it contains errors for the entire build. Also includes
average performance details, and a granular performance object. Could be used to fire off additional scripts such as generating a sitemap or copying asset files to the public folder.
From bc602a2b3871f9edd07d40cc72c9778a2b7b6e0f Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Mon, 21 Sep 2020 11:36:51 -0400
Subject: [PATCH 53/75] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20improve=20error=20?=
=?UTF-8?q?text=20on=20wrapping=20component?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/partialHydration/partialHydration.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/partialHydration/partialHydration.ts b/src/partialHydration/partialHydration.ts
index cea4a899..40c73026 100644
--- a/src/partialHydration/partialHydration.ts
+++ b/src/partialHydration/partialHydration.ts
@@ -37,7 +37,7 @@ const partialHydration = {
if (wrappedComponents && wrappedComponents.length > 0) {
throw new Error(
- `Elder.js only supports self-closing syntax on hydrated components. This means not or Something. Offending component: ${wrappedComponents[0][0]}`,
+ `Elder.js only supports self-closing syntax on hydrated components. This means not or Something. Offending component: ${wrappedComponents[0][0]}. Slots and child components aren't supported during hydration as it would result in huge HTML payloads. If you need this functionality try wrapping the offending component in a parent component without slots or child components and hydrate that.`,
);
}
From f1d6f9e105b3c7bac664bb8dc73ca216c6a6afd4 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Mon, 21 Sep 2020 14:13:02 -0400
Subject: [PATCH 54/75] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20better=20err?=
=?UTF-8?q?or=20message=20on=20partial=20hydration?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/partialHydration/partialHydration.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/partialHydration/partialHydration.ts b/src/partialHydration/partialHydration.ts
index 40c73026..44ac508e 100644
--- a/src/partialHydration/partialHydration.ts
+++ b/src/partialHydration/partialHydration.ts
@@ -37,7 +37,7 @@ const partialHydration = {
if (wrappedComponents && wrappedComponents.length > 0) {
throw new Error(
- `Elder.js only supports self-closing syntax on hydrated components. This means not or Something. Offending component: ${wrappedComponents[0][0]}. Slots and child components aren't supported during hydration as it would result in huge HTML payloads. If you need this functionality try wrapping the offending component in a parent component without slots or child components and hydrate that.`,
+ `Elder.js only supports self-closing syntax on hydrated components. This means not or Something. Offending component: ${wrappedComponents[0][0]}. Slots and child components aren't supported during hydration as it would result in huge HTML payloads. If you need this functionality try wrapping the offending component in a parent component without slots or child components and hydrate the parent component.`,
);
}
From 4260ae67b9c197bea3cfa442819b10379c73cc98 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Mon, 21 Sep 2020 14:13:30 -0400
Subject: [PATCH 55/75] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20shortcode=20debugg?=
=?UTF-8?q?ing,=20support=20for=20\\[=20\\]=20brackets?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../__snapshots__/validations.spec.ts.snap | 30 +++++++++++++++-
.../__tests__/prepareInlineShortcode.spec.ts | 23 ++++++++++++
.../__tests__/prepareShortcodeParser.spec.ts | 36 +++++++++++++++++++
src/utils/__tests__/validations.spec.ts | 1 +
src/utils/prepareInlineShortcode.ts | 11 +++---
src/utils/prepareShortcodeParser.ts | 4 +++
src/utils/types.ts | 1 +
src/utils/validations.ts | 7 +++-
8 files changed, 107 insertions(+), 6 deletions(-)
diff --git a/src/utils/__tests__/__snapshots__/validations.spec.ts.snap b/src/utils/__tests__/__snapshots__/validations.spec.ts.snap
index f755fecd..f877b1a1 100644
--- a/src/utils/__tests__/__snapshots__/validations.spec.ts.snap
+++ b/src/utils/__tests__/__snapshots__/validations.spec.ts.snap
@@ -138,6 +138,7 @@ ObjectSchema {
"automagic",
"build",
"performance",
+ "shortcodes",
"hooks",
"stacks",
],
@@ -242,7 +243,34 @@ ObjectSchema {
"_default": false,
"_deps": Array [],
"_exclusive": Object {},
- "_label": "Outputs a detauled speed report on each pageload.",
+ "_label": "Outputs a detailed speed report on each pageload.",
+ "_mutate": undefined,
+ "_options": Object {
+ "abortEarly": true,
+ "recursive": true,
+ },
+ "_type": "boolean",
+ "_typeError": [Function],
+ "_whitelist": RefSet {
+ "list": Set {},
+ "refs": Map {},
+ },
+ "tests": Array [],
+ "transforms": Array [
+ [Function],
+ ],
+ "type": "boolean",
+ },
+ "shortcodes": BooleanSchema {
+ "_blacklist": RefSet {
+ "list": Set {},
+ "refs": Map {},
+ },
+ "_conditions": Array [],
+ "_default": false,
+ "_deps": Array [],
+ "_exclusive": Object {},
+ "_label": "Output details of shortcode execution in the console.",
"_mutate": undefined,
"_options": Object {
"abortEarly": true,
diff --git a/src/utils/__tests__/prepareInlineShortcode.spec.ts b/src/utils/__tests__/prepareInlineShortcode.spec.ts
index a6733f23..317b89ae 100644
--- a/src/utils/__tests__/prepareInlineShortcode.spec.ts
+++ b/src/utils/__tests__/prepareInlineShortcode.spec.ts
@@ -42,4 +42,27 @@ describe('#prepareInlineShortcode', () => {
}),
).toEqual("
If you're looking to use Elder.js with express/polka to build a server rendered website, then you'll be interested in this hook as it includes the familiar 'req' and 'next' objects as often used in Express middleware.
If you're looking to use Elder.js with express/polka to build a server rendered website, then you'll be interested in this hook as it includes the familiar 'req' and 'next' objects as often used in Express middleware.
@@ -1062,6 +1071,17 @@ Elder {
"priority": 1,
"run": [Function],
},
+ Object {
+ "$$meta": Object {
+ "addedBy": "elder.js",
+ "type": "internal",
+ },
+ "description": "An express like middleware so requests can be served by Elder.js",
+ "hook": "middleware",
+ "name": "elderExpressLikeMiddleware",
+ "priority": 1,
+ "run": [Function],
+ },
Object {
"$$meta": Object {
"addedBy": "elder.js",
diff --git a/src/__tests__/__snapshots__/hooks.spec.ts.snap b/src/__tests__/__snapshots__/hooks.spec.ts.snap
index 793a14d4..76bdb7d3 100644
--- a/src/__tests__/__snapshots__/hooks.spec.ts.snap
+++ b/src/__tests__/__snapshots__/hooks.spec.ts.snap
@@ -88,6 +88,13 @@ Array [
"priority": 1,
"run": [Function],
},
+ Object {
+ "description": "An express like middleware so requests can be served by Elder.js",
+ "hook": "middleware",
+ "name": "elderExpressLikeMiddleware",
+ "priority": 1,
+ "run": [Function],
+ },
Object {
"description": "Builds the shortcode parser, parses shortcodes from the html returned by the route's html and appends anything needed to the stacks.",
"hook": "shortcodes",
diff --git a/src/hookInterface/hookEntityDefinitions.ts b/src/hookInterface/hookEntityDefinitions.ts
index 82624439..d521f86a 100644
--- a/src/hookInterface/hookEntityDefinitions.ts
+++ b/src/hookInterface/hookEntityDefinitions.ts
@@ -38,6 +38,8 @@ const hookEntityDefinitions = {
footerString: 'A HTML string that Elder.js will write to the footer.',
layoutHtml:
"The compiled HTML response for a route containing all of the HTML from the Route's layout and template. ",
+ serverLookupObject: `A key value object where the key is the relative permalink and the object is the 'request' object used by the Elder.js server.`,
+ runHook: `The function that powers hooks. 'await runhook('hookName', objectContainingProps)`,
};
// eslint-disable-next-line import/prefer-default-export
diff --git a/src/hookInterface/hookInterface.ts b/src/hookInterface/hookInterface.ts
index 3bb1d7f5..4c545343 100644
--- a/src/hookInterface/hookInterface.ts
+++ b/src/hookInterface/hookInterface.ts
@@ -53,32 +53,20 @@ export const hookInterface: Array = [
hook: 'middleware',
props: [
'errors',
- 'request',
'query',
'helpers',
'data',
- 'route',
- 'settings',
- 'allRequests',
- 'routes',
- 'req',
- 'next',
- 'res',
- ],
- mutable: [
- 'errors',
- 'request',
- 'query',
- 'helpers',
- 'data',
- 'route',
'settings',
'allRequests',
'routes',
'req',
'next',
'res',
+ 'serverLookupObject',
+ 'runHook',
+ 'shortcodes',
],
+ mutable: ['errors', 'query', 'helpers', 'data', 'settings', 'allRequests', 'routes', 'req', 'next', 'res'],
context:
'Fired upon a request that originates from the express/polka middleware version of Elder.js. The hook has access to "req" and "next" common in express like middleware.',
use: `
If you're looking to use Elder.js with express/polka to build a server rendered website, then you'll be interested in this hook as it includes the familiar 'req' and 'next' objects as often used in Express middleware.
diff --git a/src/hooks.ts b/src/hooks.ts
index 41b872cc..fc24b49f 100644
--- a/src/hooks.ts
+++ b/src/hooks.ts
@@ -4,6 +4,7 @@ import { parseBuildPerf } from './utils';
import externalHelpers from './externalHelpers';
import { HookOptions } from './hookInterface/types';
import prepareShortcodeParser from './utils/prepareShortcodeParser';
+import Page from './utils/Page';
const hooks: Array = [
{
@@ -29,6 +30,80 @@ const hooks: Array = [
return null;
},
},
+ {
+ hook: 'middleware',
+ name: 'elderExpressLikeMiddleware',
+ description: 'An express like middleware so requests can be served by Elder.js',
+ priority: 1,
+ run: async ({
+ serverLookupObject,
+ settings,
+ query,
+ helpers,
+ data,
+ routes,
+ allRequests,
+ runHook,
+ errors,
+ shortcodes,
+ req,
+ next,
+ res,
+ }) => {
+ if (req.path) {
+ let reqPath = req.path;
+
+ if (settings.server.prefix && settings.server.prefix.length > 0) {
+ if (reqPath.indexOf(settings.server.prefix) !== 0) {
+ return next();
+ }
+ }
+
+ // see if we have a request object with the path as is. (could include / or not.)
+ let requestObject = serverLookupObject[reqPath];
+
+ if (!requestObject && reqPath[reqPath.length - 1] === '/') {
+ // check the path without a slash.
+ requestObject = serverLookupObject[reqPath.substring(0, reqPath.length - 1)];
+ } else if (!requestObject) {
+ // check the path with a slash.
+ reqPath += '/';
+ requestObject = serverLookupObject[reqPath];
+ }
+
+ // if we have a requestObject then we know it is for ElderGuide
+ if (requestObject) {
+ const forPage = {
+ request: requestObject,
+ settings,
+ query,
+ helpers,
+ data,
+ route: routes[requestObject.route],
+ runHook,
+ allRequests,
+ routes,
+ errors,
+ shortcodes,
+ };
+
+ const page = new Page(forPage);
+
+ const html = await page.html();
+
+ if (html && !res.headerSent) {
+ res.setHeader('Content-Type', 'text/html');
+ res.end(html);
+ }
+ } else {
+ next();
+ }
+ } else {
+ next();
+ }
+ return {};
+ },
+ },
{
hook: 'shortcodes',
name: 'elderProcessShortcodes',
diff --git a/src/utils/__tests__/prepareServer.spec.ts b/src/utils/__tests__/prepareServer.spec.ts
index f07ebc6c..194b1dd1 100644
--- a/src/utils/__tests__/prepareServer.spec.ts
+++ b/src/utils/__tests__/prepareServer.spec.ts
@@ -1,6 +1,13 @@
import { prepareServer } from '../prepareServer';
-jest.mock('../Page');
+jest.mock('../Page', () => {
+ return {
+ default: jest.fn().mockImplementation(() => {
+ return {};
+ }),
+ html: () => 'html',
+ };
+});
describe('#prepareServer', () => {
it('works', async () => {
@@ -70,6 +77,7 @@ describe('#prepareServer', () => {
const nextMock = jest.fn(() => 'nextMockResult');
const setHeaderMock = jest.fn();
const endMock = jest.fn();
+
const res = {
setHeader: setHeaderMock,
end: endMock,
@@ -97,7 +105,6 @@ describe('#prepareServer', () => {
),
).toEqual(undefined);
expect(hooks).toEqual(['middleware']);
- expect(setHeaderMock).toHaveBeenCalledTimes(1);
expect(endMock).toHaveBeenCalledTimes(1);
expect(nextMock).toHaveBeenCalledTimes(1); // no new calls
// no requestObject
@@ -112,6 +119,7 @@ describe('#prepareServer', () => {
).toEqual(undefined);
expect(setHeaderMock).toHaveBeenCalledTimes(2);
expect(endMock).toHaveBeenCalledTimes(2);
+ expect(setHeaderMock).toHaveBeenCalledTimes(1);
expect(nextMock).toHaveBeenCalledTimes(2); // new call
});
});
diff --git a/src/utils/prepareServer.ts b/src/utils/prepareServer.ts
index 1c57aeb6..32855721 100644
--- a/src/utils/prepareServer.ts
+++ b/src/utils/prepareServer.ts
@@ -1,74 +1,15 @@
-import Page from './Page';
-
function prepareServer({ bootstrapComplete }) {
// eslint-disable-next-line consistent-return
return async function prepServer(req, res, next) {
- const {
- serverLookupObject,
- settings,
- query,
- helpers,
- data,
- routes,
- allRequests,
- runHook,
- errors,
- shortcodes,
- } = await bootstrapComplete;
-
- if (req.path) {
- let { path } = req;
-
- if (settings.server.prefix && settings.server.prefix.length > 0) {
- if (path.indexOf(settings.server.prefix) !== 0) {
- return next();
- }
- }
-
- // see if we have a request object with the path as is. (could include / or not.)
- let requestObject = serverLookupObject[path];
- if (!requestObject && path[path.length - 1] === '/') {
- // check the path without a slash.
- requestObject = serverLookupObject[path.substring(0, path.length - 1)];
- } else if (!requestObject) {
- // check the path with a slash.
- path += '/';
- requestObject = serverLookupObject[path];
- }
+ const { runHook, ...bootstrap } = await bootstrapComplete;
- // if we have a requestObject then we know it is for ElderGuide
- if (requestObject) {
- const forPage = {
- request: requestObject,
- settings,
- query,
- helpers,
- data,
- route: routes[requestObject.route],
- runHook,
- allRequests,
- routes,
- errors,
- shortcodes,
- };
-
- await runHook('middleware', { ...forPage, req, next, res });
-
- const page = new Page(forPage);
-
- if (!res.headerSent) {
- res.setHeader('Content-Type', 'text/html');
- res.end(await page.html());
- }
- } else {
- if (settings.server.prefix && settings.server.prefix.length > 0) {
- res.setHeader('Content-Type', 'application/json');
- res.end('{ "error": "Unknown template" }');
- }
-
- next();
- }
- }
+ await runHook('middleware', {
+ ...bootstrap,
+ runHook,
+ req,
+ next,
+ res,
+ });
};
}
From 14f8adb64f1798cb71b258e562ee907b3b54eb5e Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Mon, 21 Sep 2020 18:55:47 -0400
Subject: [PATCH 59/75] 0.1.6-next.9
---
package-lock.json | 2 +-
package.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 0c842db6..439e355e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.6-next.8",
+ "version": "0.1.6-next.9",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index a22f57fc..8e53337d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.6-next.8",
+ "version": "0.1.6-next.9",
"main": "./build/index.js",
"types": "./build/index.d.ts",
"engineStrict": true,
From 138673fdfb69ed6abd482927105a7b304e1df191 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Mon, 21 Sep 2020 19:06:32 -0400
Subject: [PATCH 60/75] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20request=20to?=
=?UTF-8?q?=20scope=20of=20middleware,=20update=20docs?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/hookInterface/hookInterface.ts | 19 +++++++++++++++++--
src/hooks.ts | 10 ++++++++--
src/utils/prepareServer.ts | 1 +
3 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/src/hookInterface/hookInterface.ts b/src/hookInterface/hookInterface.ts
index 4c545343..da587ef9 100644
--- a/src/hookInterface/hookInterface.ts
+++ b/src/hookInterface/hookInterface.ts
@@ -65,13 +65,28 @@ export const hookInterface: Array = [
'serverLookupObject',
'runHook',
'shortcodes',
+ 'request',
+ ],
+ mutable: [
+ 'errors',
+ 'query',
+ 'helpers',
+ 'data',
+ 'settings',
+ 'allRequests',
+ 'routes',
+ 'req',
+ 'next',
+ 'res',
+ 'request',
],
- mutable: ['errors', 'query', 'helpers', 'data', 'settings', 'allRequests', 'routes', 'req', 'next', 'res'],
context:
'Fired upon a request that originates from the express/polka middleware version of Elder.js. The hook has access to "req" and "next" common in express like middleware.',
use: `
If you're looking to use Elder.js with express/polka to build a server rendered website, then you'll be interested in this hook as it includes the familiar 'req' and 'next' objects as often used in Express middleware.
-
This hook could be used to set user or session information stored on the 'req' prop anywhere it is needed such as on the Elder.js 'request' object or 'data' object.
+
Under the hook Elder.js uses this hook to power the server implementation.
+
If you want to change the route of a request, you can do so by modifying the 'request.route' to the name of the new request, and it will be picked up by the default Elder.js server.
+
If you're looking to set user or session information stored on the 'req' prop we recommend using a hook to modify the 'request' object or 'data' objects. Change to the request object will be passed down.
If you're looking to pass in details about the query string deeper into your application, you could use this hook to do so.
Anything you'd use an Express 'req' or 'next' for you can do and customize other parts of the Elder.js on this hook.
If you're looking to use Elder.js with express/polka to build a server rendered website, then you'll be interested in this hook as it includes the familiar 'req' and 'next' objects as often used in Express middleware.
-
This hook could be used to set user or session information stored on the 'req' prop anywhere it is needed such as on the Elder.js 'request' object or 'data' object.
+
Under the hook Elder.js uses this hook to power the server implementation.
+
If you want to change the route of a request, you can do so by modifying the 'request.route' to the name of the new request, and it will be picked up by the default Elder.js server.
+
If you're looking to set user or session information stored on the 'req' prop we recommend using a hook to modify the 'request' object or 'data' objects. Change to the request object will be passed down.
If you're looking to pass in details about the query string deeper into your application, you could use this hook to do so.
Anything you'd use an Express 'req' or 'next' for you can do and customize other parts of the Elder.js on this hook.
If you're looking to use Elder.js with express/polka to build a server rendered website, then you'll be interested in this hook as it includes the familiar 'req' and 'next' objects as often used in Express middleware.
-
This hook could be used to set user or session information stored on the 'req' prop anywhere it is needed such as on the Elder.js 'request' object or 'data' object.
+
Under the hook Elder.js uses this hook to power the server implementation.
+
If you want to change the route of a request, you can do so by modifying the 'request.route' to the name of the new request, and it will be picked up by the default Elder.js server.
+
If you're looking to set user or session information stored on the 'req' prop we recommend using a hook to modify the 'request' object or 'data' objects. Change to the request object will be passed down.
If you're looking to pass in details about the query string deeper into your application, you could use this hook to do so.
Anything you'd use an Express 'req' or 'next' for you can do and customize other parts of the Elder.js on this hook.
",
From 2e987560a84e66b5a0e8cfe8bb59b6c539caf2c9 Mon Sep 17 00:00:00 2001
From: halafi
Date: Tue, 22 Sep 2020 13:56:54 +0200
Subject: [PATCH 63/75] test: hooks.spec.ts
---
.../__snapshots__/hooks.spec.ts.snap | 9 --
src/__tests__/hooks.spec.ts | 85 ++++++++++++++++++-
2 files changed, 81 insertions(+), 13 deletions(-)
diff --git a/src/__tests__/__snapshots__/hooks.spec.ts.snap b/src/__tests__/__snapshots__/hooks.spec.ts.snap
index 76bdb7d3..29d9458a 100644
--- a/src/__tests__/__snapshots__/hooks.spec.ts.snap
+++ b/src/__tests__/__snapshots__/hooks.spec.ts.snap
@@ -70,15 +70,6 @@ Object {
}
`;
-exports[`#hooks elderProcessShortcodes 1`] = `
-Object {
- "helpers": Object {
- "old": [MockFunction],
- "permalink": [MockFunction],
- },
-}
-`;
-
exports[`#hooks matchesSnapshot 1`] = `
Array [
Object {
diff --git a/src/__tests__/hooks.spec.ts b/src/__tests__/hooks.spec.ts
index a4e085a7..a390d307 100644
--- a/src/__tests__/hooks.spec.ts
+++ b/src/__tests__/hooks.spec.ts
@@ -2,6 +2,21 @@ import hooks from '../hooks';
jest.mock('../externalHelpers', () => () => Promise.resolve({ permalink: jest.fn() }));
+jest.mock('../utils/prepareShortcodeParser', () => ({ customJsStack, cssStack, headStack }) => ({
+ parse: (templateHtml) => {
+ customJsStack.push('console.log("test");');
+ cssStack.push('body{display:none;}');
+ headStack.push('Hello');
+ return Promise.resolve(`..${templateHtml}..`);
+ },
+}));
+
+jest.mock('../utils/Page', () => {
+ return jest.fn(() => ({
+ html: () => Promise.resolve(`new page`),
+ }));
+});
+
process.cwd = () => 'test';
jest.mock('path', () => ({
@@ -30,11 +45,73 @@ describe('#hooks', () => {
const hook = hooks.find((h) => h.name === 'elderAddExternalHelpers');
expect(await hook.run({ helpers: { old: jest.fn() }, query: {}, settings: {} })).toMatchSnapshot();
});
+ it('elderExpressLikeMiddleware', async () => {
+ const hook = hooks.find((h) => h.name === 'elderExpressLikeMiddleware');
+ const next = () => 'next() was called';
+ const settings = {
+ server: {
+ prefix: '/dev',
+ },
+ };
+ // prefix not found
+ expect(
+ await hook.run({
+ next,
+ req: { path: '/' },
+ settings,
+ }),
+ ).toEqual('next() was called');
+ const headers = [];
+ const end = jest.fn();
+ // route found with slash added
+ expect(
+ await hook.run({
+ next,
+ req: { path: '/dev' },
+ res: {
+ headerSent: false,
+ setHeader: (key, val) => {
+ headers.push(`${key}-${val}`);
+ },
+ end,
+ },
+ routes: {
+ Home: {
+ data: { foo: 'bar' },
+ },
+ },
+ serverLookupObject: {
+ '/dev/': {
+ route: 'Home',
+ },
+ },
+ settings,
+ }),
+ ).toEqual({});
+ expect(end).toHaveBeenCalledTimes(1);
+ expect(headers).toEqual(['Content-Type-text/html']);
+ });
it('elderProcessShortcodes', async () => {
- const hook = hooks.find((h) => h.name === 'elderAddExternalHelpers');
- expect(await hook.run({ helpers: { old: jest.fn() }, query: {}, settings: {} })).toMatchSnapshot();
-
- // TODO!!!
+ const hook = hooks.find((h) => h.name === 'elderProcessShortcodes');
+ const headStack = [];
+ const cssStack = [];
+ const customJsStack = [];
+ expect(
+ await hook.run({
+ headStack,
+ cssStack,
+ customJsStack,
+ templateHtml: 'hi',
+ helpers: {},
+ query: {},
+ settings: {},
+ }),
+ ).toEqual({
+ cssStack: ['body{display:none;}'],
+ customJsStack: ['console.log("test");'],
+ headStack: ['Hello'],
+ templateHtml: '..hi..',
+ });
});
it('elderAddMetaCharsetToHead', async () => {
const hook = hooks.find((h) => h.name === 'elderAddMetaCharsetToHead');
From 0372e1ef04416fd2df75ab088e9b342b6ec50305 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Tue, 22 Sep 2020 08:04:18 -0400
Subject: [PATCH 64/75] =?UTF-8?q?fix:=20=F0=9F=90=9B=20check=20for=20reque?=
=?UTF-8?q?st=20object?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/hooks.ts | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/src/hooks.ts b/src/hooks.ts
index 990a830b..6cd1e7b8 100644
--- a/src/hooks.ts
+++ b/src/hooks.ts
@@ -72,13 +72,12 @@ const hooks: Array = [
requestObject = serverLookupObject[reqPath];
}
- let route = routes[requestObject.route];
- if (request && request.route) {
- route = routes[request.route];
- }
-
// if we have a requestObject then we know it is for ElderGuide
if (requestObject) {
+ let route = routes[requestObject.route];
+ if (request && request.route) {
+ route = routes[request.route];
+ }
const forPage = {
request: { ...requestObject, ...request },
settings,
From 168baf0f779c9cfa63eb1d8055776d4c88101934 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Tue, 22 Sep 2020 08:16:07 -0400
Subject: [PATCH 65/75] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20can=20use=20/compo?=
=?UTF-8?q?ntents/name/Name.svelte=20or=20without=20folder?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/utils/getRollupConfig.ts | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/utils/getRollupConfig.ts b/src/utils/getRollupConfig.ts
index c444406a..d6cc783b 100644
--- a/src/utils/getRollupConfig.ts
+++ b/src/utils/getRollupConfig.ts
@@ -208,7 +208,7 @@ export default function getRollupConfig({ svelteConfig }) {
if (fs.existsSync(path.resolve(srcDir, `./components/`))) {
configs.push(
createBrowserConfig({
- input: [`${relSrcDir}/components/*/*.svelte`],
+ input: [`${relSrcDir}/components/*/*.svelte`, `${relSrcDir}/components/*.svelte`],
output: {
dir: clientComponents,
entryFileNames: 'entry[name]-[hash].js',
@@ -224,7 +224,7 @@ export default function getRollupConfig({ svelteConfig }) {
);
configs.push(
createSSRConfig({
- input: [`${relSrcDir}/components/*/*.svelte`],
+ input: [`${relSrcDir}/components/*/*.svelte`, `${relSrcDir}/components/*.svelte`],
output: {
dir: ssrComponents,
format: 'cjs',
@@ -240,9 +240,11 @@ export default function getRollupConfig({ svelteConfig }) {
}
} else {
// watch/dev build bundles each component individually for faster reload times during dev.
-
if (fs.existsSync(path.resolve(srcDir, `./components/`))) {
- glob.sync(path.resolve(srcDir, './components/*/*.svelte')).forEach((cv) => {
+ [
+ ...glob.sync(path.resolve(srcDir, './components/*/*.svelte')),
+ ...glob.sync(path.resolve(srcDir, './components/*.svelte')),
+ ].forEach((cv) => {
const file = cv.replace(`${rootDir}/`, '');
configs.push(
createBrowserConfig({
From 936a8f5a0d2173b64a8d8fe212320462719bf474 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Tue, 22 Sep 2020 08:17:01 -0400
Subject: [PATCH 66/75] =?UTF-8?q?fix:=20=F0=9F=90=9B=20fix=20test?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/utils/__tests__/__snapshots__/getRollupConfig.spec.ts.snap | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/utils/__tests__/__snapshots__/getRollupConfig.spec.ts.snap b/src/utils/__tests__/__snapshots__/getRollupConfig.spec.ts.snap
index f9a690a3..54c3338f 100644
--- a/src/utils/__tests__/__snapshots__/getRollupConfig.spec.ts.snap
+++ b/src/utils/__tests__/__snapshots__/getRollupConfig.spec.ts.snap
@@ -246,6 +246,7 @@ Array [
"cache": true,
"input": Array [
"rc/components/*/*.svelte",
+ "rc/components/*.svelte",
],
"output": Object {
"dir": "test/public/svelte",
@@ -310,6 +311,7 @@ Array [
"cache": true,
"input": Array [
"rc/components/*/*.svelte",
+ "rc/components/*.svelte",
],
"output": Object {
"dir": "test/___ELDER___/compiled",
From 467369334d0ffe766f08daf4bb0b580b06bdd4a6 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Tue, 22 Sep 2020 08:17:32 -0400
Subject: [PATCH 67/75] 0.1.6-next.10
---
package-lock.json | 2 +-
package.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 439e355e..f7148ac6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.6-next.9",
+ "version": "0.1.6-next.10",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index 8e53337d..dcf51773 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.6-next.9",
+ "version": "0.1.6-next.10",
"main": "./build/index.js",
"types": "./build/index.d.ts",
"engineStrict": true,
From 6f65dd19e025c3f5eef7b1b67c13262ce67fcbbb Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Tue, 22 Sep 2020 08:40:34 -0400
Subject: [PATCH 68/75] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20warning=20for=20no?=
=?UTF-8?q?=20origin=20in=20elder.config.js?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/utils/getConfig.ts | 6 ++++++
src/utils/types.ts | 1 +
2 files changed, 7 insertions(+)
diff --git a/src/utils/getConfig.ts b/src/utils/getConfig.ts
index eb06c8f4..13c9272f 100644
--- a/src/utils/getConfig.ts
+++ b/src/utils/getConfig.ts
@@ -28,6 +28,12 @@ function getConfig(): ConfigOptions {
clientComponents,
};
+ if (config.origin === '') {
+ console.error(
+ `Remember to put a valid origin in your elder.config.js. This should be a fully qualified domain. This is frequently used plugins and leaving it blank can cause SEO headaches.`,
+ );
+ }
+
return config;
}
diff --git a/src/utils/types.ts b/src/utils/types.ts
index 91373fc8..b394aa8f 100644
--- a/src/utils/types.ts
+++ b/src/utils/types.ts
@@ -50,6 +50,7 @@ export type ConfigOptions = {
distDir: string;
srcDir: string;
rootDir: string;
+ origin: string;
server: ServerOptions;
build: BuildOptions;
From 5b244196fb0552fc21316826c1dce83c94283229 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Tue, 22 Sep 2020 08:40:45 -0400
Subject: [PATCH 69/75] 0.1.6-next.11
---
package-lock.json | 2 +-
package.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index f7148ac6..bcf8c041 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.6-next.10",
+ "version": "0.1.6-next.11",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index dcf51773..30ec5745 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.6-next.10",
+ "version": "0.1.6-next.11",
"main": "./build/index.js",
"types": "./build/index.d.ts",
"engineStrict": true,
From 021848a7ec505426b6eaaa2ab0b45593d566a6ed Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Tue, 22 Sep 2020 12:40:50 -0400
Subject: [PATCH 70/75] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20shortcodeSch?=
=?UTF-8?q?ema=20to=20export?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/index.ts | 3 +--
src/utils/getConfig.ts | 2 +-
src/utils/validations.ts | 4 +---
3 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/src/index.ts b/src/index.ts
index 27fff3cb..813fcdee 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,6 +1,5 @@
/* istanbul ignore file */
-export { configSchema, hookSchema, routeSchema, pluginSchema } from './utils/validations';
-
+export { configSchema, hookSchema, routeSchema, pluginSchema, shortcodeSchema } from './utils/validations';
export { Elder, build, partialHydration } from './Elder';
export * from './utils/types';
export * from './utils/index';
diff --git a/src/utils/getConfig.ts b/src/utils/getConfig.ts
index 13c9272f..9defce0f 100644
--- a/src/utils/getConfig.ts
+++ b/src/utils/getConfig.ts
@@ -30,7 +30,7 @@ function getConfig(): ConfigOptions {
if (config.origin === '') {
console.error(
- `Remember to put a valid origin in your elder.config.js. This should be a fully qualified domain. This is frequently used plugins and leaving it blank can cause SEO headaches.`,
+ `WARN: Remember to put a valid "origin" in your elder.config.js. This should be a fully qualified domain. This is frequently used plugins and leaving it blank can cause SEO headaches.`,
);
}
diff --git a/src/utils/validations.ts b/src/utils/validations.ts
index 81849c23..67f31840 100644
--- a/src/utils/validations.ts
+++ b/src/utils/validations.ts
@@ -117,9 +117,7 @@ const routeSchema = yup.object({
.mixed()
.notRequired()
.default({})
- .label(
- `Async/sync function that returns a JS object. Can also be a plain JS object. Important: If this is a function it is passed a '{data}' parameter. This parameter should be mutated and returned to pick up any data populated via hooks or plugins.`,
- ),
+ .label(`Async/sync function that returns a JS object. Can also be a plain JS object.`),
});
const pluginSchema = yup.object({
From 50fbb16994f548fe5e3785c2550ef149b070db74 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Tue, 22 Sep 2020 12:41:35 -0400
Subject: [PATCH 71/75] 0.1.6-next.12
---
package-lock.json | 2 +-
package.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index bcf8c041..e041bc97 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.6-next.11",
+ "version": "0.1.6-next.12",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index 30ec5745..0ad30bba 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.6-next.11",
+ "version": "0.1.6-next.12",
"main": "./build/index.js",
"types": "./build/index.d.ts",
"engineStrict": true,
From 39ef2f277a31e6f3663275e123747732a056414c Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Tue, 22 Sep 2020 13:42:47 -0400
Subject: [PATCH 72/75] =?UTF-8?q?fix:=20=F0=9F=90=9B=20fix=20validation=20?=
=?UTF-8?q?so=20the=20documentation=20is=20accurate?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/utils/validations.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/utils/validations.ts b/src/utils/validations.ts
index 67f31840..6e8d4bf2 100644
--- a/src/utils/validations.ts
+++ b/src/utils/validations.ts
@@ -141,7 +141,7 @@ const pluginSchema = yup.object({
.default({})
.notRequired()
.label('(optional) An object of default configs. These will be used when none are set in their elder.config.js.'),
- shortcodes: yup.mixed().notRequired().default([]).label('Array of shortcodes'),
+ shortcodes: yup.array().notRequired().default([]).label('Array of shortcodes'),
});
const hookSchema = yup
From 8d2bd6cff33e1dbdc898758b2c44af075fc32f93 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Tue, 22 Sep 2020 14:01:39 -0400
Subject: [PATCH 73/75] 0.1.6-next.13
---
package-lock.json | 2 +-
package.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index e041bc97..b0efd7fd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.6-next.12",
+ "version": "0.1.6-next.13",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index 0ad30bba..84aafdf8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@elderjs/elderjs",
- "version": "0.1.6-next.12",
+ "version": "0.1.6-next.13",
"main": "./build/index.js",
"types": "./build/index.d.ts",
"engineStrict": true,
From a3c105e059515cbd2f3520593af3acb1790d7759 Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Tue, 22 Sep 2020 14:19:56 -0400
Subject: [PATCH 74/75] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20better=20doc?=
=?UTF-8?q?s?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 38 ++++++++++++++++++++------------------
1 file changed, 20 insertions(+), 18 deletions(-)
diff --git a/README.md b/README.md
index 04e9d542..c8a2e75c 100644
--- a/README.md
+++ b/README.md
@@ -21,33 +21,35 @@
+[Elder.js](https://github.com/elderjs/elderjs) is an opinionated static site generator and web framework built with SEO in mind. (Supports SSR and Static Site Generation.)
-Elder.js is an opinionated static site generator and web framework built with SEO in mind. :rocket:
+- [Full Docs](https://elderguide.com/tech/elderjs/)
+- [Template](https://github.com/Elderjs/template)
+- [Plugins](https://github.com/Elderjs/plugins)
-Full documentation here: https://elderguide.com/tech/elderjs/
+**Features:**
-The quickest way to get started is here: https://github.com/Elderjs/template/
+- [**Build hooks**](https://elderguide.com/tech/elderjs/#hooks-how-to-customize-elderjs) allow you to plug into any part of entire page generation process and customize as needed.
+- **A Highly Optimized Build Process:** that will span as many CPU cores as you can throw at it to make building your site as fast as possible. For reference Elder.js easily generates a data intensive 18,000 page site in 8 minutes using a budget 4 core VM.
+- **Svelte Everywhere:** Use Svelte for your SSR templates and with partial hydration on the client for tiny html/bundle sizes.
+- **Straightforward Data Flow:** By simply associating a `data` function in your `route.js`, you have complete control over how you fetch, prepare, and manipulate data before sending it to your Svelte template. Anything you can do in Node.js, you can do to fetch your data. Multiple data sources, no problem.
+- **Community Plugins:** Easily extend what your Elder.js site can do by adding [prebuilt plugins](https://github.com/Elderjs/plugins) to your site.
+- **Shortcodes:** Future proof your content, whether it lives in a CMS or in static files using smart placeholders.
+- **0KB JS**: Defaults to 0KB of JS if your page doesn't need JS.
+- **Partial Hydration**: Unlike most frameworks, Elder.js lets you hydrate just the parts of the client that need to be interactive allowing you to dramatically reduce your payloads while still having full control over component lazy-loading, preloading, and eager-loading.
-If you find bugs please open an issue.
+**Context**
-**We consider Elder.js to be in 'beta' in terms of API stability but are using it in production on https://elderguide.com.**
+Elder.js is the result of our team's work to build this site ([ElderGuide.com](https://elderguide.com)) and was purpose built to solve the unique challenges of building flagship SEO sites with 10-100k+ pages.
-## Features:
+Elder Guide Co-Founder [Nick Reese](https://nicholasreese.com) has built or managed 5 major SEO properties over the past 14 years. After leading the transition of several complex sites to static site generators he loved the benefits of the JAM stack, but wished there was a better solution for complex, data intensive, projects. Elder.js is his vision for how static site generators can become viable for sites of all sizes regardless of the number of pages or how complex the data being presented is.
-* [**Build hooks**](https://elderguide.com/tech/elderjs/#hooks-how-to-customize-elderjs) allow you to plug into any part of entire page generation process and build process and customize as needed.
-* **A Highly Optimized Build Process:** that will span as many CPU cores as you can throw at it to make building your site as fast as possible. For reference Elder.js easily generates a data intensive 18,000 page site in 8 minutes using a budget 4 core VM.
-* **Svelte Everywhere:** Use Svelte for your SSR templates and with partial hydration on the client for tiny html/bundle sizes.
-* **Straightforward Data Flow:** Each route has a `data` function and you have complete control over how you fetch, prepare, and manipulate data before sending it to your Svelte template. Anything you can do in Node.js, you can do to fetch your data. Multiple data sources, no problem.
-* **Community Plugins:** Easily extend what your Elder.js site can do by adding [prebuilt plugins](https://github.com/Elderjs/plugins) to your site.
+We hope you find this project useful whether you're building a small personal blog or a flagship SEO site that impacts millions of users.
+## Getting Started:
-## Context
-
-Elder.js is the result of our team's work to build ([ElderGuide.com](https://elderguide.com)) and was purpose built to solve the unique challenges of building flagship SEO sites with 10-100k+ pages.
-
-Elder Guide co-Founder [Nick Reese](https://nicholasreese.com) has built or managed 5 major SEO properties over the past 14 years. After leading the transition of several complex sites to static site generators he loved the benefits of the JAM stack, but wished there was a better solution for complex, data intensive, projects. Elder.js is his vision for how static site generators can become viable for sites of all sizes regardless of the number of pages or how complex the data being presented is.
-
-We hope you find this project useful whether you're building a small personal blog or a flagship SEO site that impacts millions of users.
+The quickest way to get started is to get started with the [Elder.js template](https://github.com/Elderjs/template) using [degit](https://github.com/Rich-Harris/degit):
+Here is a demo of the template: [https://elderjs.netlify.app/](https://elderjs.netlify.app/)
## Full documentation here: https://elderguide.com/tech/elderjs/
From c571d4ad5944df06782850d73cdc2483911752ab Mon Sep 17 00:00:00 2001
From: Nick Reese
Date: Tue, 22 Sep 2020 14:23:51 -0400
Subject: [PATCH 75/75] =?UTF-8?q?test:=20=F0=9F=92=8D=20update=20tests?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../__snapshots__/validations.spec.ts.snap | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/utils/__tests__/__snapshots__/validations.spec.ts.snap b/src/utils/__tests__/__snapshots__/validations.spec.ts.snap
index f877b1a1..dcac9b99 100644
--- a/src/utils/__tests__/__snapshots__/validations.spec.ts.snap
+++ b/src/utils/__tests__/__snapshots__/validations.spec.ts.snap
@@ -1230,7 +1230,7 @@ ObjectSchema {
],
"type": "object",
},
- "shortcodes": SchemaType {
+ "shortcodes": ArraySchema {
"_blacklist": RefSet {
"list": Set {},
"refs": Map {},
@@ -1245,15 +1245,19 @@ ObjectSchema {
"abortEarly": true,
"recursive": true,
},
- "_type": "mixed",
+ "_subType": undefined,
+ "_type": "array",
"_typeError": [Function],
"_whitelist": RefSet {
"list": Set {},
"refs": Map {},
},
+ "innerType": undefined,
"tests": Array [],
- "transforms": Array [],
- "type": "mixed",
+ "transforms": Array [
+ [Function],
+ ],
+ "type": "array",
},
},
"tests": Array [],
@@ -1332,7 +1336,7 @@ ObjectSchema {
"_default": Object {},
"_deps": Array [],
"_exclusive": Object {},
- "_label": "Async/sync function that returns a JS object. Can also be a plain JS object. Important: If this is a function it is passed a '{data}' parameter. This parameter should be mutated and returned to pick up any data populated via hooks or plugins.",
+ "_label": "Async/sync function that returns a JS object. Can also be a plain JS object.",
"_mutate": undefined,
"_options": Object {
"abortEarly": true,