@parameter1/base-cms-marko-web 4.8.0 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/components/browser-component.marko.js +2 -2
  2. package/components/document/components/body-wrapper.marko.js +2 -2
  3. package/components/document/components/error.marko.js +2 -2
  4. package/components/document/components/live-reload.marko.js +2 -2
  5. package/components/document/components/polyfill.marko.js +2 -2
  6. package/components/document/components/styles.marko +23 -0
  7. package/components/document/components/styles.marko.js +57 -0
  8. package/components/document/container.marko.js +2 -2
  9. package/components/document/index.marko +8 -19
  10. package/components/document/index.marko.js +15 -38
  11. package/components/element/array.marko.js +2 -2
  12. package/components/element/audio.marko.js +2 -2
  13. package/components/element/block.marko.js +2 -2
  14. package/components/element/clear.marko.js +2 -2
  15. package/components/element/components/image.marko.js +2 -2
  16. package/components/element/components/text.marko.js +2 -2
  17. package/components/element/content/address1.marko.js +2 -2
  18. package/components/element/content/address2.marko.js +2 -2
  19. package/components/element/content/audio.marko.js +2 -2
  20. package/components/element/content/authors.marko.js +2 -2
  21. package/components/element/content/body.marko.js +2 -2
  22. package/components/element/content/byline.marko.js +2 -2
  23. package/components/element/content/city-state-zip.marko.js +2 -2
  24. package/components/element/content/contributors.marko.js +2 -2
  25. package/components/element/content/country.marko.js +2 -2
  26. package/components/element/content/embed-code.marko.js +2 -2
  27. package/components/element/content/end-date.marko.js +2 -2
  28. package/components/element/content/ends.marko.js +2 -2
  29. package/components/element/content/fax.marko.js +2 -2
  30. package/components/element/content/images.marko.js +2 -2
  31. package/components/element/content/mobile.marko.js +2 -2
  32. package/components/element/content/name.marko.js +2 -2
  33. package/components/element/content/phone.marko.js +2 -2
  34. package/components/element/content/photographers.marko.js +2 -2
  35. package/components/element/content/public-email.marko.js +2 -2
  36. package/components/element/content/published.marko.js +2 -2
  37. package/components/element/content/short-name.marko.js +2 -2
  38. package/components/element/content/sidebar-stubs.marko.js +2 -2
  39. package/components/element/content/sidebars.marko.js +2 -2
  40. package/components/element/content/source.marko.js +2 -2
  41. package/components/element/content/sponsors.marko.js +2 -2
  42. package/components/element/content/start-date.marko.js +2 -2
  43. package/components/element/content/starts.marko.js +2 -2
  44. package/components/element/content/teaser.marko.js +2 -2
  45. package/components/element/content/title.marko.js +2 -2
  46. package/components/element/content/tollfree.marko.js +2 -2
  47. package/components/element/content/transcript.marko.js +2 -2
  48. package/components/element/content/website.marko.js +2 -2
  49. package/components/element/date.marko.js +2 -2
  50. package/components/element/image/caption.marko.js +2 -2
  51. package/components/element/image/credit.marko.js +2 -2
  52. package/components/element/image/display-name.marko.js +2 -2
  53. package/components/element/image/slider.marko.js +2 -2
  54. package/components/element/img.marko.js +2 -2
  55. package/components/element/index.marko.js +2 -2
  56. package/components/element/link.marko.js +2 -2
  57. package/components/element/magazine-issue/description.marko.js +2 -2
  58. package/components/element/magazine-issue/digital-edition-url.marko.js +2 -2
  59. package/components/element/magazine-issue/name.marko.js +2 -2
  60. package/components/element/magazine-issue/pdf-url.marko.js +2 -2
  61. package/components/element/magazine-publication/cancel-url.marko.js +2 -2
  62. package/components/element/magazine-publication/change-address-url.marko.js +2 -2
  63. package/components/element/magazine-publication/description.marko.js +2 -2
  64. package/components/element/magazine-publication/einquiry-url.marko.js +2 -2
  65. package/components/element/magazine-publication/name.marko.js +2 -2
  66. package/components/element/magazine-publication/renewal-url.marko.js +2 -2
  67. package/components/element/magazine-publication/reprints-url.marko.js +2 -2
  68. package/components/element/magazine-publication/subscribe-url.marko.js +2 -2
  69. package/components/element/obj-array.marko.js +2 -2
  70. package/components/element/obj-audio.marko.js +2 -2
  71. package/components/element/obj-date.marko.js +2 -2
  72. package/components/element/obj-nodes.marko.js +2 -2
  73. package/components/element/obj-text.marko.js +2 -2
  74. package/components/element/obj.marko.js +2 -2
  75. package/components/element/picture.marko.js +2 -2
  76. package/components/element/text.marko.js +2 -2
  77. package/components/element/website-section/description.marko.js +2 -2
  78. package/components/element/website-section/hierarchy.marko.js +2 -2
  79. package/components/element/website-section/name.marko.js +2 -2
  80. package/components/font/google.marko.js +2 -2
  81. package/components/font/link.marko.js +2 -2
  82. package/components/font/typekit.marko.js +2 -2
  83. package/components/load-more/index.marko.js +2 -2
  84. package/components/load-more/trigger.marko.js +2 -2
  85. package/components/node/body.marko.js +2 -2
  86. package/components/node/element.marko.js +2 -2
  87. package/components/node/footer.marko.js +2 -2
  88. package/components/node/header.marko.js +2 -2
  89. package/components/node/image-inner-wrapper.marko.js +2 -2
  90. package/components/node/image-wrapper.marko.js +2 -2
  91. package/components/node/image.marko.js +2 -2
  92. package/components/node/index.marko.js +2 -2
  93. package/components/node-list/body.marko.js +2 -2
  94. package/components/node-list/element.marko.js +2 -2
  95. package/components/node-list/footer.marko.js +2 -2
  96. package/components/node-list/header.marko.js +2 -2
  97. package/components/node-list/index.marko.js +2 -2
  98. package/components/node-list/node.marko.js +2 -2
  99. package/components/node-list/nodes.marko.js +2 -2
  100. package/components/page/container.marko.js +2 -2
  101. package/components/page/description.marko.js +2 -2
  102. package/components/page/image.marko.js +2 -2
  103. package/components/page/layouts/content.marko.js +2 -2
  104. package/components/page/layouts/default.marko.js +2 -2
  105. package/components/page/layouts/dynamic-page.marko.js +2 -2
  106. package/components/page/layouts/magazine-issue.marko.js +2 -2
  107. package/components/page/layouts/magazine-publication.marko.js +2 -2
  108. package/components/page/layouts/website-section.marko.js +2 -2
  109. package/components/page/metadata/components/common.marko.js +2 -2
  110. package/components/page/metadata/content.marko.js +2 -2
  111. package/components/page/metadata/default.marko.js +2 -2
  112. package/components/page/metadata/dynamic-page.marko.js +2 -2
  113. package/components/page/metadata/magazine-issue.marko.js +2 -2
  114. package/components/page/metadata/magazine-publication.marko.js +2 -2
  115. package/components/page/metadata/website-section.marko.js +2 -2
  116. package/components/page/rel-canonical.marko.js +2 -2
  117. package/components/page/title.marko.js +2 -2
  118. package/components/page/wrapper.marko.js +2 -2
  119. package/components/resolve/page.marko.js +2 -2
  120. package/components/rss/website-section.marko.js +2 -2
  121. package/config/core.js +0 -41
  122. package/eslint.log +3 -0
  123. package/express/asset-loader.js +55 -0
  124. package/express/cdn.js +27 -0
  125. package/express/css-loader.js +117 -0
  126. package/express/error-handlers.js +2 -0
  127. package/express/index.js +12 -3
  128. package/middleware/with-content.js +4 -0
  129. package/middleware/with-dynamic-page.js +4 -0
  130. package/middleware/with-magazine-issue.js +4 -0
  131. package/middleware/with-magazine-publication.js +4 -0
  132. package/middleware/with-website-section.js +4 -0
  133. package/package.json +3 -3
  134. package/scss/fonts/alata-fallback.scss +7 -0
  135. package/scss/fonts/arimo-fallback.scss +7 -0
  136. package/scss/fonts/fira-sans-fallback.scss +1 -0
  137. package/scss/fonts/ibm-plex-sans-fallback.scss +7 -0
  138. package/scss/fonts/informapro-fallback.scss +6 -0
  139. package/scss/fonts/lato-fallback.scss +7 -0
  140. package/scss/fonts/montserrat-fallback.scss +1 -0
  141. package/scss/fonts/open-sans-condensed-fallback.scss +1 -0
  142. package/scss/fonts/open-sans-fallback.scss +1 -0
  143. package/scss/fonts/oswold-fallback.scss +1 -0
  144. package/scss/fonts/roboto-condensed-fallback.scss +7 -0
  145. package/scss/fonts/roboto-fallback.scss +7 -0
  146. package/scss/fonts/roboto-slab-fallback.scss +7 -0
  147. package/scss/fonts/solitaire-mvb-pro-fallback.scss +6 -0
  148. package/scss/fonts/source-sans-4-fallback.scss +1 -0
  149. package/scss/fonts/source-serif-pro-fallback.scss +7 -0
  150. package/base-cms-marko-web-0.7.4.tgz +0 -0
  151. package/base-cms-marko-web-0.9.37.tgz +0 -0
  152. package/base-cms-marko-web-0.9.55.tgz +0 -0
  153. package/config/dist-loader.js +0 -42
  154. package/express/purged-css.js +0 -11
  155. package/public/lazysizes/v5.3.2.js +0 -2
