gatsby-theme-q3 3.2.0 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [3.2.1](https://github.com/3merge/q/compare/v3.2.0...v3.2.1) (2022-02-09)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * misc domain issues ([17cb74b](https://github.com/3merge/q/commit/17cb74b927721f11b5fcd8f8a9a1a28a86867048))
12
+
13
+
14
+
15
+
16
+
6
17
  # [3.2.0](https://github.com/3merge/q/compare/v3.1.5...v3.2.0) (2022-02-09)
7
18
 
8
19
 
package/gatsby-browser.js CHANGED
@@ -11,6 +11,11 @@ export {
11
11
  export const onClientEntry = async () => {
12
12
  if (!browser.isBrowserReady()) return;
13
13
 
14
+ // set api default root
15
+ axios.defaults.baseURL =
16
+ process.env.GATSBY_APP_BASE_URL ||
17
+ 'http://localhost:9000';
18
+
14
19
  // set language default
15
20
  axios.defaults.headers['Content-Language'] =
16
21
  window.localStorage.getItem('q3-locale') || 'en';
package/gatsby-config.js CHANGED
@@ -4,14 +4,7 @@ require('dotenv').config();
4
4
  const genKey = (url) =>
5
5
  String(url).includes('netlify') ? 'disallow' : 'allow';
6
6
 
7
- module.exports = ({
8
- siteUrl,
9
- title,
10
- brandingColor,
11
- icon,
12
- netlify,
13
- ...options
14
- }) => {
7
+ module.exports = (options) => {
15
8
  const plugins = [
16
9
  {
17
10
  resolve: 'gatsby-theme-q3-mui',
@@ -48,24 +41,20 @@ module.exports = ({
48
41
  },
49
42
  },
50
43
  },
51
- ];
52
-
53
- if (netlify)
54
- plugins.push({
44
+ {
55
45
  resolve: 'gatsby-plugin-netlify',
56
46
  options: {
57
47
  generateMatchPathRewrites: true,
58
48
  },
59
- });
60
-
61
- if (siteUrl)
62
- plugins.push({
49
+ },
50
+ {
63
51
  resolve: 'gatsby-plugin-canonical-urls',
64
52
  options: {
65
53
  stripQueryString: true,
66
- siteUrl,
54
+ siteUrl: process.env.URL,
67
55
  },
68
- });
56
+ },
57
+ ];
69
58
 
70
59
  return {
71
60
  plugins,
package/gatsby-node.js CHANGED
@@ -70,7 +70,6 @@ exports.onCreatePage = async ({ page, actions }) => {
70
70
  createPage({
71
71
  ...page,
72
72
  context: {
73
- contentful_id: 'APP',
74
73
  to: '/app',
75
74
  },
76
75
  });
@@ -17,8 +17,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
17
17
 
18
18
  const PageWrapper = ({
19
19
  children,
20
- includeLoader,
21
- includeLocale
20
+ includeLoader
22
21
  }) => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_SearchEngine.default, null), includeLoader && /*#__PURE__*/_react.default.createElement(_components.Loader, null), children);
23
22
 
24
23
  PageWrapper.defaultProps = {
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.getStartUrl = exports.generateMetaTitleOptions = exports.generateMetaDescriptionOptions = exports.generateManifest = exports.generateIcons = exports.generateBrand = exports.default = exports.Manifest = void 0;
6
+ exports.getStartUrl = exports.generateMetaTitleOptions = exports.generateMetaDescriptionOptions = exports.generateManifest = exports.generateIcons = exports.generateBrand = exports.default = void 0;
7
7
 
8
8
  var _react = _interopRequireDefault(require("react"));
9
9
 
@@ -69,13 +69,6 @@ const generateManifest = (site = {}) => ({
69
69
 
70
70
  exports.generateManifest = generateManifest;
71
71
 
72
- const Manifest = props => (0, _lodash.isObject)(props) ? /*#__PURE__*/_react.default.createElement("link", {
73
- rel: "manifest",
74
- href: `data:application/manifest+json,${encodeURIComponent(JSON.stringify(props))}`
75
- }) : null;
76
-
77
- exports.Manifest = Manifest;
78
-
79
72
  const SEO = ({
80
73
  description,
81
74
  lang,
@@ -85,12 +78,13 @@ const SEO = ({
85
78
  const site = (0, _useSiteMetaData.default)();
86
79
  const metaDescription = description || site.description;
87
80
  const metaTitle = title || site.title;
81
+ const manifestData = generateManifest(site);
88
82
  return /*#__PURE__*/_react.default.createElement(_reactHelmet.Helmet, {
89
83
  htmlAttributes: {
90
84
  lang
91
85
  },
92
86
  title: metaTitle,
93
- titleTemplate: generateBrand((0, _lodash.get)(site, 'brand', 'Q3')),
87
+ titleTemplate: generateBrand(site.brand),
94
88
  meta: [...generateMetaTitleOptions(metaTitle), ...generateMetaDescriptionOptions(metaDescription), {
95
89
  property: 'og:type',
96
90
  content: 'website'
@@ -98,7 +92,10 @@ const SEO = ({
98
92
  name: 'twitter:card',
99
93
  content: 'summary'
100
94
  }].concat(meta)
101
- }, /*#__PURE__*/_react.default.createElement(Manifest, generateManifest(site)), /*#__PURE__*/_react.default.createElement("link", {
95
+ }, (0, _lodash.isObject)(manifestData) ? /*#__PURE__*/_react.default.createElement("link", {
96
+ rel: "manifest",
97
+ href: `data:application/manifest+json,${encodeURIComponent(JSON.stringify(manifestData))}`
98
+ }) : null, /*#__PURE__*/_react.default.createElement("link", {
102
99
  rel: "icon",
103
100
  href: site.favicon
104
101
  }));
@@ -7,8 +7,6 @@ exports.default = void 0;
7
7
 
8
8
  var _react = _interopRequireDefault(require("react"));
9
9
 
10
- var _axios = _interopRequireDefault(require("axios"));
11
-
12
10
  var _propTypes = _interopRequireDefault(require("prop-types"));
13
11
 
14
12
  var _q3UiPermissions = _interopRequireDefault(require("q3-ui-permissions"));
@@ -16,27 +14,12 @@ var _q3UiPermissions = _interopRequireDefault(require("q3-ui-permissions"));
16
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
15
 
18
16
  /* eslint-disable import/no-extraneous-dependencies */
19
- const setBaseUrlForRest = (baseURL = process.env.GATSBY_APP_BASE_URL || 'http://localhost:9000') => {
20
- _axios.default.defaults.baseURL = baseURL;
21
- return _axios.default.defaults;
22
- };
23
-
24
17
  const Wrapper = ({
25
- baseURL,
26
18
  children
27
- }) => {
28
- setBaseUrlForRest(baseURL);
29
- return /*#__PURE__*/_react.default.createElement(_q3UiPermissions.default, null, children);
30
- };
19
+ }) => /*#__PURE__*/_react.default.createElement(_q3UiPermissions.default, null, children);
31
20
 
32
- Wrapper.defaultProps = {
33
- baseURL: undefined
34
- };
35
21
  Wrapper.propTypes = {
36
- baseURL: _propTypes.default.string,
37
- children: _propTypes.default.node.isRequired,
38
- // eslint-disable-next-line
39
- locale: _propTypes.default.object.isRequired
22
+ children: _propTypes.default.node.isRequired
40
23
  };
41
24
  var _default = Wrapper;
42
25
  exports.default = _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gatsby-theme-q3",
3
- "version": "3.2.0",
3
+ "version": "3.2.1",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "peerDependencies": {
@@ -28,13 +28,13 @@
28
28
  "gatsby-plugin-robots-txt": "^1.6.14",
29
29
  "gatsby-plugin-sharp": "^4.2.0",
30
30
  "gatsby-plugin-sitemap": "^5.2.0",
31
- "gatsby-theme-q3-mui": "^3.2.0",
31
+ "gatsby-theme-q3-mui": "^3.2.1",
32
32
  "gatsby-transformer-sharp": "^4.2.0",
33
33
  "lodash": "^4.17.20",
34
34
  "process": "^0.11.10",
35
35
  "prop-types": "^15.7.2",
36
36
  "q3-ui-helpers": "^3.2.0",
37
- "q3-ui-locale": "^3.2.0",
37
+ "q3-ui-locale": "^3.2.1",
38
38
  "query-string": "^7.0.1",
39
39
  "react-helmet": "^6.1.0",
40
40
  "react-share": "^4.3.1",
@@ -42,5 +42,5 @@
42
42
  "transform-loader": "^0.2.4",
43
43
  "yarn": "^1.22.17"
44
44
  },
45
- "gitHead": "e7b26a194d8779024212ba64ca440222c28d82c7"
45
+ "gitHead": "b9ee55eb96e7d61f86f9d5d091d8a9d770c720cc"
46
46
  }
@@ -3,11 +3,7 @@ import PropTypes from 'prop-types';
3
3
  import { Loader } from 'q3-admin/lib/components';
4
4
  import SearchEngine from './SearchEngine';
5
5
 
6
- const PageWrapper = ({
7
- children,
8
- includeLoader,
9
- includeLocale,
10
- }) => (
6
+ const PageWrapper = ({ children, includeLoader }) => (
11
7
  <>
12
8
  <SearchEngine />
13
9
  {includeLoader && <Loader />}
@@ -68,20 +68,11 @@ export const generateManifest = (site = {}) => ({
68
68
  theme_color: site.color,
69
69
  });
70
70
 
71
- export const Manifest = (props) =>
72
- isObject(props) ? (
73
- <link
74
- rel="manifest"
75
- href={`data:application/manifest+json,${encodeURIComponent(
76
- JSON.stringify(props),
77
- )}`}
78
- />
79
- ) : null;
80
-
81
71
  const SEO = ({ description, lang, meta, title }) => {
82
72
  const site = useSiteMetaData();
83
73
  const metaDescription = description || site.description;
84
74
  const metaTitle = title || site.title;
75
+ const manifestData = generateManifest(site);
85
76
 
86
77
  return (
87
78
  <Helmet
@@ -89,9 +80,7 @@ const SEO = ({ description, lang, meta, title }) => {
89
80
  lang,
90
81
  }}
91
82
  title={metaTitle}
92
- titleTemplate={generateBrand(
93
- get(site, 'brand', 'Q3'),
94
- )}
83
+ titleTemplate={generateBrand(site.brand)}
95
84
  meta={[
96
85
  ...generateMetaTitleOptions(metaTitle),
97
86
  ...generateMetaDescriptionOptions(metaDescription),
@@ -105,7 +94,14 @@ const SEO = ({ description, lang, meta, title }) => {
105
94
  },
106
95
  ].concat(meta)}
107
96
  >
108
- <Manifest {...generateManifest(site)} />
97
+ {isObject(manifestData) ? (
98
+ <link
99
+ rel="manifest"
100
+ href={`data:application/manifest+json,${encodeURIComponent(
101
+ JSON.stringify(manifestData),
102
+ )}`}
103
+ />
104
+ ) : null}
109
105
  <link rel="icon" href={site.favicon} />
110
106
  </Helmet>
111
107
  );
@@ -1,32 +1,14 @@
1
1
  /* eslint-disable import/no-extraneous-dependencies */
2
2
  import React from 'react';
3
- import axios from 'axios';
4
3
  import PropTypes from 'prop-types';
5
4
  import AuthProvider from 'q3-ui-permissions';
6
5
 
7
- const setBaseUrlForRest = (
8
- baseURL = process.env.GATSBY_APP_BASE_URL ||
9
- 'http://localhost:9000',
10
- ) => {
11
- axios.defaults.baseURL = baseURL;
12
- return axios.defaults;
13
- };
14
-
15
- const Wrapper = ({ baseURL, children }) => {
16
- setBaseUrlForRest(baseURL);
17
- return <AuthProvider>{children}</AuthProvider>;
18
- };
19
-
20
- Wrapper.defaultProps = {
21
- baseURL: undefined,
22
- };
6
+ const Wrapper = ({ children }) => (
7
+ <AuthProvider>{children}</AuthProvider>
8
+ );
23
9
 
24
10
  Wrapper.propTypes = {
25
- baseURL: PropTypes.string,
26
11
  children: PropTypes.node.isRequired,
27
-
28
- // eslint-disable-next-line
29
- locale: PropTypes.object.isRequired,
30
12
  };
31
13
 
32
14
  export default Wrapper;
@@ -1,62 +0,0 @@
1
- import { get } from 'lodash';
2
- import config from '../gatsby-config';
3
-
4
- const CANONICAL = 'gatsby-plugin-canonical-urls';
5
- const ROBOTS = 'gatsby-plugin-robots-txt';
6
-
7
- const ENV = {
8
- contentfulSpaceID: 1,
9
- contentfulAccessToken: 1,
10
- };
11
-
12
- const containsResolver = (plugins = [], name) =>
13
- plugins.find(
14
- (p) => typeof p === 'object' && p.resolve === name,
15
- );
16
-
17
- const checkPlugins = (args = {}, plugin) => {
18
- const { plugins } = config({ ...ENV, ...args });
19
- const statement = expect(
20
- containsResolver(plugins, plugin),
21
- );
22
-
23
- return {
24
- has: () => statement.not.toBeUndefined(),
25
- hasNot: () => statement.toBeUndefined(),
26
- };
27
- };
28
-
29
- describe('gatsby-config', () => {
30
- describe('plugins', () => {
31
- it('should include conditional plugins', () =>
32
- [CANONICAL].forEach((name) =>
33
- checkPlugins(
34
- {
35
- brandingColor: '#FFF',
36
- title: 'Foo',
37
- siteUrl: 'https://google.ca',
38
- },
39
- name,
40
- ).has(),
41
- ));
42
-
43
- it('should exclude conditional plugins', () =>
44
- [CANONICAL].forEach((name) =>
45
- checkPlugins({}, name).hasNot(),
46
- ));
47
-
48
- it.each([
49
- ['https://dev.netlify.3merge.com', 'disallow'],
50
- ['https://3merge.com', 'allow'],
51
- ])('should disable indexing', (url, key) => {
52
- process.env.URL = url;
53
- const { plugins } = config({ ...ENV });
54
- const res = containsResolver(plugins, ROBOTS);
55
- const prod = get(
56
- res,
57
- 'options.env.production.policy',
58
- )[0];
59
- expect(prod).toHaveProperty(key, '/');
60
- });
61
- });
62
- });
@@ -1,13 +0,0 @@
1
- const path = require('path');
2
- const loadContent = require('../loadContent');
3
-
4
- describe('loadContent', () => {
5
- it('should fetch all content from directory', () => {
6
- const out = loadContent(
7
- path.resolve(__dirname, '../../__fixtures__'),
8
- );
9
-
10
- expect(out).toHaveProperty('en');
11
- expect(out).toHaveProperty('fr');
12
- });
13
- });
@@ -1,139 +0,0 @@
1
- const {
2
- genCursor,
3
- appendSiblingsToContext,
4
- getPreviousArchiveUrl,
5
- getNextArchiveUrl,
6
- getNumberOfPages,
7
- paginateArchiveContext,
8
- } = require('../pagination');
9
-
10
- const genEntries = () => {
11
- const entries = [];
12
- for (let i = 0; i < 30; i += 1) entries.push(i);
13
- return entries;
14
- };
15
-
16
- describe('pagination', () => {
17
- describe('"genCursor"', () => {
18
- const stub = ['foo', 'bar', 'quuz', 'garply'];
19
- const cursor = genCursor(stub, 2);
20
- // current index targets "quuz"
21
-
22
- it('should identify first item', () => {
23
- expect(cursor.first).toMatch('foo');
24
- });
25
-
26
- it('should identify last item', () => {
27
- expect(cursor.last).toMatch('garply');
28
- });
29
-
30
- it('should identify next item', () => {
31
- expect(cursor.next).toMatch('garply');
32
- });
33
-
34
- it('should identify previous item', () => {
35
- expect(cursor.prev).toMatch('bar');
36
- });
37
-
38
- it('should identify first position', () => {
39
- expect(cursor.isFirst).toBeFalsy();
40
- expect(genCursor(stub, 0).isFirst).toBeTruthy();
41
- });
42
-
43
- it('should identify last position', () => {
44
- expect(cursor.isLast).toBeFalsy();
45
- expect(genCursor(stub, 3).isLast).toBeTruthy();
46
- });
47
- });
48
-
49
- describe('"appendSiblingsToContext"', () => {
50
- const mockContentfulEntry = (id) => ({
51
- contentful_id: id,
52
- });
53
-
54
- const stubWithContentful = [
55
- mockContentfulEntry(1),
56
- mockContentfulEntry(2),
57
- mockContentfulEntry(3),
58
- ];
59
-
60
- it('should map contentful entries using cursor', () => {
61
- const entries = appendSiblingsToContext(
62
- stubWithContentful,
63
- );
64
- expect(entries[0]).toMatchObject({
65
- prev: 3,
66
- next: 2,
67
- });
68
- expect(entries[2]).toMatchObject({
69
- prev: 2,
70
- next: 1,
71
- });
72
- });
73
- });
74
-
75
- describe('"getPreviousArchiveUrl"', () => {
76
- it('should return null', () => {
77
- expect(getPreviousArchiveUrl('/foo', 1)).toBeNull();
78
- });
79
-
80
- it('should return archive', () => {
81
- expect(getPreviousArchiveUrl('/foo', 2)).toEqual(
82
- '/foo',
83
- );
84
- });
85
-
86
- it('should return archive sub-directory', () => {
87
- expect(getPreviousArchiveUrl('/foo', 3)).toEqual(
88
- '/foo/2',
89
- );
90
- });
91
- });
92
-
93
- describe('"getNextArchiveUrl"', () => {
94
- it('should return sub-directory', () => {
95
- expect(getNextArchiveUrl('/foo', 8, 9)).toEqual(
96
- '/foo/9',
97
- );
98
- });
99
-
100
- it('should return null', () => {
101
- expect(getNextArchiveUrl('/foo', 9, 9)).toBeNull();
102
- });
103
- });
104
-
105
- describe('"getNumberOfPages"', () => {
106
- it('should return number divisible by', () => {
107
- expect(getNumberOfPages(genEntries(), 5)).toBe(6);
108
- });
109
- });
110
-
111
- describe('"paginateArchiveContext"', () => {
112
- it('should return pagination meta', () => {
113
- // default 15 per page
114
- const res = paginateArchiveContext(
115
- genEntries(),
116
- '/foo',
117
- );
118
-
119
- expect(res).toHaveLength(2);
120
- expect(res[0]).toMatchObject({
121
- path: '/foo',
122
- limit: 15,
123
- skip: 0,
124
- pageNum: 0,
125
- prev: null,
126
- next: '/foo/2',
127
- });
128
-
129
- expect(res[1]).toMatchObject({
130
- path: '/foo/2',
131
- limit: 15,
132
- skip: 15,
133
- pageNum: 1,
134
- prev: '/foo',
135
- next: null,
136
- });
137
- });
138
- });
139
- });
@@ -1,21 +0,0 @@
1
- const slug = require('../slug');
2
-
3
- describe('slug', () => {
4
- it('should combine use slug attribute', () => {
5
- expect(
6
- slug({ slug: 'already-formatted-as-slug' }),
7
- ).toMatch('/already-formatted-as-slug');
8
- });
9
-
10
- it('should combine use title attribute', () => {
11
- expect(
12
- slug({ title: 'This is a post' }, 'foos'),
13
- ).toMatch('/foos/this-is-a-post');
14
- });
15
-
16
- it('should combine use name attribute', () => {
17
- expect(slug({ name: "Post's name" }, '/foos')).toMatch(
18
- '/foos/posts-name',
19
- );
20
- });
21
- });
@@ -1,42 +0,0 @@
1
- const { get } = require('lodash');
2
- const { resolve } = require('path');
3
- const {
4
- appendSiblingsToContext,
5
- paginateArchiveContext,
6
- } = require('./pagination');
7
-
8
- module.exports = ({
9
- archiveComponentRelativePath,
10
- createPage,
11
- detailComponentRelativePath,
12
- nodesKeyName,
13
- slug,
14
- }) => async ({ data, errors }) => {
15
- if (errors) throw errors;
16
- const { nodes = [] } = get(data, nodesKeyName, {
17
- nodes: [],
18
- });
19
-
20
- const archives = appendSiblingsToContext(nodes).map(
21
- (context) =>
22
- createPage({
23
- path:
24
- // see slugType for more details on this field
25
- context.to || `/${slug}/${context.contentful_id}`,
26
- component: resolve(detailComponentRelativePath),
27
- context,
28
- }),
29
- );
30
-
31
- const entries = paginateArchiveContext(nodes, slug).map(
32
- ({ path, ...context }) =>
33
- createPage({
34
- component: resolve(archiveComponentRelativePath),
35
- path,
36
- context,
37
- }),
38
- );
39
-
40
- await Promise.all(archives);
41
- await Promise.all(entries);
42
- };
package/helpers/index.js DELETED
@@ -1,19 +0,0 @@
1
- const ArchiveBuilder = require('./archive');
2
- const loadContent = require('./loadContent');
3
- const {
4
- appendSiblingsToContext,
5
- paginateArchiveContext,
6
- } = require('./pagination');
7
- const slug = require('./slug');
8
- const slugType = require('./slugType');
9
- const setup = require('./setup');
10
-
11
- module.exports = {
12
- ArchiveBuilder,
13
- loadContent,
14
- appendSiblingsToContext,
15
- paginateArchiveContext,
16
- setup,
17
- slug,
18
- slugType,
19
- };
@@ -1,45 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
-
4
- const readJsonFile = (dir, filename) => {
5
- try {
6
- const file = path.resolve(dir, filename);
7
- const buffer = fs.readFileSync(file);
8
- return JSON.parse(buffer);
9
- } catch (e) {
10
- return {};
11
- }
12
- };
13
-
14
- const reduceFileSystem = (name, next) =>
15
- fs
16
- .readdirSync(name, { withFileTypes: true })
17
- .reduce(next, {});
18
-
19
- const getJsonFileNameFromDirent = ({ name }) =>
20
- path.basename(name, '.json');
21
-
22
- const readFilePathFromDirent = ({ name }, root, next) =>
23
- next(path.join(root, name));
24
-
25
- const recurseFileSystem = (pathName) =>
26
- reduceFileSystem(pathName, (curr, dirent) =>
27
- Object.assign(curr, {
28
- [getJsonFileNameFromDirent(
29
- dirent,
30
- )]: dirent.isDirectory()
31
- ? readFilePathFromDirent(
32
- dirent,
33
- pathName,
34
- recurseFileSystem,
35
- )
36
- : readJsonFile(pathName, dirent.name),
37
- }),
38
- );
39
-
40
- recurseFileSystem.readJsonFile = readJsonFile;
41
- recurseFileSystem.reduceFileSystem = reduceFileSystem;
42
- recurseFileSystem.getJsonFileNameFromDirent = getJsonFileNameFromDirent;
43
- recurseFileSystem.readFilePathFromDirent = readFilePathFromDirent;
44
-
45
- module.exports = recurseFileSystem;
@@ -1,10 +0,0 @@
1
- module.exports = (src) => {
2
- try {
3
- if (!src) throw new Error('No theme file detected');
4
-
5
- // eslint-disable-next-line
6
- return require(src);
7
- } catch (e) {
8
- return {};
9
- }
10
- };
@@ -1,109 +0,0 @@
1
- const { get } = require('lodash');
2
-
3
- const getId = (v) => get(v, 'contentful_id');
4
-
5
- const genCursor = (a = [], i = 0) => ({
6
- isFirst: i === 0,
7
- isLast: i === a.length - 1,
8
- next: a[i + 1],
9
- prev: a[i - 1],
10
- first: a[0],
11
- last: a[a.length - 1],
12
- });
13
-
14
- const joinArchiveUrlWithPageNumber = (url, page) =>
15
- `${url}/${page}`;
16
-
17
- const getPreviousArchiveUrl = (archiveUrl, page) => {
18
- if (page === 2) return archiveUrl;
19
- if (page !== 1)
20
- return joinArchiveUrlWithPageNumber(
21
- archiveUrl,
22
- page - 1,
23
- );
24
-
25
- return null;
26
- };
27
-
28
- const getNextArchiveUrl = (
29
- archiveUrl,
30
- page,
31
- totalNumberOfPages,
32
- ) => {
33
- if (page < totalNumberOfPages)
34
- return joinArchiveUrlWithPageNumber(
35
- archiveUrl,
36
- page + 1,
37
- );
38
-
39
- return null;
40
- };
41
-
42
- const getCurrentArchiveUrl = (archiveUrl, page) =>
43
- page < 2
44
- ? archiveUrl
45
- : joinArchiveUrlWithPageNumber(archiveUrl, page);
46
-
47
- const getNumberOfPages = (
48
- entries = [],
49
- postsPerPage = 15,
50
- ) => {
51
- const len = Array.isArray(entries) ? entries.length : 0;
52
- return Math.ceil(len / postsPerPage);
53
- };
54
-
55
- const appendSiblingsToContext = (entries) =>
56
- entries.map((node, i) => {
57
- const cursor = genCursor(entries, i);
58
- const prev = getId(
59
- cursor.isFirst ? cursor.last : cursor.prev,
60
- );
61
-
62
- const next = getId(
63
- cursor.isLast ? cursor.first : cursor.next,
64
- );
65
-
66
- return {
67
- ...node,
68
- prev,
69
- next,
70
- };
71
- });
72
-
73
- const paginateArchiveContext = (entries = [], pathName) => {
74
- const postsPerPage = 15;
75
- const numPages = getNumberOfPages(entries, postsPerPage);
76
- const output = [];
77
-
78
- for (let i = 0; i < numPages; i += 1) {
79
- const page = i + 1; // always offset for pretty URLs
80
- const path = getCurrentArchiveUrl(pathName, page);
81
- const prev = getPreviousArchiveUrl(pathName, page);
82
- const next = getNextArchiveUrl(
83
- pathName,
84
- page,
85
- numPages,
86
- );
87
-
88
- output.push({
89
- limit: postsPerPage,
90
- skip: i * postsPerPage,
91
- total: numPages,
92
- pageNum: i,
93
- path,
94
- next,
95
- prev,
96
- });
97
- }
98
-
99
- return output;
100
- };
101
-
102
- module.exports = {
103
- appendSiblingsToContext,
104
- genCursor,
105
- getNextArchiveUrl,
106
- getNumberOfPages,
107
- getPreviousArchiveUrl,
108
- paginateArchiveContext,
109
- };
package/helpers/setup.js DELETED
@@ -1,60 +0,0 @@
1
- const path = require('path');
2
- const fs = require('fs');
3
- const { compact, get } = require('lodash');
4
- const loadContent = require('./loadContent');
5
- const loadTheme = require('./loadTheme');
6
-
7
- const getFile =
8
- (directory) =>
9
- (possibleFileNames = []) =>
10
- possibleFileNames.reduce((acc, curr) => {
11
- if (acc) return acc;
12
- const filename = path.resolve(directory, curr);
13
- return fs.existsSync(filename) ? filename : undefined;
14
- }, undefined);
15
-
16
- module.exports = (
17
- siteMetadata,
18
- plugins = [],
19
- workingDirection = process.cwd(),
20
- ) => {
21
- const f = getFile(workingDirection);
22
-
23
- const locale = loadContent(f(['locale', 'lang']));
24
- const theme = loadTheme(
25
- f(['theme.js', 'gatsby-theme.js', 'mui.js']),
26
- );
27
-
28
- return {
29
- siteMetadata: {
30
- appDirectory: '/app',
31
- author: '3merge',
32
- description: '',
33
- siteUrl: 'https://3merge.ca/',
34
- ...siteMetadata,
35
- },
36
- plugins: compact(
37
- [
38
- {
39
- resolve: 'gatsby-theme-q3',
40
- options: {
41
- icon: f([
42
- 'static/favicon.png',
43
- 'static/favicon.jpg',
44
- ]),
45
-
46
- brandingColor: get(
47
- theme,
48
- 'palette.primary.main',
49
- '#000',
50
- ),
51
-
52
- locale,
53
- theme,
54
- ...siteMetadata,
55
- },
56
- },
57
- ].concat(plugins),
58
- ),
59
- };
60
- };
package/helpers/slug.js DELETED
@@ -1,31 +0,0 @@
1
- const slugify = require('slugify');
2
-
3
- const getSlug = (target) => {
4
- const keys = ['slug', 'title', 'name', 'contentful_id'];
5
-
6
- let slug;
7
- let i = 0;
8
-
9
- do {
10
- const v = target[keys[i]];
11
- if (v)
12
- slug = slugify(v, {
13
- replacement: '-',
14
- remove: undefined,
15
- lower: true,
16
- strict: true,
17
- });
18
-
19
- i += 1;
20
- } while (!slug);
21
-
22
- return slug;
23
- };
24
-
25
- const getDirectoryPath = (v) => {
26
- if (typeof v !== 'string') return '/';
27
- return v.startsWith('/') ? v : `/${v}`;
28
- };
29
-
30
- module.exports = (node = {}, basepath = '/') =>
31
- [getDirectoryPath(basepath), getSlug(node)].join('/');
@@ -1,24 +0,0 @@
1
- const slug = require('./slug');
2
-
3
- module.exports = (
4
- dir,
5
- resourceName,
6
- { createFieldExtension, createTypes },
7
- ) => {
8
- // mirrors reach router prop
9
- // an unlikely name otherwise
10
- const resolverKey = 'to';
11
-
12
- createFieldExtension({
13
- name: resolverKey,
14
- extend: () => ({
15
- resolve: (source) => slug(source, dir),
16
- }),
17
- });
18
-
19
- createTypes(`
20
- type ${resourceName} implements Node {
21
- ${resolverKey}: String @${resolverKey}
22
- }
23
- `);
24
- };