soames-gatsby-theme 0.1.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 (73) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +24 -0
  3. package/dist/gatsby-config.js +47 -0
  4. package/dist/gatsby-node.js +7 -0
  5. package/dist/src/components/Bio.js +23 -0
  6. package/dist/src/components/BlogSidebar.js +30 -0
  7. package/dist/src/components/Footer.js +11 -0
  8. package/dist/src/components/FooterMenu.js +26 -0
  9. package/dist/src/components/Header.js +12 -0
  10. package/dist/src/components/HeaderMenu.js +34 -0
  11. package/dist/src/components/HeroHeader.js +39 -0
  12. package/dist/src/components/Layout.js +24 -0
  13. package/dist/src/components/Logo.js +17 -0
  14. package/dist/src/components/Seo.js +59 -0
  15. package/dist/src/components/shortcodes/RemoveContentAreaPadding.js +12 -0
  16. package/dist/src/components/shortcodes/SoamesFeature.js +9 -0
  17. package/dist/src/components/shortcodes/SoamesGalleryMenu.js +15 -0
  18. package/dist/src/components/shortcodes/SoamesIconList.js +15 -0
  19. package/dist/src/components/shortcodes/SoamesSoundCloud.js +18 -0
  20. package/dist/src/components/shortcodes/SoamesTextBlock.js +8 -0
  21. package/dist/src/components/shortcodes/SoamesTextList.js +8 -0
  22. package/dist/src/components/shortcodes/SoamesTitle.js +7 -0
  23. package/dist/src/components/shortcodes/SoamesTitleBar.js +7 -0
  24. package/dist/src/components/shortcodes/SoamesTitleBarLg.js +25 -0
  25. package/dist/src/components/shortcodes/SoamesVideo.js +8 -0
  26. package/dist/src/pages/index.js +9 -0
  27. package/dist/src/templates/blog-post-archive.js +59 -0
  28. package/dist/src/templates/blog-post.js +67 -0
  29. package/dist/src/templates/page.js +33 -0
  30. package/dist/src/utils/shortcodes/Shortcodes.js +105 -0
  31. package/dist/src/utils/shortcodes/getAttributes.js +18 -0
  32. package/dist/src/utils/shortcodes/getContent.js +7 -0
  33. package/gatsby-browser.js +11 -0
  34. package/gatsby-node.js +138 -0
  35. package/gatsby-ssr.js +12 -0
  36. package/package.json +76 -0
  37. package/src/components/Bio.tsx +63 -0
  38. package/src/components/BlogSidebar.tsx +86 -0
  39. package/src/components/Footer.tsx +53 -0
  40. package/src/components/FooterMenu.tsx +66 -0
  41. package/src/components/Header.tsx +37 -0
  42. package/src/components/HeaderMenu.tsx +123 -0
  43. package/src/components/HeroHeader.tsx +75 -0
  44. package/src/components/Layout.tsx +60 -0
  45. package/src/components/Logo.tsx +49 -0
  46. package/src/components/Seo.tsx +84 -0
  47. package/src/components/shortcodes/RemoveContentAreaPadding.tsx +13 -0
  48. package/src/components/shortcodes/SoamesFeature.tsx +54 -0
  49. package/src/components/shortcodes/SoamesGalleryMenu.tsx +63 -0
  50. package/src/components/shortcodes/SoamesIconList.tsx +57 -0
  51. package/src/components/shortcodes/SoamesSoundCloud.tsx +71 -0
  52. package/src/components/shortcodes/SoamesTextBlock.tsx +27 -0
  53. package/src/components/shortcodes/SoamesTextList.tsx +27 -0
  54. package/src/components/shortcodes/SoamesTitle.tsx +23 -0
  55. package/src/components/shortcodes/SoamesTitleBar.tsx +21 -0
  56. package/src/components/shortcodes/SoamesTitleBarLg.tsx +56 -0
  57. package/src/components/shortcodes/SoamesVideo.tsx +34 -0
  58. package/src/styles/soames/base.css +592 -0
  59. package/src/styles/soames/components.css +1551 -0
  60. package/src/styles/soames/layout.css +209 -0
  61. package/src/styles/soames/overrides.css +1779 -0
  62. package/src/styles/soames/typography.css +23 -0
  63. package/src/styles/theme.css +8 -0
  64. package/src/styles/vendor/normalize.css +343 -0
  65. package/src/styles/vendor/wordpress-blocks.css +3451 -0
  66. package/src/templates/blog-post-archive.tsx +167 -0
  67. package/src/templates/blog-post.tsx +183 -0
  68. package/src/templates/page.tsx +65 -0
  69. package/src/utils/shortcodes/Shortcodes.tsx +119 -0
  70. package/src/utils/shortcodes/getAttributes.ts +19 -0
  71. package/src/utils/shortcodes/getContent.ts +5 -0
  72. package/static/js/soames-nav-dropdown.js +646 -0
  73. package/static/js/soames-navbar-dropdown.js +127 -0
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.pageQuery = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const gatsby_1 = require("gatsby");
9
+ const html_react_parser_1 = __importDefault(require("html-react-parser"));
10
+ const Layout_1 = __importDefault(require("../components/Layout"));
11
+ const Seo_1 = __importDefault(require("../components/Seo"));
12
+ const HeroHeader_1 = __importDefault(require("../components/HeroHeader"));
13
+ const BlogIndex = ({ data, pageContext }) => {
14
+ const posts = data.allWpPost.nodes;
15
+ const archive = data.wpPage;
16
+ const { nextPagePath, previousPagePath } = pageContext;
17
+ if (!posts.length) {
18
+ return ((0, jsx_runtime_1.jsxs)(Layout_1.default, { children: [(0, jsx_runtime_1.jsx)(Seo_1.default, { title: "All posts" }), (0, jsx_runtime_1.jsx)(HeroHeader_1.default, { title: archive.title ? (0, html_react_parser_1.default)(archive.title) : "Blog", subhead: archive.excerpt ? (0, html_react_parser_1.default)(archive.excerpt) : "", backgroundImage: archive.featuredImage?.node.guid || null, backgroundImageTitle: archive.featuredImage?.node.title || null }), (0, jsx_runtime_1.jsx)("p", { children: "No blog posts found. Add posts to your WordPress site and they'll appear here!" })] }));
19
+ }
20
+ const groupedPosts = posts.reduce((groups, post, index) => {
21
+ if (index % 3 === 0) {
22
+ groups.push([post]);
23
+ }
24
+ else {
25
+ groups[groups.length - 1].push(post);
26
+ }
27
+ return groups;
28
+ }, []);
29
+ return ((0, jsx_runtime_1.jsxs)(Layout_1.default, { isHomePage: true, children: [(0, jsx_runtime_1.jsx)(Seo_1.default, { title: "All posts" }), (0, jsx_runtime_1.jsx)(HeroHeader_1.default, { title: archive.title ? (0, html_react_parser_1.default)(archive.title) : "Blog", subhead: archive.excerpt ? (0, html_react_parser_1.default)(archive.excerpt) : "", backgroundImage: archive.featuredImage?.node.guid || null, backgroundImageTitle: archive.featuredImage?.node.title || null }), (0, jsx_runtime_1.jsx)("section", { className: "soames-blog-roll", children: (0, jsx_runtime_1.jsx)("div", { className: "container", children: groupedPosts.map((group, index) => ((0, jsx_runtime_1.jsx)("div", { className: "media-container-row", children: group.map((post, idx) => ((0, jsx_runtime_1.jsx)("div", { className: "card p-3 col-12 col-lg-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "card-wrapper", children: [(0, jsx_runtime_1.jsxs)("div", { className: "card-box", children: [(0, jsx_runtime_1.jsx)("h4", { className: "card-title mbr-fonts-style display-5", children: (0, html_react_parser_1.default)(post.title) }), (0, jsx_runtime_1.jsx)("h4", { className: "mbr-fonts-style display-7", children: post.date }), (0, html_react_parser_1.default)(post.excerpt)] }), (0, jsx_runtime_1.jsx)("div", { className: "mbr-section-btn text-center", children: (0, jsx_runtime_1.jsx)(gatsby_1.Link, { to: `/blog${post.uri}`, itemProp: "url", className: "btn btn-primary display-4", children: (0, jsx_runtime_1.jsx)("span", { itemProp: "headline", children: "Read More" }) }) })] }) }, idx))) }, index))) }) }), (0, jsx_runtime_1.jsxs)("section", { children: [previousPagePath && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(gatsby_1.Link, { to: `/blog${previousPagePath}`, children: "Previous page" }), (0, jsx_runtime_1.jsx)("br", {})] })), nextPagePath && (0, jsx_runtime_1.jsx)(gatsby_1.Link, { to: `/blog${nextPagePath}`, children: "Next page" })] })] }));
30
+ };
31
+ exports.default = BlogIndex;
32
+ exports.pageQuery = (0, gatsby_1.graphql) `
33
+ query WordPressPostArchive($offset: Int!, $postsPerPage: Int!) {
34
+ allWpPost(sort: { date: DESC }, limit: $postsPerPage, skip: $offset) {
35
+ nodes {
36
+ excerpt
37
+ uri
38
+ date(formatString: "MMMM DD, YYYY")
39
+ title
40
+ featuredImage {
41
+ node {
42
+ guid
43
+ title
44
+ }
45
+ }
46
+ }
47
+ }
48
+ wpPage(isPostsPage: { eq: true }) {
49
+ title
50
+ excerpt
51
+ featuredImage {
52
+ node {
53
+ guid
54
+ title
55
+ }
56
+ }
57
+ }
58
+ }
59
+ `;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.pageQuery = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const gatsby_1 = require("gatsby");
9
+ const gatsby_plugin_image_1 = require("gatsby-plugin-image");
10
+ const html_react_parser_1 = __importDefault(require("html-react-parser"));
11
+ require("../styles/vendor/wordpress-blocks.css");
12
+ const Bio_1 = __importDefault(require("../components/Bio"));
13
+ const Layout_1 = __importDefault(require("../components/Layout"));
14
+ const Seo_1 = __importDefault(require("../components/Seo"));
15
+ const HeroHeader_1 = __importDefault(require("../components/HeroHeader"));
16
+ const BlogSidebar_1 = __importDefault(require("../components/BlogSidebar"));
17
+ const BlogPostTemplate = ({ data }) => {
18
+ const { post, previous, next, page } = data;
19
+ const featuredImageData = post.featuredImage?.node?.gatsbyImage ?? null;
20
+ const featuredImageAlt = post.featuredImage?.node?.altText || "Featured image";
21
+ return ((0, jsx_runtime_1.jsxs)(Layout_1.default, { children: [(0, jsx_runtime_1.jsx)(Seo_1.default, { title: post.title || "", description: post.excerpt || undefined }), (0, jsx_runtime_1.jsx)(HeroHeader_1.default, { title: page?.title ? (0, html_react_parser_1.default)(page.title) : "Blog", subhead: page?.excerpt ? (0, html_react_parser_1.default)(page.excerpt) : "", backgroundImage: page?.featuredImage?.node?.guid || null, backgroundImageTitle: page?.title || null }), (0, jsx_runtime_1.jsx)("section", { children: (0, jsx_runtime_1.jsxs)("div", { className: "media-container-row", children: [(0, jsx_runtime_1.jsx)("div", { className: "col-12 col-lg-8", children: (0, jsx_runtime_1.jsxs)("section", { id: "soames-gatsby-content-container", className: "soames-gatsby-blog-content", children: [(0, jsx_runtime_1.jsxs)("article", { className: "blog-post", itemScope: true, itemType: "http://schema.org/Article", children: [(0, jsx_runtime_1.jsxs)("header", { children: [(0, jsx_runtime_1.jsx)("h1", { itemProp: "headline", children: post.title ? (0, html_react_parser_1.default)(post.title) : "" }), (0, jsx_runtime_1.jsx)("p", { children: post.date })] }), post.content && ((0, jsx_runtime_1.jsx)("section", { itemProp: "articleBody", className: "blog-post-content", children: (0, html_react_parser_1.default)(post.content) })), (0, jsx_runtime_1.jsx)("hr", {}), (0, jsx_runtime_1.jsx)("footer", { children: (0, jsx_runtime_1.jsx)(Bio_1.default, {}) })] }), (0, jsx_runtime_1.jsx)("nav", { className: "blog-post-nav", children: (0, jsx_runtime_1.jsxs)("ul", { style: {
22
+ display: `flex`,
23
+ flexWrap: `wrap`,
24
+ justifyContent: `space-between`,
25
+ listStyle: `none`,
26
+ padding: 0,
27
+ }, children: [(0, jsx_runtime_1.jsx)("li", { children: previous && ((0, jsx_runtime_1.jsxs)(gatsby_1.Link, { to: `/blog${previous.uri}`, rel: "prev", children: ["\u2190 ", previous.title ? (0, html_react_parser_1.default)(previous.title) : ""] })) }), (0, jsx_runtime_1.jsx)("li", { children: next && ((0, jsx_runtime_1.jsxs)(gatsby_1.Link, { to: `/blog${next.uri}`, rel: "next", children: [next.title ? (0, html_react_parser_1.default)(next.title) : "", " \u2192"] })) })] }) })] }) }), (0, jsx_runtime_1.jsx)("div", { className: "col-12 col-lg-4", children: (0, jsx_runtime_1.jsxs)("section", { id: "soames-gatsby-sidebar-container", className: "soames-gatsby-sidebar", children: [featuredImageData && ((0, jsx_runtime_1.jsx)(gatsby_plugin_image_1.GatsbyImage, { image: featuredImageData, alt: featuredImageAlt, style: { marginBottom: 50 } })), (0, jsx_runtime_1.jsx)("h1", { children: "Recent Posts" }), (0, jsx_runtime_1.jsx)(BlogSidebar_1.default, { postId: post.id })] }) })] }) })] }));
28
+ };
29
+ exports.default = BlogPostTemplate;
30
+ exports.pageQuery = (0, gatsby_1.graphql) `
31
+ query BlogPostById($id: String!, $previousPostId: String, $nextPostId: String) {
32
+ post: wpPost(id: { eq: $id }) {
33
+ id
34
+ excerpt
35
+ content
36
+ title
37
+ date(formatString: "MMMM DD, YYYY")
38
+ featuredImage {
39
+ node {
40
+ altText
41
+ gatsbyImage(
42
+ width: 1200
43
+ layout: CONSTRAINED
44
+ placeholder: BLURRED
45
+ )
46
+ }
47
+ }
48
+ }
49
+ previous: wpPost(id: { eq: $previousPostId }) {
50
+ uri
51
+ title
52
+ }
53
+ next: wpPost(id: { eq: $nextPostId }) {
54
+ uri
55
+ title
56
+ }
57
+ page: wpPage(isPostsPage: { eq: true }) {
58
+ title
59
+ excerpt
60
+ featuredImage {
61
+ node {
62
+ guid
63
+ }
64
+ }
65
+ }
66
+ }
67
+ `;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.pageQuery = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const gatsby_1 = require("gatsby");
9
+ const html_react_parser_1 = __importDefault(require("html-react-parser"));
10
+ const Layout_1 = __importDefault(require("../components/Layout"));
11
+ const Seo_1 = __importDefault(require("../components/Seo"));
12
+ const HeroHeader_1 = __importDefault(require("../components/HeroHeader"));
13
+ const Shortcodes_1 = require("../utils/shortcodes/Shortcodes");
14
+ // Gutenberg block styles
15
+ require("../styles/vendor/wordpress-blocks.css");
16
+ const Page = ({ data: { page } }) => ((0, jsx_runtime_1.jsxs)(Layout_1.default, { children: [(0, jsx_runtime_1.jsx)(Seo_1.default, { title: page.title }), (0, jsx_runtime_1.jsx)(HeroHeader_1.default, { title: (0, html_react_parser_1.default)(page.title), subhead: page.excerpt ? (0, html_react_parser_1.default)(page.excerpt) : "", backgroundImage: page.featuredImage?.node.guid || null, backgroundImageTitle: page.featuredImage?.node.title || null }), page.content && ((0, jsx_runtime_1.jsx)("section", { id: "soames-gatsby-content-container", className: "soames-gatsby-content", children: (0, jsx_runtime_1.jsx)(Shortcodes_1.Shortcodes, { children: page.content }) }))] }));
17
+ exports.default = Page;
18
+ exports.pageQuery = (0, gatsby_1.graphql) `
19
+ query PageById($id: String!) {
20
+ page: wpPage(id: { eq: $id }) {
21
+ id
22
+ title
23
+ excerpt
24
+ content
25
+ featuredImage {
26
+ node {
27
+ title
28
+ guid
29
+ }
30
+ }
31
+ }
32
+ }
33
+ `;
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Shortcodes = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const html_react_parser_1 = __importDefault(require("html-react-parser"));
9
+ const getAttributes_1 = require("./getAttributes");
10
+ const getContent_1 = require("./getContent");
11
+ const RemoveContentAreaPadding_1 = __importDefault(require("../../components/shortcodes/RemoveContentAreaPadding"));
12
+ const SoamesTitle_1 = __importDefault(require("../../components/shortcodes/SoamesTitle"));
13
+ const SoamesTitleBar_1 = __importDefault(require("../../components/shortcodes/SoamesTitleBar"));
14
+ const SoamesTitleBarLg_1 = __importDefault(require("../../components/shortcodes/SoamesTitleBarLg"));
15
+ const SoamesTextBlock_1 = __importDefault(require("../../components/shortcodes/SoamesTextBlock"));
16
+ const SoamesIconList_1 = __importDefault(require("../../components/shortcodes/SoamesIconList"));
17
+ const SoamesFeature_1 = __importDefault(require("../../components/shortcodes/SoamesFeature"));
18
+ const SoamesGalleryMenu_1 = __importDefault(require("../../components/shortcodes/SoamesGalleryMenu"));
19
+ const SoamesVideo_1 = __importDefault(require("../../components/shortcodes/SoamesVideo"));
20
+ const SoamesTextList_1 = __importDefault(require("../../components/shortcodes/SoamesTextList"));
21
+ const SoamesSoundCloud_1 = __importDefault(require("../../components/shortcodes/SoamesSoundCloud"));
22
+ const handleShortcodes = (node) => {
23
+ if (node.type === "tag" && node.children && node.children.length > 0) {
24
+ const child = node.children[0];
25
+ if (child.type === "text") {
26
+ const shortcode = child.data.trim();
27
+ if (shortcode === "[soames-remove-content-area-padding]") {
28
+ return (0, jsx_runtime_1.jsx)(RemoveContentAreaPadding_1.default, {});
29
+ }
30
+ const shortcodeMappings = [
31
+ {
32
+ regex: /\[soames-title([^\]]*)\]([\s\S]*?)\[\/soames-title\]/,
33
+ component: SoamesTitle_1.default,
34
+ propsExtractor: (match) => ({ title: (0, getContent_1.getContent)(match) }),
35
+ },
36
+ {
37
+ regex: /\[soames-title-bar([^\]]*)\]([\s\S]*?)\[\/soames-title-bar\]/,
38
+ component: SoamesTitleBar_1.default,
39
+ propsExtractor: (match) => ({ title: (0, getContent_1.getContent)(match) }),
40
+ },
41
+ {
42
+ regex: /\[soames-title-bar-lg([^\]]*)\]([\s\S]*?)\[\/soames-title-bar-lg\]/,
43
+ component: SoamesTitleBarLg_1.default,
44
+ propsExtractor: (match) => ({
45
+ title: (0, getContent_1.getContent)(match),
46
+ attributes: (0, getAttributes_1.getAttributes)(match),
47
+ }),
48
+ },
49
+ {
50
+ regex: /\[soames-text-block([^\]]*)\]([\s\S]*?)\[\/soames-text-block\]/,
51
+ component: SoamesTextBlock_1.default,
52
+ propsExtractor: (match) => ({ content: (0, getContent_1.getContent)(match) }),
53
+ },
54
+ {
55
+ regex: /\[soames-text-list([^\]]*)\]([\s\S]*?)\[\/soames-text-list\]/,
56
+ component: SoamesTextList_1.default,
57
+ propsExtractor: (match) => ({ content: (0, getContent_1.getContent)(match) }),
58
+ },
59
+ {
60
+ regex: /\[soames-icon-list([^\]]*)\]/,
61
+ component: SoamesIconList_1.default,
62
+ propsExtractor: (match) => ({ attributes: (0, getAttributes_1.getAttributes)(match) }),
63
+ },
64
+ {
65
+ regex: /\[soames-feature([^\]]*)\]([\s\S]*?)\[\/soames-feature\]/,
66
+ component: SoamesFeature_1.default,
67
+ propsExtractor: (match) => ({
68
+ content: (0, getContent_1.getContent)(match),
69
+ attributes: (0, getAttributes_1.getAttributes)(match),
70
+ }),
71
+ },
72
+ {
73
+ regex: /\[soames-gallery-menu([^\]]*)\]/,
74
+ component: SoamesGalleryMenu_1.default,
75
+ propsExtractor: (match) => ({ attributes: (0, getAttributes_1.getAttributes)(match) }),
76
+ },
77
+ {
78
+ regex: /\[soames-video([^\]]*)\]/,
79
+ component: SoamesVideo_1.default,
80
+ propsExtractor: (match) => ({ attributes: (0, getAttributes_1.getAttributes)(match) }),
81
+ },
82
+ {
83
+ regex: /\[soames-soundcloud([^\]]*)\]/,
84
+ component: SoamesSoundCloud_1.default,
85
+ propsExtractor: (match) => ({ attributes: (0, getAttributes_1.getAttributes)(match) }),
86
+ },
87
+ ];
88
+ for (const { regex, component: Component, propsExtractor } of shortcodeMappings) {
89
+ const match = shortcode.match(regex);
90
+ if (match) {
91
+ const props = propsExtractor(match);
92
+ return (0, jsx_runtime_1.jsx)(Component, { ...props });
93
+ }
94
+ }
95
+ }
96
+ }
97
+ return undefined;
98
+ };
99
+ const Shortcodes = ({ children }) => {
100
+ const reactElements = (0, html_react_parser_1.default)(children || "", {
101
+ replace: handleShortcodes,
102
+ });
103
+ return (0, jsx_runtime_1.jsx)("div", { children: reactElements });
104
+ };
105
+ exports.Shortcodes = Shortcodes;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ // src/utils/shortcodes/getAttributes.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.getAttributes = getAttributes;
5
+ function getAttributes(match) {
6
+ if (!match || !match[1])
7
+ return null;
8
+ const attributes = {};
9
+ const attrString = match[1];
10
+ const regex = /(\w+)=["']?((?:.(?!["']?\s+(?:\S+)=|\s*\/?[>"']))+.)["']?/g;
11
+ let attrMatch;
12
+ while ((attrMatch = regex.exec(attrString)) !== null) {
13
+ const key = attrMatch[1];
14
+ const value = attrMatch[2].replace(/[″”]+/g, '').split(',');
15
+ attributes[key] = value;
16
+ }
17
+ return attributes;
18
+ }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ // src/utils/shortcodes/getContent.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.getContent = getContent;
5
+ function getContent(match) {
6
+ return match && match[2] ? match[2] : null;
7
+ }
@@ -0,0 +1,11 @@
1
+ // Vendor styles only
2
+ import "bootstrap/dist/css/bootstrap.min.css";
3
+ import "jquery/dist/jquery.min.js";
4
+ import "@popperjs/core/dist/umd/popper.min.js";
5
+ import "bootstrap/dist/js/bootstrap.min.js";
6
+ //import "./src/styles/vendor/normalize.css";
7
+ import "./src/styles/vendor/wordpress-blocks.css";
8
+
9
+ // Soames - custom JS
10
+ import "./static/js/soames-nav-dropdown.js";
11
+ import "./static/js/soames-navbar-dropdown.js";
package/gatsby-node.js ADDED
@@ -0,0 +1,138 @@
1
+ const { createRemoteFileNode } = require(`gatsby-source-filesystem`);
2
+
3
+ exports.createResolvers = ({ actions, cache, createNodeId, createResolvers, store, reporter }) => {
4
+ const { createNode } = actions;
5
+ createResolvers({
6
+ WpMediaItem: {
7
+ localFile: {
8
+ type: `File`,
9
+ resolve(source) {
10
+ return createRemoteFileNode({
11
+ url: source.sourceUrl,
12
+ store,
13
+ cache,
14
+ createNode,
15
+ createNodeId,
16
+ reporter,
17
+ });
18
+ },
19
+ },
20
+ },
21
+ });
22
+ };
23
+
24
+ const path = require('path');
25
+ const { chunk } = require('lodash');
26
+
27
+ exports.createPages = async ({ graphql, actions, reporter }) => {
28
+ const { createPage } = actions;
29
+
30
+ // Fetch posts
31
+ const postsResult = await graphql(`
32
+ query WpPosts {
33
+ allWpPost(sort: { date: DESC }) {
34
+ edges {
35
+ previous {
36
+ id
37
+ }
38
+ node {
39
+ id
40
+ uri
41
+ }
42
+ next {
43
+ id
44
+ }
45
+ }
46
+ }
47
+ }
48
+ `);
49
+
50
+ if (postsResult.errors) {
51
+ reporter.panicOnBuild('Error loading blog posts', postsResult.errors);
52
+ return;
53
+ }
54
+
55
+ const postEdges = postsResult.data.allWpPost.edges;
56
+
57
+ // Fetch pages
58
+ const pagesResult = await graphql(`
59
+ query WpPages {
60
+ allWpPage {
61
+ edges {
62
+ node {
63
+ id
64
+ uri
65
+ title
66
+ }
67
+ }
68
+ }
69
+ }
70
+ `);
71
+
72
+ if (pagesResult.errors) {
73
+ reporter.panicOnBuild('Error loading pages', pagesResult.errors);
74
+ return;
75
+ }
76
+
77
+ const pageEdges = pagesResult.data.allWpPage.edges;
78
+
79
+ // Create individual blog post pages
80
+ postEdges.forEach(({ previous, node, next }) => {
81
+ createPage({
82
+ path: `/blog${node.uri}`,
83
+ component: path.resolve(__dirname, 'src/templates/blog-post.tsx'),
84
+ context: {
85
+ id: node.id,
86
+ previousPostId: previous ? previous.id : null,
87
+ nextPostId: next ? next.id : null,
88
+ },
89
+ });
90
+ });
91
+
92
+ // Create blog post archive pages
93
+ const readingSettingsResult = await graphql(`
94
+ {
95
+ wp {
96
+ readingSettings {
97
+ postsPerPage
98
+ }
99
+ }
100
+ }
101
+ `);
102
+
103
+ if (readingSettingsResult.errors) {
104
+ reporter.panicOnBuild('Error loading reading settings', readingSettingsResult.errors);
105
+ return;
106
+ }
107
+
108
+ const postsPerPage = readingSettingsResult.data.wp.readingSettings.postsPerPage;
109
+ const postsChunkedIntoArchivePages = chunk(postEdges, postsPerPage);
110
+ const totalPages = postsChunkedIntoArchivePages.length;
111
+
112
+ postsChunkedIntoArchivePages.forEach((_, index) => {
113
+ const pageNumber = index + 1;
114
+ const pathSuffix = pageNumber === 1 ? '' : `/${pageNumber}`;
115
+ createPage({
116
+ path: `/blog${pathSuffix}`,
117
+ component: path.resolve(__dirname, 'src/templates/blog-post-archive.tsx'),
118
+ context: {
119
+ offset: index * postsPerPage,
120
+ postsPerPage,
121
+ nextPagePath: pageNumber < totalPages ? `/blog/${pageNumber + 1}` : null,
122
+ previousPagePath: pageNumber > 1 ? `/blog/${pageNumber - 1}` : null,
123
+ },
124
+ });
125
+ });
126
+
127
+ // Create individual pages
128
+ pageEdges.forEach(({ node }) => {
129
+ createPage({
130
+ path: node.uri || '/soames-blog-archive/',
131
+ component: path.resolve(__dirname, 'src/templates/page.tsx'),
132
+ context: {
133
+ id: node.id,
134
+ title: node.title,
135
+ },
136
+ });
137
+ });
138
+ };
package/gatsby-ssr.js ADDED
@@ -0,0 +1,12 @@
1
+ const React = require("react")
2
+
3
+ export const onRenderBody = ({ setHeadComponents }, pluginOptions) => {
4
+ setHeadComponents([
5
+ <script
6
+ key="jquery-for-ssr"
7
+ src="https://code.jquery.com/jquery-3.4.1.min.js"
8
+ integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
9
+ crossOrigin="anonymous">
10
+ </script>,
11
+ ])
12
+ }
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "soames-gatsby-theme",
3
+ "version": "0.1.0",
4
+ "description": "A customizable Gatsby theme for personal websites using WordPress as a headless CMS.",
5
+ "main": "dist/gatsby-config.js",
6
+ "scripts": {
7
+ "build": "tsc",
8
+ "prepare": "npm run build"
9
+ },
10
+ "keywords": [
11
+ "gatsby",
12
+ "gatsby-theme",
13
+ "wordpress",
14
+ "headless-cms",
15
+ "typescript",
16
+ "react",
17
+ "blog",
18
+ "personal-site"
19
+ ],
20
+ "author": "Orbi Software",
21
+ "license": "BSD-3-Clause",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/orbivision/soames-gatsby-theme"
25
+ },
26
+ "bugs": {
27
+ "url": "https://github.com/orbivision/soames-gatsby-theme/issues"
28
+ },
29
+ "homepage": "https://github.com/orbivision/soames-gatsby-theme#readme",
30
+ "files": [
31
+ "dist",
32
+ "src",
33
+ "static",
34
+ "gatsby-config.js",
35
+ "gatsby-node.js",
36
+ "gatsby-ssr.js",
37
+ "gatsby-browser.js",
38
+ "README.md",
39
+ "LICENSE"
40
+ ],
41
+ "engines": {
42
+ "node": ">=18.0.0",
43
+ "npm": ">=9.0.0"
44
+ },
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "peerDependencies": {
49
+ "gatsby": "^5.14.3",
50
+ "react": "^18.2.0",
51
+ "react-dom": "^18.2.0"
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "^18.19.86",
55
+ "@types/react": "^18.3.20",
56
+ "@types/react-dom": "^18.3.6",
57
+ "@types/react-helmet": "^6.1.11",
58
+ "@types/styled-components": "^5.1.34",
59
+ "typescript": "^5.8.3"
60
+ },
61
+ "dependencies": {
62
+ "@popperjs/core": "^2.11.8",
63
+ "@wordpress/block-library": "^9.22.0",
64
+ "bootstrap": "^5.3.5",
65
+ "gatsby-plugin-image": "^3.14.0",
66
+ "gatsby-plugin-manifest": "^5.14.0",
67
+ "gatsby-plugin-react-helmet": "^6.14.0",
68
+ "gatsby-plugin-sharp": "^5.14.0",
69
+ "gatsby-source-filesystem": "^5.14.0",
70
+ "gatsby-source-wordpress": "^7.15.0",
71
+ "gatsby-transformer-sharp": "^5.14.0",
72
+ "html-react-parser": "^5.2.3",
73
+ "jquery": "^3.7.1",
74
+ "react-helmet": "^6.1.0"
75
+ }
76
+ }
@@ -0,0 +1,63 @@
1
+ // src/components/Bio.tsx
2
+
3
+ import React from "react";
4
+ import { useStaticQuery, graphql } from "gatsby";
5
+
6
+ interface Author {
7
+ firstName: string;
8
+ name: string; // Used as Twitter handle
9
+ description: string;
10
+ avatar?: {
11
+ url: string;
12
+ };
13
+ }
14
+
15
+ interface BioQueryData {
16
+ author: Author;
17
+ }
18
+
19
+ const Bio: React.FC = () => {
20
+ const data = useStaticQuery<BioQueryData>(graphql`
21
+ query BioQuery {
22
+ author: wpUser {
23
+ firstName
24
+ name
25
+ description
26
+ avatar {
27
+ url
28
+ }
29
+ }
30
+ }
31
+ `);
32
+
33
+ const { author } = data;
34
+ const avatarUrl = author?.avatar?.url;
35
+ const twitterHandle = author?.name;
36
+
37
+ return (
38
+ <div className="bio">
39
+ {avatarUrl && (
40
+ <img
41
+ alt={author.firstName}
42
+ className="bio-avatar"
43
+ src={avatarUrl}
44
+ />
45
+ )}
46
+ {author.firstName && (
47
+ <p>
48
+ Written by <strong>{author.firstName}</strong>
49
+ {` `}
50
+ {author.description}
51
+ {` `}
52
+ {twitterHandle && (
53
+ <a href={`https://twitter.com/${twitterHandle}`}>
54
+ You should follow them on Twitter
55
+ </a>
56
+ )}
57
+ </p>
58
+ )}
59
+ </div>
60
+ );
61
+ };
62
+
63
+ export default Bio;