@@ -0,0 +1,55 @@
1
+ const path = require('path');
2
+ const { readFile } = require('fs').promises;
3
+ const { asyncRoute } = require('@parameter1/base-cms-utils');
4
+
5
+ const readManifest = async (loc) => {
6
+ try {
7
+ const contents = await readFile(loc, 'utf8');
8
+ return JSON.parse(contents);
9
+ } catch (e) {
10
+ if (e.code === 'ENOENT') return null;
11
+ throw e;
12
+ }
13
+ };
14
+
15
+ const getRelPathFromManifest = async ({ distDir, type, entry }) => {
16
+ const file = path.resolve(distDir, type, 'manifest.json');
17
+ const manifest = await readManifest(file);
18
+ if (!manifest) throw new Error(`Unable to load the asset manifest for type ${type}`);
19
+
20
+ const asset = manifest[entry];
21
+ if (!asset) throw new Error(`Unable to extract an asset for type ${type} using manifest entry ${entry}`);
22
+ return `${type}/${asset.file}`;
23
+ };
24
+
25
+ const isProduction = process.env.NODE_ENV === 'production';
26
+ const types = [
27
+ { type: 'js', entry: 'browser/index.js' },
28
+ ];
29
+
30
+ module.exports = ({ distDir }) => asyncRoute(async (req, res, next) => {
31
+ const { cdn } = res.locals;
32
+ const { app } = req;
33
+
34
+ if (!app.locals.assets) app.locals.assets = {};
35
+ const { assets } = app.locals;
36
+
37
+ // when on production, only load the file paths from the manifest once
38
+ // as long as the cdn configs are the same (allows for changing the cdn env var in prod)
39
+ if (isProduction && assets.files && assets.cdn === cdn.enabled) return next();
40
+
41
+ // get file paths from manifests
42
+ const rels = await Promise.all(types.map(async ({ type, entry }) => {
43
+ const rel = await getRelPathFromManifest({ distDir, type, entry });
44
+ return { type, rel };
45
+ }));
46
+
47
+ assets.files = rels.reduce((map, { type, rel }) => {
48
+ const href = cdn.dist(rel);
49
+ map.set(type, [href]);
50
+ return map;
51
+ }, new Map());
52
+ assets.cdn = cdn.enabled;
53
+
54
+ return next();
55
+ });
package/express/cdn.js ADDED
@@ -0,0 +1,27 @@
1
+ const { cleanPath } = require('@parameter1/base-cms-utils');
2
+
3
+ module.exports = ({ enabled = false, origin, siteVersion } = {}) => (req, res, next) => {
4
+ const { config, tenantKey } = req.app.locals;
5
+ const url = `${cleanPath(origin)}/web-assets/${tenantKey}/${config.website('id')}/v${siteVersion}`;
6
+
7
+ const key = '__cdn';
8
+ const values = new Set(['true', '1']);
9
+ let isEnabled = enabled;
10
+ if (values.has(req.query[key])) isEnabled = true;
11
+ if (values.has(req.cookies[key])) isEnabled = true;
12
+
13
+ res.locals.cdn = {
14
+ enabled: isEnabled,
15
+ origin,
16
+ url,
17
+ dist: (path) => {
18
+ const cleaned = `dist/${cleanPath(path)}`;
19
+ return isEnabled ? `${url}/${cleaned}` : `/${cleaned}`;
20
+ },
21
+ public: (path) => {
22
+ const cleaned = cleanPath(path);
23
+ return isEnabled ? `${url}/public/${cleaned}` : `/${cleaned}`;
24
+ },
25
+ };
26
+ next();
27
+ };
@@ -0,0 +1,117 @@
1
+ const path = require('path');
2
+ const { readFile } = require('fs').promises;
3
+ const { readFileSync } = require('fs');
4
+ const { asyncRoute } = require('@parameter1/base-cms-utils');
5
+
6
+ const modes = new Set(['main', 'purged', 'optimized', 'critical']);
7
+
8
+ const readManifest = async (loc) => {
9
+ try {
10
+ const contents = await readFile(loc, 'utf8');
11
+ return JSON.parse(contents);
12
+ } catch (e) {
13
+ if (e.code === 'ENOENT') return null;
14
+ throw e;
15
+ }
16
+ };
17
+
18
+ /**
19
+ * @typedef {import("@parameter1/base-cms-web-cli/build/utils/css.js")
20
+ * .WrittenCSSOutputAsset} WrittenCSSOutputAsset
21
+ *
22
+ * @param {object} params
23
+ * @param {string} params.distDir
24
+ * @returns {Promise<WrittenCSSOutputAsset[]>}
25
+ */
26
+ const loadManifestEntries = async ({ distDir }) => {
27
+ const file = path.resolve(distDir, 'css', 'manifest.json');
28
+ const manifest = await readManifest(file);
29
+ if (!manifest) throw new Error('Unable to load the CSS asset manifest');
30
+ return Object.keys(manifest).map((key) => {
31
+ const asset = { key, ...manifest[key] };
32
+ return asset;
33
+ });
34
+ };
35
+
36
+ const isProduction = process.env.NODE_ENV === 'production';
37
+
38
+ module.exports = ({ distDir }) => asyncRoute(async (req, res, next) => {
39
+ const { cdn } = res.locals;
40
+ const { app } = req;
41
+ if (!app.locals.css) app.locals.css = {};
42
+ const { css } = app.locals;
43
+
44
+ // determine the current CSS mode
45
+ // use the env first and fallback to main (all).
46
+ let mode = process.env.CSS_MODE || 'main';
47
+ if (!modes.has(mode)) mode = 'main';
48
+
49
+ // then allow the request query or a cookie to override this.
50
+ const key = '__css';
51
+ if (modes.has(req.query[key])) {
52
+ mode = req.query[key];
53
+ } else if (modes.has(req.cookies[key])) {
54
+ mode = req.cookie[key];
55
+ }
56
+
57
+ // always set the mode to the app on every request.
58
+ css.mode = mode;
59
+
60
+ // when on production, only load the file paths and/or contents from the manifest once
61
+ // as long as the cdn configs are the same (allows for changing the cdn env var in prod)
62
+ if (isProduction && css.ready && css.cdn === cdn.enabled) return next();
63
+
64
+ css.cdn = cdn.enabled;
65
+
66
+ const items = await loadManifestEntries({ distDir });
67
+ const files = items.reduce((map, asset) => {
68
+ if (asset.embedded) return map;
69
+ map.set(asset.key, cdn.dist(`css/${asset.file}`));
70
+ return map;
71
+ }, new Map());
72
+ css.files = files;
73
+
74
+ const embeddable = items.reduce((map, asset) => {
75
+ if (!asset.embedded) return map;
76
+ map.set(asset.key, path.resolve(distDir, 'css', asset.file));
77
+ return map;
78
+ }, new Map());
79
+ css.embeddable = embeddable;
80
+
81
+ css.main = () => files.get('main');
82
+ css.purged = () => files.get('purged');
83
+
84
+ css.optimized = ({ kind, type } = {}) => {
85
+ // attempt to load the optimized file from most to least specific.
86
+ const keys = [];
87
+ if (kind && type) keys.push(`optimized-${kind}.${type}`);
88
+ if (kind) keys.push(`optimized-${kind}`);
89
+ keys.push('optimized');
90
+
91
+ return keys.reduce((file, k) => {
92
+ if (file) return file;
93
+ return files.get(k) || null;
94
+ }, null);
95
+ };
96
+
97
+ css.critical = ({ kind, type } = {}) => {
98
+ // attempt to load the critical file from most to least specific.
99
+ const keys = [];
100
+ if (kind && type) keys.push(`critical-${kind}.${type}`);
101
+ if (kind) keys.push(`critical-${kind}`);
102
+ keys.push('critical');
103
+
104
+ const critical = keys.reduce((file, k) => {
105
+ if (file) return file;
106
+ return embeddable.get(k) || null;
107
+ }, null);
108
+ if (!critical) return null;
109
+ // @todo determine if this should read contents all the time or store in memory?
110
+ const contents = readFileSync(critical, 'utf8');
111
+ return `/* ${critical.split('/').pop()} */ ${contents}`;
112
+ };
113
+
114
+ css.ready = true;
115
+
116
+ return next();
117
+ });
@@ -1,5 +1,6 @@
1
1
  const { STATUS_CODES } = require('http');
