diff --git a/gatsby-node.js b/gatsby-node.js index a024c806f..8446b817f 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -1,4 +1,5 @@ const path = require(`path`); +const fs = require("fs"); // eslint-disable-next-line import/no-extraneous-dependencies const webpack = require("webpack"); const pagesConfig = require("./src/config"); @@ -236,6 +237,11 @@ exports.createResolvers = ({ createResolvers }) => { exports.onCreateWebpackConfig = ({ actions }) => { actions.setWebpackConfig({ + resolve: { + fallback: { + fs: false, + }, + }, plugins: [ /** * See line 203 of: @@ -277,3 +283,52 @@ exports.onCreateWebpackConfig = ({ actions }) => { ], }); }; + +exports.sourceNodes = ({ actions, createNodeId, createContentDigest }) => { + const { createNode } = actions; + + // Read all files in the sub-directories of the patterns folder + function getFilePaths(dirPath) { + let filePaths = []; + const files = fs.readdirSync(dirPath); + + files.forEach((file) => { + const absolutePath = path.join(dirPath, file); + if (fs.statSync(absolutePath).isDirectory()) { + filePaths = filePaths.concat(getFilePaths(absolutePath)); + } else { + filePaths.push(absolutePath); + } + }); + + return filePaths; + } + + // Read all files in the patterns folder + const patternsDir = path.resolve( + __dirname, + "src/content/structured/patterns/templates" + ); + const filePaths = getFilePaths(patternsDir); + + // For each file in the patterns folder, read the contents of the file and create a data node + filePaths.forEach((filePath) => { + const content = fs.readFileSync(filePath, "utf8"); + const regex = /(?:\\|\/)patterns(?:\\|\/)templates((?:\\|\/).*)$/; + const regexMatchedFilePath = filePath.match(regex)[0]; + + const nodeMeta = { + id: createNodeId(`${regexMatchedFilePath}`), + parent: null, + children: [], + internal: { + type: `PatternsTemplates`, + contentFilePath: regexMatchedFilePath, + content, + contentDigest: createContentDigest(content), + }, + }; + + createNode(nodeMeta); + }); +}; diff --git a/package-lock.json b/package-lock.json index 0c947efd1..b7e08b1a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@mdi/react": "^1.5.0", "@mdx-js/mdx": "^1.6.22", "@mdx-js/react": "^1.6.22", + "@stackblitz/sdk": "^1.9.0", "@ukic/docs": "^2.10.0", "@ukic/fonts": "^2.6.0", "@ukic/react": "^2.14.0", @@ -50,6 +51,8 @@ "gatsby-transformer-remark": "^6.12.0", "gatsby-transformer-sharp": "^4.2.0", "github-slugger": "^1.4.0", + "lodash.kebabcase": "^4.1.1", + "lodash.startcase": "^4.4.0", "performant-array-to-tree": "^1.9.1", "prism-react-renderer": "^1.3.1", "prismjs": "^1.25.0", @@ -58,6 +61,7 @@ "react": "^17.0.2", "react-dom": "^17.0.2", "react-helmet": "^6.1.0", + "react-jss": "^10.10.0", "react-markdown": "^7.1.0", "react-router-dom": "^6.0.2", "react-table": "^7.7.0", @@ -74,6 +78,8 @@ "@testing-library/react-hooks": "^7.0.2", "@types/dateformat": "^5.0.0", "@types/github-slugger": "^1.3.0", + "@types/lodash.kebabcase": "^4.1.9", + "@types/lodash.startcase": "^4.4.9", "@types/react-helmet": "^6.1.5", "@types/react-table": "^7.7.11", "@typescript-eslint/eslint-plugin": "^5.9.1", @@ -2675,6 +2681,19 @@ "tslib": "^2.4.0" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.7.3.tgz", + "integrity": "sha512-uxJqm/sqwXw3YPA5GXX365OBcJGFtxUVkB6WyezqFHlNe9jqUWH5ur2O2M8dGBz61kn1g3ZBlzUunFQXQIClhA==", + "dependencies": { + "@emotion/memoize": "0.7.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.1.tgz", + "integrity": "sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg==" + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -5965,6 +5984,11 @@ "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, + "node_modules/@stackblitz/sdk": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@stackblitz/sdk/-/sdk-1.9.0.tgz", + "integrity": "sha512-3m6C7f8pnR5KXys/Hqx2x6ylnpqOak6HtnZI6T5keEO0yT+E4Spkw37VEbdwuC+2oxmjdgq6YZEgiKX7hM1GmQ==" + }, "node_modules/@stencil/core": { "version": "4.13.0", "resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.13.0.tgz", @@ -6423,6 +6447,24 @@ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==" }, + "node_modules/@types/lodash.kebabcase": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/lodash.kebabcase/-/lodash.kebabcase-4.1.9.tgz", + "integrity": "sha512-kPrrmcVOhSsjAVRovN0lRfrbuidfg0wYsrQa5IYuoQO1fpHHGSme66oyiYA/5eQPVl8Z95OA3HG0+d2SvYC85w==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/lodash.startcase": { + "version": "4.4.9", + "resolved": "https://registry.npmjs.org/@types/lodash.startcase/-/lodash.startcase-4.4.9.tgz", + "integrity": "sha512-C0M4DlN1pnn2vEEhLHkTHxiRZ+3GlTegpoAEHHGXnuJkSOXyJMHGiSc+SLRzBlFZWHsBkixe6FqvEAEU04g14g==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/mdast": { "version": "3.0.15", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", @@ -10085,6 +10127,16 @@ "postcss": "^8.0.9" } }, + "node_modules/css-jss": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/css-jss/-/css-jss-10.10.0.tgz", + "integrity": "sha512-YyMIS/LsSKEGXEaVJdjonWe18p4vXLo8CMA4FrW/kcaEyqdIGKCFXao31gbJddXEdIxSXFFURWrenBJPlKTgAA==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "^10.10.0", + "jss-preset-default": "^10.10.0" + } + }, "node_modules/css-loader": { "version": "5.2.7", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", @@ -10192,6 +10244,15 @@ "node": ">=0.10.0" } }, + "node_modules/css-vendor": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", + "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", + "dependencies": { + "@babel/runtime": "^7.8.3", + "is-in-browser": "^1.0.2" + } + }, "node_modules/css-what": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", @@ -11769,38 +11830,6 @@ "eslint": ">=7.0.0" } }, - "node_modules/eslint-config-react-app": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz", - "integrity": "sha512-bpoAAC+YRfzq0dsTk+6v9aHm/uqnDwayNAXleMypGl6CpxI9oXXscVHo4fk3eJPIn+rsbtNetB4r/ZIidFIE8A==", - "dependencies": { - "confusing-browser-globals": "^1.0.10" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^4.0.0", - "@typescript-eslint/parser": "^4.0.0", - "babel-eslint": "^10.0.0", - "eslint": "^7.5.0", - "eslint-plugin-flowtype": "^5.2.0", - "eslint-plugin-import": "^2.22.0", - "eslint-plugin-jest": "^24.0.0", - "eslint-plugin-jsx-a11y": "^6.3.1", - "eslint-plugin-react": "^7.20.3", - "eslint-plugin-react-hooks": "^4.0.8", - "eslint-plugin-testing-library": "^3.9.0" - }, - "peerDependenciesMeta": { - "eslint-plugin-jest": { - "optional": true - }, - "eslint-plugin-testing-library": { - "optional": true - } - } - }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", @@ -15830,6 +15859,38 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/gatsby/node_modules/eslint-config-react-app": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz", + "integrity": "sha512-bpoAAC+YRfzq0dsTk+6v9aHm/uqnDwayNAXleMypGl6CpxI9oXXscVHo4fk3eJPIn+rsbtNetB4r/ZIidFIE8A==", + "dependencies": { + "confusing-browser-globals": "^1.0.10" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^4.0.0", + "@typescript-eslint/parser": "^4.0.0", + "babel-eslint": "^10.0.0", + "eslint": "^7.5.0", + "eslint-plugin-flowtype": "^5.2.0", + "eslint-plugin-import": "^2.22.0", + "eslint-plugin-jest": "^24.0.0", + "eslint-plugin-jsx-a11y": "^6.3.1", + "eslint-plugin-react": "^7.20.3", + "eslint-plugin-react-hooks": "^4.0.8", + "eslint-plugin-testing-library": "^3.9.0" + }, + "peerDependenciesMeta": { + "eslint-plugin-jest": { + "optional": true + }, + "eslint-plugin-testing-library": { + "optional": true + } + } + }, "node_modules/gatsby/node_modules/eslint-visitor-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", @@ -16845,6 +16906,19 @@ "tslib": "^2.0.3" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", @@ -17159,6 +17233,11 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/hyphenate-style-name": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", + "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -17745,6 +17824,11 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/is-in-browser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", + "integrity": "sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==" + }, "node_modules/is-installed-globally": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", @@ -19783,6 +19867,158 @@ "node": ">=0.6.0" } }, + "node_modules/jss": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss/-/jss-10.10.0.tgz", + "integrity": "sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "csstype": "^3.0.2", + "is-in-browser": "^1.1.3", + "tiny-warning": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/jss" + } + }, + "node_modules/jss-plugin-camel-case": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.10.0.tgz", + "integrity": "sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "hyphenate-style-name": "^1.0.3", + "jss": "10.10.0" + } + }, + "node_modules/jss-plugin-compose": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-compose/-/jss-plugin-compose-10.10.0.tgz", + "integrity": "sha512-F5kgtWpI2XfZ3Z8eP78tZEYFdgTIbpA/TMuX3a8vwrNolYtN1N4qJR/Ob0LAsqIwCMLojtxN7c7Oo/+Vz6THow==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0", + "tiny-warning": "^1.0.2" + } + }, + "node_modules/jss-plugin-default-unit": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.10.0.tgz", + "integrity": "sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0" + } + }, + "node_modules/jss-plugin-expand": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-expand/-/jss-plugin-expand-10.10.0.tgz", + "integrity": "sha512-ymT62W2OyDxBxr7A6JR87vVX9vTq2ep5jZLIdUSusfBIEENLdkkc0lL/Xaq8W9s3opUq7R0sZQpzRWELrfVYzA==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0" + } + }, + "node_modules/jss-plugin-extend": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-extend/-/jss-plugin-extend-10.10.0.tgz", + "integrity": "sha512-sKYrcMfr4xxigmIwqTjxNcHwXJIfvhvjTNxF+Tbc1NmNdyspGW47Ey6sGH8BcQ4FFQhLXctpWCQSpDwdNmXSwg==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0", + "tiny-warning": "^1.0.2" + } + }, + "node_modules/jss-plugin-global": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.10.0.tgz", + "integrity": "sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0" + } + }, + "node_modules/jss-plugin-nested": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.10.0.tgz", + "integrity": "sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0", + "tiny-warning": "^1.0.2" + } + }, + "node_modules/jss-plugin-props-sort": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.10.0.tgz", + "integrity": "sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0" + } + }, + "node_modules/jss-plugin-rule-value-function": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.10.0.tgz", + "integrity": "sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0", + "tiny-warning": "^1.0.2" + } + }, + "node_modules/jss-plugin-rule-value-observable": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-observable/-/jss-plugin-rule-value-observable-10.10.0.tgz", + "integrity": "sha512-ZLMaYrR3QE+vD7nl3oNXuj79VZl9Kp8/u6A1IbTPDcuOu8b56cFdWRZNZ0vNr8jHewooEeq2doy8Oxtymr2ZPA==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0", + "symbol-observable": "^1.2.0" + } + }, + "node_modules/jss-plugin-template": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-template/-/jss-plugin-template-10.10.0.tgz", + "integrity": "sha512-ocXZBIOJOA+jISPdsgkTs8wwpK6UbsvtZK5JI7VUggTD6LWKbtoxUzadd2TpfF+lEtlhUmMsCkTRNkITdPKa6w==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0", + "tiny-warning": "^1.0.2" + } + }, + "node_modules/jss-plugin-vendor-prefixer": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.10.0.tgz", + "integrity": "sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "css-vendor": "^2.0.8", + "jss": "10.10.0" + } + }, + "node_modules/jss-preset-default": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-preset-default/-/jss-preset-default-10.10.0.tgz", + "integrity": "sha512-GL175Wt2FGhjE+f+Y3aWh+JioL06/QWFgZp53CbNNq6ZkVU0TDplD8Bxm9KnkotAYn3FlplNqoW5CjyLXcoJ7Q==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0", + "jss-plugin-camel-case": "10.10.0", + "jss-plugin-compose": "10.10.0", + "jss-plugin-default-unit": "10.10.0", + "jss-plugin-expand": "10.10.0", + "jss-plugin-extend": "10.10.0", + "jss-plugin-global": "10.10.0", + "jss-plugin-nested": "10.10.0", + "jss-plugin-props-sort": "10.10.0", + "jss-plugin-rule-value-function": "10.10.0", + "jss-plugin-rule-value-observable": "10.10.0", + "jss-plugin-template": "10.10.0", + "jss-plugin-vendor-prefixer": "10.10.0" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -20251,6 +20487,11 @@ "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", "integrity": "sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g==" }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==" + }, "node_modules/lodash.map": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", @@ -20291,6 +20532,11 @@ "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", "integrity": "sha512-j7MJE+TuT51q9ggt4fSgVqro163BEFjAt3u97IqU+JA2DkWl80nFTrowzLpZ/BnpN7rrl0JA/593NAdd8p/scQ==" }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==" + }, "node_modules/lodash.template": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", @@ -25135,6 +25381,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/react-display-name": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/react-display-name/-/react-display-name-0.2.5.tgz", + "integrity": "sha512-I+vcaK9t4+kypiSgaiVWAipqHRXYmZIuAiS8vzFvXHHXVigg/sMKwlRgLy6LH2i3rmP+0Vzfl5lFsFRwF1r3pg==" + }, "node_modules/react-dom": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", @@ -25193,6 +25444,27 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-jss": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/react-jss/-/react-jss-10.10.0.tgz", + "integrity": "sha512-WLiq84UYWqNBF6579/uprcIUnM1TSywYq6AIjKTTTG5ziJl9Uy+pwuvpN3apuyVwflMbD60PraeTKT7uWH9XEQ==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "@emotion/is-prop-valid": "^0.7.3", + "css-jss": "10.10.0", + "hoist-non-react-statics": "^3.2.0", + "is-in-browser": "^1.1.3", + "jss": "10.10.0", + "jss-preset-default": "10.10.0", + "prop-types": "^15.6.0", + "shallow-equal": "^1.2.0", + "theming": "^3.3.0", + "tiny-warning": "^1.0.2" + }, + "peerDependencies": { + "react": ">=16.8.6" + } + }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", @@ -27659,6 +27931,11 @@ "resolved": "https://registry.npmjs.org/shallow-compare/-/shallow-compare-1.2.2.tgz", "integrity": "sha512-LUMFi+RppPlrHzbqmFnINTrazo0lPNwhcgzuAXVVcfy/mqPDrQmHAyz5bvV0gDAuRFrk804V0HpQ6u9sZ0tBeg==" }, + "node_modules/shallow-equal": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", + "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==" + }, "node_modules/sharp": { "version": "0.33.1", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.1.tgz", @@ -29039,6 +29316,14 @@ "tslib": "^2.0.3" } }, + "node_modules/symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -29358,6 +29643,23 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" }, + "node_modules/theming": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/theming/-/theming-3.3.0.tgz", + "integrity": "sha512-u6l4qTJRDaWZsqa8JugaNt7Xd8PPl9+gonZaIe28vAhqgHMIG/DOyFPqiKN/gQLQYj05tHv+YQdNILL4zoiAVA==", + "dependencies": { + "hoist-non-react-statics": "^3.3.0", + "prop-types": "^15.5.8", + "react-display-name": "^0.2.4", + "tiny-warning": "^1.0.2" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.3" + } + }, "node_modules/throat": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", @@ -29401,6 +29703,11 @@ "next-tick": "1" } }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, "node_modules/title-case": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/title-case/-/title-case-3.0.3.tgz", diff --git a/package.json b/package.json index 599cb88a1..d6a4147aa 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "@mdi/react": "^1.5.0", "@mdx-js/mdx": "^1.6.22", "@mdx-js/react": "^1.6.22", + "@stackblitz/sdk": "^1.9.0", "@ukic/docs": "^2.10.0", "@ukic/fonts": "^2.6.0", "@ukic/react": "^2.14.0", @@ -45,6 +46,8 @@ "gatsby-transformer-remark": "^6.12.0", "gatsby-transformer-sharp": "^4.2.0", "github-slugger": "^1.4.0", + "lodash.kebabcase": "^4.1.1", + "lodash.startcase": "^4.4.0", "performant-array-to-tree": "^1.9.1", "prism-react-renderer": "^1.3.1", "prismjs": "^1.25.0", @@ -53,6 +56,7 @@ "react": "^17.0.2", "react-dom": "^17.0.2", "react-helmet": "^6.1.0", + "react-jss": "^10.10.0", "react-markdown": "^7.1.0", "react-router-dom": "^6.0.2", "react-table": "^7.7.0", @@ -69,6 +73,8 @@ "@testing-library/react-hooks": "^7.0.2", "@types/dateformat": "^5.0.0", "@types/github-slugger": "^1.3.0", + "@types/lodash.kebabcase": "^4.1.9", + "@types/lodash.startcase": "^4.4.9", "@types/react-helmet": "^6.1.5", "@types/react-table": "^7.7.11", "@typescript-eslint/eslint-plugin": "^5.9.1", diff --git a/src/assets/svg/index.ts b/src/assets/svg/index.ts index a1f43ba82..1486ed922 100644 --- a/src/assets/svg/index.ts +++ b/src/assets/svg/index.ts @@ -3,3 +3,4 @@ export { default as GCHQLogo } from "./gchq-logo.svg"; export { default as MI5Logo } from "./mi5-logo.svg"; export { default as SISLogo } from "./sis-logo.svg"; export { default as ICDSLogo } from "./icds-logo.svg"; +export { default as StackblitzLogo } from "./stackblitz-logo.svg"; diff --git a/src/assets/svg/stackblitz-logo.svg b/src/assets/svg/stackblitz-logo.svg new file mode 100644 index 000000000..d3feff844 --- /dev/null +++ b/src/assets/svg/stackblitz-logo.svg @@ -0,0 +1 @@ +StackBlitz \ No newline at end of file diff --git a/src/components/CodePreview/index.css b/src/components/CodePreview/index.css index 8c92fa037..4bdd3c3d6 100644 --- a/src/components/CodePreview/index.css +++ b/src/components/CodePreview/index.css @@ -72,9 +72,7 @@ } .snippet-container ic-button { - margin-top: var(--ic-space-xxs); - margin-right: var(--ic-space-xs); - margin-bottom: var(--ic-space-xs); + margin: var(--ic-space-xxs) var(--ic-space-xxs) var(--ic-space-xxs) 0; } .snippet-container ic-button button.button { diff --git a/src/components/CodePreview/index.tsx b/src/components/CodePreview/index.tsx index 537dd8576..ce5e750fc 100644 --- a/src/components/CodePreview/index.tsx +++ b/src/components/CodePreview/index.tsx @@ -1,6 +1,6 @@ import Highlight, { defaultProps } from "prism-react-renderer"; -import React, { CSSProperties, ReactNode } from "react"; - +import React, { CSSProperties, ReactNode, useState, useEffect } from "react"; +import startCase from "lodash.startcase"; import { mdiCheckboxMarkedCircle, mdiCloseCircle, @@ -9,7 +9,11 @@ import { import Icon from "@mdi/react"; import clsx from "clsx"; import { SlottedSVG } from "@ukic/react"; - +import StackblitzButton, { + StackblitzProps, +} from "../../content/structured/patterns/components/StackblitzButton"; +import { debounce } from "../../utils/helpers"; +import PageMetadataContext from "../../context/PageMetadata"; import "./index.css"; interface Snippet { @@ -17,7 +21,7 @@ interface Snippet { snippet: string; } -interface ComponentPreviewProps { +interface ComponentPreviewProps extends Partial { snippets?: Snippet[]; left?: boolean; noPadding?: boolean; @@ -25,42 +29,93 @@ interface ComponentPreviewProps { children: ReactNode; style: CSSProperties; state: "none" | "good" | "bad"; + showStackblitzBtn?: boolean; + type?: string; } -const CodeSnippet: React.FC<{ code: string }> = ({ code }) => ( - <> - - {({ className, style, tokens, getLineProps, getTokenProps }) => ( -
-          
-            {tokens.map((line, i) => (
-              
- {line.map((token, key) => ( - - ))} -
- ))} -
-
- )} -
-
- { - navigator.clipboard.writeText(code); - document - .querySelector("#copy-to-clipboard-toast") - ?.setVisible(); - }} - > - Copy code - - -
- -); +interface CodeSnippetProps extends Partial { + code: string; + showStackblitzBtn?: boolean; +} + +const CodeSnippet: React.FC = ({ + code, + isWebComponents, + showStackblitzBtn, + projectTitle, + projectDescription, +}) => { + let defaultViewportWidth = 0; + + if (typeof window !== "undefined") { + defaultViewportWidth = window.innerWidth; + } + + const [viewportWidth, setViewportWidth] = + useState(defaultViewportWidth); + + const isLargeViewport: boolean = viewportWidth > 992; + + useEffect(() => { + const handleResize = debounce(() => setViewportWidth(window.innerWidth)); + + window.addEventListener("resize", handleResize); + + // Cleanup function + return () => { + window.removeEventListener("resize", handleResize); + }; + }, []); + + return ( + <> + + {({ className, style, tokens, getLineProps, getTokenProps }) => ( +
+            
+              {tokens.map((line, i) => (
+                
+ {line.map((token, key) => ( + + ))} +
+ ))} +
+
+ )} +
+
+ {showStackblitzBtn && projectTitle !== undefined && ( + + )} + { + navigator.clipboard.writeText(code); + document + .querySelector("#copy-to-clipboard-toast") + ?.setVisible(); + }} + > + + {isLargeViewport && "Copy code"} + +
+ + ); +}; const ComponentPreview: React.FC = ({ snippets, @@ -70,53 +125,85 @@ const ComponentPreview: React.FC = ({ centered = true, style, state = "none", -}) => ( -
-

Interactive example

-
- {(state === "good" && ( -
-); + ); +}; export default ComponentPreview; diff --git a/src/content/static/components/CookiesData/index.tsx b/src/content/static/components/CookiesData/index.tsx index e0bc43306..345597f28 100644 --- a/src/content/static/components/CookiesData/index.tsx +++ b/src/content/static/components/CookiesData/index.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { debounce } from "../../../../utils/helpers"; import CookiesCards from "./CookiesCards"; @@ -31,14 +31,18 @@ const CookiesData = ({ headers, data, caption }: CookiesDataProps) => { const [viewportWidth, setViewportWidth] = useState(defaultViewportWidth); - React.useEffect(() => { - window.addEventListener( - "resize", - debounce(() => setViewportWidth(window.innerWidth)) - ); + useEffect(() => { + const handleResize = debounce(() => setViewportWidth(window.innerWidth)); + + window.addEventListener("resize", handleResize); + + // Cleanup function + return () => { + window.removeEventListener("resize", handleResize); + }; }, []); - if (viewportWidth > 991) { + if (viewportWidth > 992) { return ; } diff --git a/src/content/structured/patterns/components/StackblitzButton/index.tsx b/src/content/structured/patterns/components/StackblitzButton/index.tsx new file mode 100644 index 000000000..30b9cc92e --- /dev/null +++ b/src/content/structured/patterns/components/StackblitzButton/index.tsx @@ -0,0 +1,127 @@ +import React, { useEffect, useState } from "react"; +import sdk from "@stackblitz/sdk"; +import { + createIndexTsx, + createReactIndexHTML, + createWebComponentsIndexHTML, + packageJson, + tsConfig, + viteConfig, +} from "./stackblitz-helpers"; +import { StackblitzLogo } from "../../../../../assets/svg"; +import { debounce } from "../../../../../utils/helpers"; + +export type StackblitzProps = { + codeSnippet?: string; + isWebComponents?: boolean; + projectTitle: string; + projectDescription?: string; +}; + +const StackblitzButton: React.FC = ({ + codeSnippet, + isWebComponents, + projectTitle, + projectDescription, +}) => { + let defaultViewportWidth = 0; + + if (typeof window !== "undefined") { + defaultViewportWidth = window.innerWidth; + } + + const [viewportWidth, setViewportWidth] = + useState(defaultViewportWidth); + + const isLargeViewport: boolean = viewportWidth > 992; + + useEffect(() => { + const handleResize = debounce(() => setViewportWidth(window.innerWidth)); + + window.addEventListener("resize", handleResize); + + // Cleanup function + return () => { + window.removeEventListener("resize", handleResize); + }; + }, []); + + const createStackblitzProject = () => { + const files: { [key: string]: string } = {}; + const isWebComponentsInternal: boolean = + isWebComponents !== undefined ? isWebComponents : true; + const isJSX: boolean = true; + // Add functionality to manage whether Stackblitz project should use TypeScript or JavaScript + const ext = isJSX ? "jsx" : "tsx"; + + if (codeSnippet !== undefined && codeSnippet !== "") { + if (isWebComponents) { + files[`index.html`] = createWebComponentsIndexHTML(codeSnippet); + } else { + files[`src/index.${ext}`] = codeSnippet; + } + } + + // Define the index.tsx content for a React app + const indexTsx = createIndexTsx(projectTitle, true); + + // Change file structure for React code examples + if ( + (isWebComponents !== undefined && !isWebComponents) || + !isWebComponentsInternal + ) { + files[`src/app.${ext}`] = files[`src/index.${ext}`]; + files[`src/index.${ext}`] = indexTsx; + files[`index.html`] = createReactIndexHTML(ext); + files["vite.config.js"] = viteConfig; + if (ext === "tsx") { + files["tsconfig.json"] = tsConfig; + } + } + + files["package.json"] = JSON.stringify( + packageJson(projectTitle, isWebComponentsInternal, ext), + null, + 2 + ); + + const description = + projectDescription === undefined || projectDescription === "" + ? "" + : projectDescription; + + sdk.openProject( + { + title: `ICDS ${projectTitle}`, + description, + files, + template: "node", + }, + { + openFile: isWebComponentsInternal ? [`index.html`] : [`src/app.${ext}`], + } + ); + }; + + return ( + createStackblitzProject()} + > + {isLargeViewport && ( + <> + + + + Stackblitz + + )} + {!isLargeViewport && } + + ); +}; + +export default StackblitzButton; diff --git a/src/content/structured/patterns/components/StackblitzButton/stackblitz-helpers.ts b/src/content/structured/patterns/components/StackblitzButton/stackblitz-helpers.ts new file mode 100644 index 000000000..7b42bd0ad --- /dev/null +++ b/src/content/structured/patterns/components/StackblitzButton/stackblitz-helpers.ts @@ -0,0 +1,272 @@ +import kebabCase from "lodash.kebabcase"; +import startCase from "lodash.startcase"; + +const designSystemPackageJson = require("../../../../../../package.json"); + +export const createIndexTsx = ( + componentName: string, + isCodeSnippet?: boolean +) => { + const component = isCodeSnippet + ? startCase(componentName.replace(/\(.*?\)/g, "")).replace(/\s/g, "") + : componentName; + return `import { StrictMode } from 'react'; + import { createRoot } from 'react-dom/client'; + import { BrowserRouter } from 'react-router-dom'; + + import ${component} from './app'; + + const root = createRoot(document.getElementById('root')); + + root.render( + + + <${component} /> + + + );`; +}; + +export const createReactIndexHTML = (ext: string) => ` + + + + Vite + React + TS + + +
+ + + `; + +export const packageJson = ( + projectTitle: string, + isWebComponents: boolean, + fileExtension: "jsx" | "tsx" +) => { + const dependenciesArray = isWebComponents + ? [] + : [ + ["@mdi/js", "^7.4.47"], + [ + "@ukic/fonts", + `${designSystemPackageJson.dependencies["@ukic/fonts"]}`, + ], + [ + "@ukic/react", + `${designSystemPackageJson.dependencies["@ukic/react"]}`, + ], + ["react", "^18.2.0"], + ["react-dom", "^18.2.0"], + ["react-jss", "^10.10.0"], + ["react-router-dom", "^6.22.0"], + ]; + + if (fileExtension === "tsx") { + dependenciesArray.splice(3, 0, [ + "@ukic/web-components", + `${designSystemPackageJson.dependencies["@ukic/web-components"]}`, + ]); + } + + const dependencies = Object.fromEntries(dependenciesArray); + + const reactDevDependencies = { + "@types/react": "^18.2.48", + "@types/react-dom": "^18.2.18", + "@vitejs/plugin-react": "^4.2.1", + }; + const devDependencies = { vite: "^5.0.12" }; + + return { + name: `icds-${kebabCase(projectTitle)}`, + version: "0.0.0", + private: true, + scripts: { + dev: "vite", + build: "vite build", + preview: "vite preview", + prettier: "prettier --write .", + }, + dependencies, + devDependencies: isWebComponents + ? { ...devDependencies } + : { ...devDependencies, ...reactDevDependencies }, + stackblitz: { + startCommand: + "npm i --save-dev prettier && npm run prettier && npm run dev", + }, + }; +}; + +export const tsConfig = `{ + "compilerOptions": { + "jsx": "react-jsx", + "lib": ["DOM", "ES2022"], + "moduleResolution": "node", + "target": "ES2022" + } + }`; + +export const viteConfig = `import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}) +`; + +export const createWebComponentsIndexHTML = ( + codeSnippet: string +) => ` + + Home + + + + + + + ${codeSnippet} + + + + `; + +export const createReactAppTsx = ( + codeSnippet: string, + componentName: string, + fileExtension: "jsx" | "tsx", + isPattern: boolean = false +): string => { + // Helper function to find uses of ICDS components and MDI in code snippet + const getImports = ( + tag: string | undefined, + isMDI: boolean = false, + isPatternInternal: boolean = false + ) => { + let regex: RegExp; + if (isMDI) { + regex = new RegExp(`{${tag}[^}]*}`, "g"); + } else if (isPatternInternal) { + regex = /(?!(<|<\/|\.))\bIc[A-Za-z]+/g; + } else { + regex = new RegExp(`<${tag}[^>]*>`, "g"); + } + + return isPatternInternal + ? codeSnippet.match(regex) || [] + : (codeSnippet.match(regex) || []).map((match) => + match + .slice(isPatternInternal ? 0 : 1, match.indexOf(isMDI ? "}" : " ")) + .trim() + ); + }; + + // Helper function to sort and remove duplicates + const sortAndRemoveDuplicates = (matches: string[]) => + Array.from(new Set(matches)).sort(); + + // Get matches for "Ic", "SlottedSVG", and "mdi". + // Sort and remove duplicates + const sortedICDSComponents = sortAndRemoveDuplicates([ + ...getImports("Ic"), + ...getImports("SlottedSVG"), + ]); + const sortedMDIcons = sortAndRemoveDuplicates(getImports("mdi", true)); + const component = startCase(componentName.replace(/\(.*?\)/g, "")).replace( + /\s/g, + "" + ); + let getIcTypes: string[] = []; + if (isPattern) { + const allIcMatches = getImports(undefined, false, true); + const allIcComponents = getImports("Ic"); + getIcTypes = allIcMatches + .filter((item: string) => !allIcComponents.includes(item)) + .concat( + allIcComponents.filter((item: string) => !allIcMatches.includes(item)) + ) + .sort(); + } + + // Check if codeSnippet contains "return(" or "return (" + const containsReturn = /return\s*\(/g.test(codeSnippet); + + // Check if codeSnippet contains "createUseStyles" from 'react-jss' + const containsCreateUseStyles = /createUseStyles\(\{/.test(codeSnippet); + + // Check if codeSnippet contains any React hooks + const getReactHooks = (code: string) => { + const hooks = ["useState", "useRef", "useEffect"]; + const foundHooks = hooks.filter((hook) => code.includes(hook)); + return foundHooks; + }; + + const reactHookImports = getReactHooks(codeSnippet); + + // Create React import statement + let reactImportStatement = "import React"; + const reactImports = []; + if (fileExtension === "tsx") { + reactImports.push("FC"); + } + if (reactHookImports.length > 0) { + reactImports.push(...reactHookImports); + } + if (reactImports.length > 0) { + reactImportStatement += `, { ${reactImports.join(", ")} }`; + } + reactImportStatement += " from 'react';"; + + // Conditionally render "return(" in the returned output string + const returnStatement = containsReturn ? "" : "return("; + + let importedICDSComponents; + if (sortedICDSComponents.length > 3) { + importedICDSComponents = ` + ${sortedICDSComponents.join(",\n ")}\n`; + } else { + importedICDSComponents = `${sortedICDSComponents.join(", ")} `; + } + + return `${reactImportStatement} +import { ${importedICDSComponents}} from '@ukic/react'; +${ + fileExtension === "tsx" && isPattern && getIcTypes.length > 0 + ? `import type { ${getIcTypes.join(", ")} } from '@ukic/web-components';` + : "" +} +${ + sortedMDIcons.length > 0 + ? `import { ${sortedMDIcons.join(", ")} } from '@mdi/js';` + : "" +} +${ + containsCreateUseStyles + ? `import { createUseStyles } from 'react-jss'; +` + : "" +} +import "@ukic/fonts/dist/fonts.css"; +import "@ukic/react/dist/core/core.css"; +import "@ukic/react/dist/core/normalize.css"; + +const ${component}${fileExtension === "tsx" ? `: FC` : ""} = () => { + ${returnStatement} + ${codeSnippet} + ${containsReturn ? "" : ")"}}; +export default ${component};`; +}; diff --git a/src/context/PageMetadata.tsx b/src/context/PageMetadata.tsx new file mode 100644 index 000000000..155bb7e68 --- /dev/null +++ b/src/context/PageMetadata.tsx @@ -0,0 +1,11 @@ +import React from "react"; + +interface PageMetadataContextProps { + pageTitle: string; +} + +const PageMetadataContext = React.createContext({ + pageTitle: "", +}); + +export default PageMetadataContext; diff --git a/src/templates/CoreTemplate/index.tsx b/src/templates/CoreTemplate/index.tsx index 45406a6b7..51bc93bf0 100644 --- a/src/templates/CoreTemplate/index.tsx +++ b/src/templates/CoreTemplate/index.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useMemo } from "react"; import { MDXRenderer } from "gatsby-plugin-mdx"; import clsx from "clsx"; @@ -20,6 +20,7 @@ import WrappedH4 from "../../components/WrappedH4"; import WrappedLi from "../../components/WrappedLi"; import WrappedLink from "../../components/WrappedLink"; import WrappedP from "../../components/WrappedP"; +import PageMetadataContext from "../../context/PageMetadata"; const { MDXProvider } = require("@mdx-js/react"); @@ -52,6 +53,11 @@ const CoreMDXLayout: React.FC = ({ DoubleDoDontCaution, }; + const pageTitleValue = useMemo( + () => ({ pageTitle: mdx.frontmatter.title }), + [] + ); + return (
@@ -65,7 +71,9 @@ const CoreMDXLayout: React.FC = ({
- {children} + + {children} +
{mdx.fields.navSection === "components" && (