2
2
  const createError = require('http-errors');
3
+ const setRouteKind = require('@parameter1/base-cms-marko-express/utils/set-route-kind');
3
4
  const errorTemplate = require('../components/document/components/error');
4
5
  const getRedirect = require('./get-redirect');
5
6
  const findContentAlias = require('./find-content-alias');
@@ -16,6 +17,7 @@ const noCache = (res) => {
16
17
  };
17
18
 
18
19
  const renderError = (res, { statusCode, err, template }) => {
20
+ setRouteKind(res, { kind: 'error', type: statusCode });
19
21
  res.status(statusCode);
20
22
  res.marko(template || errorTemplate, {
21
23
  statusCode,
package/express/index.js CHANGED
@@ -12,7 +12,9 @@ const embeddedMedia = require('./embedded-media');
12
12
  const loadObject = require('./load-object');
13
13
  const loadDocument = require('./load-document');
14
14
  const oembed = require('./oembed');
15
- const purgedCSS = require('./purged-css');
15
+ const cdn = require('./cdn');
16
+ const assetLoader = require('./asset-loader');
17
+ const cssLoader = require('./css-loader');
16
18
  const rss = require('./rss');
17
19
  const sitemaps = require('./sitemaps');
18
20
  const { version } = require('../package.json');
@@ -117,14 +119,21 @@ module.exports = (config = {}) => {
117
119
  // Set website context.
118
120
  app.use(websiteContext(app.locals.config));
119
121
 
122
+ // Load CDN info before dist and CSS loading (but after the website context).
123
+ app.use(cdn({
124
+ enabled: ['true', '1'].includes(process.env.USE_ASSET_CDN),
125
+ origin: process.env.ASSET_CDN_ORIGIN || 'https://cdn.parameter1.com',
126
+ siteVersion: sitePackage.version,
127
+ }));
128
+ app.use(cssLoader({ distDir }));
129
+ app.use(assetLoader({ distDir }));
130
+
120
131
  // Register the Marko middleware.
121
132
  app.use(markoMiddleware());
122
- app.use(purgedCSS());
123
133
  app.use(cleanMarkoResponse());
124
134
 
125
135
  // Serve static assets
126
136
  app.use('/dist/css', express.static(`${distDir}/css`, { maxAge: '2y', immutable: true }));
127
- app.use('/dist/js/lazysizes', express.static(path.resolve(__dirname, '../public/lazysizes'), { maxAge: '2y', immutable: true }));
128
137
  app.use('/dist/js', express.static(`${distDir}/js`, { maxAge: '2y', immutable: true }));
129
138
  app.use('/dist', express.static(distDir));
130
139
 
@@ -2,6 +2,7 @@ const { get } = require('@parameter1/base-cms-object-path');
2
2
  const { asyncRoute, isFunction: isFn } = require('@parameter1/base-cms-utils');
3
3
  const { content: loader } = require('@parameter1/base-cms-web-common/page-loaders');
4
4
  const { blockContent: queryFactory } = require('@parameter1/base-cms-web-common/query-factories');
5
+ const setRouteKind = require('@parameter1/base-cms-marko-express/utils/set-route-kind');
5
6
  const PageNode = require('./page-node');
6
7
  const buildContentInput = require('../utils/build-content-input');
7
8
  const applyQueryParams = require('../utils/apply-query-params');
@@ -22,6 +23,9 @@ module.exports = ({
22
23
 
23
24
  const additionalInput = buildContentInput({ req });
24
25
  const content = await loader(apollo, { id, additionalInput, queryFragment: loaderQueryFragment });
26
+
27
+ // set the route kind
28
+ setRouteKind(res, { kind: 'content', type: content.type });
25
29
  const redirectTo = isFn(redirectToFn) ? redirectToFn({ content }) : content.redirectTo;
26
30
  const path = isFn(pathFn) ? pathFn({ content }) : get(content, 'siteContext.path');
27
31
 
@@ -2,6 +2,7 @@ const { get } = require('@parameter1/base-cms-object-path');
2
2
  const { asyncRoute, isFunction: isFn } = require('@parameter1/base-cms-utils');
3
3
  const { dynamicPage: loader } = require('@parameter1/base-cms-web-common/page-loaders');
4
4
  const { blockDynamicPage: queryFactory } = require('@parameter1/base-cms-web-common/query-factories');
5
+ const setRouteKind = require('@parameter1/base-cms-marko-express/utils/set-route-kind');
5
6
  const PageNode = require('./page-node');
6
7
  const applyQueryParams = require('../utils/apply-query-params');
7
8
 
@@ -15,6 +16,9 @@ module.exports = ({
15
16
  const { apollo, query } = req;
16
17
 
17
18
  const page = await loader(apollo, { alias });
19
+
20
+ setRouteKind(res, { kind: 'dynamic-page', type: alias });
21
+
18
22
  const { redirectTo } = page;
19
23
  const path = get(page, 'siteContext.path');
20
24
  if (redirectTo) {
@@ -1,6 +1,7 @@
1
1
  const { asyncRoute } = require('@parameter1/base-cms-utils');
2
2
  const { magazineIssue: loader } = require('@parameter1/base-cms-web-common/page-loaders');
3
3
  const { blockMagazineIssue: queryFactory } = require('@parameter1/base-cms-web-common/query-factories');
4
+ const setRouteKind = require('@parameter1/base-cms-marko-express/utils/set-route-kind');
4
5
  const PageNode = require('./page-node');
5
6
 
6
7
  module.exports = ({
@@ -10,6 +11,9 @@ module.exports = ({
10
11
  const { apollo } = req;
11
12
  const id = Number(req.params.id);
12
13
  const issue = await loader(apollo, { id });
14
+
15
+ // set the route kind
16
+ setRouteKind(res, { kind: 'magazine-issue', type: '' });
13
17
  const pageNode = new PageNode(apollo, {
14
18
  queryFactory,
15
19
  queryFragment,
@@ -1,6 +1,7 @@
1
1
  const { asyncRoute } = require('@parameter1/base-cms-utils');
2
2
  const { magazinePublication: loader } = require('@parameter1/base-cms-web-common/page-loaders');
3
3
  const { blockMagazinePublication: queryFactory } = require('@parameter1/base-cms-web-common/query-factories');
4
+ const setRouteKind = require('@parameter1/base-cms-marko-express/utils/set-route-kind');
4
5
  const PageNode = require('./page-node');
5
6
 
6
7
  module.exports = ({
@@ -10,6 +11,9 @@ module.exports = ({
10
11
  const { apollo } = req;
11
12
  const { id } = req.params;
12
13
  const publication = await loader(apollo, { id });
14
+
15
+ // set the route kind
16
+ setRouteKind(res, { kind: 'magazine-publication', type: '' });
13
17
  const pageNode = new PageNode(apollo, {
14
18
  queryFactory,
15
19
  queryFragment,
@@ -1,6 +1,7 @@
1
1
  const { asyncRoute, isFunction: isFn } = require('@parameter1/base-cms-utils');
2
2
  const { websiteSection: loader } = require('@parameter1/base-cms-web-common/page-loaders');
3
3
  const { blockWebsiteSection: queryFactory } = require('@parameter1/base-cms-web-common/query-factories');
4
+ const setRouteKind = require('@parameter1/base-cms-marko-express/utils/set-route-kind');
4
5
  const PageNode = require('./page-node');
5
6
  const applyQueryParams = require('../utils/apply-query-params');
6
7
 
@@ -16,6 +17,9 @@ module.exports = ({
16
17
  const cleanedAlias = alias.replace(/\/+$/, '').replace(/^\/+/, '');
17
18
 
18
19
  const section = await loader(apollo, { alias: cleanedAlias });
20
+
21
+ // set the route kind
22
+ setRouteKind(res, { kind: 'website-section', type: section.alias });
19
23
  const { redirectTo, canonicalPath } = section;
20
24
  if (redirectTo) {
21
25
  return res.redirect(301, applyQueryParams({ path: redirectTo, query }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parameter1/base-cms-marko-web",
3
- "version": "4.8.0",
3
+ "version": "4.9.0",
4
4
  "description": "Core Marko+Express components for BaseCMS websites",
5
5
  "author": "Jacob Bare <jacob@parameter1.com>",
6
6
  "main": "index.js",
@@ -31,7 +31,7 @@
31
31
  "@parameter1/base-cms-html": "^4.5.12",
32
32
  "@parameter1/base-cms-image": "^4.6.0",
33
33
  "@parameter1/base-cms-inflector": "^4.5.12",
34
- "@parameter1/base-cms-marko-express": "^4.6.0",
34
+ "@parameter1/base-cms-marko-express": "^4.9.0",
35
35
  "@parameter1/base-cms-marko-node-require": "^4.5.12",
36
36
  "@parameter1/base-cms-marko-web-deferred-script-loader": "^4.5.12",
37
37
  "@parameter1/base-cms-object-path": "^4.5.12",
@@ -60,5 +60,5 @@
60
60
  "publishConfig": {
61
61
  "access": "public"
62
62
  },
63
- "gitHead": "dcef09f69fd79065c563e850f19bf3c3826b4802"
63
+ "gitHead": "4e879581f5dea1692abd1b2942c1be27c1910bf4"
64
64
  }
@@ -0,0 +1,7 @@
1
+ @font-face {
2
+ /*! critical */
3
+ font-family: alata-fallback;
4
+ size-adjust: 102.30000000000004%;
5
+ ascent-override: 110%;
6
+ src: local("Arial");
7
+ }
@@ -0,0 +1,7 @@
1
+ @font-face {
2
+ /*! critical */
3
+ font-family: arimo-fallback;
4
+ size-adjust: 100%;
5
+ ascent-override: 90%;
6
+ src: local("Arial");
7
+ }
@@ -1,4 +1,5 @@
1
1
  @font-face {
2
+ /*! critical */
2
3
  font-family: fira-sans-fallback;
3
4
  size-adjust: 102.56%;
4
5
  ascent-override: 92%;
@@ -0,0 +1,7 @@
1
+ @font-face {
2
+ /*! critical */
3
+ font-family: ibm-plex-sans-fallback;
4
+ size-adjust: 101.44000000000005%;
5
+ ascent-override: 106%;
6
+ src: local("Arial");
7
+ }
@@ -0,0 +1,6 @@
1
+ @font-face {
2
+ /*! critical */
3
+ font-family: informapro-fallback;
4
+ size-adjust: 96.59999999999997%;
5
+ src: local("Arial");
6
+ }
@@ -0,0 +1,7 @@
1
+ @font-face {
2
+ /*! critical */
3
+ font-family: lato-fallback;
4
+ size-adjust: 97.38%;
5
+ ascent-override: 101%;
6
+ src: local("Arial");
7
+ }
@@ -1,4 +1,5 @@
1
1
  @font-face {
2
+ /*! critical */
2
3
  font-family: montserrat-fallback;
3
4
  size-adjust: 113.39999999999998%;
4
5
  ascent-override: 82%;
@@ -1,4 +1,5 @@
1
1
  @font-face {
2
+ /*! critical */
2
3
  font-family: open-sans-condensed-fallback;
3
4
  size-adjust: 102.56%;
4
5
  ascent-override: 92%;
@@ -1,4 +1,5 @@
1
1
  @font-face {
2
+ /*! critical */
2
3
  font-family: open-sans-fallback;
3
4
  size-adjust: 105.42999999999994%;
4
5
  ascent-override: 105%;
@@ -1,4 +1,5 @@
1
1
  @font-face {
2
+ /*! critical */
2
3
  font-family: oswald-fallback;
3
4
  size-adjust: 81.91000000000001%;
4
5
  ascent-override: 154%;
@@ -0,0 +1,7 @@
1
+ @font-face {
2
+ /*! critical */
3
+ font-family: roboto-condensed-fallback;
4
+ size-adjust: 88.91000000000001%;
5
+ ascent-override: 110%;
6
+ src: local("Arial");
7
+ }
@@ -0,0 +1,7 @@
1
+ @font-face {
2
+ /*! critical */
3
+ font-family: roboto-fallback;
4
+ size-adjust: 100.06%;
5
+ ascent-override: 95%;
6
+ src: local("Arial");
7
+ }
@@ -0,0 +1,7 @@
1
+ @font-face {
2
+ /*! critical */
3
+ font-family: roboto-slab-fallback;
4
+ size-adjust: 117.79999999999995%;
5
+ ascent-override: 87%;
6
+ src: local("Times New Roman");
7
+ }
@@ -0,0 +1,6 @@
1
+ @font-face {
2
+ /*! critical */
3
+ font-family: "solitaire-mvb-pro-fallback";
4
+ size-adjust: 94.70000000000002%;
5
+ src: local("Arial");
6
+ }
@@ -1,4 +1,5 @@
1
1
  @font-face {
2
+ /*! critical */
2
3
  font-family: source-sans-4-fallback;
3
4
  size-adjust: 93.75%;
4
5
  ascent-override: 110%;
@@ -0,0 +1,7 @@
1
+ @font-face {
2
+ /*! critical */
3
+ font-family: source-serif-pro-fallback;
4
+ size-adjust: 110.86999999999993%;
5
+ ascent-override: 84%;
6
+ src: local("Times New Roman");
7
+ }
Binary file
Binary file
Binary file
@@ -1,42 +0,0 @@
1
- const path = require('path');
2
- const { readFileSync } = require('fs');
3
-
4
- const read = (file) => {
5
- try {
6
- return JSON.parse(readFileSync(file, 'utf8'));
7
- } catch (e) {
8
- if (e.code === 'ENOENT') return null;
9
- throw e;
10
- }
11
- };
12
-
13
- const loadFromManifest = ({ distDir, type, entry }) => {
14
- const file = path.resolve(distDir, type, 'manifest.json');
15
- const manifest = read(file);
16
- if (!manifest) throw new Error(`Unable to load the asset manifest for type ${type}`);
17
- const asset = manifest[entry];
18
- if (!asset) throw new Error(`Unable to extract an asset for type ${type} using manifest entry ${entry}`);
19
- return `/dist/${type}/${asset.file}`;
20
- };
21
-
22
- const load = ({ distDir, file }) => readFileSync(path.resolve(distDir, `.${file.replace('/dist/', '/')}`), 'utf8');
23
-
24
- module.exports = ({ distDir, type, entry }) => {
25
- let file;
26
- let contents;
27
- return ({ embedded } = {}) => {
28
- const isDevelopment = process.env.NODE_ENV !== 'production';
29
- // when on dev, always return the file from the manifest
30
- // as it may have changed during build.
31
- if (isDevelopment) {
32
- const f = loadFromManifest({ distDir, type, entry });
33
- if (!embedded) return f;
34
- return load({ distDir, file: f });
35
- }
36
- // otherwise, only retrieve it once
37
- if (!file) file = loadFromManifest({ distDir, type, entry });
38
- if (!embedded) return file;
39
- if (!contents) contents = load({ distDir, file });
40
- return contents;
41
- };
42
- };
@@ -1,11 +0,0 @@
1
- module.exports = () => (req, res, next) => {
2
- res.locals.usePurgedCSS = ['cookies', 'query'].some((key) => {
3
- const { __purgecss: purge } = req[key];
4
- return purge && !['false', '0', 'null'].includes(purge);
5
- });
6
- res.locals.embedCSS = ['cookies', 'query'].some((key) => {
7
- const { __embedcss: embed } = req[key];
8
- return embed && !['false', '0', 'null'].includes(embed);
9
- });
10
- next();
11
- };
@@ -1,2 +0,0 @@
1
- /*! lazysizes - v5.3.2 */
2
- !function(e){var t=function(u,D,f){"use strict";var k,H;if(function(){var e;var t={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",fastLoadedClass:"ls-is-cached",iframeLoadMode:0,srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:true,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:true,ricTimeout:0,throttleDelay:125};H=u.lazySizesConfig||u.lazysizesConfig||{};for(e in t){if(!(e in H)){H[e]=t[e]}}}(),!D||!D.getElementsByClassName){return{init:function(){},cfg:H,noSupport:true}}var O=D.documentElement,i=u.HTMLPictureElement,P="addEventListener",$="getAttribute",q=u[P].bind(u),I=u.setTimeout,U=u.requestAnimationFrame||I,o=u.requestIdleCallback,j=/^picture$/i,r=["load","error","lazyincluded","_lazyloaded"],a={},G=Array.prototype.forEach,J=function(e,t){if(!a[t]){a[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")}return a[t].test(e[$]("class")||"")&&a[t]},K=function(e,t){if(!J(e,t)){e.setAttribute("class",(e[$]("class")||"").trim()+" "+t)}},Q=function(e,t){var a;if(a=J(e,t)){e.setAttribute("class",(e[$]("class")||"").replace(a," "))}},V=function(t,a,e){var i=e?P:"removeEventListener";if(e){V(t,a)}r.forEach(function(e){t[i](e,a)})},X=function(e,t,a,i,r){var n=D.createEvent("Event");if(!a){a={}}a.instance=k;n.initEvent(t,!i,!r);n.detail=a;e.dispatchEvent(n);return n},Y=function(e,t){var a;if(!i&&(a=u.picturefill||H.pf)){if(t&&t.src&&!e[$]("srcset")){e.setAttribute("srcset",t.src)}a({reevaluate:true,elements:[e]})}else if(t&&t.src){e.src=t.src}},Z=function(e,t){return(getComputedStyle(e,null)||{})[t]},s=function(e,t,a){a=a||e.offsetWidth;while(a<H.minSize&&t&&!e._lazysizesWidth){a=t.offsetWidth;t=t.parentNode}return a},ee=function(){var a,i;var t=[];var r=[];var n=t;var s=function(){var e=n;n=t.length?r:t;a=true;i=false;while(e.length){e.shift()()}a=false};var e=function(e,t){if(a&&!t){e.apply(this,arguments)}else{n.push(e);if(!i){i=true;(D.hidden?I:U)(s)}}};e._lsFlush=s;return e}(),te=function(a,e){return e?function(){ee(a)}:function(){var e=this;var t=arguments;ee(function(){a.apply(e,t)})}},ae=function(e){var a;var i=0;var r=H.throttleDelay;var n=H.ricTimeout;var t=function(){a=false;i=f.now();e()};var s=o&&n>49?function(){o(t,{timeout:n});if(n!==H.ricTimeout){n=H.ricTimeout}}:te(function(){I(t)},true);return function(e){var t;if(e=e===true){n=33}if(a){return}a=true;t=r-(f.now()-i);if(t<0){t=0}if(e||t<9){s()}else{I(s,t)}}},ie=function(e){var t,a;var i=99;var r=function(){t=null;e()};var n=function(){var e=f.now()-a;if(e<i){I(n,i-e)}else{(o||r)(r)}};return function(){a=f.now();if(!t){t=I(n,i)}}},e=function(){var v,m,c,h,e;var y,z,g,p,C,b,A;var n=/^img$/i;var d=/^iframe$/i;var E="onscroll"in u&&!/(gle|ing)bot/.test(navigator.userAgent);var _=0;var w=0;var M=0;var N=-1;var L=function(e){M--;if(!e||M<0||!e.target){M=0}};var x=function(e){if(A==null){A=Z(D.body,"visibility")=="hidden"}return A||!(Z(e.parentNode,"visibility")=="hidden"&&Z(e,"visibility")=="hidden")};var W=function(e,t){var a;var i=e;var r=x(e);g-=t;b+=t;p-=t;C+=t;while(r&&(i=i.offsetParent)&&i!=D.body&&i!=O){r=(Z(i,"opacity")||1)>0;if(r&&Z(i,"overflow")!="visible"){a=i.getBoundingClientRect();r=C>a.left&&p<a.right&&b>a.top-1&&g<a.bottom+1}}return r};var t=function(){var e,t,a,i,r,n,s,o,l,u,f,c;var d=k.elements;if((h=H.loadMode)&&M<8&&(e=d.length)){t=0;N++;for(;t<e;t++){if(!d[t]||d[t]._lazyRace){continue}if(!E||k.prematureUnveil&&k.prematureUnveil(d[t])){R(d[t]);continue}if(!(o=d[t][$]("data-expand"))||!(n=o*1)){n=w}if(!u){u=!H.expand||H.expand<1?O.clientHeight>500&&O.clientWidth>500?500:370:H.expand;k._defEx=u;f=u*H.expFactor;c=H.hFac;A=null;if(w<f&&M<1&&N>2&&h>2&&!D.hidden){w=f;N=0}else if(h>1&&N>1&&M<6){w=u}else{w=_}}if(l!==n){y=innerWidth+n*c;z=innerHeight+n;s=n*-1;l=n}a=d[t].getBoundingClientRect();if((b=a.bottom)>=s&&(g=a.top)<=z&&(C=a.right)>=s*c&&(p=a.left)<=y&&(b||C||p||g)&&(H.loadHidden||x(d[t]))&&(m&&M<3&&!o&&(h<3||N<4)||W(d[t],n))){R(d[t]);r=true;if(M>9){break}}else if(!r&&m&&!i&&M<4&&N<4&&h>2&&(v[0]||H.preloadAfterLoad)&&(v[0]||!o&&(b||C||p||g||d[t][$](H.sizesAttr)!="auto"))){i=v[0]||d[t]}}if(i&&!r){R(i)}}};var a=ae(t);var S=function(e){var t=e.target;if(t._lazyCache){delete t._lazyCache;return}L(e);K(t,H.loadedClass);Q(t,H.loadingClass);V(t,B);X(t,"lazyloaded")};var i=te(S);var B=function(e){i({target:e.target})};var T=function(e,t){var a=e.getAttribute("data-load-mode")||H.iframeLoadMode;if(a==0){e.contentWindow.location.replace(t)}else if(a==1){e.src=t}};var F=function(e){var t;var a=e[$](H.srcsetAttr);if(t=H.customMedia[e[$]("data-media")||e[$]("media")]){e.setAttribute("media",t)}if(a){e.setAttribute("srcset",a)}};var s=te(function(t,e,a,i,r){var n,s,o,l,u,f;if(!(u=X(t,"lazybeforeunveil",e)).defaultPrevented){if(i){if(a){K(t,H.autosizesClass)}else{t.setAttribute("sizes",i)}}s=t[$](H.srcsetAttr);n=t[$](H.srcAttr);if(r){o=t.parentNode;l=o&&j.test(o.nodeName||"")}f=e.firesLoad||"src"in t&&(s||n||l);u={target:t};K(t,H.loadingClass);if(f){clearTimeout(c);c=I(L,2500);V(t,B,true)}if(l){G.call(o.getElementsByTagName("source"),F)}if(s){t.setAttribute("srcset",s)}else if(n&&!l){if(d.test(t.nodeName)){T(t,n)}else{t.src=n}}if(r&&(s||l)){Y(t,{src:n})}}if(t._lazyRace){delete t._lazyRace}Q(t,H.lazyClass);ee(function(){var e=t.complete&&t.naturalWidth>1;if(!f||e){if(e){K(t,H.fastLoadedClass)}S(u);t._lazyCache=true;I(function(){if("_lazyCache"in t){delete t._lazyCache}},9)}if(t.loading=="lazy"){M--}},true)});var R=function(e){if(e._lazyRace){return}var t;var a=n.test(e.nodeName);var i=a&&(e[$](H.sizesAttr)||e[$]("sizes"));var r=i=="auto";if((r||!m)&&a&&(e[$]("src")||e.srcset)&&!e.complete&&!J(e,H.errorClass)&&J(e,H.lazyClass)){return}t=X(e,"lazyunveilread").detail;if(r){re.updateElem(e,true,e.offsetWidth)}e._lazyRace=true;M++;s(e,t,r,i,a)};var r=ie(function(){H.loadMode=3;a()});var o=function(){if(H.loadMode==3){H.loadMode=2}r()};var l=function(){if(m){return}if(f.now()-e<999){I(l,999);return}m=true;H.loadMode=3;a();q("scroll",o,true)};return{_:function(){e=f.now();k.elements=D.getElementsByClassName(H.lazyClass);v=D.getElementsByClassName(H.lazyClass+" "+H.preloadClass);q("scroll",a,true);q("resize",a,true);q("pageshow",function(e){if(e.persisted){var t=D.querySelectorAll("."+H.loadingClass);if(t.length&&t.forEach){U(function(){t.forEach(function(e){if(e.complete){R(e)}})})}}});if(u.MutationObserver){new MutationObserver(a).observe(O,{childList:true,subtree:true,attributes:true})}else{O[P]("DOMNodeInserted",a,true);O[P]("DOMAttrModified",a,true);setInterval(a,999)}q("hashchange",a,true);["focus","mouseover","click","load","transitionend","animationend"].forEach(function(e){D[P](e,a,true)});if(/d$|^c/.test(D.readyState)){l()}else{q("load",l);D[P]("DOMContentLoaded",a);I(l,2e4)}if(k.elements.length){t();ee._lsFlush()}else{a()}},checkElems:a,unveil:R,_aLSL:o}}(),re=function(){var a;var n=te(function(e,t,a,i){var r,n,s;e._lazysizesWidth=i;i+="px";e.setAttribute("sizes",i);if(j.test(t.nodeName||"")){r=t.getElementsByTagName("source");for(n=0,s=r.length;n<s;n++){r[n].setAttribute("sizes",i)}}if(!a.detail.dataAttr){Y(e,a.detail)}});var i=function(e,t,a){var i;var r=e.parentNode;if(r){a=s(e,r,a);i=X(e,"lazybeforesizes",{width:a,dataAttr:!!t});if(!i.defaultPrevented){a=i.detail.width;if(a&&a!==e._lazysizesWidth){n(e,r,i,a)}}}};var e=function(){var e;var t=a.length;if(t){e=0;for(;e<t;e++){i(a[e])}}};var t=ie(e);return{_:function(){a=D.getElementsByClassName(H.autosizesClass);q("resize",t)},checkElems:t,updateElem:i}}(),t=function(){if(!t.i&&D.getElementsByClassName){t.i=true;re._();e._()}};return I(function(){H.init&&t()}),k={cfg:H,autoSizer:re,loader:e,init:t,uP:Y,aC:K,rC:Q,hC:J,fire:X,gW:s,rAF:ee}}(e,e.document,Date);e.lazySizes=t,"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:{});