From ee969f30037fa99232292014431854773735d0a0 Mon Sep 17 00:00:00 2001 From: Lennart Date: Sat, 1 Oct 2022 15:24:36 +0200 Subject: [PATCH] BREAKING: MDX v2, Theme UI v0.15, Gatsby Head API (#967) --- .changeset/bright-plums-melt.md | 104 + .changeset/chatty-apricots-hope.md | 30 + .changeset/dull-roses-complain.md | 5 + .changeset/flat-seals-flow.md | 5 + .changeset/four-hairs-breathe.md | 22 + .changeset/nine-garlics-hug.md | 28 + .changeset/popular-toes-attack.md | 27 + .changeset/sour-crabs-hide.md | 28 + .changeset/stupid-hairs-occur.md | 18 + .changeset/tidy-geese-eat.md | 18 + .changeset/unlucky-scissors-sip.md | 34 + .eslintrc.js | 19 + .github/workflows/e2e_testing.yml | 3 +- .github/workflows/publish-starters.yml | 4 +- .github/workflows/release.yml | 4 +- .nvmrc | 2 +- .yarnrc.yml | 2 + CONTRIBUTING.md | 2 +- cypress/e2e/cara.ts | 6 + cypress/e2e/emilia.ts | 8 + cypress/e2e/emma.ts | 9 + cypress/e2e/graphql-playground.ts | 7 + cypress/e2e/jodie.ts | 17 +- cypress/e2e/minimal-blog.ts | 56 +- cypress/e2e/status-dashboard.ts | 6 + cypress/e2e/styleguide.ts | 12 +- examples/cara/README.md | 11 +- examples/cara/gatsby-config.js | 5 +- examples/cara/gatsby-ssr.js | 3 + examples/cara/package.json | 9 +- examples/cara/src/pages/404.jsx | 5 +- examples/cara/static/icons.svg | 12 + examples/emilia/README.md | 11 +- examples/emilia/gatsby-config.js | 5 +- examples/emilia/gatsby-ssr.js | 3 + examples/emilia/package.json | 11 +- examples/emilia/src/pages/404.jsx | 6 +- examples/emilia/static/icons.svg | 42 + examples/emma/README.md | 11 +- examples/emma/content/projects/emma/index.mdx | 2 - examples/emma/gatsby-config.js | 5 +- examples/emma/gatsby-ssr.js | 3 + examples/emma/package.json | 11 +- examples/emma/src/pages/404.jsx | 6 +- examples/graphql-playground/README.md | 11 +- examples/graphql-playground/gatsby-config.js | 4 +- examples/graphql-playground/gatsby-ssr.js | 3 + examples/graphql-playground/package.json | 7 +- examples/jodie/README.md | 25 +- examples/jodie/content/pages/about/index.mdx | 2 - examples/jodie/gatsby-browser.js | 1 + examples/jodie/gatsby-config.js | 20 +- examples/jodie/gatsby-ssr.js | 16 + examples/jodie/global.css | 8 + examples/jodie/package.json | 12 +- .../jodie/src/gatsby-plugin-theme-ui/index.js | 10 + .../jodie/static/fonts/work-sans.var.woff2 | Bin 0 -> 47800 bytes examples/minimal-blog/README.md | 85 +- .../SpotifyPlayer.js | 0 .../index.mdx | 53 +- .../index.mdx | 210 - .../posts/markdown-reference/index.mdx | 162 + .../index.mdx | 8 +- .../defence-against-the-dark-arts.jpg | Bin .../index.mdx | 5 +- .../potions.jpg | Bin examples/minimal-blog/gatsby-config.js | 20 +- examples/minimal-blog/gatsby-ssr.js | 3 + examples/minimal-blog/package.json | 15 +- .../gatsby-theme-minimal-blog/texts/hero.mdx | 7 +- examples/specimens/README.md | 11 +- examples/specimens/gatsby-browser.js | 4 - examples/specimens/gatsby-config.js | 17 +- examples/specimens/gatsby-ssr.js | 7 +- examples/specimens/package.json | 33 +- .../src/components/{code.js => code.jsx} | 71 +- examples/specimens/src/components/layout.js | 81 - examples/specimens/src/components/layout.jsx | 43 + .../src/components/mdx-components.jsx | 105 + examples/specimens/src/components/seo.jsx | 40 + ...e-of-contents.js => table-of-contents.jsx} | 10 +- .../src/components/wrapPageElement.js | 4 - .../src/gatsby-plugin-theme-ui/components.js | 100 - .../src/gatsby-plugin-theme-ui/index.js | 20 + examples/specimens/src/pages/index.mdx | 78 +- examples/specimens/src/pages/preview.mdx | 7 +- examples/specimens/theme.js | 143 +- examples/status-dashboard/README.md | 11 +- examples/status-dashboard/gatsby-config.js | 5 +- examples/status-dashboard/gatsby-ssr.js | 3 + examples/status-dashboard/package.json | 15 +- examples/status-dashboard/src/pages/index.jsx | 273 +- examples/styleguide/README.md | 11 +- examples/styleguide/gatsby-config.js | 5 +- examples/styleguide/gatsby-ssr.js | 3 + examples/styleguide/package.json | 15 +- .../gatsby-theme-styleguide/layout.jsx | 2 - .../gatsby-theme-styleguide/template.jsx | 7 + examples/styleguide/src/components/seo.jsx | 17 +- .../src/gatsby-plugin-theme-ui/index.js | 153 +- .../src/hooks/use-site-metadata.jsx | 1 - lint-staged.config.js | 2 +- package.json | 20 +- packages/rehype-meta-as-attributes/README.md | 13 + packages/rehype-meta-as-attributes/index.js | 23 + .../rehype-meta-as-attributes/package.json | 29 + packages/themes-utils/README.md | 3 + packages/themes-utils/index.js | 49 + packages/themes-utils/package.json | 29 + plop-templates/cypress-test.ts.hbs | 3 +- plop-templates/example/LICENSE.hbs | 2 +- plop-templates/example/README.md.hbs | 5 +- ...sby-config.js.hbs => gatsby-config.ts.hbs} | 15 +- .../{index-page.js.hbs => index-page.tsx.hbs} | 0 plop-templates/example/package.json.hbs | 13 +- .../theme-core-parent/README.md.hbs | 6 +- .../theme-core-parent/gatsby-config.js.hbs | 2 - .../theme-core-parent/gatsby-ssr.js.hbs | 3 + .../homepage-component.tsx.hbs | 7 +- .../theme-core-parent/homepage.tsx.hbs | 6 +- .../theme-core-parent/package.json.hbs | 15 +- plop-templates/theme-core-parent/seo.tsx.hbs | 21 +- .../theme-core-parent/theme-ui.js.hbs | 6 +- .../use-site-metadata.tsx.hbs | 2 - .../theme-core/homepage-query.tsx.hbs | 4 +- plop-templates/theme-core/homepage.tsx.hbs | 4 +- plop-templates/theme-core/package.json.hbs | 12 +- plop-templates/theme/README.md.hbs | 6 +- plop-templates/theme/gatsby-config.js.hbs | 2 - plop-templates/theme/gatsby-ssr.js.hbs | 3 + plop-templates/theme/package.json.hbs | 15 +- plop-templates/theme/seo.tsx.hbs | 21 +- plop-templates/theme/theme-ui.js.hbs | 4 +- .../theme/use-site-metadata.tsx.hbs | 2 - plopfile.mjs | 18 +- themes/gatsby-theme-cara/README.md | 6 +- themes/gatsby-theme-cara/gatsby-config.js | 13 +- themes/gatsby-theme-cara/gatsby-ssr.js | 5 + themes/gatsby-theme-cara/package.json | 24 +- .../src/components/about.tsx | 3 +- .../src/components/contact.tsx | 3 +- .../gatsby-theme-cara/src/components/hero.tsx | 5 +- .../src/components/layout.tsx | 8 +- .../src/components/mdx-components.tsx | 12 + .../src/components/project-card.tsx | 14 +- .../src/components/projects.tsx | 3 +- .../gatsby-theme-cara/src/components/seo.tsx | 14 +- .../gatsby-theme-cara/src/components/svg.tsx | 81 +- .../src/gatsby-plugin-theme-ui/components.js | 13 - .../src/gatsby-plugin-theme-ui/index.js | 4 +- .../src/hooks/use-site-metadata.tsx | 2 - .../gatsby-theme-cara/src/templates/cara.tsx | 4 + .../gatsby-theme-emilia-core/gatsby-config.js | 12 +- .../gatsby-theme-emilia-core/gatsby-node.js | 43 +- themes/gatsby-theme-emilia-core/package.json | 17 +- .../src/components/project.tsx | 11 +- .../src/components/projects.tsx | 2 + .../src/templates/project-query.tsx | 5 +- .../src/templates/projects-query.tsx | 4 +- themes/gatsby-theme-emilia/README.md | 6 +- themes/gatsby-theme-emilia/gatsby-config.js | 8 +- themes/gatsby-theme-emilia/gatsby-ssr.js | 5 + themes/gatsby-theme-emilia/package.json | 18 +- .../components/project.tsx | 20 +- .../components/projects.tsx | 4 +- .../src/assets/bg-pattern.tsx | 23 - .../src/assets/left-arrow.tsx | 14 - .../src/assets/location.tsx | 18 - .../src/components/card.tsx | 1 + .../src/components/footer.tsx | 3 +- .../src/components/header-background.tsx | 8 +- .../src/components/header-project.tsx | 10 +- .../src/components/header.tsx | 21 +- .../src/components/layout.tsx | 2 - .../src/components/project-pagination.tsx | 8 +- .../src/components/project.tsx | 105 +- .../src/components/projects.tsx | 7 +- .../src/components/seo.tsx | 14 +- .../src/components/social-media-list.tsx | 3 +- .../src/components/svg.tsx | 17 + .../src/gatsby-plugin-theme-ui/index.js | 4 +- .../src/hooks/use-site-metadata.tsx | 2 - .../gatsby-theme-emma-core/gatsby-config.js | 7 +- themes/gatsby-theme-emma-core/gatsby-node.js | 40 +- themes/gatsby-theme-emma-core/package.json | 21 +- .../src/components/page.tsx | 2 + .../src/components/project.tsx | 2 + .../src/components/projects.tsx | 2 + .../src/templates/page-query.tsx | 5 +- .../src/templates/project-query.tsx | 5 +- .../src/templates/projects-query.tsx | 4 +- themes/gatsby-theme-emma/README.md | 6 +- themes/gatsby-theme-emma/gatsby-config.js | 1 - themes/gatsby-theme-emma/package.json | 21 +- .../components/page.tsx | 15 +- .../components/project.tsx | 15 +- .../components/projects.tsx | 4 +- .../src/components/layout.tsx | 2 - .../gatsby-theme-emma/src/components/page.tsx | 35 +- .../src/components/project.tsx | 67 +- .../src/components/projects.tsx | 12 +- .../gatsby-theme-emma/src/components/seo.tsx | 10 +- .../src/gatsby-plugin-theme-ui/index.js | 4 +- .../src/hooks/use-site-metadata.tsx | 2 - .../gatsby-theme-graphql-playground/README.md | 6 +- .../gatsby-config.js | 21 +- .../gatsby-node.js | 59 +- .../package.json | 26 +- .../src/components/layout.tsx | 11 +- .../src/components/mdx-components.tsx | 8 + .../src/components/nav-link.tsx | 6 +- .../src/components/seo.tsx | 12 +- .../src/components/sidebar.tsx | 7 +- .../src/data/index.mdx | 8 +- .../src/gatsby-plugin-theme-ui/components.js | 10 - .../src/gatsby-plugin-theme-ui/index.js | 6 +- .../src/hooks/use-site-metadata.tsx | 2 - .../src/templates/homepage.tsx | 7 +- .../src/templates/item.tsx | 27 +- .../utils/remark-get-preview-query.js | 21 + .../gatsby-theme-jodie-core/gatsby-config.js | 5 +- themes/gatsby-theme-jodie-core/gatsby-node.js | 40 +- themes/gatsby-theme-jodie-core/package.json | 18 +- .../src/components/homepage.tsx | 2 + .../src/components/page.tsx | 11 +- .../src/components/project.tsx | 11 +- .../src/components/projects.tsx | 2 + .../src/templates/homepage-query.tsx | 8 +- .../src/templates/page-query.tsx | 5 +- .../src/templates/project-query.tsx | 5 +- .../src/templates/projects-query.tsx | 4 +- themes/gatsby-theme-jodie/README.md | 6 +- themes/gatsby-theme-jodie/gatsby-config.js | 2 - themes/gatsby-theme-jodie/package.json | 16 +- .../components/homepage.tsx | 36 +- .../components/page.tsx | 26 +- .../components/project.tsx | 37 +- .../components/projects.tsx | 23 +- .../src/components/homepage.tsx | 9 +- .../src/components/layout.tsx | 2 - .../src/components/page.tsx | 25 +- .../src/components/project.tsx | 30 +- .../src/components/projects.tsx | 11 +- .../gatsby-theme-jodie/src/components/seo.tsx | 17 +- .../src/gatsby-plugin-theme-ui/components.js | 8 - .../src/gatsby-plugin-theme-ui/index.js | 8 +- .../src/hooks/use-site-metadata.tsx | 2 - .../gatsby-config.js | 15 +- .../gatsby-node.js | 59 +- .../package.json | 23 +- .../src/components/blog.tsx | 2 + .../src/components/homepage.tsx | 2 + .../src/components/page.tsx | 9 +- .../src/components/post.tsx | 9 +- .../src/components/tag.tsx | 2 + .../src/components/tags.tsx | 2 + .../src/templates/blog-query.tsx | 4 +- .../src/templates/homepage-query.tsx | 4 +- .../src/templates/page-query.tsx | 5 +- .../src/templates/post-query.tsx | 5 +- .../src/templates/tag-query.tsx | 4 +- .../src/templates/tags-query.tsx | 4 +- .../utils/default-options.js | 2 +- themes/gatsby-theme-minimal-blog/README.md | 67 +- .../gatsby-config.js | 9 +- themes/gatsby-theme-minimal-blog/package.json | 26 +- .../components/blog.tsx | 4 +- .../components/homepage.tsx | 4 +- .../components/page.tsx | 15 +- .../components/post.tsx | 15 +- .../components/tag.tsx | 4 +- .../components/tags.tsx | 4 +- .../src/components/blog.tsx | 9 +- .../src/components/code.tsx | 110 +- .../src/components/colormode-toggle.tsx | 2 +- .../src/components/header-title.tsx | 2 +- .../src/components/homepage.tsx | 16 +- .../src/components/layout.tsx | 8 +- .../src/components/mdx-components.tsx | 22 + .../src/components/page.tsx | 25 +- .../src/components/post-footer.tsx | 27 +- .../src/components/post.tsx | 71 +- .../src/components/seo.tsx | 10 +- .../src/components/tag.tsx | 10 +- .../src/components/tags.tsx | 11 +- .../src/components/title.tsx | 22 +- .../src/gatsby-plugin-theme-ui/components.js | 27 - .../src/gatsby-plugin-theme-ui/index.js | 45 +- .../src/hooks/use-site-metadata.tsx | 2 - .../src/styles/code.ts | 53 +- themes/gatsby-theme-specimens/README.md | 4 +- themes/gatsby-theme-specimens/package.json | 6 +- .../src/components/__tests__/audio.tsx | 2 +- .../src/components/__tests__/color-row.tsx | 5 +- .../src/components/__tests__/table.tsx | 11 +- .../src/components/__tests__/video.tsx | 2 +- .../src/components/color-families.tsx | 5 +- .../src/components/palette.tsx | 8 +- .../src/utils/__tests__/filter-styles.ts | 2 +- .../__tests__/normalize-theme-ui-colors.ts | 51 +- .../src/utils/filter-styles.ts | 2 +- .../src/utils/normalize-theme-ui-colors.ts | 13 +- .../gatsby-theme-status-dashboard/README.md | 4 +- .../package.json | 12 +- .../src/components/card.tsx | 3 +- themes/gatsby-theme-styleguide/README.md | 4 +- themes/gatsby-theme-styleguide/package.json | 7 +- .../src/colors-palettes.tsx | 3 +- themes/gatsby-theme-styleguide/src/colors.tsx | 5 +- themes/gatsby-theme-styleguide/src/footer.tsx | 3 +- themes/gatsby-theme-styleguide/src/header.tsx | 3 +- themes/gatsby-theme-styleguide/src/space.tsx | 3 +- .../gatsby-theme-styleguide/src/template.tsx | 2 + .../src/typography.tsx | 3 +- www/gatsby-browser.tsx | 1 + www/gatsby-config.ts | 19 +- www/gatsby-ssr.tsx | 49 + www/package.json | 44 +- www/src/components/3d-model.tsx | 1 + www/src/components/about-me.tsx | 3 +- www/src/components/hero.tsx | 3 +- www/src/components/layout.tsx | 10 +- www/src/components/listing.tsx | 3 +- www/src/components/seo.tsx | 8 +- www/src/fonts/benguiat.css | 7 - www/src/gatsby-plugin-theme-ui/index.ts | 1 - www/src/hooks/use-site-metadata.tsx | 2 - www/src/pages/404.tsx | 8 +- www/src/pages/index.tsx | 4 + www/src/styles/fonts.css | 43 + www/src/webgl/model.tsx | 1 + www/static/fonts/ibm-plex-sans-400.woff2 | Bin 0 -> 13044 bytes www/static/fonts/ibm-plex-sans-500.woff2 | Bin 0 -> 13868 bytes www/static/fonts/ibm-plex-sans-600.woff2 | Bin 0 -> 14128 bytes www/static/fonts/ibm-plex-sans-700.woff2 | Bin 0 -> 13224 bytes www/yarn.lock | 3613 ++--- yarn.lock | 11459 ++++++++-------- 337 files changed, 9754 insertions(+), 10960 deletions(-) create mode 100644 .changeset/bright-plums-melt.md create mode 100644 .changeset/chatty-apricots-hope.md create mode 100644 .changeset/dull-roses-complain.md create mode 100644 .changeset/flat-seals-flow.md create mode 100644 .changeset/four-hairs-breathe.md create mode 100644 .changeset/nine-garlics-hug.md create mode 100644 .changeset/popular-toes-attack.md create mode 100644 .changeset/sour-crabs-hide.md create mode 100644 .changeset/stupid-hairs-occur.md create mode 100644 .changeset/tidy-geese-eat.md create mode 100644 .changeset/unlucky-scissors-sip.md create mode 100644 examples/cara/gatsby-ssr.js create mode 100644 examples/cara/static/icons.svg create mode 100644 examples/emilia/gatsby-ssr.js create mode 100644 examples/emilia/static/icons.svg create mode 100644 examples/emma/gatsby-ssr.js create mode 100644 examples/graphql-playground/gatsby-ssr.js create mode 100644 examples/jodie/gatsby-browser.js create mode 100644 examples/jodie/gatsby-ssr.js create mode 100644 examples/jodie/global.css create mode 100644 examples/jodie/src/gatsby-plugin-theme-ui/index.js create mode 100644 examples/jodie/static/fonts/work-sans.var.woff2 rename examples/minimal-blog/content/posts/{fantastic-beasts-and-where-to-find-them => code-block-examples}/SpotifyPlayer.js (100%) rename examples/minimal-blog/content/posts/{fantastic-beasts-and-where-to-find-them => code-block-examples}/index.mdx (80%) delete mode 100644 examples/minimal-blog/content/posts/harry-potter-and-the-half-blood-prince/index.mdx create mode 100644 examples/minimal-blog/content/posts/markdown-reference/index.mdx rename examples/minimal-blog/content/posts/{curses-and-counter-courses => normal-text}/index.mdx (82%) rename examples/minimal-blog/content/posts/{introduction-to-defence-against-the-dark-arts => with-images}/defence-against-the-dark-arts.jpg (100%) rename examples/minimal-blog/content/posts/{introduction-to-defence-against-the-dark-arts => with-images}/index.mdx (97%) rename examples/minimal-blog/content/posts/{introduction-to-defence-against-the-dark-arts => with-images}/potions.jpg (100%) create mode 100644 examples/minimal-blog/gatsby-ssr.js delete mode 100755 examples/specimens/gatsby-browser.js rename examples/specimens/src/components/{code.js => code.jsx} (53%) delete mode 100755 examples/specimens/src/components/layout.js create mode 100755 examples/specimens/src/components/layout.jsx create mode 100644 examples/specimens/src/components/mdx-components.jsx create mode 100644 examples/specimens/src/components/seo.jsx rename examples/specimens/src/components/{table-of-contents.js => table-of-contents.jsx} (66%) delete mode 100755 examples/specimens/src/components/wrapPageElement.js delete mode 100755 examples/specimens/src/gatsby-plugin-theme-ui/components.js create mode 100755 examples/status-dashboard/gatsby-ssr.js create mode 100644 examples/styleguide/gatsby-ssr.js create mode 100644 examples/styleguide/src/@lekoarts/gatsby-theme-styleguide/template.jsx create mode 100644 packages/rehype-meta-as-attributes/README.md create mode 100644 packages/rehype-meta-as-attributes/index.js create mode 100644 packages/rehype-meta-as-attributes/package.json create mode 100644 packages/themes-utils/README.md create mode 100644 packages/themes-utils/index.js create mode 100644 packages/themes-utils/package.json rename plop-templates/example/{gatsby-config.js.hbs => gatsby-config.ts.hbs} (75%) rename plop-templates/example/{index-page.js.hbs => index-page.tsx.hbs} (100%) create mode 100644 plop-templates/theme-core-parent/gatsby-ssr.js.hbs create mode 100644 plop-templates/theme/gatsby-ssr.js.hbs create mode 100644 themes/gatsby-theme-cara/gatsby-ssr.js create mode 100644 themes/gatsby-theme-cara/src/components/mdx-components.tsx delete mode 100755 themes/gatsby-theme-cara/src/gatsby-plugin-theme-ui/components.js create mode 100644 themes/gatsby-theme-emilia/gatsby-ssr.js delete mode 100755 themes/gatsby-theme-emilia/src/assets/bg-pattern.tsx delete mode 100755 themes/gatsby-theme-emilia/src/assets/left-arrow.tsx delete mode 100755 themes/gatsby-theme-emilia/src/assets/location.tsx create mode 100755 themes/gatsby-theme-emilia/src/components/svg.tsx create mode 100644 themes/gatsby-theme-graphql-playground/src/components/mdx-components.tsx delete mode 100644 themes/gatsby-theme-graphql-playground/src/gatsby-plugin-theme-ui/components.js create mode 100644 themes/gatsby-theme-graphql-playground/utils/remark-get-preview-query.js delete mode 100644 themes/gatsby-theme-jodie/src/gatsby-plugin-theme-ui/components.js create mode 100644 themes/gatsby-theme-minimal-blog/src/components/mdx-components.tsx delete mode 100755 themes/gatsby-theme-minimal-blog/src/gatsby-plugin-theme-ui/components.js create mode 100644 www/gatsby-browser.tsx create mode 100644 www/gatsby-ssr.tsx delete mode 100644 www/src/fonts/benguiat.css create mode 100644 www/src/styles/fonts.css create mode 100644 www/static/fonts/ibm-plex-sans-400.woff2 create mode 100644 www/static/fonts/ibm-plex-sans-500.woff2 create mode 100644 www/static/fonts/ibm-plex-sans-600.woff2 create mode 100644 www/static/fonts/ibm-plex-sans-700.woff2 diff --git a/.changeset/bright-plums-melt.md b/.changeset/bright-plums-melt.md new file mode 100644 index 000000000..645e122fb --- /dev/null +++ b/.changeset/bright-plums-melt.md @@ -0,0 +1,104 @@ +--- +"@lekoarts/gatsby-theme-minimal-blog": major +"@lekoarts/gatsby-theme-minimal-blog-core": major +--- + +In preparation for the upcoming [Gatsby 5 release](https://github.com/gatsbyjs/gatsby/discussions/36609) this release will focus on some breaking changes unrelated to the `gatsby` core package. Another new major version will follow once Gatsby 5 is out so that you can upgrade in steps. + +**Features:** + +- Update to [MDX 2](https://mdxjs.com/blog/v2/) and [`gatsby-plugin-mdx` 4](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/) (**Breaking Change**) +- Update [Theme UI](https://theme-ui.com/) from v0.11 to v0.15 ([Theme UI Changelog](https://github.com/system-ui/theme-ui/blob/develop/CHANGELOG.md)) (**Breaking Change**) +- Replace [`react-helmet`](https://github.com/nfl/react-helmet) with [Gatsby Head API](https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-head/) (**Breaking Change**) +- Improved Typography on the overall site and especially for the blog content +- Light/Dark Theme for code blocks and overall improved styling for code blocks + +**Breaking Changes:** + +- Any breaking changes from `theme-ui` between v0.11 and v0.15 +- Bump `react` & `react-dom` peerDependency to `>=18.0.0` +- Removal of `siteLanguage` from `siteMetadata` +- The MDX components are not managed by `gatsby-plugin-theme-ui/components` anymore but defined in a `` in `src/components/layout` +- [`useColorSchemeMediaQuery`](https://theme-ui.com/color-modes#responding-to-the-prefers-color-scheme-media-query) in Theme UI config is set to `system` +- Removal of `body` from the `Post` and `Page` type. The field `contentFilePath` was added. +- Removal of `gatsby-omni-font-loader` +- `body` font style is changed from `"IBM Plex Sans"` to a system font stack +- Removal of `react-live` +- Change in syntax of highlighting lines, adding code title, and adding line numbers +- The `showLineNumbers` option is `false` by default now + +**Migration:** + +- Internally the necessary changes of the [gatsby-plugin-mdx migration guide](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/#migrating-from-v3-to-v4) were made, but if you set the `mdx` option to `false` and/or shadowed the theme in any way, you'll need to read the migration guide to e.g. change your `gatsby-config`. You'll also need to add any `remarkPlugins` or `rehypePlugins` that the theme is adding by default. +- MDX 2 is more strict about the allowed syntax, so you'll need to [update your MDX content](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/#updating-mdx-content) to be compliant. +- See [Theme UI's migration guide](https://github.com/system-ui/theme-ui/blob/develop/MIGRATING.md) +- If you shadowed a file or used `react-helmet` in any form in your site, you'll either need to migrate to the Gatsby Head API or re-install the necessary dependencies. By default, the theme no longer ships with `react-helmet` as internally everything was migrated to Gatsby Head API. To have the `lang` tag work correctly on the `` element you'll need to set it by using the [`setHtmlAttributes` API](https://www.gatsbyjs.com/docs/reference/config-files/gatsby-ssr/#onRenderBody). The current starter already has this included (you can copy it from there). Thus the `` component should only be used together with Gatsby Head API. +- With the removal of `gatsby-omni-font-loader` in the example you'll now need to self-host your fonts and change the Theme UI config. The theme switched to a system font stack in its Theme UI config and the example doesn't provide any custom font anymore. +- If you want to continue using `react-live`, you have to add the dependency and shadow the `` component. +- The syntax for adding code titles changed. + Before: + + ````md + ```js:title=test.js + // content + ``` + ```` + + After: + + ````md + ```js title=test.js + // content + ``` + ```` + +- The syntax for adding line highlighting changed. + Before: + + ````md + ```js {1,2-3} + // content + ``` + ```` + + After: + + ````md + ```js highlight=1,2-3 + // content + ``` + ```` + +- The syntax for adding line numbers changed. You no longer _negate_ line numbers (previously `noLineNumbers`) but opt-in. + Before: + + ````md + ```js noLineNumbers + // content that had line numbers by default + ``` + ```` + + After: + + ````md + ```js withLineNumbers + // content + ``` + ```` + +- All syntax changes together. + Before: + + ````md + ```js:title=test.js {1,2-3} + // content + ``` + ```` + + After: + + ````md + ```js title=test.js highlight=1,2-3 withLineNumbers + // content + ``` + ```` diff --git a/.changeset/chatty-apricots-hope.md b/.changeset/chatty-apricots-hope.md new file mode 100644 index 000000000..ebce68be1 --- /dev/null +++ b/.changeset/chatty-apricots-hope.md @@ -0,0 +1,30 @@ +--- +"@lekoarts/gatsby-theme-emilia": major +"@lekoarts/gatsby-theme-emilia-core": major +--- + +In preparation for the upcoming [Gatsby 5 release](https://github.com/gatsbyjs/gatsby/discussions/36609) this release will focus on some breaking changes unrelated to the `gatsby` core package. Another new major version will follow once Gatsby 5 is out so that you can upgrade in steps. + +**Features:** + +- Update to [MDX 2](https://mdxjs.com/blog/v2/) and [`gatsby-plugin-mdx` 4](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/) (**Breaking Change**) +- Update [Theme UI](https://theme-ui.com/) from v0.11 to v0.15 ([Theme UI Changelog](https://github.com/system-ui/theme-ui/blob/develop/CHANGELOG.md)) (**Breaking Change**) +- Replace [`react-helmet`](https://github.com/nfl/react-helmet) with [Gatsby Head API](https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-head/) (**Breaking Change**) +- Improve performance by moving all SVG to [SVG Sprites](https://benadam.me/thoughts/react-svg-sprites/) (**Breaking Change**) + +**Breaking Changes:** + +- Any breaking changes from `theme-ui` between v0.11 and v0.15 +- Bump `react` & `react-dom` peerDependency to `>=18.0.0` +- Removal of `siteLanguage` from `siteMetadata` +- The MDX components are not managed by `gatsby-plugin-theme-ui/components` anymore but defined in a `` in `src/components/layout` +- [`useColorSchemeMediaQuery`](https://theme-ui.com/color-modes#responding-to-the-prefers-color-scheme-media-query) in Theme UI config is set to `system` +- Removal of `body` from the `Project` type. The field `contentFilePath` was added. + +**Migration:** + +- Internally the necessary changes of the [gatsby-plugin-mdx migration guide](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/#migrating-from-v3-to-v4) were made, but if you set the `mdx` option to `false` and/or shadowed the theme in any way, you'll need to read the migration guide to e.g. change your `gatsby-config`. You'll also need to add any `remarkPlugins` or `rehypePlugins` that the theme is adding by default. +- MDX 2 is more strict about the allowed syntax, so you'll need to [update your MDX content](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/#updating-mdx-content) to be compliant. +- See [Theme UI's migration guide](https://github.com/system-ui/theme-ui/blob/develop/MIGRATING.md) +- If you shadowed a file or used `react-helmet` in any form in your site, you'll either need to migrate to the Gatsby Head API or re-install the necessary dependencies. By default, the theme no longer ships with `react-helmet` as internally everything was migrated to Gatsby Head API. To have the `lang` tag work correctly on the `` element you'll need to set it by using the [`setHtmlAttributes` API](https://www.gatsbyjs.com/docs/reference/config-files/gatsby-ssr/#onRenderBody). The current starter already has this included (you can copy it from there). Thus the `` component should only be used together with Gatsby Head API. +- The files inside the `assets` folder (`bg-pattern`, `left-arrow`, and `location`) were removed and a new `` component was added. The `` component is expecting a `icons.svg` file inside the `static` folder. The current starter already has this included (you can copy it from there). diff --git a/.changeset/dull-roses-complain.md b/.changeset/dull-roses-complain.md new file mode 100644 index 000000000..fe00318ae --- /dev/null +++ b/.changeset/dull-roses-complain.md @@ -0,0 +1,5 @@ +--- +"@lekoarts/rehype-meta-as-attributes": major +--- + +Moving this utility from v0.x version range to proper semver range. No changes between 0.0.1 and 1.0.0 were made. diff --git a/.changeset/flat-seals-flow.md b/.changeset/flat-seals-flow.md new file mode 100644 index 000000000..7950d56f1 --- /dev/null +++ b/.changeset/flat-seals-flow.md @@ -0,0 +1,5 @@ +--- +"@lekoarts/themes-utils": major +--- + +Moving this utility from v0.x version range to proper semver range. No changes between 0.0.1 and 1.0.0 were made. diff --git a/.changeset/four-hairs-breathe.md b/.changeset/four-hairs-breathe.md new file mode 100644 index 000000000..467ba6982 --- /dev/null +++ b/.changeset/four-hairs-breathe.md @@ -0,0 +1,22 @@ +--- +"@lekoarts/gatsby-theme-styleguide": major +--- + +In preparation for the upcoming [Gatsby 5 release](https://github.com/gatsbyjs/gatsby/discussions/36609) this release will focus on some breaking changes unrelated to the `gatsby` core package. Another new major version will follow once Gatsby 5 is out so that you can upgrade in steps. + +**Features:** + +- Update [Theme UI](https://theme-ui.com/) from v0.11 to v0.15 ([Theme UI Changelog](https://github.com/system-ui/theme-ui/blob/develop/CHANGELOG.md)) (**Breaking Change**) +- Replace [`react-helmet`](https://github.com/nfl/react-helmet) with [Gatsby Head API](https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-head/) (**Breaking Change**) +- Support for colors defined in object notation (previously only array notation) + +**Breaking Changes:** + +- Any breaking changes from `theme-ui` between v0.11 and v0.15 +- Bump `react` & `react-dom` peerDependency to `>=18.0.0` +- Bump `theme-ui` peerDependency to `>=0.15.0` +- Add `@emotion/react` as peerDependency + +**Migration:** + +- See [Theme UI's migration guide](https://github.com/system-ui/theme-ui/blob/develop/MIGRATING.md) diff --git a/.changeset/nine-garlics-hug.md b/.changeset/nine-garlics-hug.md new file mode 100644 index 000000000..1db66682e --- /dev/null +++ b/.changeset/nine-garlics-hug.md @@ -0,0 +1,28 @@ +--- +"@lekoarts/gatsby-theme-cara": major +--- + +In preparation for the upcoming [Gatsby 5 release](https://github.com/gatsbyjs/gatsby/discussions/36609) this release will focus on some breaking changes unrelated to the `gatsby` core package. Another new major version will follow once Gatsby 5 is out so that you can upgrade in steps. + +**Features:** + +- Update to [MDX 2](https://mdxjs.com/blog/v2/) and [`gatsby-plugin-mdx` 4](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/) (**Breaking Change**) +- Update [Theme UI](https://theme-ui.com/) from v0.11 to v0.15 ([Theme UI Changelog](https://github.com/system-ui/theme-ui/blob/develop/CHANGELOG.md)) (**Breaking Change**) +- Replace [`react-helmet`](https://github.com/nfl/react-helmet) with [Gatsby Head API](https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-head/) (**Breaking Change**) +- Improve performance by moving all SVG to [SVG Sprites](https://benadam.me/thoughts/react-svg-sprites/) (**Breaking Change**) + +**Breaking Changes:** + +- Any breaking changes from `theme-ui` between v0.11 and v0.15 +- Bump `react` & `react-dom` peerDependency to `>=18.0.0` +- Removal of `siteLanguage` from `siteMetadata` +- The MDX components are not managed by `gatsby-plugin-theme-ui/components` anymore but defined in a `` in `src/components/layout` +- [`useColorSchemeMediaQuery`](https://theme-ui.com/color-modes#responding-to-the-prefers-color-scheme-media-query) in Theme UI config is set to `system` + +**Migration:** + +- Internally the necessary changes of the [gatsby-plugin-mdx migration guide](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/#migrating-from-v3-to-v4) were made, but if you set the `mdx` option to `false` and/or shadowed the theme in any way, you'll need to read the migration guide to e.g. change your `gatsby-config`. You'll also need to add any `remarkPlugins` or `rehypePlugins` that the theme is adding by default. +- MDX 2 is more strict about the allowed syntax, so you'll need to [update your MDX content](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/#updating-mdx-content) to be compliant. +- See [Theme UI's migration guide](https://github.com/system-ui/theme-ui/blob/develop/MIGRATING.md) +- If you shadowed a file or used `react-helmet` in any form in your site, you'll either need to migrate to the Gatsby Head API or re-install the necessary dependencies. By default, the theme no longer ships with `react-helmet` as internally everything was migrated to Gatsby Head API. To have the `lang` tag work correctly on the `` element you'll need to set it by using the [`setHtmlAttributes` API](https://www.gatsbyjs.com/docs/reference/config-files/gatsby-ssr/#onRenderBody). The current starter already has this included (you can copy it from there). Thus the `` component should only be used together with Gatsby Head API. +- The `` component is expecting a `icons.svg` file inside the `static` folder. The current starter already has this included (you can copy it from there). diff --git a/.changeset/popular-toes-attack.md b/.changeset/popular-toes-attack.md new file mode 100644 index 000000000..031411f0c --- /dev/null +++ b/.changeset/popular-toes-attack.md @@ -0,0 +1,27 @@ +--- +"@lekoarts/gatsby-theme-emma": major +"@lekoarts/gatsby-theme-emma-core": major +--- + +In preparation for the upcoming [Gatsby 5 release](https://github.com/gatsbyjs/gatsby/discussions/36609) this release will focus on some breaking changes unrelated to the `gatsby` core package. Another new major version will follow once Gatsby 5 is out so that you can upgrade in steps. + +**Features:** + +- Update to [MDX 2](https://mdxjs.com/blog/v2/) and [`gatsby-plugin-mdx` 4](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/) (**Breaking Change**) +- Update [Theme UI](https://theme-ui.com/) from v0.11 to v0.15 ([Theme UI Changelog](https://github.com/system-ui/theme-ui/blob/develop/CHANGELOG.md)) (**Breaking Change**) +- Replace [`react-helmet`](https://github.com/nfl/react-helmet) with [Gatsby Head API](https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-head/) (**Breaking Change**) + +**Breaking Changes:** + +- Any breaking changes from `theme-ui` between v0.11 and v0.15 +- Bump `react` & `react-dom` peerDependency to `>=18.0.0` +- Removal of `siteLanguage` from `siteMetadata` +- [`useColorSchemeMediaQuery`](https://theme-ui.com/color-modes#responding-to-the-prefers-color-scheme-media-query) in Theme UI config is set to `system` +- Removal of `body` from the `Project` and `Page` type. The field `contentFilePath` was added. + +**Migration:** + +- Internally the necessary changes of the [gatsby-plugin-mdx migration guide](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/#migrating-from-v3-to-v4) were made, but if you set the `mdx` option to `false` and/or shadowed the theme in any way, you'll need to read the migration guide to e.g. change your `gatsby-config`. You'll also need to add any `remarkPlugins` or `rehypePlugins` that the theme is adding by default. +- MDX 2 is more strict about the allowed syntax, so you'll need to [update your MDX content](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/#updating-mdx-content) to be compliant. +- See [Theme UI's migration guide](https://github.com/system-ui/theme-ui/blob/develop/MIGRATING.md) +- If you shadowed a file or used `react-helmet` in any form in your site, you'll either need to migrate to the Gatsby Head API or re-install the necessary dependencies. By default, the theme no longer ships with `react-helmet` as internally everything was migrated to Gatsby Head API. To have the `lang` tag work correctly on the `` element you'll need to set it by using the [`setHtmlAttributes` API](https://www.gatsbyjs.com/docs/reference/config-files/gatsby-ssr/#onRenderBody). The current starter already has this included (you can copy it from there). Thus the `` component should only be used together with Gatsby Head API. diff --git a/.changeset/sour-crabs-hide.md b/.changeset/sour-crabs-hide.md new file mode 100644 index 000000000..49a243d7d --- /dev/null +++ b/.changeset/sour-crabs-hide.md @@ -0,0 +1,28 @@ +--- +"@lekoarts/gatsby-theme-graphql-playground": major +--- + +In preparation for the upcoming [Gatsby 5 release](https://github.com/gatsbyjs/gatsby/discussions/36609) this release will focus on some breaking changes unrelated to the `gatsby` core package. Another new major version will follow once Gatsby 5 is out so that you can upgrade in steps. + +**Features:** + +- Update to [MDX 2](https://mdxjs.com/blog/v2/) and [`gatsby-plugin-mdx` 4](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/) (**Breaking Change**) +- Update [Theme UI](https://theme-ui.com/) from v0.11 to v0.15 ([Theme UI Changelog](https://github.com/system-ui/theme-ui/blob/develop/CHANGELOG.md)) (**Breaking Change**) +- Replace [`react-helmet`](https://github.com/nfl/react-helmet) with [Gatsby Head API](https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-head/) (**Breaking Change**) + +**Breaking Changes:** + +- Any breaking changes from `theme-ui` between v0.11 and v0.15 +- Bump `react` & `react-dom` peerDependency to `>=18.0.0` +- Removal of `siteLanguage` from `siteMetadata` +- The MDX components are not managed by `gatsby-plugin-theme-ui/components` anymore but defined in a `` in `src/components/layout` +- [`useColorSchemeMediaQuery`](https://theme-ui.com/color-modes#responding-to-the-prefers-color-scheme-media-query) in Theme UI config is set to `system` +- Removal of `body` from the `Playground` type. The field `contentFilePath` was added. +- Changed from `@theme-ui/prism` to `@mapbox/rehype-prism` + +**Migration:** + +- Internally the necessary changes of the [gatsby-plugin-mdx migration guide](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/#migrating-from-v3-to-v4) were made, but if you set the `mdx` option to `false` and/or shadowed the theme in any way, you'll need to read the migration guide to e.g. change your `gatsby-config`. You'll also need to add any `remarkPlugins` or `rehypePlugins` that the theme is adding by default. +- MDX 2 is more strict about the allowed syntax, so you'll need to [update your MDX content](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/#updating-mdx-content) to be compliant. +- See [Theme UI's migration guide](https://github.com/system-ui/theme-ui/blob/develop/MIGRATING.md) +- If you shadowed a file or used `react-helmet` in any form in your site, you'll either need to migrate to the Gatsby Head API or re-install the necessary dependencies. By default, the theme no longer ships with `react-helmet` as internally everything was migrated to Gatsby Head API. To have the `lang` tag work correctly on the `` element you'll need to set it by using the [`setHtmlAttributes` API](https://www.gatsbyjs.com/docs/reference/config-files/gatsby-ssr/#onRenderBody). The current starter already has this included (you can copy it from there). Thus the `` component should only be used together with Gatsby Head API. diff --git a/.changeset/stupid-hairs-occur.md b/.changeset/stupid-hairs-occur.md new file mode 100644 index 000000000..f6f6b5860 --- /dev/null +++ b/.changeset/stupid-hairs-occur.md @@ -0,0 +1,18 @@ +--- +"@lekoarts/gatsby-theme-status-dashboard": major +--- + +In preparation for the upcoming [Gatsby 5 release](https://github.com/gatsbyjs/gatsby/discussions/36609) this release will focus on some breaking changes unrelated to the `gatsby` core package. Another new major version will follow once Gatsby 5 is out so that you can upgrade in steps. + +**Features:** + +- Update [Theme UI](https://theme-ui.com/) from v0.11 to v0.15 ([Theme UI Changelog](https://github.com/system-ui/theme-ui/blob/develop/CHANGELOG.md)) (**Breaking Change**) + +**Breaking Changes:** + +- Any breaking changes from `theme-ui` between v0.11 and v0.15 +- Bump `react` & `react-dom` peerDependency to `>=18.0.0` + +**Migration:** + +- See [Theme UI's migration guide](https://github.com/system-ui/theme-ui/blob/develop/MIGRATING.md) diff --git a/.changeset/tidy-geese-eat.md b/.changeset/tidy-geese-eat.md new file mode 100644 index 000000000..b01677050 --- /dev/null +++ b/.changeset/tidy-geese-eat.md @@ -0,0 +1,18 @@ +--- +"@lekoarts/gatsby-theme-specimens": major +--- + +In preparation for the upcoming [Gatsby 5 release](https://github.com/gatsbyjs/gatsby/discussions/36609) this release will focus on some breaking changes unrelated to the `gatsby` core package. Another new major version will follow once Gatsby 5 is out so that you can upgrade in steps. + +**Features:** + +- Support for colors defined in object notation (previously only array notation) + +**Breaking Changes:** + +- Bump `react` & `react-dom` peerDependency to `>=18.0.0` +- Bump `theme-ui` peerDependency to `>=0.15.0` + +**Migration:** + +- See [Theme UI's migration guide](https://github.com/system-ui/theme-ui/blob/develop/MIGRATING.md) diff --git a/.changeset/unlucky-scissors-sip.md b/.changeset/unlucky-scissors-sip.md new file mode 100644 index 000000000..fedeac941 --- /dev/null +++ b/.changeset/unlucky-scissors-sip.md @@ -0,0 +1,34 @@ +--- +"@lekoarts/gatsby-theme-jodie": major +"@lekoarts/gatsby-theme-jodie-core": major +--- + +In preparation for the upcoming [Gatsby 5 release](https://github.com/gatsbyjs/gatsby/discussions/36609) this release will focus on some breaking changes unrelated to the `gatsby` core package. Another new major version will follow once Gatsby 5 is out so that you can upgrade in steps. + +**Features:** + +- Update to [MDX 2](https://mdxjs.com/blog/v2/) and [`gatsby-plugin-mdx` 4](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/) (**Breaking Change**) +- Update [Theme UI](https://theme-ui.com/) from v0.11 to v0.15 ([Theme UI Changelog](https://github.com/system-ui/theme-ui/blob/develop/CHANGELOG.md)) (**Breaking Change**) +- Replace [`react-helmet`](https://github.com/nfl/react-helmet) with [Gatsby Head API](https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-head/) (**Breaking Change**) + +**Breaking Changes:** + +- Any breaking changes from `theme-ui` between v0.11 and v0.15 +- Bump `react` & `react-dom` peerDependency to `>=18.0.0` +- Removal of `siteLanguage` from `siteMetadata` +- [`useColorSchemeMediaQuery`](https://theme-ui.com/color-modes#responding-to-the-prefers-color-scheme-media-query) in Theme UI config is set to `system` +- Removal of `body` from the `Project` and `Page` type. The field `contentFilePath` was added. +- Removal of `gatsby-omni-font-loader` +- Removal of `gatsby-plugin-theme-ui/components` and `@theme-ui/prism`. If you want to have `` styles, re-add them to your project again (e.g. by using `@theme-ui/prism` or `@mapbox/rehype-prism` with `gatsby-plugin-mdx`) + +**Non-Breaking Changes:** + +- The homepage images are now served with `[AUTO, WEBP, AVIF]` (previously it was `[AUTO, WEBP]`) + +**Migration:** + +- Internally the necessary changes of the [gatsby-plugin-mdx migration guide](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/#migrating-from-v3-to-v4) were made, but if you set the `mdx` option to `false` and/or shadowed the theme in any way, you'll need to read the migration guide to e.g. change your `gatsby-config`. You'll also need to add any `remarkPlugins` or `rehypePlugins` that the theme is adding by default. +- MDX 2 is more strict about the allowed syntax, so you'll need to [update your MDX content](https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/#updating-mdx-content) to be compliant. +- See [Theme UI's migration guide](https://github.com/system-ui/theme-ui/blob/develop/MIGRATING.md) +- If you shadowed a file or used `react-helmet` in any form in your site, you'll either need to migrate to the Gatsby Head API or re-install the necessary dependencies. By default, the theme no longer ships with `react-helmet` as internally everything was migrated to Gatsby Head API. To have the `lang` tag work correctly on the `` element you'll need to set it by using the [`setHtmlAttributes` API](https://www.gatsbyjs.com/docs/reference/config-files/gatsby-ssr/#onRenderBody). The current starter already has this included (you can copy it from there). Thus the `` component should only be used together with Gatsby Head API. +- With the removal of `gatsby-omni-font-loader` in the example you'll now need to self-host your fonts. The current starter already has this included (you can copy it from there). diff --git a/.eslintrc.js b/.eslintrc.js index 1ea13313c..6a565562b 100755 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -88,6 +88,7 @@ module.exports = { "react/require-default-props": 0, "react/forbid-prop-types": 0, "react/no-unescaped-entities": 0, + "react/no-unknown-property": [`error`, { ignore: [`sx`, `css`] }], "react/prop-types": 0, "react/jsx-props-no-spreading": 0, "react/jsx-fragments": 0, @@ -122,4 +123,22 @@ module.exports = { }, ], }, + overrides: [ + { + files: `*.mdx`, + parser: `eslint-mdx`, + extends: [`plugin:mdx/recommended`], + rules: { + indent: 0, + "react/jsx-no-undef": 0, + "react/jsx-filename-extension": 0, + "react/self-closing-comp": 0, + "jsx-a11y/heading-has-content": 0, + "import/no-named-as-default": 0, + "import/no-named-as-default-member": 0, + "@typescript-eslint/no-unused-vars": 0, + "react/no-children-prop": 0, + }, + }, + ], } diff --git a/.github/workflows/e2e_testing.yml b/.github/workflows/e2e_testing.yml index 2babae4f9..2ba005292 100644 --- a/.github/workflows/e2e_testing.yml +++ b/.github/workflows/e2e_testing.yml @@ -15,7 +15,7 @@ jobs: timeout-minutes: 10 runs-on: ubuntu-latest container: - image: cypress/browsers:node16.13.2-chrome100-ff98 + image: cypress/browsers:node16.14.2-slim-chrome103-ff102 options: --user 1001 strategy: fail-fast: false @@ -35,6 +35,7 @@ jobs: start: yarn workspace ${{ matrix.containers }} serve config: "baseUrl=http://localhost:9000" cache-key: node-${{ matrix.containers }}-on-${{ runner.os }}-hash-${{ hashFiles('yarn.lock') }} + install-command: yarn --immutable --silent env: CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/publish-starters.yml b/.github/workflows/publish-starters.yml index f9f26cbc7..837764e47 100755 --- a/.github/workflows/publish-starters.yml +++ b/.github/workflows/publish-starters.yml @@ -8,10 +8,10 @@ jobs: steps: - name: Checkout Repo uses: actions/checkout@v3 - - name: Setup Node.js 14.x + - name: Setup Node.js 18.x uses: actions/setup-node@v3 with: - node-version: '14' + node-version: '18' - name: Publish Starters uses: LekoArts/actions-push-subdirectories@master env: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e17677726..d071dfb5a 100755 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,10 +12,10 @@ jobs: uses: actions/checkout@v3 with: fetch-depth: 0 - - name: Setup Node.js 14.x + - name: Setup Node.js 18.x uses: actions/setup-node@v3 with: - node-version: '14' + node-version: '18' - name: Install Dependencies run: yarn --immutable - name: Create Release Pull Request or Publish to npm diff --git a/.nvmrc b/.nvmrc index 5dbac1ed0..bc7eb5874 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v16.13.0 \ No newline at end of file +v18.10.0 \ No newline at end of file diff --git a/.yarnrc.yml b/.yarnrc.yml index f98f1ac63..118449a18 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -5,3 +5,5 @@ plugins: spec: "@yarnpkg/plugin-interactive-tools" yarnPath: .yarn/releases/yarn-3.2.3.cjs + +checksumBehavior: update diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 018411b41..bffb3e6d4 100755 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ Changes to themes need to evaluated in more detail (e.g. if they would be breaki ## Prerequisites -- [Node.js](http://nodejs.org/) >= v14 must be installed. +- [Node.js](http://nodejs.org/) >= v18 must be installed. - [Yarn](https://yarnpkg.com/en/docs/install) ## Local Development diff --git a/cypress/e2e/cara.ts b/cypress/e2e/cara.ts index 8ce05831d..faa676a50 100755 --- a/cypress/e2e/cara.ts +++ b/cypress/e2e/cara.ts @@ -5,6 +5,12 @@ describe(`gatsby-theme-cara`, () => { beforeEach(() => { cy.visit(`/`).waitForRouteChange() }) + it(`should have correct html[lang] attribute`, () => { + cy.get(`html`).should(`have.attr`, `lang`, `en`) + }) + it(`should have correct title in head`, () => { + cy.title().should(`eq`, `Cara - Gatsby Starter Portfolio`) + }) it(`should render hero content`, () => { cy.findByText(/hi, i'm your name/i) }) diff --git a/cypress/e2e/emilia.ts b/cypress/e2e/emilia.ts index e9e26a416..c24ab3232 100755 --- a/cypress/e2e/emilia.ts +++ b/cypress/e2e/emilia.ts @@ -5,6 +5,12 @@ describe(`gatsby-theme-emilia`, () => { beforeEach(() => { cy.visit(`/`).waitForRouteChange() }) + it(`should have correct html[lang] attribute`, () => { + cy.get(`html`).should(`have.attr`, `lang`, `en`) + }) + it(`should have correct title in head`, () => { + cy.title().should(`eq`, `Emilia - Gatsby Starter Portfolio`) + }) it(`should render the name`, () => { cy.get(`h1`).within(() => { cy.findByText(/lekoarts/i) @@ -56,11 +62,13 @@ describe(`gatsby-theme-emilia`, () => { cy.findByText(/more projects/i) cy.findByLabelText(/visit jodie project page/i) cy.findByText(/About Me/i) + cy.title().should(`eq`, `Emilia | Emilia`) }) it(`should accept custom slug in frontmatter and use that as URL`, () => { cy.findByLabelText(/Visit Ars Aurea project page/i) .click() .waitForRouteChange() .assertRoute(`/ars-aurea-goldene-kunst`) + cy.title().should(`eq`, `Ars Aurea | Emilia`) }) }) diff --git a/cypress/e2e/emma.ts b/cypress/e2e/emma.ts index e442163f8..cee8f373f 100755 --- a/cypress/e2e/emma.ts +++ b/cypress/e2e/emma.ts @@ -5,6 +5,12 @@ describe(`gatsby-theme-emma`, () => { beforeEach(() => { cy.visit(`/`).waitForRouteChange() }) + it(`should have correct html[lang] attribute`, () => { + cy.get(`html`).should(`have.attr`, `lang`, `en`) + }) + it(`should have correct title in head`, () => { + cy.title().should(`eq`, `Emma - Gatsby Starter Portfolio`) + }) it(`should render the site title`, () => { cy.findByLabelText(/emma, back to homepage/i) }) @@ -54,13 +60,16 @@ describe(`gatsby-theme-emma`, () => { cy.findByText(/hogwarts/i) cy.findByText(/10.06.2019/i) cy.findByText(/witchcraft/i) + cy.title().should(`eq`, `Hermione Granger | Emma`) }) it(`should accept custom slug in frontmatter and use that as URL`, () => { cy.findByLabelText(/View detail page of Proprius: steady, individual, personal/i) .click() .assertRoute(`/proprius`) + cy.title().should(`eq`, `Proprius: steady, individual, personal | Emma`) }) it(`should link and display the about page`, () => { cy.findByText(/about/i).click().waitForRouteChange().assertRoute(`/about`) + cy.title().should(`eq`, `About | Emma`) }) }) diff --git a/cypress/e2e/graphql-playground.ts b/cypress/e2e/graphql-playground.ts index d5c60bb30..a57346f5f 100755 --- a/cypress/e2e/graphql-playground.ts +++ b/cypress/e2e/graphql-playground.ts @@ -5,6 +5,12 @@ describe(`gatsby-theme-graphql-playground`, () => { it(`should work`, () => { cy.visit(`/`).assertRoute(`/`) }) + it(`should have correct html[lang] attribute`, () => { + cy.get(`html`).should(`have.attr`, `lang`, `en`) + }) + it(`should have correct title in head`, () => { + cy.title().should(`eq`, `GraphQL Playground - @lekoarts/gatsby-theme-graphql-playground`) + }) it(`should contain the title`, () => { cy.findByTestId(`Title`).contains(`GraphQL Playground`) }) @@ -25,6 +31,7 @@ describe(`gatsby-theme-graphql-playground`, () => { cy.findByTestId(`item-title`) cy.findByText(/Start with the basics, pulling up the site/i) cy.findByTestId(/iFrame-Get the Site Title/i) + cy.title().should(`eq`, `Get the Site Title | GraphQL Playground`) }) it(`should have functioning theme toggle`, () => { cy.get(`html`) diff --git a/cypress/e2e/jodie.ts b/cypress/e2e/jodie.ts index 83c7c962a..b20eec4b6 100755 --- a/cypress/e2e/jodie.ts +++ b/cypress/e2e/jodie.ts @@ -5,7 +5,12 @@ describe(`gatsby-theme-jodie`, () => { beforeEach(() => { cy.visit(`/`).waitForRouteChange() }) - + it(`should have correct html[lang] attribute`, () => { + cy.get(`html`).should(`have.attr`, `lang`, `en`) + }) + it(`should have correct title in head`, () => { + cy.title().should(`eq`, `Jodie - Gatsby Starter Portfolio`) + }) it(`should have functioning navigation`, () => { cy.get(`nav`).within(() => { cy.findByText(/projects/i) @@ -15,49 +20,47 @@ describe(`gatsby-theme-jodie`, () => { cy.assertRoute(`/projects`) cy.findByTestId(`page-title`) cy.should(`have.text`, `Projects`) + cy.title().should(`eq`, `Projects | Jodie`) cy.get(`nav`).within(() => { cy.findByText(/art/i).click().waitForRouteChange() }) cy.assertRoute(`/art`) cy.findByTestId(`page-title`) cy.should(`have.text`, `Art`) + cy.title().should(`eq`, `Art | Jodie`) cy.get(`nav`).within(() => { cy.findByText(/about/i).click().waitForRouteChange() }) cy.assertRoute(`/about`) cy.get(`h1`).first() cy.should(`have.text`, `About`) + cy.title().should(`eq`, `About | Jodie`) }) - it(`should have existing footer`, () => { cy.get(`footer`).within(() => { cy.findByText(/jodie/i) cy.findByText(/lekoarts/i) }) }) - it(`should link to a custom page on index page`, () => { cy.findByTestId(`About`).click().waitForRouteChange().assertRoute(`/about`) }) - it(`should have a complete project page`, () => { cy.findByTestId(`Color`).click().waitForRouteChange().assertRoute(`/color-in-all-its-glory`) cy.get(`h1`).should(`have.text`, `Color - In all its glory`) cy.findByText(/street art/i) cy.findByText(/Very colorful./i) cy.findByAltText(/projects-color-001/i) + cy.title().should(`eq`, `Color - In all its glory | Jodie`) }) - it(`should have items on projects page`, () => { cy.visit(`/projects`).waitForRouteChange() cy.findByTestId(`Extreme Neon`).click().waitForRouteChange().assertRoute(`/extreme-neon-what-is-this-trend-about`) }) - it(`should accept "custom" flag in frontmatter of pages`, () => { cy.visit(`/art`).waitForRouteChange() cy.findByTestId(`page-content`).should(`have.css`, `margin`, `0px`).should(`have.css`, `padding`, `0px`) }) - it(`should use the "color" flag in frontmatter`, () => { cy.visit(`/art`).waitForRouteChange() cy.findByTestId(`sidebar`).should( diff --git a/cypress/e2e/minimal-blog.ts b/cypress/e2e/minimal-blog.ts index 08bc5316b..f7809fed7 100755 --- a/cypress/e2e/minimal-blog.ts +++ b/cypress/e2e/minimal-blog.ts @@ -5,6 +5,12 @@ describe(`gatsby-theme-minimal-blog`, () => { beforeEach(() => { cy.visit(`/`).waitForRouteChange() }) + it(`should have correct html[lang] attribute`, () => { + cy.get(`html`).should(`have.attr`, `lang`, `en`) + }) + it(`should have correct title in head`, () => { + cy.title().should(`eq`, `Minimal Blog - Gatsby Theme`) + }) it(`should render the title`, () => { cy.get(`h1`).within(() => { cy.findByText(/Minimal Blog/i) @@ -13,6 +19,7 @@ describe(`gatsby-theme-minimal-blog`, () => { it(`should link the about page`, () => { cy.get(`nav`).within(() => { cy.findByText(/About/i).click().waitForRouteChange().assertRoute(`/about`) + cy.title().should(`eq`, `About | Minimal Blog`) }) }) it(`should link the blog page`, () => { @@ -25,8 +32,9 @@ describe(`gatsby-theme-minimal-blog`, () => { .within(() => { cy.findByText(/Blog/i) }) - cy.findByText(/Fantastic Beasts and Where to Find Them/i) + cy.findByText(/With Images/i) cy.findByText(/View all tags/i) + cy.title().should(`eq`, `Blog | Minimal Blog`) }) it(`should have functioning tags in list items`, () => { cy.visit(`/blog`).waitForRouteChange() @@ -38,7 +46,8 @@ describe(`gatsby-theme-minimal-blog`, () => { .within(() => { cy.findByText(/Tutorial/i) }) - cy.findByText(/Introduction to "Defence against the Dark Arts"/i) + cy.findByText(/With Images/i) + cy.title().should(`eq`, `Tag: Tutorial | Minimal Blog`) }) it(`should have functioning tags overview page`, () => { cy.visit(`/blog`).waitForRouteChange() @@ -50,7 +59,8 @@ describe(`gatsby-theme-minimal-blog`, () => { .within(() => { cy.findByText(/Tags/i) }) - cy.findByText(/Novel/i) + cy.findByText(/Tutorial/i) + cy.title().should(`eq`, `Tags | Minimal Blog`) }) it(`should have social media links`, () => { cy.get(`header`).within(() => { @@ -62,7 +72,7 @@ describe(`gatsby-theme-minimal-blog`, () => { }) it(`should render the latest posts`, () => { cy.findByText(/Latest Posts/i) - cy.findByText(/Fantastic Beasts and Where to Find Them/i) + cy.findByText(/With Images/i) cy.findByText(/Read all posts/i) }) it(`should render the bottom part`, () => { @@ -78,36 +88,30 @@ describe(`gatsby-theme-minimal-blog`, () => { cy.findByLabelText(`Link to the theme author's website`).contains(`LekoArts`) }) it(`should link to individual blog post`, () => { - cy.findByText(/Introduction to "Defence against the Dark Arts"/i) + cy.findByText(/Markdown Reference/i) .click() .waitForRouteChange() - .assertRoute(`/introduction-to-defence-against-the-dark-arts`) + .assertRoute(`/markdown-reference`) .get(`h1`) .within(() => { - cy.findByText(/Introduction to "Defence against the Dark Arts"/i) + cy.findByText(/Markdown Reference/i) }) - cy.findByText(/07.11.2019/i) - cy.findByText(/Tutorial/i) - cy.findByText(/2 min read/i) + cy.findByText(/12.09.2022/i) + cy.get(`a[href='/tags/code']`).contains(`Code`) + cy.get(`a[href='/tags/markdown']`).contains(`Markdown`) + cy.findByText(/7 min read/i) cy.findByText( - /Thestral dirigible plums, Viktor Krum hexed memory charm Animagus Invisibility Cloak three-headed Dog./i + /What follows from here is just a bunch of absolute nonsense I've written to dogfood the plugin itself./i ) + cy.title().should(`eq`, `Markdown Reference | Minimal Blog`) }) - it(`should render blogpost with code component`, () => { - cy.visit(`/fantastic-beasts-and-where-to-find-them`) - cy.findByTitle(`Spotify`) - .get(`[data-name="live-editor"]`) - .should(`exist`) - .get(`[data-language="jsx"]`) - .should(`exist`) + it(`should render blogpost with code components`, () => { + cy.visit(`/code-block-examples`) }) it(`should accept custom slug in frontmatter and use that as URL`, () => { - cy.findByText( - `Curses and Counter-curses (Bewitch Your Friends and Befuddle Your Enemies with the Latest Revenges: Hair Loss, Jelly-Legs, Tongue-Tying, and Much, Much More)` - ) - .click() - .waitForRouteChange() - .assertRoute(`/curses-counter-curses-and-more`) + cy.visit(`/blog`).waitForRouteChange() + cy.findByText(`Normal Text`).click().waitForRouteChange().assertRoute(`/normal-text-override`) + cy.title().should(`eq`, `Normal Text | Minimal Blog`) }) it(`should render the light/dark mode toggle`, () => { cy.findByLabelText(/Activate Dark Mode/i) @@ -122,7 +126,7 @@ describe(`gatsby-theme-minimal-blog`, () => { .should(`have.css`, `background`, `rgb(26, 32, 44) none repeat scroll 0% 0% / auto padding-box border-box`) }) it(`should accept canonical url in frontmatter and set in head`, () => { - cy.visit(`/curses-counter-curses-and-more`).waitForRouteChange() - cy.get(`head link[rel='canonical']`).should(`have.attr`, `href`, `https://random-blog-about-curses.com`) + cy.visit(`/normal-text-override`).waitForRouteChange() + cy.get(`head link[rel='canonical']`).should(`have.attr`, `href`, `https://blog-about-normal-text.com`) }) }) diff --git a/cypress/e2e/status-dashboard.ts b/cypress/e2e/status-dashboard.ts index 74f1f6683..74696839e 100755 --- a/cypress/e2e/status-dashboard.ts +++ b/cypress/e2e/status-dashboard.ts @@ -5,6 +5,12 @@ describe(`gatsby-theme-status-dashboard`, () => { beforeEach(() => { cy.visit(`/`).waitForRouteChange() }) + it(`should have correct html[lang] attribute`, () => { + cy.get(`html`).should(`have.attr`, `lang`, `en`) + }) + it(`should have correct title in head`, () => { + cy.title().should(`eq`, `Status Dashboard - LekoArts`) + }) it(`should render the title`, () => { cy.get(`h1`).within(() => { cy.findByText(/status dashboard - lekoarts/i) diff --git a/cypress/e2e/styleguide.ts b/cypress/e2e/styleguide.ts index b6718e179..1f35e3feb 100644 --- a/cypress/e2e/styleguide.ts +++ b/cypress/e2e/styleguide.ts @@ -2,17 +2,23 @@ /// describe(`gatsby-theme-styleguide`, () => { + beforeEach(() => { + cy.visit(`/`).waitForRouteChange() + }) + it(`should have correct html[lang] attribute`, () => { + cy.get(`html`).should(`have.attr`, `lang`, `en`) + }) + it(`should have correct title in head`, () => { + cy.title().should(`eq`, `Theme UI Styleguide`) + }) it(`should render the title`, () => { - cy.visit(`/`).assertRoute(`/`) cy.findByText(/Style Guide/i) }) it(`should render the colors section`, () => { - cy.visit(`/`) cy.findByText(/Colors/i) cy.findByText(/danger/i) }) it(`should render the footer`, () => { - cy.visit(`/`) cy.findByText(`@lekoarts/gatsby-theme-styleguide`).should( `have.attr`, `href`, diff --git a/examples/cara/README.md b/examples/cara/README.md index 88d68bc4d..585b1a44f 100755 --- a/examples/cara/README.md +++ b/examples/cara/README.md @@ -40,19 +40,16 @@ Also be sure to check out other [Free & Open Source Gatsby Themes](https://theme ### 1. **Create a Gatsby site.** -Use `git` to clone the site and navigate into it: +Use the Gatsby CLI to clone the site and install dependencies: ```sh -git clone https://github.com/LekoArts/gatsby-starter-portfolio-cara project-name -cd project-name +npx gatsby new gatsby-starter-portfolio-cara https://github.com/LekoArts/gatsby-starter-portfolio-cara ``` -### 2. **Install dependencies.** - -If you use npm 7 or above use the `--legacy-peer-deps` flag. If you use npm 6 you can use `npm install`. +### 2. **Navigate to your new project.** ```sh -npm install --legacy-peer-deps +cd gatsby-starter-portfolio-cara ``` ### 3. **Open the code and start customizing!** diff --git a/examples/cara/gatsby-config.js b/examples/cara/gatsby-config.js index 80382763e..b6f6f895a 100755 --- a/examples/cara/gatsby-config.js +++ b/examples/cara/gatsby-config.js @@ -2,6 +2,9 @@ require(`dotenv`).config() const shouldAnalyseBundle = process.env.ANALYSE_BUNDLE +/** + * @type {import('gatsby').GatsbyConfig} + */ module.exports = { siteMetadata: { // You can overwrite values here that are used for the SEO component @@ -12,7 +15,6 @@ module.exports = { siteHeadline: `Cara - Gatsby Theme from @lekoarts`, siteUrl: `https://cara.lekoarts.de`, siteDescription: `Playful and Colorful One-Page portfolio featuring Parallax effects and animations`, - siteLanguage: `en`, siteImage: `/banner.jpg`, author: `@lekoarts_de`, }, @@ -48,7 +50,6 @@ module.exports = { ], }, }, - `gatsby-plugin-gatsby-cloud`, shouldAnalyseBundle && { resolve: `gatsby-plugin-webpack-bundle-analyser-v2`, options: { diff --git a/examples/cara/gatsby-ssr.js b/examples/cara/gatsby-ssr.js new file mode 100644 index 000000000..466c3ff5b --- /dev/null +++ b/examples/cara/gatsby-ssr.js @@ -0,0 +1,3 @@ +export const onRenderBody = ({ setHtmlAttributes }) => { + setHtmlAttributes({ lang: `en` }) +} diff --git a/examples/cara/package.json b/examples/cara/package.json index c97880feb..d36a8321c 100755 --- a/examples/cara/package.json +++ b/examples/cara/package.json @@ -17,12 +17,11 @@ }, "dependencies": { "@lekoarts/gatsby-theme-cara": "^3.0.0", - "gatsby": "^4.18.2", - "gatsby-plugin-gatsby-cloud": "^4.18.1", - "gatsby-plugin-manifest": "^4.18.1", + "gatsby": "^4.24.1", + "gatsby-plugin-manifest": "^4.24.0", "gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.27", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "devDependencies": { "cross-env": "^7.0.3" diff --git a/examples/cara/src/pages/404.jsx b/examples/cara/src/pages/404.jsx index 55535d73e..784c89134 100755 --- a/examples/cara/src/pages/404.jsx +++ b/examples/cara/src/pages/404.jsx @@ -1,7 +1,7 @@ import * as React from "react" import { Link } from "gatsby" import { Parallax } from "@react-spring/parallax" -import { Themed } from "theme-ui" +import { Themed } from "@theme-ui/mdx" import Layout from "@lekoarts/gatsby-theme-cara/src/components/layout" import Divider from "@lekoarts/gatsby-theme-cara/src/elements/divider" import { UpDown, UpDownWide } from "@lekoarts/gatsby-theme-cara/src/styles/animations" @@ -12,7 +12,6 @@ import Inner from "@lekoarts/gatsby-theme-cara/src/elements/inner" const NotFound = () => ( -
@@ -57,3 +56,5 @@ const NotFound = () => ( ) export default NotFound + +export const Head = () => diff --git a/examples/cara/static/icons.svg b/examples/cara/static/icons.svg new file mode 100644 index 000000000..63fbb200c --- /dev/null +++ b/examples/cara/static/icons.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/emilia/README.md b/examples/emilia/README.md index 80f5fa23e..97e62ee21 100755 --- a/examples/emilia/README.md +++ b/examples/emilia/README.md @@ -44,19 +44,16 @@ Also be sure to check out other [Free & Open Source Gatsby Themes](https://theme ### 1. **Create a Gatsby site.** -Use `git` to clone the site and navigate into it: +Use the Gatsby CLI to clone the site and install dependencies: ```sh -git clone https://github.com/LekoArts/gatsby-starter-portfolio-emilia project-name -cd project-name +npx gatsby new gatsby-starter-portfolio-emilia https://github.com/LekoArts/gatsby-starter-portfolio-emilia ``` -### 2. **Install dependencies.** - -If you use npm 7 or above use the `--legacy-peer-deps` flag. If you use npm 6 you can use `npm install`. +### 2. **Navigate to your new project.** ```sh -npm install --legacy-peer-deps +cd gatsby-starter-portfolio-emilia ``` ### 3. **Open the code and start customizing!** diff --git a/examples/emilia/gatsby-config.js b/examples/emilia/gatsby-config.js index b3267d913..03c50f66a 100755 --- a/examples/emilia/gatsby-config.js +++ b/examples/emilia/gatsby-config.js @@ -2,6 +2,9 @@ require(`dotenv`).config() const shouldAnalyseBundle = process.env.ANALYSE_BUNDLE +/** + * @type {import('gatsby').GatsbyConfig} + */ module.exports = { siteMetadata: { // You can overwrite values here that are used for the SEO component @@ -12,7 +15,6 @@ module.exports = { siteHeadline: `Emilia - Gatsby Theme from @lekoarts`, siteUrl: `https://emilia.lekoarts.de`, siteDescription: `Minimalistic portfolio/photography site with masonry grid, page transitions and big images. Themeable with Theme UI. Includes Light/Dark mode.`, - siteLanguage: `en`, siteImage: `/banner.jpg`, author: `@lekoarts_de`, }, @@ -54,7 +56,6 @@ module.exports = { ], }, }, - `gatsby-plugin-gatsby-cloud`, shouldAnalyseBundle && { resolve: `gatsby-plugin-webpack-bundle-analyser-v2`, options: { diff --git a/examples/emilia/gatsby-ssr.js b/examples/emilia/gatsby-ssr.js new file mode 100644 index 000000000..466c3ff5b --- /dev/null +++ b/examples/emilia/gatsby-ssr.js @@ -0,0 +1,3 @@ +export const onRenderBody = ({ setHtmlAttributes }) => { + setHtmlAttributes({ lang: `en` }) +} diff --git a/examples/emilia/package.json b/examples/emilia/package.json index d9f67c64f..a5a63461a 100755 --- a/examples/emilia/package.json +++ b/examples/emilia/package.json @@ -17,13 +17,12 @@ }, "dependencies": { "@lekoarts/gatsby-theme-emilia": "^3.0.0", - "gatsby": "^4.18.2", - "gatsby-plugin-gatsby-cloud": "^4.18.1", - "gatsby-plugin-manifest": "^4.18.1", - "gatsby-plugin-sitemap": "^5.18.1", + "gatsby": "^4.24.1", + "gatsby-plugin-manifest": "^4.24.0", + "gatsby-plugin-sitemap": "^5.24.0", "gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.27", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "devDependencies": { "cross-env": "^7.0.3" diff --git a/examples/emilia/src/pages/404.jsx b/examples/emilia/src/pages/404.jsx index 474e4beb7..3ca8fc822 100755 --- a/examples/emilia/src/pages/404.jsx +++ b/examples/emilia/src/pages/404.jsx @@ -1,13 +1,13 @@ import * as React from "react" import { Link } from "gatsby" -import { Container, Themed, Link as TLink } from "theme-ui" +import { Container, Link as TLink } from "theme-ui" +import { Themed } from "@theme-ui/mdx" import Header from "@lekoarts/gatsby-theme-emilia/src/components/header" import Layout from "@lekoarts/gatsby-theme-emilia/src/components/layout" import Seo from "@lekoarts/gatsby-theme-emilia/src/components/seo" const NotFound = () => ( -
@@ -23,3 +23,5 @@ const NotFound = () => ( ) export default NotFound + +export const Head = () => diff --git a/examples/emilia/static/icons.svg b/examples/emilia/static/icons.svg new file mode 100644 index 000000000..763e8ccc3 --- /dev/null +++ b/examples/emilia/static/icons.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/emma/README.md b/examples/emma/README.md index 283b9129a..27088340c 100755 --- a/examples/emma/README.md +++ b/examples/emma/README.md @@ -44,19 +44,16 @@ Also be sure to check out other [Free & Open Source Gatsby Themes](https://theme ### 1. **Create a Gatsby site.** -Use `git` to clone the site and navigate into it: +Use the Gatsby CLI to clone the site and install dependencies: ```sh -git clone https://github.com/LekoArts/gatsby-starter-portfolio-emma project-name -cd project-name +npx gatsby new gatsby-starter-portfolio-emma https://github.com/LekoArts/gatsby-starter-portfolio-emma ``` -### 2. **Install dependencies.** - -If you use npm 7 or above use the `--legacy-peer-deps` flag. If you use npm 6 you can use `npm install`. +### 2. **Navigate to your new project.** ```sh -npm install --legacy-peer-deps +cd gatsby-starter-portfolio-emma ``` ### 3. **Open the code and start customizing!** diff --git a/examples/emma/content/projects/emma/index.mdx b/examples/emma/content/projects/emma/index.mdx index 0fb7d883f..0890e2d2f 100644 --- a/examples/emma/content/projects/emma/index.mdx +++ b/examples/emma/content/projects/emma/index.mdx @@ -122,8 +122,6 @@ Paragraph: Code - - Paragraph: Code diff --git a/examples/emma/gatsby-config.js b/examples/emma/gatsby-config.js index 0e6835edf..3882818b5 100755 --- a/examples/emma/gatsby-config.js +++ b/examples/emma/gatsby-config.js @@ -2,6 +2,9 @@ require(`dotenv`).config() const shouldAnalyseBundle = process.env.ANALYSE_BUNDLE +/** + * @type {import('gatsby').GatsbyConfig} + */ module.exports = { siteMetadata: { // You can overwrite values here that are used for the SEO component @@ -12,7 +15,6 @@ module.exports = { siteHeadline: `Emma - Gatsby Theme from @lekoarts`, siteUrl: `https://emma.lekoarts.de`, siteDescription: `Minimalistic portfolio with full-width grid, page transitions, support for additional MDX pages, and a focus on large images`, - siteLanguage: `en`, siteImage: `/banner.jpg`, author: `@lekoarts_de`, }, @@ -54,7 +56,6 @@ module.exports = { ], }, }, - `gatsby-plugin-gatsby-cloud`, shouldAnalyseBundle && { resolve: `gatsby-plugin-webpack-bundle-analyser-v2`, options: { diff --git a/examples/emma/gatsby-ssr.js b/examples/emma/gatsby-ssr.js new file mode 100644 index 000000000..466c3ff5b --- /dev/null +++ b/examples/emma/gatsby-ssr.js @@ -0,0 +1,3 @@ +export const onRenderBody = ({ setHtmlAttributes }) => { + setHtmlAttributes({ lang: `en` }) +} diff --git a/examples/emma/package.json b/examples/emma/package.json index a4009e465..8314eba21 100755 --- a/examples/emma/package.json +++ b/examples/emma/package.json @@ -17,13 +17,12 @@ }, "dependencies": { "@lekoarts/gatsby-theme-emma": "^3.0.0", - "gatsby": "^4.18.2", - "gatsby-plugin-gatsby-cloud": "^4.18.1", - "gatsby-plugin-manifest": "^4.18.1", - "gatsby-plugin-sitemap": "^5.18.1", + "gatsby": "^4.24.1", + "gatsby-plugin-manifest": "^4.24.0", + "gatsby-plugin-sitemap": "^5.24.0", "gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.27", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "devDependencies": { "cross-env": "^7.0.3" diff --git a/examples/emma/src/pages/404.jsx b/examples/emma/src/pages/404.jsx index c78152adf..78c059f6f 100755 --- a/examples/emma/src/pages/404.jsx +++ b/examples/emma/src/pages/404.jsx @@ -1,12 +1,12 @@ import * as React from "react" import { Link } from "gatsby" -import { Container, Themed, Link as TLink } from "theme-ui" +import { Container, Link as TLink } from "theme-ui" +import { Themed } from "@theme-ui/mdx" import Layout from "@lekoarts/gatsby-theme-emma/src/components/layout" import Seo from "@lekoarts/gatsby-theme-emma/src/components/seo" const NotFound = () => ( - Oh, no! @@ -21,3 +21,5 @@ const NotFound = () => ( ) export default NotFound + +export const Head = () => diff --git a/examples/graphql-playground/README.md b/examples/graphql-playground/README.md index 6f33ac986..1ee3aba0b 100755 --- a/examples/graphql-playground/README.md +++ b/examples/graphql-playground/README.md @@ -41,19 +41,16 @@ Also be sure to check out other [Free & Open Source Gatsby Themes](https://theme ### 1. **Create a Gatsby site.** -Use `git` to clone the site and navigate into it: +Use the Gatsby CLI to clone the site and install dependencies: ```sh -git clone https://github.com/LekoArts/gatsby-starter-graphql-playground project-name -cd project-name +npx gatsby new gatsby-starter-graphql-playground https://github.com/LekoArts/gatsby-starter-graphql-playground ``` -### 2. **Install dependencies.** - -If you use npm 7 or above use the `--legacy-peer-deps` flag. If you use npm 6 you can use `npm install`. +### 2. **Navigate to your new project.** ```sh -npm install --legacy-peer-deps +cd gatsby-starter-graphql-playground ``` ### 3. **Open the code and start customizing!** diff --git a/examples/graphql-playground/gatsby-config.js b/examples/graphql-playground/gatsby-config.js index 3349eea65..d06fda0d4 100755 --- a/examples/graphql-playground/gatsby-config.js +++ b/examples/graphql-playground/gatsby-config.js @@ -2,6 +2,9 @@ require(`dotenv`).config() const shouldAnalyseBundle = process.env.ANALYSE_BUNDLE +/** + * @type {import('gatsby').GatsbyConfig} + */ module.exports = { plugins: [ { @@ -9,7 +12,6 @@ module.exports = { // See the theme's README for all available options options: {}, }, - `gatsby-plugin-gatsby-cloud`, shouldAnalyseBundle && { resolve: `gatsby-plugin-webpack-bundle-analyser-v2`, options: { diff --git a/examples/graphql-playground/gatsby-ssr.js b/examples/graphql-playground/gatsby-ssr.js new file mode 100644 index 000000000..466c3ff5b --- /dev/null +++ b/examples/graphql-playground/gatsby-ssr.js @@ -0,0 +1,3 @@ +export const onRenderBody = ({ setHtmlAttributes }) => { + setHtmlAttributes({ lang: `en` }) +} diff --git a/examples/graphql-playground/package.json b/examples/graphql-playground/package.json index 400b4dc93..75fa74e03 100755 --- a/examples/graphql-playground/package.json +++ b/examples/graphql-playground/package.json @@ -17,11 +17,10 @@ }, "dependencies": { "@lekoarts/gatsby-theme-graphql-playground": "^3.0.0", - "gatsby": "^4.18.2", - "gatsby-plugin-gatsby-cloud": "^4.18.1", + "gatsby": "^4.24.1", "gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.27", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "devDependencies": { "cross-env": "^7.0.3" diff --git a/examples/jodie/README.md b/examples/jodie/README.md index 6234af175..93f8eac61 100755 --- a/examples/jodie/README.md +++ b/examples/jodie/README.md @@ -44,19 +44,16 @@ Also be sure to check out other [Free & Open Source Gatsby Themes](https://theme ### 1. **Create a Gatsby site.** -Use `git` to clone the site and navigate into it: +Use the Gatsby CLI to clone the site and install dependencies: ```sh -git clone https://github.com/LekoArts/gatsby-starter-portfolio-jodie project-name -cd project-name +npx gatsby new gatsby-starter-portfolio-jodie https://github.com/LekoArts/gatsby-starter-portfolio-jodie ``` -### 2. **Install dependencies.** - -If you use npm 7 or above use the `--legacy-peer-deps` flag. If you use npm 6 you can use `npm install`. +### 2. **Navigate to your new project.** ```sh -npm install --legacy-peer-deps +cd gatsby-starter-portfolio-jodie ``` ### 3. **Open the code and start customizing!** @@ -83,16 +80,19 @@ Edit the file at `src/@lekoarts/gatsby-theme-jodie/icons/logo.jsx`. By default, the underlying theme and thus this starter uses "Work Sans" as its font. It's used throughout the site and set as a `font-family` on the `html` element. -If you want to change your default font or add any additional fonts, you'll need to change two things: +If you want to change your default font or add any additional fonts, you'll need to change a couple of things: -1. The configuration for `gatsby-omni-font-loader` => Responsible for loading the font CSS files -1. The Theme UI config and its `fonts` key (see [Theme UI Typography Docs](https://theme-ui.com/theming#typography)) => Responsible for setting the `font-family` in the example +1. Font file inside `static/fonts` +1. Preload link inside `gatsby-ssr.js` (the name of the font file) +1. CSS in `global.css` +1. The Theme UI config and its `fonts` key (see [Theme UI Typography Docs](https://theme-ui.com/theming#typography)) -After adjusting the configuration for `gatsby-omni-font-loader` you'll need to shadow the theme's Theme UI config and overwrite the `fonts` key. For the sake of this explanation it's assumed that you replaced "Work Sans" with "Roboto Mono". +For the sake of this explanation it's assumed that you replaced "Work Sans" with "Roboto Mono". -Create a file at `src/gatsby-plugin-theme-ui/index.js` with the following contents: +Change the file `src/gatsby-plugin-theme-ui/index.js` with the following contents: ```js +// Inside src/gatsby-plugin-theme-ui/index.js import { merge } from "theme-ui"; import originalTheme from "@lekoarts/gatsby-theme-jodie/src/gatsby-plugin-theme-ui/index"; @@ -112,6 +112,7 @@ As defined in the [Theme Specification](https://theme-ui.com/theme-spec#typograp Then you'd not overwrite `body` but add a `heading` key: ```js +// Inside src/gatsby-plugin-theme-ui/index.js import { merge } from "theme-ui"; import originalTheme from "@lekoarts/gatsby-theme-jodie/src/gatsby-plugin-theme-ui/index"; diff --git a/examples/jodie/content/pages/about/index.mdx b/examples/jodie/content/pages/about/index.mdx index 3d1790307..67ab84852 100644 --- a/examples/jodie/content/pages/about/index.mdx +++ b/examples/jodie/content/pages/about/index.mdx @@ -143,8 +143,6 @@ Paragraph: Code - - Paragraph: Code diff --git a/examples/jodie/gatsby-browser.js b/examples/jodie/gatsby-browser.js new file mode 100644 index 000000000..be552c7f5 --- /dev/null +++ b/examples/jodie/gatsby-browser.js @@ -0,0 +1 @@ +import "./global.css" diff --git a/examples/jodie/gatsby-config.js b/examples/jodie/gatsby-config.js index d90a0a852..f529758f4 100755 --- a/examples/jodie/gatsby-config.js +++ b/examples/jodie/gatsby-config.js @@ -2,6 +2,9 @@ require(`dotenv`).config() const shouldAnalyseBundle = process.env.ANALYSE_BUNDLE +/** + * @type {import('gatsby').GatsbyConfig} + */ module.exports = { siteMetadata: { // You can overwrite values here that are used for the SEO component @@ -12,7 +15,6 @@ module.exports = { siteHeadline: `Jodie - Gatsby Theme from @lekoarts`, siteUrl: `https://jodie.lekoarts.de`, siteDescription: `Image-heavy photography portfolio with colorful accents & customizable pages. Includes adaptive image grids powered by CSS grid and automatic image integration into projects.`, - siteLanguage: `en`, siteImage: `/banner.jpg`, author: `@lekoarts_de`, }, @@ -28,21 +30,6 @@ module.exports = { ], }, }, - { - resolve: `gatsby-omni-font-loader`, - options: { - enableListener: true, - preconnect: [`https://fonts.gstatic.com`], - // If you plan on changing the font you'll also need to adjust the Theme UI config to edit the CSS - // See: https://github.com/LekoArts/gatsby-themes/tree/main/examples/jodie#changing-your-fonts - web: [ - { - name: `Work Sans`, - file: `https://fonts.googleapis.com/css2?family=Work+Sans:wght@400..700&display=swap`, - }, - ], - }, - }, { resolve: `gatsby-plugin-sitemap`, options: { @@ -75,7 +62,6 @@ module.exports = { ], }, }, - `gatsby-plugin-gatsby-cloud`, shouldAnalyseBundle && { resolve: `gatsby-plugin-webpack-bundle-analyser-v2`, options: { diff --git a/examples/jodie/gatsby-ssr.js b/examples/jodie/gatsby-ssr.js new file mode 100644 index 000000000..7787eab3f --- /dev/null +++ b/examples/jodie/gatsby-ssr.js @@ -0,0 +1,16 @@ +import * as React from "react" + +export const onRenderBody = ({ setHtmlAttributes, setHeadComponents }) => { + setHtmlAttributes({ lang: `en` }) + + setHeadComponents([ + , + ]) +} diff --git a/examples/jodie/global.css b/examples/jodie/global.css new file mode 100644 index 000000000..5a00f5ab4 --- /dev/null +++ b/examples/jodie/global.css @@ -0,0 +1,8 @@ +@font-face { + font-family: 'Work Sans'; + font-style: normal; + font-weight: 400 700; + font-display: swap; + src: url(/fonts/work-sans.var.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} \ No newline at end of file diff --git a/examples/jodie/package.json b/examples/jodie/package.json index 9983a0cb7..deb4729c7 100755 --- a/examples/jodie/package.json +++ b/examples/jodie/package.json @@ -17,14 +17,12 @@ }, "dependencies": { "@lekoarts/gatsby-theme-jodie": "^3.0.0", - "gatsby": "^4.18.2", - "gatsby-omni-font-loader": "^2.0.0", - "gatsby-plugin-gatsby-cloud": "^4.18.1", - "gatsby-plugin-manifest": "^4.18.1", - "gatsby-plugin-sitemap": "^5.18.1", + "gatsby": "^4.24.1", + "gatsby-plugin-manifest": "^4.24.0", + "gatsby-plugin-sitemap": "^5.24.0", "gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.27", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "devDependencies": { "cross-env": "^7.0.3" diff --git a/examples/jodie/src/gatsby-plugin-theme-ui/index.js b/examples/jodie/src/gatsby-plugin-theme-ui/index.js new file mode 100644 index 000000000..e1c1ac5d7 --- /dev/null +++ b/examples/jodie/src/gatsby-plugin-theme-ui/index.js @@ -0,0 +1,10 @@ +import { merge } from "theme-ui" +import originalTheme from "@lekoarts/gatsby-theme-jodie/src/gatsby-plugin-theme-ui/index" + +const theme = merge(originalTheme, { + fonts: { + body: `"Work Sans", -apple-system, BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"`, + }, +}) + +export default theme diff --git a/examples/jodie/static/fonts/work-sans.var.woff2 b/examples/jodie/static/fonts/work-sans.var.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..13b9ece14a5dcc79469f2bf84df7a001603e1c78 GIT binary patch literal 47800 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

cu%oHt5k`4!wvk(U!bF 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 literal 0 HcmV?d00001 diff --git a/examples/minimal-blog/README.md b/examples/minimal-blog/README.md index e9a09d2ce..8e444b358 100755 --- a/examples/minimal-blog/README.md +++ b/examples/minimal-blog/README.md @@ -35,7 +35,7 @@ Also be sure to check out other [Free & Open Source Gatsby Themes](https://theme - Light Mode / Dark Mode - Typography driven, minimal style - Tags/Categories support -- Code highlighting with [prism-react-renderer](https://github.com/FormidableLabs/prism-react-renderer) and [react-live](https://github.com/FormidableLabs/react-live) support. Also allows adding line numbers, line highlighting, language tabs, and file titles. +- Code highlighting with [prism-react-renderer](https://github.com/FormidableLabs/prism-react-renderer). Also allows adding line numbers, line highlighting, language tabs, and file titles. - RSS Feed for blog posts - SEO (Sitemap, OpenGraph tags, Twitter tags) - WebApp Manifest @@ -46,19 +46,16 @@ Also be sure to check out other [Free & Open Source Gatsby Themes](https://theme ### 1. **Create a Gatsby site.** -Use `git` to clone the site and navigate into it: +Use the Gatsby CLI to clone the site and install dependencies: ```sh -git clone https://github.com/LekoArts/gatsby-starter-minimal-blog project-name -cd project-name +npx gatsby new gatsby-starter-minimal-blog https://github.com/LekoArts/gatsby-starter-minimal-blog ``` -### 2. **Install dependencies.** - -If you use npm 7 or above use the `--legacy-peer-deps` flag. If you use npm 6 you can use `npm install`. +### 2. **Navigate to your new project.** ```sh -npm install --legacy-peer-deps +cd gatsby-starter-minimal-blog ``` ### 3. **Open the code and start customizing!** @@ -79,7 +76,7 @@ Have a look at the theme's README and files to see what options are available an ### Code Highlighting -Since the underlying theme ships with [prism-react-renderer](https://github.com/FormidableLabs/prism-react-renderer) and [react-live](https://github.com/FormidableLabs/react-live) certain additional features were added to code blocks. You can find an overview / usage example in the [example repository](https://github.com/LekoArts/gatsby-themes/tree/main/examples/minimal-blog/content/posts/fantastic-beasts-and-where-to-find-them/index.mdx)! If you want to change certain code styles or add additional language tabs, you need to shadow the file `src/@lekoarts/gatsby-theme-minimal-blog/styles/code.js`. +Since the underlying theme ships with [prism-react-renderer](https://github.com/FormidableLabs/prism-react-renderer) certain additional features were added to code blocks. You can find an overview / usage example in the [example repository](https://github.com/LekoArts/gatsby-themes/tree/main/examples/minimal-blog/content/posts/fantastic-beasts-and-where-to-find-them/index.mdx)! If you want to change certain code styles or add additional language tabs, you need to shadow the file `src/@lekoarts/gatsby-theme-minimal-blog/styles/code.js`. **Language tabs:** @@ -96,7 +93,7 @@ When you add a language (such as e.g. `js` or `javascript`) to the code block, a You can display a title (e.g. the file path) above the code block. ```` -```jsx:title=your-title +```jsx title=your-title // code goes here ``` ```` @@ -104,7 +101,7 @@ You can display a title (e.g. the file path) above the code block. Or without a specific language: ```` -```:title=your-title +```none title=your-title // code goes here ``` ```` @@ -114,7 +111,7 @@ Or without a specific language: You can highlight single or multiple (or both) lines in a code block. You need to add a language. ```` -```js {2,4-5} +```js highlight=2,4-5 const test = 3 const foo = 'bar' const harry = 'potter' @@ -123,29 +120,16 @@ const ron = 'weasley' ``` ```` -**Hide line numbers:** +**Show line numbers:** -If you want to hide line numbers you can either globally disable them (see Theme options) or on a block-by-block basis. You can also combine that with the other attributes. +If you want to show line numbers you can either globally enable them (see theme options) or on a block-by-block basis. You can also combine that with the other attributes. ```` -```noLineNumbers +```js withLineNumbers // code goes here ``` ```` -**react-live:** - -Add `react-live` to the code block (and render the component) to see a preview below it. - -```` -```js react-live -const onClick = () => { - alert("You opened me"); -}; -render(); -``` -```` - ### Adding content #### Adding a new blog post @@ -212,51 +196,6 @@ To edit the projects part below "Latest posts", create a file at `src/@lekoarts/ Inside the [`` component](https://github.com/LekoArts/gatsby-themes/blob/main/themes/gatsby-theme-minimal-blog/src/components/post.tsx) there's also a `` component that you can shadow to display elements between the end of the post and the global footer. By default it returns `null`. Create a file at `src/@lekoarts/gatsby-theme-minimal-blog/components/post-footer.jsx` to edit this section. The `` component receives the complete `post` prop that `` also receives. -### Changing your fonts - -By default, the underlying theme and thus this starter uses "IBM Plex Sans" as its font. It's used throughout the site and set as a `font-family` on the `html` element. - -If you want to change your default font or add any additional fonts, you'll need to change two things: - -1. The configuration for `gatsby-omni-font-loader` => Responsible for loading the font CSS files -1. The Theme UI config and its `fonts` key (see [Theme UI Typography Docs](https://theme-ui.com/theming#typography)) => Responsible for setting the `font-family` in the example - -After adjusting the configuration for `gatsby-omni-font-loader` you'll need to shadow the theme's Theme UI config and overwrite the `fonts` key. For the sake of this explanation it's assumed that you replaced "IBM Plex Sans" with "Roboto Mono". - -Create a file at `src/gatsby-plugin-theme-ui/index.js` with the following contents: - -```js -import { merge } from "theme-ui"; -import originalTheme from "@lekoarts/gatsby-theme-minimal-blog/src/gatsby-plugin-theme-ui/index"; - -const theme = merge(originalTheme, { - fonts: { - body: `"Roboto Mono", monospace`, - }, -}); - -export default theme; -``` - -As defined in the [Theme Specification](https://theme-ui.com/theme-spec#typography) `body` is the default body font family. - -**Another example:** You didn't replace "IBM Plex Sans" but added "Roboto Mono" additionally since you want to use it for your headings. - -Then you'd not overwrite `body` but add a `heading` key: - -```js -import { merge } from "theme-ui"; -import originalTheme from "@lekoarts/gatsby-theme-minimal-blog/src/gatsby-plugin-theme-ui/index"; - -const theme = merge(originalTheme, { - fonts: { - heading: `"Roboto Mono", monospace`, - }, -}); - -export default theme; -``` - ### Change your `static` folder The `static` folder contains the icons, social media images and `robots.txt`. Don't forget to change these files, too! You can use [Real Favicon Generator](https://realfavicongenerator.net/) to generate the image files inside `static`. diff --git a/examples/minimal-blog/content/posts/fantastic-beasts-and-where-to-find-them/SpotifyPlayer.js b/examples/minimal-blog/content/posts/code-block-examples/SpotifyPlayer.js similarity index 100% rename from examples/minimal-blog/content/posts/fantastic-beasts-and-where-to-find-them/SpotifyPlayer.js rename to examples/minimal-blog/content/posts/code-block-examples/SpotifyPlayer.js diff --git a/examples/minimal-blog/content/posts/fantastic-beasts-and-where-to-find-them/index.mdx b/examples/minimal-blog/content/posts/code-block-examples/index.mdx similarity index 80% rename from examples/minimal-blog/content/posts/fantastic-beasts-and-where-to-find-them/index.mdx rename to examples/minimal-blog/content/posts/code-block-examples/index.mdx index 541876639..82081dd06 100755 --- a/examples/minimal-blog/content/posts/fantastic-beasts-and-where-to-find-them/index.mdx +++ b/examples/minimal-blog/content/posts/code-block-examples/index.mdx @@ -1,8 +1,8 @@ --- -title: Fantastic Beasts and Where to Find Them -date: 2019-11-01 +title: Code Block Examples +date: 2022-09-11 tags: - - Novel + - Code --- import SpotifyPlayer from "./SpotifyPlayer"; @@ -16,15 +16,6 @@ Here will a React component go: view="list" /> -Here will a live code example go: - -```js react-live -const onClick = () => { - alert("You opened me"); -}; -render(); -``` - Here will a normal code block go: ```js @@ -38,14 +29,14 @@ var dependencies = {}; var treeURL = 'https://api.github.com/repos/PrismJS/prism/git/trees/gh-pages?recursive=1'; var treePromise = new Promise(function(resolve) { - $u.xhr({ - url: treeURL, - callback: function(xhr) { - if (xhr.status < 400) { - resolve(JSON.parse(xhr.responseText).tree); - } - } - }); + $u.xhr({ + url: treeURL, + callback: function(xhr) { + if (xhr.status < 400) { + resolve(JSON.parse(xhr.responseText).tree); + } + } + }); }); ``` @@ -100,7 +91,7 @@ export default Layout Code block with code highlighting: -```jsx:title=src/components/post.jsx {5-7,10} +```jsx title=src/components/post.jsx highlight=5-7,10 import * as React from "react"; const Post = ({ data: { post } }) => ( @@ -145,33 +136,33 @@ Code block without title: Harry Potter and the Philosopher's Stone ``` -Code block without lineNumbers (but lang): +Code block with lineNumbers (and lang): -```text noLineNumbers +```text withLineNumbers Harry Potter and the Chamber of Secrets ``` -Code block without lineNumbers (and without lang): +Code block with lineNumbers (and without lang): -```noLineNumbers +```none withLineNumbers Harry Potter and the Chamber of Secrets ``` Code block with only the title: -```:title=src/utils/scream.js +```none title=src/utils/scream.js const scream = (input) => window.alert(input) ``` -Code block with only the title but without lineNumbers: +Code block with only the title and with lineNumbers: -```:title=src/utils/scream.js noLineNumbers +```none title=src/utils/scream.js withLineNumbers const scream = (input) => window.alert(input) ``` Line highlighting without code title: -```js {2,4-5} +```js highlight=2,4-5 const test = 3; const foo = "bar"; const harry = "potter"; @@ -181,9 +172,9 @@ const ron = "weasley"; Here will `inline code` go, just inside the text. Wow! -Code block without line numbers but with highlighting, language, and title: +Code block with line numbers, highlighting, language, and title: -```tsx:title=src/components/blog.tsx {7-9,16} noLineNumbers +```tsx title=src/components/blog.tsx highlight=7-9,16 withLineNumbers import * as React from "react"; const Blog = ({ posts }: PostsProps) => { diff --git a/examples/minimal-blog/content/posts/harry-potter-and-the-half-blood-prince/index.mdx b/examples/minimal-blog/content/posts/harry-potter-and-the-half-blood-prince/index.mdx deleted file mode 100644 index 928dc221d..000000000 --- a/examples/minimal-blog/content/posts/harry-potter-and-the-half-blood-prince/index.mdx +++ /dev/null @@ -1,210 +0,0 @@ ---- -title: Harry Potter and the Half-Blood Prince -date: 2019-09-01 -tags: - - Novel - - Highlight ---- - -| Number | Title | Year | -| ------ | ---------------------------------------- | ---: | -| 1 | Harry Potter and the Philosopher’s Stone | 2001 | -| 2 | Harry Potter and the Chamber of Secrets | 2002 | -| 3 | Harry Potter and the Prisoner of Azkaban | 2004 | - -[View raw (TEST.md)](https://raw.github.com/adamschwartz/github-markdown-kitchen-sink/master/README.md) - -This is a paragraph. - - This is a paragraph. - -# Header 1 - -## Header 2 - - Header 1 - ======== - - Header 2 - -------- - -# Header 1 - -## Header 2 - -### Header 3 - -#### Header 4 - -##### Header 5 - -###### Header 6 - - # Header 1 - ## Header 2 - ### Header 3 - #### Header 4 - ##### Header 5 - ###### Header 6 - -# Header 1 - -## Header 2 - -### Header 3 - -#### Header 4 - -##### Header 5 - -###### Header 6 - - # Header 1 # - ## Header 2 ## - ### Header 3 ### - #### Header 4 #### - ##### Header 5 ##### - ###### Header 6 ###### - -> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. - - > Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. - -> ## This is a header. -> -> 1. This is the first list item. -> 2. This is the second list item. -> -> Here's some example code: -> -> Markdown.generate(); - - > ## This is a header. - > 1. This is the first list item. - > 2. This is the second list item. - > - > Here's some example code: - > - > Markdown.generate(); - -- Red -- Green -- Blue - -* Red -* Green -* Blue - -- Red -- Green -- Blue - -```markdown -- Red -- Green -- Blue - -* Red -* Green -* Blue - -- Red -- Green -- Blue -``` - -- `code goes` here in this line -- **bold** goes here - -```markdown -- `code goes` here in this line -- **bold** goes here -``` - -1. Buy flour and salt -1. Mix together with water -1. Bake - -```markdown -1. Buy flour and salt -1. Mix together with water -1. Bake -``` - -1. `code goes` here in this line -1. **bold** goes here - -```markdown -1. `code goes` here in this line -1. **bold** goes here -``` - -Paragraph: - - Code - - - - Paragraph: - - Code - ---- - ---- - ---- - ---- - ---- - - * * * - - *** - - ***** - - - - - - - --------------------------------------- - -This is [an example](http://example.com "Example") link. - -[This link](http://example.com) has no title attr. - -This is [an example][id] reference-style link. - -[id]: http://example.com "Optional Title" - - This is [an example](http://example.com "Example") link. - - [This link](http://example.com) has no title attr. - - This is [an example] [id] reference-style link. - - [id]: http://example.com "Optional Title" - -_single asterisks_ - -_single underscores_ - -**double asterisks** - -**double underscores** - - *single asterisks* - - _single underscores_ - - **double asterisks** - - __double underscores__ - -This paragraph has some `code` in it. - - This paragraph has some `code` in it. - -![Alt Text](https://placehold.it/200x50 "Image Title") - - ![Alt Text](https://placehold.it/200x50 "Image Title") diff --git a/examples/minimal-blog/content/posts/markdown-reference/index.mdx b/examples/minimal-blog/content/posts/markdown-reference/index.mdx new file mode 100644 index 000000000..891f3ccb4 --- /dev/null +++ b/examples/minimal-blog/content/posts/markdown-reference/index.mdx @@ -0,0 +1,162 @@ +--- +title: Markdown Reference +date: 2022-09-12 +tags: + - Code + - Markdown +--- + +## What to expect from here on out + +What follows from here is just a bunch of absolute nonsense I've written to dogfood the plugin itself. It includes every sensible typographic element I could think of, like **bold text**, unordered lists, ordered lists, code blocks, block quotes, _and even italics_. + +It's important to cover all of these use cases for a few reasons: + +1. We want everything to look good out of the box. +2. Really just the first reason, that's the whole point of the plugin. +3. Here's a third pretend reason though a list with three items looks more realistic than a list with two items. + +Now we're going to try out another header style. + +### Typography should be easy + +So that's a header for you — with any luck if we've done our job correctly that will look pretty reasonable. + +Something a wise person once told me about typography is: + +> Typography is pretty important if you don't want your stuff to look like trash. Make it good then it won't be bad. + +It's probably important that images look okay here by default as well: + +![](https://images.unsplash.com/photo-1556740758-90de374c12ad?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1000&q=80) + +Now I'm going to show you an example of an unordered list to make sure that looks good, too: + +- So here is the first item in this list. +- In this example we're keeping the items short. +- Later, we'll use longer, more complex list items. + +And that's the end of this section. + +## What if we stack headings? + +### We should make sure that looks good, too. + +Sometimes you have headings directly underneath each other. In those cases you often have to undo the top margin on the second heading because it usually looks better for the headings to be closer together than a paragraph followed by a heading should be. + +### When a heading comes after a paragraph … + +When a heading comes after a paragraph, we need a bit more space, like I already mentioned above. Now let's see what a more complex list would look like. + +- **I often do this thing where list items have headings.** + + For some reason I think this looks cool which is unfortunate because it's pretty annoying to get the styles right. + + I often have two or three paragraphs in these list items, too, so the hard part is getting the spacing between the paragraphs, list item heading, and separate list items to all make sense. Pretty tough honestly, you could make a strong argument that you just shouldn't write this way. + +- **Since this is a list, I need at least two items.** + + I explained what I'm doing already in the previous list item, but a list wouldn't be a list if it only had one item, and we really want this to look realistic. That's why I've added this second list item so I actually have something to look at when writing the styles. + +- **It's not a bad idea to add a third item either.** + + I think it probably would've been fine to just use two items but three is definitely not worse, and since I seem to be having no trouble making up arbitrary things to type, I might as well include it. + +After this sort of list I usually have a closing statement or paragraph, because it kinda looks weird jumping right to a heading. + +## Code should look okay by default. + +I think most people are going to use [highlight.js](https://highlightjs.org/) or [Prism](https://prismjs.com/) or something if they want to style their code blocks but it wouldn't hurt to make them look _okay_ out of the box, even with no syntax highlighting. + +Here's what a default `tailwind.config.js` file looks like at the time of writing: + +```js +module.exports = { + purge: [], + theme: { + extend: {}, + }, + variants: {}, + plugins: [], +}; +``` + +Hopefully that looks good enough to you. + +### What about nested lists? + +Nested lists basically always look bad which is why editors like Medium don't even let you do it, but I guess since some of you goofballs are going to do it we have to carry the burden of at least making it work. + +1. **Nested lists are rarely a good idea.** + - You might feel like you are being really "organized" or something but you are just creating a gross shape on the screen that is hard to read. + - Nested navigation in UIs is a bad idea too, keep things as flat as possible. + - Nesting tons of folders in your source code is also not helpful. +2. **Since we need to have more items, here's another one.** + - I'm not sure if we'll bother styling more than two levels deep. + - Two is already too much, three is guaranteed to be a bad idea. + - If you nest four levels deep you belong in prison. +3. **Two items isn't really a list, three is good though.** + - Again please don't nest lists if you want people to actually read your content. + - Nobody wants to look at this. + - I'm upset that we even have to bother styling this. + +The most annoying thing about lists in Markdown is that `

  • ` elements aren't given a child `

    ` tag unless there are multiple paragraphs in the list item. That means I have to worry about styling that annoying situation too. + +- **For example, here's another nested list.** + + But this time with a second paragraph. + + - These list items won't have `

    ` tags + - Because they are only one line each + +- **But in this second top-level list item, they will.** + + This is especially annoying because of the spacing on this paragraph. + + - As you can see here, because I've added a second line, this list item now has a `

    ` tag. + + This is the second line I'm talking about by the way. + + - Finally here's another list item so it's more like a list. + +- A closing list item, but with no nested list, because why not? + +And finally a sentence to close off this section. + +## There are other elements we need to style + +I almost forgot to mention links, like [this link to the Tailwind CSS website](https://tailwindcss.com). We almost made them blue but that's so yesterday, so we went with dark gray, feels edgier. + +We even included table styles, check it out: + +| Wrestler | Origin | Finisher | +| ----------------------- | ------------ | ------------------ | +| Bret "The Hitman" Hart | Calgary, AB | Sharpshooter | +| Stone Cold Steve Austin | Austin, TX | Stone Cold Stunner | +| Randy Savage | Sarasota, FL | Elbow Drop | +| Vader | Boulder, CO | Vader Bomb | +| Razor Ramon | Chuluota, FL | Razor's Edge | + +We also need to make sure inline code looks good, like if I wanted to talk about `` elements or tell you the good news about `@tailwindcss/typography`. + +### Sometimes I even use `code` in headings + +Even though it's probably a bad idea, and historically I've had a hard time making it look good. This _"wrap the code blocks in backticks"_ trick works pretty well though really. + +Another thing I've done in the past is put a `code` tag inside of a link, like if I wanted to tell you about the [`tailwindcss/docs`](https://github.com/tailwindcss/docs) repository. I don't love that there is an underline below the backticks but it is absolutely not worth the madness it would require to avoid it. + +#### We haven't used an `h4` yet + +But now we have. Please don't use `h5` or `h6` in your content, Medium only supports two heading levels for a reason, you animals. I honestly considered using a `before` pseudo-element to scream at you if you use an `h5` or `h6`. + +We don't style them at all out of the box because `h4` elements are already so small that they are the same size as the body copy. What are we supposed to do with an `h5`, make it _smaller_ than the body copy? No thanks. + +### We still need to think about stacked headings though. + +#### Let's make sure we don't screw that up with `h4` elements, either. + +Phew, with any luck we have styled the headings above this text and they look pretty good. + +Let's add a closing paragraph here so things end with a decently sized block of text. I can't explain why I want things to end that way but I have to assume it's because I think things will look weird or unbalanced if there is a heading too close to the end of the document. + +What I've written here is probably long enough, but adding this final sentence can't hurt. diff --git a/examples/minimal-blog/content/posts/curses-and-counter-courses/index.mdx b/examples/minimal-blog/content/posts/normal-text/index.mdx similarity index 82% rename from examples/minimal-blog/content/posts/curses-and-counter-courses/index.mdx rename to examples/minimal-blog/content/posts/normal-text/index.mdx index a2f09f1dd..524db57ee 100644 --- a/examples/minimal-blog/content/posts/curses-and-counter-courses/index.mdx +++ b/examples/minimal-blog/content/posts/normal-text/index.mdx @@ -1,8 +1,8 @@ --- -title: "Curses and Counter-curses (Bewitch Your Friends and Befuddle Your Enemies with the Latest Revenges: Hair Loss, Jelly-Legs, Tongue-Tying, and Much, Much More)" -date: 2019-10-25 -slug: "/curses-counter-curses-and-more" -canonicalUrl: "https://random-blog-about-curses.com" +title: "Normal Text" +date: 2022-09-10 +slug: "/normal-text-override" +canonicalUrl: "https://blog-about-normal-text.com" --- Thestral dirigible plums, Viktor Krum hexed memory charm Animagus Invisibility Cloak three-headed Dog. Half-Blood Prince Invisibility Cloak cauldron cakes, hiya Harry! Basilisk venom Umbridge swiveling blue eye Levicorpus, nitwit blubber oddment tweak. Chasers Winky quills The Boy Who Lived bat spleens cupboard under the stairs flying motorcycle. Sirius Black Holyhead Harpies, you’ve got dirt on your nose. Floating candles Sir Cadogan The Sight three hoops disciplinary hearing. Grindlewald pig’s tail Sorcerer's Stone biting teacup. Side-along dragon-scale suits Filch 20 points, Mr. Potter. diff --git a/examples/minimal-blog/content/posts/introduction-to-defence-against-the-dark-arts/defence-against-the-dark-arts.jpg b/examples/minimal-blog/content/posts/with-images/defence-against-the-dark-arts.jpg similarity index 100% rename from examples/minimal-blog/content/posts/introduction-to-defence-against-the-dark-arts/defence-against-the-dark-arts.jpg rename to examples/minimal-blog/content/posts/with-images/defence-against-the-dark-arts.jpg diff --git a/examples/minimal-blog/content/posts/introduction-to-defence-against-the-dark-arts/index.mdx b/examples/minimal-blog/content/posts/with-images/index.mdx similarity index 97% rename from examples/minimal-blog/content/posts/introduction-to-defence-against-the-dark-arts/index.mdx rename to examples/minimal-blog/content/posts/with-images/index.mdx index 7874932d6..053c890ed 100644 --- a/examples/minimal-blog/content/posts/introduction-to-defence-against-the-dark-arts/index.mdx +++ b/examples/minimal-blog/content/posts/with-images/index.mdx @@ -1,10 +1,9 @@ --- -title: Introduction to "Defence against the Dark Arts" -date: 2019-11-07 +title: With Images +date: 2022-09-17 description: Defence Against the Dark Arts (abbreviated as DADA) is a subject taught at Hogwarts School of Witchcraft and Wizardry and Ilvermorny School of Witchcraft and Wizardry. In this class, students study and learn how to defend themselves against all aspects of the Dark Arts, including dark creatures, curses, hexes and jinxes (dark charms), and duelling. tags: - Tutorial - - Dark Arts banner: ./defence-against-the-dark-arts.jpg --- diff --git a/examples/minimal-blog/content/posts/introduction-to-defence-against-the-dark-arts/potions.jpg b/examples/minimal-blog/content/posts/with-images/potions.jpg similarity index 100% rename from examples/minimal-blog/content/posts/introduction-to-defence-against-the-dark-arts/potions.jpg rename to examples/minimal-blog/content/posts/with-images/potions.jpg diff --git a/examples/minimal-blog/gatsby-config.js b/examples/minimal-blog/gatsby-config.js index 9f4f612b6..90b691a59 100755 --- a/examples/minimal-blog/gatsby-config.js +++ b/examples/minimal-blog/gatsby-config.js @@ -2,6 +2,9 @@ require(`dotenv`).config() const shouldAnalyseBundle = process.env.ANALYSE_BUNDLE +/** + * @type {import('gatsby').GatsbyConfig} + */ module.exports = { siteMetadata: { // You can overwrite values here that are used for the SEO component @@ -12,7 +15,6 @@ module.exports = { siteHeadline: `Minimal Blog - Gatsby Theme from @lekoarts`, siteUrl: `https://minimal-blog.lekoarts.de`, siteDescription: `Typography driven, feature-rich blogging theme with minimal aesthetics. Includes tags/categories support and extensive features for code blocks such as live preview, line numbers, and line highlighting.`, - siteLanguage: `en`, siteImage: `/banner.jpg`, author: `@lekoarts_de`, }, @@ -43,21 +45,6 @@ module.exports = { ], }, }, - { - resolve: `gatsby-omni-font-loader`, - options: { - enableListener: true, - preconnect: [`https://fonts.gstatic.com`], - // If you plan on changing the font you'll also need to adjust the Theme UI config to edit the CSS - // See: https://github.com/LekoArts/gatsby-themes/tree/main/examples/minimal-blog#changing-your-fonts - web: [ - { - name: `IBM Plex Sans`, - file: `https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600;700&display=swap`, - }, - ], - }, - }, { resolve: `gatsby-plugin-sitemap`, options: { @@ -139,7 +126,6 @@ module.exports = { ], }, }, - `gatsby-plugin-gatsby-cloud`, shouldAnalyseBundle && { resolve: `gatsby-plugin-webpack-bundle-analyser-v2`, options: { diff --git a/examples/minimal-blog/gatsby-ssr.js b/examples/minimal-blog/gatsby-ssr.js new file mode 100644 index 000000000..466c3ff5b --- /dev/null +++ b/examples/minimal-blog/gatsby-ssr.js @@ -0,0 +1,3 @@ +export const onRenderBody = ({ setHtmlAttributes }) => { + setHtmlAttributes({ lang: `en` }) +} diff --git a/examples/minimal-blog/package.json b/examples/minimal-blog/package.json index d709030c8..79709481c 100755 --- a/examples/minimal-blog/package.json +++ b/examples/minimal-blog/package.json @@ -17,15 +17,14 @@ }, "dependencies": { "@lekoarts/gatsby-theme-minimal-blog": "^4.0.0", - "gatsby": "^4.18.2", - "gatsby-omni-font-loader": "^2.0.0", - "gatsby-plugin-feed": "^4.18.1", - "gatsby-plugin-gatsby-cloud": "^4.18.1", - "gatsby-plugin-manifest": "^4.18.1", - "gatsby-plugin-sitemap": "^5.18.1", + "gatsby": "^4.24.1", + "gatsby-plugin-feed": "^4.24.0", + "gatsby-plugin-manifest": "^4.24.0", + "gatsby-plugin-sitemap": "^5.24.0", "gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.27", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-helmet": "^6.1.0" }, "devDependencies": { "cross-env": "^7.0.3" diff --git a/examples/minimal-blog/src/@lekoarts/gatsby-theme-minimal-blog/texts/hero.mdx b/examples/minimal-blog/src/@lekoarts/gatsby-theme-minimal-blog/texts/hero.mdx index 79a8a9515..fc6d560f1 100644 --- a/examples/minimal-blog/src/@lekoarts/gatsby-theme-minimal-blog/texts/hero.mdx +++ b/examples/minimal-blog/src/@lekoarts/gatsby-theme-minimal-blog/texts/hero.mdx @@ -1,5 +1,6 @@ - - Hi. - + I'm LekoArts, your theme creator. I'm passionate about open source & teaching. Learn more about Gatsby & React on [my website](https://www.lekoarts.de?utm_source=minimal-blog&utm_medium=Starter). diff --git a/examples/specimens/README.md b/examples/specimens/README.md index 8eaf2c832..c34862421 100755 --- a/examples/specimens/README.md +++ b/examples/specimens/README.md @@ -46,19 +46,16 @@ Also be sure to check out other [Free & Open Source Gatsby Themes](https://theme ### 1. **Create a Gatsby site.** -Use `git` to clone the site and navigate into it: +Use the Gatsby CLI to clone the site and install dependencies: ```sh -git clone https://github.com/LekoArts/gatsby-starter-specimens project-name -cd project-name +npx gatsby new gatsby-starter-specimens https://github.com/LekoArts/gatsby-starter-specimens ``` -### 2. **Install dependencies.** - -If you use npm 7 or above use the `--legacy-peer-deps` flag. If you use npm 6 you can use `npm install`. +### 2. **Navigate to your new project.** ```sh -npm install --legacy-peer-deps +cd gatsby-starter-specimens ``` ### 3. **Open the code and start customizing!** diff --git a/examples/specimens/gatsby-browser.js b/examples/specimens/gatsby-browser.js deleted file mode 100755 index 224e6d692..000000000 --- a/examples/specimens/gatsby-browser.js +++ /dev/null @@ -1,4 +0,0 @@ -import * as React from "react" -import { WrapPageElement } from "./src/components/wrapPageElement" - -export const wrapPageElement = ({ element }) => diff --git a/examples/specimens/gatsby-config.js b/examples/specimens/gatsby-config.js index 22c6c45cb..04422f478 100755 --- a/examples/specimens/gatsby-config.js +++ b/examples/specimens/gatsby-config.js @@ -1,8 +1,12 @@ -// eslint-disable-next-line global-require -const remarkPlugins = [require(`remark-slug`)] +const remarkGfm = require(`remark-gfm`) +const remarkSlug = require(`remark-slug`) +const rehypeMetaAsAttributes = require(`@lekoarts/rehype-meta-as-attributes`) const shouldAnalyseBundle = process.env.ANALYSE_BUNDLE +/** + * @type {import('gatsby').GatsbyConfig} + */ module.exports = { siteMetadata: { siteTitle: `Specimens for Design Systems - @lekoarts/gatsby-theme-specimens`, @@ -28,13 +32,13 @@ module.exports = { { resolve: `gatsby-plugin-mdx`, options: { - lessBabel: true, - extensions: [`.mdx`], - remarkPlugins, + mdxOptions: { + remarkPlugins: [remarkGfm, remarkSlug], + rehypePlugins: [rehypeMetaAsAttributes], + }, }, }, `gatsby-plugin-catch-links`, - `gatsby-plugin-react-helmet`, `gatsby-plugin-theme-ui`, { resolve: `gatsby-plugin-manifest`, @@ -62,7 +66,6 @@ module.exports = { ], }, }, - `gatsby-plugin-gatsby-cloud`, shouldAnalyseBundle && { resolve: `gatsby-plugin-webpack-bundle-analyser-v2`, options: { diff --git a/examples/specimens/gatsby-ssr.js b/examples/specimens/gatsby-ssr.js index 224e6d692..466c3ff5b 100755 --- a/examples/specimens/gatsby-ssr.js +++ b/examples/specimens/gatsby-ssr.js @@ -1,4 +1,3 @@ -import * as React from "react" -import { WrapPageElement } from "./src/components/wrapPageElement" - -export const wrapPageElement = ({ element }) => +export const onRenderBody = ({ setHtmlAttributes }) => { + setHtmlAttributes({ lang: `en` }) +} diff --git a/examples/specimens/package.json b/examples/specimens/package.json index 011a1e30f..6ff4cdf84 100755 --- a/examples/specimens/package.json +++ b/examples/specimens/package.json @@ -16,27 +16,28 @@ "clean": "gatsby clean" }, "dependencies": { + "@emotion/react": "^11.10.4", "@lekoarts/gatsby-theme-specimens": "^4.0.0", + "@lekoarts/rehype-meta-as-attributes": "^0.0.1", + "@lekoarts/themes-utils": "^0.0.1", "@loadable/component": "^5.15.2", - "@mdx-js/mdx": "^1.6.22", - "@theme-ui/presets": "^0.11.1", - "gatsby": "^4.18.2", - "gatsby-plugin-catch-links": "^4.18.0", - "gatsby-plugin-gatsby-cloud": "^4.18.1", - "gatsby-plugin-manifest": "^4.18.1", - "gatsby-plugin-mdx": "^3.18.1", - "gatsby-plugin-react-helmet": "^5.18.0", - "gatsby-plugin-theme-ui": "^0.9.1", + "@mdx-js/react": "^2.1.3", + "@theme-ui/mdx": "^0.15.1", + "@theme-ui/presets": "^0.15.1", + "gatsby": "^4.24.1", + "gatsby-plugin-catch-links": "^4.24.0", + "gatsby-plugin-manifest": "^4.24.0", + "gatsby-plugin-mdx": "^4.3.0", + "gatsby-plugin-theme-ui": "^0.15.1", "gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.27", - "gatsby-source-filesystem": "^4.18.1", - "mdx-utils": "^0.2.0", + "gatsby-source-filesystem": "^4.24.0", "prism-react-renderer": "^1.3.5", - "react": "^18.0.0", - "react-dom": "^18.0.0", - "react-helmet": "^6.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", "react-live": "^2.4.1", - "remark-slug": "^6.1.0", - "theme-ui": "^0.11.1" + "remark-gfm": "^1", + "remark-slug": "^6", + "theme-ui": "^0.15.1" }, "devDependencies": { "cross-env": "^7.0.3" diff --git a/examples/specimens/src/components/code.js b/examples/specimens/src/components/code.jsx similarity index 53% rename from examples/specimens/src/components/code.js rename to examples/specimens/src/components/code.jsx index 82fdc327e..c0ac50876 100755 --- a/examples/specimens/src/components/code.js +++ b/examples/specimens/src/components/code.jsx @@ -3,9 +3,9 @@ import { jsx } from "theme-ui" import Highlight, { defaultProps } from "prism-react-renderer" import theme from "prism-react-renderer/themes/vsDark" -import loadable from "@loadable/component" -import { useMDXScope } from "gatsby-plugin-mdx/context" +import { LiveProvider, LiveEditor, LiveError, LivePreview } from "react-live" import { useMDXComponents } from "@mdx-js/react" +import { normalizeThemeUIColors, filterStyles } from "@lekoarts/gatsby-theme-specimens" const badgeStyle = { marginBottom: `0.5rem`, @@ -19,34 +19,59 @@ const badgeStyle = { letterSpacing: `0.05em`, } -const LazyLiveProvider = loadable(async () => { - const Module = await import(`react-live`) - const { LiveProvider, LiveEditor, LiveError, LivePreview } = Module - return (props) => ( - -

    Editor
    - - -
    Preview
    - - - ) -}) - const Code = ({ codeString, language, live, noInline }) => { - const imported = useMDXScope() - const defined = useMDXComponents() - - delete defined.delete + const { + Alert, + Audio, + BorderRadius, + ColorFamilies, + ColorRow, + ColorSwatch, + Download, + FontFamily, + FontSize, + FontWeight, + Heading, + Palette, + Shadow, + Space, + Table, + Video, + } = useMDXComponents() if (live) { return ( - + scope={{ + Alert, + Audio, + BorderRadius, + ColorFamilies, + ColorRow, + ColorSwatch, + Download, + FontFamily, + FontSize, + FontWeight, + Heading, + Palette, + Shadow, + Space, + Table, + Video, + normalizeThemeUIColors, + filterStyles, + }} + > +
    Editor
    + + +
    Preview
    + + ) } return ( diff --git a/examples/specimens/src/components/layout.js b/examples/specimens/src/components/layout.js deleted file mode 100755 index d63cbaa95..000000000 --- a/examples/specimens/src/components/layout.js +++ /dev/null @@ -1,81 +0,0 @@ -import * as React from "react" -import { useStaticQuery, graphql } from "gatsby" -import { Global } from "@emotion/react" -import { Helmet } from "react-helmet" - -const Layout = ({ children }) => { - const { site } = useStaticQuery(graphql` - { - site { - siteMetadata { - banner - siteDescription - siteTitle - siteUrl - } - } - } - `) - - const meta = site.siteMetadata - - return ( - - - - {meta.siteTitle} - - - - - - - - - - - - - - - ({ - "*": { - boxSizing: `border-box`, - }, - html: { fontSize: `16px`, WebkitTextSizeAdjust: `100%` }, - body: { border: `0`, margin: `0`, padding: `0` }, - "h1, h2, h3, h4, h5, h6": { - marginTop: `2rem !important`, - marginBottom: `1rem !important`, - }, - h3: { marginTop: `6rem !important` }, - ".sizes-table": { - "> div:not(:first-of-type)": { - paddingTop: `0.5rem !important`, - paddingBottom: `0.5rem !important`, - }, - }, - pre: { - padding: `0.75rem`, - borderRadius: `0.25rem`, - fontSize: `1rem`, - overflow: `auto`, - }, - code: { - backgroundColor: `rgb(30, 30, 30)`, - color: `white`, - padding: `0.25rem 0.5rem`, - borderRadius: `0.25rem`, - fontSize: `1rem`, - marginLeft: `0.25rem`, - marginRight: `0.25rem`, - }, - })} - /> -
    {children}
    -
    - ) -} - -export default Layout diff --git a/examples/specimens/src/components/layout.jsx b/examples/specimens/src/components/layout.jsx new file mode 100755 index 000000000..b621aa839 --- /dev/null +++ b/examples/specimens/src/components/layout.jsx @@ -0,0 +1,43 @@ +import * as React from "react" +import { Global } from "@emotion/react" +import { MDXProvider } from "@mdx-js/react" +import MdxComponents from "./mdx-components" + +const Layout = ({ children }) => ( + + ({ + "*": { + boxSizing: `border-box`, + }, + html: { fontSize: `16px`, WebkitTextSizeAdjust: `100%` }, + body: { border: `0`, margin: `0`, padding: `0` }, + "h1, h2, h3, h4, h5, h6": { + marginTop: `2rem !important`, + marginBottom: `1rem !important`, + }, + h3: { marginTop: `4rem !important` }, + ".sizes-table": { + "> div:not(:first-of-type)": { + paddingTop: `0.5rem !important`, + paddingBottom: `0.5rem !important`, + }, + }, + pre: { + padding: `0.75rem`, + borderRadius: `0.25rem`, + overflow: `auto`, + }, + code: { + padding: `0.25rem 0.5rem`, + borderRadius: `0.25rem`, + marginLeft: `0.25rem`, + marginRight: `0.25rem`, + }, + })} + /> +
    {children}
    +
    +) + +export default Layout diff --git a/examples/specimens/src/components/mdx-components.jsx b/examples/specimens/src/components/mdx-components.jsx new file mode 100644 index 000000000..0140da4e4 --- /dev/null +++ b/examples/specimens/src/components/mdx-components.jsx @@ -0,0 +1,105 @@ +/** @jsx jsx */ +import { jsx } from "theme-ui" +import { preToCodeBlock } from "@lekoarts/themes-utils" +import { + Alert, + Audio, + BorderRadius, + ColorFamilies, + ColorRow, + ColorSwatch, + Download, + FontFamily, + FontSize, + FontWeight, + Heading, + Palette, + Shadow, + Space, + Table, + Video, +} from "@lekoarts/gatsby-theme-specimens" +import Code from "./code" + +const headingProps = { + h1: { + variant: `text.display`, + }, + h2: { + variant: `text.heading`, + fontSize: 5, + }, + h3: { + variant: `text.heading`, + fontSize: 4, + }, + h4: { + variant: `text.heading`, + fontSize: 3, + }, + h5: { + variant: `text.heading`, + fontSize: 2, + }, + h6: { + variant: `text.heading`, + fontSize: 1, + }, +} + +const heading = (Tag) => (props) => { + const { id, children } = props + return id ? ( + + + {children} + + + ) : ( + + ) +} + +const MdxComponents = { + Alert, + Audio, + BorderRadius, + ColorFamilies, + ColorRow, + ColorSwatch, + Download, + FontFamily, + FontSize, + FontWeight, + Heading, + Palette, + Shadow, + Space, + Table, + Video, + h2: heading(`h2`), + h3: heading(`h3`), + h4: heading(`h4`), + h5: heading(`h5`), + h6: heading(`h6`), + pre: (preProps) => { + const props = preToCodeBlock(preProps) + // if there's a codeString and some props, we passed the test + if (props) { + return + } + // it's possible to have a pre without a code in it + return
    +  },
    +}
    +
    +export default MdxComponents
    diff --git a/examples/specimens/src/components/seo.jsx b/examples/specimens/src/components/seo.jsx
    new file mode 100644
    index 000000000..f3870108c
    --- /dev/null
    +++ b/examples/specimens/src/components/seo.jsx
    @@ -0,0 +1,40 @@
    +import * as React from "react"
    +import { useStaticQuery, graphql } from "gatsby"
    +
    +const Seo = () => {
    +  const { site } = useStaticQuery(graphql`
    +    {
    +      site {
    +        siteMetadata {
    +          banner
    +          siteDescription
    +          siteTitle
    +          siteUrl
    +        }
    +      }
    +    }
    +  `)
    +
    +  const meta = site.siteMetadata
    +
    +  return (
    +    <>
    +      {meta.siteTitle}
    +      
    +      
    +      
    +      
    +      
    +      
    +      
    +      
    +      
    +      
    +      
    +      
    +      
    +    
    +  )
    +}
    +
    +export default Seo
    diff --git a/examples/specimens/src/components/table-of-contents.js b/examples/specimens/src/components/table-of-contents.jsx
    similarity index 66%
    rename from examples/specimens/src/components/table-of-contents.js
    rename to examples/specimens/src/components/table-of-contents.jsx
    index bfae8f37d..84844eaed 100755
    --- a/examples/specimens/src/components/table-of-contents.js
    +++ b/examples/specimens/src/components/table-of-contents.jsx
    @@ -1,17 +1,19 @@
     import * as React from "react"
    -import { Themed } from "theme-ui"
    +import { Themed } from "@theme-ui/mdx"
     import { useStaticQuery, graphql } from "gatsby"
     
     const TableOfContents = () => {
       const result = useStaticQuery(graphql`
         query {
    -      mdx(fileAbsolutePath: { regex: "/index.mdx/" }) {
    -        tableOfContents
    +      file(name: { eq: "index" }) {
    +        childMdx {
    +          tableOfContents
    +        }
           }
         }
       `)
     
    -  const toc = result.mdx.tableOfContents.items[0].items[2].items || false
    +  const toc = result.file.childMdx.tableOfContents.items[0].items[2].items || false
     
       return (
         
      diff --git a/examples/specimens/src/components/wrapPageElement.js b/examples/specimens/src/components/wrapPageElement.js deleted file mode 100755 index 53226ee97..000000000 --- a/examples/specimens/src/components/wrapPageElement.js +++ /dev/null @@ -1,4 +0,0 @@ -import * as React from "react" -import Layout from "./layout" - -export const WrapPageElement = ({ element }) => {element} diff --git a/examples/specimens/src/gatsby-plugin-theme-ui/components.js b/examples/specimens/src/gatsby-plugin-theme-ui/components.js deleted file mode 100755 index 37acabaa1..000000000 --- a/examples/specimens/src/gatsby-plugin-theme-ui/components.js +++ /dev/null @@ -1,100 +0,0 @@ -/* eslint-disable react/display-name */ -/* eslint-disable react/destructuring-assignment */ - -/** @jsx jsx */ -import { jsx } from "theme-ui" -import * as React from "react" -import { - Alert, - Audio, - BorderRadius, - ColorFamilies, - ColorRow, - ColorSwatch, - Download, - FontFamily, - FontSize, - FontWeight, - Heading, - Palette, - Shadow, - Space, - Table, - Video, -} from "@lekoarts/gatsby-theme-specimens" -import { preToCodeBlock } from "mdx-utils" -import Code from "../components/code" - -const heading = (Tag) => (props) => - props.id ? ( - - - {props.children} - - - ) : ( - - ) - -const shortcodes = { - Alert: ({ type, children }) => {children}, - Audio: ({ autoplay, loop, name, desc, src }) => ( -
  • + + +) export default Index +export const Head = ({ + data: { + config: { + siteMetadata: { siteDescription, siteName, siteUrl }, + }, + }, +}) => ( + <> + {siteName} + + + + + + + + + + + + + + +) + export const query = graphql` query IndexQuery { config: site { diff --git a/examples/styleguide/README.md b/examples/styleguide/README.md index 6f4f2e5e0..bdde02257 100755 --- a/examples/styleguide/README.md +++ b/examples/styleguide/README.md @@ -40,19 +40,16 @@ Also be sure to check out other [Free & Open Source Gatsby Themes](https://theme ### 1. **Create a Gatsby site.** -Use `git` to clone the site and navigate into it: +Use the Gatsby CLI to clone the site and install dependencies: ```sh -git clone https://github.com/LekoArts/gatsby-starter-styleguide project-name -cd project-name +npx gatsby new gatsby-starter-styleguide https://github.com/LekoArts/gatsby-starter-styleguide ``` -### 2. **Install dependencies.** - -If you use npm 7 or above use the `--legacy-peer-deps` flag. If you use npm 6 you can use `npm install`. +### 2. **Navigate to your new project.** ```sh -npm install --legacy-peer-deps +cd gatsby-starter-styleguide ``` ### 3. **Open the code and start customizing!** diff --git a/examples/styleguide/gatsby-config.js b/examples/styleguide/gatsby-config.js index 20df8a791..98c1e4872 100755 --- a/examples/styleguide/gatsby-config.js +++ b/examples/styleguide/gatsby-config.js @@ -2,6 +2,9 @@ require(`dotenv`).config() const shouldAnalyseBundle = process.env.ANALYSE_BUNDLE +/** + * @type {import('gatsby').GatsbyConfig} + */ module.exports = { siteMetadata: { siteTitle: `Styleguide`, @@ -9,7 +12,6 @@ module.exports = { siteHeadline: `Styleguide - Gatsby Theme from @lekoarts`, siteUrl: `https://theme-ui-styleguide.netlify.com`, siteDescription: `Instantly create a styleguide page based on your Theme UI configuration. Zero-config — just install the theme and see your Theme UI config displayed in a beautiful manner.`, - siteLanguage: `en`, siteImage: `/banner.jpg`, author: `@lekoarts_de`, }, @@ -22,7 +24,6 @@ module.exports = { basePath: `/`, }, }, - `gatsby-plugin-gatsby-cloud`, shouldAnalyseBundle && { resolve: `gatsby-plugin-webpack-bundle-analyser-v2`, options: { diff --git a/examples/styleguide/gatsby-ssr.js b/examples/styleguide/gatsby-ssr.js new file mode 100644 index 000000000..1a0b17ccc --- /dev/null +++ b/examples/styleguide/gatsby-ssr.js @@ -0,0 +1,3 @@ +exports.onRenderBody = ({ setHtmlAttributes }) => { + setHtmlAttributes({ lang: `en` }) +} diff --git a/examples/styleguide/package.json b/examples/styleguide/package.json index 4a2199c0e..19cf27686 100755 --- a/examples/styleguide/package.json +++ b/examples/styleguide/package.json @@ -16,16 +16,15 @@ "clean": "gatsby clean" }, "dependencies": { + "@emotion/react": "^11.10.4", "@lekoarts/gatsby-theme-styleguide": "^3.0.0", - "gatsby": "^4.18.2", - "gatsby-plugin-gatsby-cloud": "^4.18.1", - "gatsby-plugin-react-helmet": "^5.18.0", - "gatsby-plugin-theme-ui": "^0.9.1", + "@theme-ui/mdx": "^0.15.1", + "gatsby": "^4.24.1", + "gatsby-plugin-theme-ui": "^0.15.1", "gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.27", - "react": "^18.0.0", - "react-dom": "^18.0.0", - "react-helmet": "^6.1.0", - "theme-ui": "^0.11.1" + "react": "^18.2.0", + "react-dom": "^18.2.0", + "theme-ui": "^0.15.1" }, "devDependencies": { "cross-env": "^7.0.3" diff --git a/examples/styleguide/src/@lekoarts/gatsby-theme-styleguide/layout.jsx b/examples/styleguide/src/@lekoarts/gatsby-theme-styleguide/layout.jsx index a2b518f0f..f477eecb4 100755 --- a/examples/styleguide/src/@lekoarts/gatsby-theme-styleguide/layout.jsx +++ b/examples/styleguide/src/@lekoarts/gatsby-theme-styleguide/layout.jsx @@ -2,7 +2,6 @@ import * as React from "react" import { jsx } from "theme-ui" import { Global } from "@emotion/react" -import Seo from "../../components/seo" const Layout = ({ children }) => ( @@ -25,7 +24,6 @@ const Layout = ({ children }) => ( }, })} /> -
    {children}
    ) diff --git a/examples/styleguide/src/@lekoarts/gatsby-theme-styleguide/template.jsx b/examples/styleguide/src/@lekoarts/gatsby-theme-styleguide/template.jsx new file mode 100644 index 000000000..a6b7a2032 --- /dev/null +++ b/examples/styleguide/src/@lekoarts/gatsby-theme-styleguide/template.jsx @@ -0,0 +1,7 @@ +import * as React from "react" +import ThemeTemplate from "@lekoarts/gatsby-theme-styleguide/src/template" +import Seo from "../../components/seo" + +export default ThemeTemplate + +export const Head = () => diff --git a/examples/styleguide/src/components/seo.jsx b/examples/styleguide/src/components/seo.jsx index 5018a1b36..aea1dbb93 100755 --- a/examples/styleguide/src/components/seo.jsx +++ b/examples/styleguide/src/components/seo.jsx @@ -1,9 +1,8 @@ import * as React from "react" -import { Helmet } from "react-helmet" import { withPrefix } from "gatsby" import useSiteMetadata from "../hooks/use-site-metadata" -const Seo = ({ title = ``, description = false, pathname = false, image = false, children = null }) => { +const Seo = ({ title = ``, description = ``, pathname = ``, image = ``, children = null, canonicalUrl = `` }) => { const site = useSiteMetadata() const { @@ -11,20 +10,23 @@ const Seo = ({ title = ``, description = false, pathname = false, image = false, siteTitleAlt: defaultTitle, siteUrl, siteDescription: defaultDescription, - siteLanguage, siteImage: defaultImage, author, } = site const seo = { - title: title || defaultTitle, + title: title ? `${title} | ${siteTitle}` : defaultTitle, description: description || defaultDescription, url: `${siteUrl}${pathname || ``}`, image: `${siteUrl}${image || defaultImage}`, } return ( - - + <> + {seo.title} + @@ -44,8 +46,9 @@ const Seo = ({ title = ``, description = false, pathname = false, image = false, + {canonicalUrl ? : null} {children} - + ) } diff --git a/examples/styleguide/src/gatsby-plugin-theme-ui/index.js b/examples/styleguide/src/gatsby-plugin-theme-ui/index.js index 175f6325d..d43bd5f03 100644 --- a/examples/styleguide/src/gatsby-plugin-theme-ui/index.js +++ b/examples/styleguide/src/gatsby-plugin-theme-ui/index.js @@ -1,7 +1,7 @@ // Based on https://github.com/tailwindcss/tailwindcss/blob/master/stubs/defaultConfig.stub.js // and https://tailwindcss.com/components -const borderWidths = { +export const borderWidths = { px: `1px`, 0: `0`, 2: `2px`, @@ -9,57 +9,138 @@ const borderWidths = { 8: `8px`, } -const breakpoints = [`640px`, `768px`, `1024px`, `1280px`] +export const breakpoints = [`640px`, `758px`, `1024px`, `1280px`] -const baseColors = { +export const baseColors = { + transparent: `transparent`, black: `#000`, white: `#fff`, - gray: [null, `#f7fafc`, `#edf2f7`, `#e2e8f0`, `#cbd5e0`, `#a0aec0`, `#718096`, `#4a5568`, `#2d3748`, `#1a202c`], - red: [null, `#fff5f5`, `#fed7d7`, `#feb2b2`, `#fc8181`, `#f56565`, `#e53e3e`, `#c53030`, `#9b2c2c`, `#742a2a`], - blue: [null, `#ebf8ff`, `#bee3f8`, `#90cdf4`, `#63b3ed`, `#4299e1`, `#3182ce`, `#2b6cb0`, `#2c5282`, `#2a4365`], + gray: { + 50: `#f9fafb`, + 100: `#f3f4f6`, + 200: `#e5e7eb`, + 300: `#d1d5db`, + 400: `#9ca3af`, + 500: `#6b7280`, + 600: `#4b5563`, + 700: `#374151`, + 800: `#1f2937`, + 900: `#111827`, + }, + red: { + 50: `#fef2f2`, + 100: `#fee2e2`, + 200: `#fecaca`, + 300: `#fca5a5`, + 400: `#f87171`, + 500: `#ef4444`, + 600: `#dc2626`, + 700: `#b91c1c`, + 800: `#991b1b`, + 900: `#7f1d1d`, + }, + orange: { + 50: `#fff7ed`, + 100: `#ffedd5`, + 200: `#fed7aa`, + 300: `#fdba74`, + 400: `#fb923c`, + 500: `#f97316`, + 600: `#ea580c`, + 700: `#c2410c`, + 800: `#9a3412`, + 900: `#7c2d12`, + }, + green: { + 50: `#f0fdf4`, + 100: `#dcfce7`, + 200: `#bbf7d0`, + 300: `#86efac`, + 400: `#4ade80`, + 500: `#22c55e`, + 600: `#16a34a`, + 700: `#15803d`, + 800: `#166534`, + 900: `#14532d`, + }, + blue: { + 50: `#eff6ff`, + 100: `#dbeafe`, + 200: `#bfdbfe`, + 300: `#93c5fd`, + 400: `#60a5fa`, + 500: `#3b82f6`, + 600: `#2563eb`, + 700: `#1d4ed8`, + 800: `#1e40af`, + 900: `#1e3a8a`, + }, + indigo: [ + `#eef2ff`, + `#e0e7ff`, + `#c7d2fe`, + `#a5b4fc`, + `#818cf8`, + `#6366f1`, + `#4f46e5`, + `#4338ca`, + `#3730a3`, + `#312e81`, + ], } -const colors = { +export const colors = { ...baseColors, - text: baseColors.gray[8], + grayDark: baseColors.gray[800], + text: baseColors.gray[800], background: baseColors.white, - primary: baseColors.blue[7], - secondary: baseColors.gray[6], - muted: baseColors.gray[3], - info: baseColors.blue[4], - danger: baseColors.red[3], + primary: baseColors.blue[700], + primaryHover: baseColors.blue[800], + secondary: baseColors.gray[600], + muted: baseColors.gray[300], + success: baseColors.green[300], + info: baseColors.blue[400], + warning: baseColors.orange[300], + danger: baseColors.red[300], + light: baseColors.gray[100], + dark: baseColors.gray[800], + textMuted: baseColors.gray[600], } -const baseFonts = { +export const baseFonts = { sans: `-apple-system, BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"`, serif: `Georgia, Cambria, "Times New Roman", Times, serif`, mono: `Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace`, } -const fonts = { +export const fonts = { ...baseFonts, body: baseFonts.sans, heading: `inherit`, monospace: baseFonts.mono, } -const fontSizes = [`0.875rem`, `1rem`, `1.25rem`, `1.5rem`, `1.875rem`, `2.25rem`, `3rem`] +export const fontSizes = [`0.875rem`, `1rem`, `1.25rem`, `1.5rem`, `1.875rem`, `2.25rem`, `3rem`, `4rem`, `4.5rem`] -const baseFontWeights = { +export const baseFontWeights = { + hairline: `100`, + thin: `200`, light: `300`, normal: `400`, medium: `500`, + semibold: `600`, bold: `700`, + extrabold: `800`, black: `900`, } -const fontWeights = { +export const fontWeights = { ...baseFontWeights, body: baseFontWeights.normal, heading: baseFontWeights.bold, } -const letterSpacings = { +export const letterSpacings = { tighter: `-0.05em`, tight: `-0.025em`, normal: `0`, @@ -68,7 +149,7 @@ const letterSpacings = { widest: `0.1em`, } -const baseLineHeights = { +export const baseLineHeights = { none: `1`, tight: `1.25`, snug: `1.375`, @@ -77,13 +158,13 @@ const baseLineHeights = { loose: `2`, } -const lineHeights = { +export const lineHeights = { ...baseLineHeights, body: baseLineHeights.relaxed, heading: baseLineHeights.tight, } -const radii = { +export const radii = { none: `0`, sm: `0.125rem`, default: `0.25rem`, @@ -91,7 +172,7 @@ const radii = { full: `9999px`, } -const sizes = { +export const sizes = { px: `1px`, 0: `0`, 1: `0.25rem`, @@ -107,12 +188,26 @@ const sizes = { 20: `5rem`, 24: `6rem`, 32: `8rem`, + 40: `10rem`, + 48: `12rem`, + 56: `14rem`, + 64: `16rem`, + xs: `20rem`, + sm: `24rem`, + md: `28rem`, + lg: `32rem`, + xl: `36rem`, + "2xl": `42rem`, + "3xl": `48rem`, + "4xl": `56rem`, + "5xl": `64rem`, + "6xl": `72rem`, full: `100%`, screenHeight: `100vh`, screenWidth: `100vw`, } -const shadows = { +export const shadows = { default: `0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)`, md: `0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)`, lg: `0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)`, @@ -123,9 +218,9 @@ const shadows = { none: `none`, } -const space = [0, `0.25rem`, `0.5rem`, `1rem`, `2rem`, `4rem`, `8rem`, `16rem`] +export const space = [0, `0.25rem`, `0.5rem`, `1rem`, `2rem`, `4rem`, `8rem`, `16rem`, `32rem`] -const zIndices = { +export const zIndices = { auto: `auto`, 0: `0`, 10: `10`, @@ -143,7 +238,7 @@ const heading = { mb: 1, } -const styles = { +export const styles = { root: { fontFamily: `body`, lineHeight: `body`, @@ -185,7 +280,7 @@ const styles = { }, } -const tailwind = { +export const theme = { borderWidths, breakpoints, colors, @@ -202,4 +297,4 @@ const tailwind = { styles, } -export default tailwind +export default theme diff --git a/examples/styleguide/src/hooks/use-site-metadata.jsx b/examples/styleguide/src/hooks/use-site-metadata.jsx index d991daec0..f9e0194a2 100644 --- a/examples/styleguide/src/hooks/use-site-metadata.jsx +++ b/examples/styleguide/src/hooks/use-site-metadata.jsx @@ -10,7 +10,6 @@ const useSiteMetadata = () => { siteHeadline siteUrl siteDescription - siteLanguage siteImage author } diff --git a/lint-staged.config.js b/lint-staged.config.js index 3ea2ea80b..5c067a0d2 100644 --- a/lint-staged.config.js +++ b/lint-staged.config.js @@ -1,4 +1,4 @@ module.exports = { - "*.{js,ts,tsx}": [`eslint --ignore-path .gitignore --ignore-path .prettierignore --fix`], + "*.{js,ts,tsx,mdx}": [`eslint --ignore-path .gitignore --ignore-path .prettierignore --fix`], "*.{md,mdx,json,yaml}": [`prettier "**/*.{md,mdx,json,yaml}" --write`], } diff --git a/package.json b/package.json index d6495d6f0..a7c0d1dc6 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,13 @@ "author": "LekoArts ", "workspaces": [ "themes/*", - "examples/*" + "examples/*", + "packages/*" ], "scripts": { "typecheck": "tsc --noEmit", "typecheck:ci": "tsc -p tsconfig.ci.json --noEmit", - "lint": "eslint . --ignore-path .gitignore --ignore-path .prettierignore --ext .ts,.tsx,.js", + "lint": "eslint . --ignore-path .gitignore --ignore-path .prettierignore --ext .ts,.tsx,.js,.mdx", "lint:fix": "yarn lint --fix", "format": "prettier \"**/*.{md,mdx,json,yaml}\" --write", "test:watch": "vitest watch", @@ -35,10 +36,9 @@ "@testing-library/react": "^13.4.0", "@types/chroma-js": "^2.1.4", "@types/loadable__component": "^5.13.4", - "@types/node": "^17.0.23", + "@types/node": "^18.7.23", "@types/react": "^18.0.21", "@types/react-dom": "^18.0.6", - "@types/react-helmet": "^6.1.5", "@types/styled-system": "^5.1.15", "@types/styled-system__css": "^5.0.17", "@types/three": "^0.144.0", @@ -47,19 +47,20 @@ "c8": "^7.12.0", "cross-env": "^7.0.3", "cypress": "^10.9.0", - "eslint": "^8.21.0", + "eslint": "^8.24.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-prettier": "^8.5.0", "eslint-plugin-import": "^2.26.0", "eslint-plugin-jsx-a11y": "^6.6.1", + "eslint-plugin-mdx": "^2.0.5", "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-react": "^7.30.1", + "eslint-plugin-react": "^7.31.8", "eslint-plugin-react-hooks": "^4.6.0", "fs-extra": "^10.1.0", "gatsby-cypress": "^2.24.0", "glob": "^8.0.3", + "happy-dom": "^6.0.4", "husky": "^8.0.1", - "jsdom": "^20.0.0", "lint-staged": "^13.0.3", "plop": "^3.1.1", "prettier": "^2.7.1", @@ -68,10 +69,7 @@ "vitest": "^0.23.4" }, "resolutions": { - "cypress": "^10.9.0", - "@emotion/react": "^11.10.4", - "@mdx-js/mdx": "^1.6.22", - "@mdx-js/react": "^1.6.22" + "cypress": "^10.9.0" }, "packageManager": "yarn@3.2.3" } diff --git a/packages/rehype-meta-as-attributes/README.md b/packages/rehype-meta-as-attributes/README.md new file mode 100644 index 000000000..eefe1eb8a --- /dev/null +++ b/packages/rehype-meta-as-attributes/README.md @@ -0,0 +1,13 @@ +# @lekoarts/rehype-meta-as-attributes + +Adds code block meta to the `node.properties`. + +```` +```js title=hello hightlight +const hello = "world" +``` +```` + +Is turned into `title: "hello"` and `highlight: true`. + +You can access those in e.g. React then in the `props` of `
    ` tags.
    diff --git a/packages/rehype-meta-as-attributes/index.js b/packages/rehype-meta-as-attributes/index.js
    new file mode 100644
    index 000000000..029043795
    --- /dev/null
    +++ b/packages/rehype-meta-as-attributes/index.js
    @@ -0,0 +1,23 @@
    +/* eslint-disable no-cond-assign */
    +const visit = require(`unist-util-visit`)
    +
    +const re = /\b([-\w]+)(?:=(?:"([^"]*)"|'([^']*)'|([^"'\s]+)))?/g
    +
    +/** @type {import('unified').Plugin, import('hast').Root>} */
    +function rehypeMetaAsAttributes() {
    +  return (tree) => {
    +    visit(tree, `element`, (node) => {
    +      let match
    +
    +      if (node.tagName === `code` && node.data && node.data.meta) {
    +        re.lastIndex = 0 // Reset regex.
    +
    +        while ((match = re.exec(node.data.meta))) {
    +          node.properties[match[1]] = match[2] || match[3] || match[4] || true
    +        }
    +      }
    +    })
    +  }
    +}
    +
    +module.exports = rehypeMetaAsAttributes
    diff --git a/packages/rehype-meta-as-attributes/package.json b/packages/rehype-meta-as-attributes/package.json
    new file mode 100644
    index 000000000..a7f9ca8e3
    --- /dev/null
    +++ b/packages/rehype-meta-as-attributes/package.json
    @@ -0,0 +1,29 @@
    +{
    +  "name": "@lekoarts/rehype-meta-as-attributes",
    +  "description": "Pass MDX metadata as prop to React components",
    +  "version": "0.0.1",
    +  "main": "index.js",
    +  "author": "LekoArts",
    +  "license": "MIT",
    +  "publishConfig": {
    +    "access": "public"
    +  },
    +  "files": [
    +    "index.js"
    +  ],
    +  "dependencies": {
    +    "unist-util-visit": "^2.0.3"
    +  },
    +  "bugs": {
    +    "url": "https://github.com/LekoArts/gatsby-themes/issues"
    +  },
    +  "homepage": "https://themes.lekoarts.de",
    +  "repository": {
    +    "type": "git",
    +    "url": "https://github.com/LekoArts/gatsby-themes.git",
    +    "directory": "packages/rehype-meta-as-attributes"
    +  },
    +  "engines": {
    +    "node": ">=14.15.0"
    +  }
    +}
    diff --git a/packages/themes-utils/README.md b/packages/themes-utils/README.md
    new file mode 100644
    index 000000000..acaefb9ae
    --- /dev/null
    +++ b/packages/themes-utils/README.md
    @@ -0,0 +1,3 @@
    +# @lekoarts/themes-utils
    +
    +Utilities to build [themes.lekoarts.de](https://themes.lekoarts.de).
    diff --git a/packages/themes-utils/index.js b/packages/themes-utils/index.js
    new file mode 100644
    index 000000000..d4e724877
    --- /dev/null
    +++ b/packages/themes-utils/index.js
    @@ -0,0 +1,49 @@
    +const kebabCase = require(`lodash.kebabcase`)
    +
    +const getLanguage = (className) => className.split(`language-`).pop()
    +
    +const preToCodeBlock = (preProps) => {
    +  const { children: codeString, className = ``, ...props } = preProps.children.props
    +
    +  const match = className.match(/language-([\0-\uFFFF]*)/)
    +  return {
    +    codeString: codeString.trim(),
    +    className,
    +    language: match !== null ? match[1] : ``,
    +    ...props,
    +  }
    +}
    +
    +const calculateLinesToHighlight = (meta) => {
    +  if (!meta) {
    +    return () => false
    +  }
    +  const lineNumbers = meta.split(`,`).map((v) => v.split(`-`).map((x) => parseInt(x, 10)))
    +  return (index) => {
    +    const lineNumber = index + 1
    +    return lineNumbers.some(([start, end]) => (end ? lineNumber >= start && lineNumber <= end : lineNumber === start))
    +  }
    +}
    +
    +const mdxResolverPassthrough = (fieldName) => async (source, args, context, info) => {
    +  const type = info.schema.getType(`Mdx`)
    +  const mdxNode = context.nodeModel.getNodeById({
    +    id: source.parent,
    +  })
    +  const resolver = type.getFields()[fieldName].resolve
    +  const result = await resolver(mdxNode, args, context, info)
    +  return result
    +}
    +
    +const slugify = (source, basePath) => {
    +  const slug = source.slug ? source.slug : kebabCase(source.title)
    +
    +  return `/${basePath}/${slug}`.replace(/\/\/+/g, `/`)
    +}
    +
    +exports.getLanguage = getLanguage
    +exports.preToCodeBlock = preToCodeBlock
    +exports.calculateLinesToHighlight = calculateLinesToHighlight
    +exports.mdxResolverPassthrough = mdxResolverPassthrough
    +exports.slugify = slugify
    +exports.kebabCase = kebabCase
    diff --git a/packages/themes-utils/package.json b/packages/themes-utils/package.json
    new file mode 100644
    index 000000000..bf263cf5c
    --- /dev/null
    +++ b/packages/themes-utils/package.json
    @@ -0,0 +1,29 @@
    +{
    +  "name": "@lekoarts/themes-utils",
    +  "description": "Utilities to build my themes",
    +  "version": "0.0.1",
    +  "main": "index.js",
    +  "author": "LekoArts",
    +  "license": "MIT",
    +  "publishConfig": {
    +    "access": "public"
    +  },
    +  "files": [
    +    "index.js"
    +  ],
    +  "dependencies": {
    +    "lodash.kebabcase": "^4.1.1"
    +  },
    +  "bugs": {
    +    "url": "https://github.com/LekoArts/gatsby-themes/issues"
    +  },
    +  "homepage": "https://themes.lekoarts.de",
    +  "repository": {
    +    "type": "git",
    +    "url": "https://github.com/LekoArts/gatsby-themes.git",
    +    "directory": "packages/rehype-meta-as-attributes"
    +  },
    +  "engines": {
    +    "node": ">=14.15.0"
    +  }
    +}
    diff --git a/plop-templates/cypress-test.ts.hbs b/plop-templates/cypress-test.ts.hbs
    index 6a2a14cca..3d75499d8 100644
    --- a/plop-templates/cypress-test.ts.hbs
    +++ b/plop-templates/cypress-test.ts.hbs
    @@ -1,6 +1,5 @@
    -/// 
     /// 
    -/// 
    +/// 
     
     describe(`gatsby-theme-{{kebabCase name}}`, () => {
       it(`should work`, () => {
    diff --git a/plop-templates/example/LICENSE.hbs b/plop-templates/example/LICENSE.hbs
    index 7f8f482c6..e09be3a8a 100644
    --- a/plop-templates/example/LICENSE.hbs
    +++ b/plop-templates/example/LICENSE.hbs
    @@ -1,6 +1,6 @@
     The BSD Zero Clause License (0BSD)
     
    -Copyright (c) 2020 LekoArts
    +Copyright (c) 2022 LekoArts
     
     Permission to use, copy, modify, and/or distribute this software for any
     purpose with or without fee is hereby granted.
    diff --git a/plop-templates/example/README.md.hbs b/plop-templates/example/README.md.hbs
    index 6e75a1812..efc7d0bcc 100755
    --- a/plop-templates/example/README.md.hbs
    +++ b/plop-templates/example/README.md.hbs
    @@ -41,7 +41,7 @@ Also, be sure to check out other [Free & Open Source Gatsby Themes](https://them
     Use the Gatsby CLI to create a new site, specifying this project
     
     ```sh
    -gatsby new project-name https://github.com/LekoArts/{{kebabCase starter-name}}
    +npx gatsby new {{kebabCase starter-name}} https://github.com/LekoArts/{{kebabCase starter-name}}
     ```
     
     2. **Start developing.**
    @@ -49,8 +49,7 @@ gatsby new project-name https://github.com/LekoArts/{{kebabCase starter-name}}
     Navigate into your new site's directory and start it up.
     
     ```sh
    -cd project-name
    -gatsby develop
    +npm run develop
     ```
     
     3. **Open the code and start customizing!**
    diff --git a/plop-templates/example/gatsby-config.js.hbs b/plop-templates/example/gatsby-config.ts.hbs
    similarity index 75%
    rename from plop-templates/example/gatsby-config.js.hbs
    rename to plop-templates/example/gatsby-config.ts.hbs
    index a9c2580e9..6c59bc9f2 100755
    --- a/plop-templates/example/gatsby-config.js.hbs
    +++ b/plop-templates/example/gatsby-config.ts.hbs
    @@ -1,6 +1,6 @@
    -require(`dotenv`).config()
    +import { GatsbyConfig } from "gatsby"
     
    -module.exports = {
    +const config: GatsbyConfig = {
       siteMetadata: {
         siteTitleAlt: `{{readme-name}} - TODO`,
       },
    @@ -9,12 +9,6 @@ module.exports = {
           resolve: `@lekoarts/gatsby-theme-{{kebabCase name}}`,
           options: {},
         },
    -    {
    -      resolve: `gatsby-plugin-google-analytics`,
    -      options: {
    -        trackingId: process.env.GOOGLE_ANALYTICS_ID,
    -      },
    -    },
         {
           resolve: `gatsby-plugin-manifest`,
           options: {
    @@ -39,8 +33,7 @@ module.exports = {
             ],
           },
         },
    -    `gatsby-plugin-offline`,
    -    `gatsby-plugin-gatsby-cloud`,
    -    `gatsby-plugin-netlify`,
       ],
     }
    +
    +export default config
    diff --git a/plop-templates/example/index-page.js.hbs b/plop-templates/example/index-page.tsx.hbs
    similarity index 100%
    rename from plop-templates/example/index-page.js.hbs
    rename to plop-templates/example/index-page.tsx.hbs
    diff --git a/plop-templates/example/package.json.hbs b/plop-templates/example/package.json.hbs
    index 0c108d7c3..4f9809a60 100755
    --- a/plop-templates/example/package.json.hbs
    +++ b/plop-templates/example/package.json.hbs
    @@ -17,15 +17,12 @@
       },
       "dependencies": {
         "@lekoarts/gatsby-theme-{{kebabCase name}}": "*",
    -    "gatsby": "^3.0.0",
    -    "gatsby-plugin-google-analytics": "^^3.0.0",
    -    "gatsby-plugin-manifest": "^3.0.0",
    -    "gatsby-plugin-netlify": "^3.0.0",
    -    "gatsby-plugin-offline": "^3.0.0",
    -    "react": "^17.1.0",
    -    "react-dom": "^17.1.0"
    +    "gatsby": "^4.0.0",
    +    "gatsby-plugin-manifest": "^4.0.0",
    +    "react": "^18.0.0",
    +    "react-dom": "^18.0.0"
       },
       "devDependencies": {
    -    "cross-env": "^7.3.0"
    +    "cross-env": "^7.0.0"
       }
     }
    diff --git a/plop-templates/theme-core-parent/README.md.hbs b/plop-templates/theme-core-parent/README.md.hbs
    index 625270586..1cd191f7f 100755
    --- a/plop-templates/theme-core-parent/README.md.hbs
    +++ b/plop-templates/theme-core-parent/README.md.hbs
    @@ -48,10 +48,10 @@ npm install @lekoarts/gatsby-theme-{{kebabCase name}}
     
     ### Install as a starter
     
    -This will generate a new site that pre-configures use of the theme.
    +This will generate a new site that pre-configures the theme including example content and additional plugins.
     
     ```sh
    -gatsby new {{kebabCase name}} LekoArts/{{kebabCase starter-name}}
    +npx gatsby new {{kebabCase starter-name}} https://github.com/LekoArts/{{kebabCase starter-name}}
     ```
     
     [**View the starter's code**](https://github.com/LekoArts/{{kebabCase starter-name}})
    @@ -99,8 +99,6 @@ module.exports = {
         siteUrl: `https://{{kebabCase name}}.lekoarts.de`,
         // Used for SEO
         siteDescription: `TODO`,
    -    // Will be set on the html tag
    -    siteLanguage: `en`,
         // Used for og:image and must be placed inside the `static` folder
         siteImage: `/banner.jpg`,
         // Twitter Handle
    diff --git a/plop-templates/theme-core-parent/gatsby-config.js.hbs b/plop-templates/theme-core-parent/gatsby-config.js.hbs
    index c3875e7c5..d7c3e1b3f 100644
    --- a/plop-templates/theme-core-parent/gatsby-config.js.hbs
    +++ b/plop-templates/theme-core-parent/gatsby-config.js.hbs
    @@ -6,7 +6,6 @@ module.exports = (options) => {
           siteHeadline: `{{readme-name}} - Gatsby Theme from @lekoarts`,
           siteUrl: `https://{{kebabCase name}}.lekoarts.de`,
           siteDescription: `Stub description for {{kebabCase name}}`,
    -      siteLanguage: `en`,
           siteImage: `/banner.jpg`,
           author: `@lekoarts_de`,
         },
    @@ -15,7 +14,6 @@ module.exports = (options) => {
             resolve: `@lekoarts/gatsby-theme-{{kebabCase name}}-core`,
             options,
           },
    -      `gatsby-plugin-react-helmet`,
           `gatsby-plugin-theme-ui`,
         ].filter(Boolean),
       }
    diff --git a/plop-templates/theme-core-parent/gatsby-ssr.js.hbs b/plop-templates/theme-core-parent/gatsby-ssr.js.hbs
    new file mode 100644
    index 000000000..1a0b17ccc
    --- /dev/null
    +++ b/plop-templates/theme-core-parent/gatsby-ssr.js.hbs
    @@ -0,0 +1,3 @@
    +exports.onRenderBody = ({ setHtmlAttributes }) => {
    +  setHtmlAttributes({ lang: `en` })
    +}
    diff --git a/plop-templates/theme-core-parent/homepage-component.tsx.hbs b/plop-templates/theme-core-parent/homepage-component.tsx.hbs
    index a3965c836..4a555462d 100644
    --- a/plop-templates/theme-core-parent/homepage-component.tsx.hbs
    +++ b/plop-templates/theme-core-parent/homepage-component.tsx.hbs
    @@ -1,12 +1,13 @@
     /** @jsx jsx */
     import { jsx } from "theme-ui"
    +import type { HeadFC } from "gatsby"
    +import { Seo } from "./seo"
     
     type PostsProps = {
       TODO
     }
     
     const Homepage = ({ posts }: PostsProps) => {
    -
       return (
         
    {JSON.stringify(posts, null, 2)}
    @@ -14,4 +15,6 @@ const Homepage = ({ posts }: PostsProps) => { ) } -export default Homepage \ No newline at end of file +export default Homepage + +export const Head: HeadFC = () => \ No newline at end of file diff --git a/plop-templates/theme-core-parent/homepage.tsx.hbs b/plop-templates/theme-core-parent/homepage.tsx.hbs index 97ec6cc53..79efc03a4 100644 --- a/plop-templates/theme-core-parent/homepage.tsx.hbs +++ b/plop-templates/theme-core-parent/homepage.tsx.hbs @@ -1,5 +1,5 @@ import React from "react" -import Homepage from "../../../components/homepage" +import Homepage, { Head } from "../../../components/homepage" type Props = { data: { @@ -11,4 +11,6 @@ export default function MinimalBlogCoreHomepage({ data }: Props) { const { TODO } = data return -} \ No newline at end of file +} + +export { Head } \ No newline at end of file diff --git a/plop-templates/theme-core-parent/package.json.hbs b/plop-templates/theme-core-parent/package.json.hbs index fc8815fd8..501f7f4fb 100755 --- a/plop-templates/theme-core-parent/package.json.hbs +++ b/plop-templates/theme-core-parent/package.json.hbs @@ -15,17 +15,16 @@ "clean": "gatsby clean" }, "peerDependencies": { - "gatsby": "^3.0.0", - "react": "^17.1.0", - "react-dom": "^17.1.0" + "gatsby": "^4.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "dependencies": { "@lekoarts/gatsby-theme-{{kebabCase name}}-core": "^1.0.0", - "@theme-ui/presets": "^0.3.0", - "gatsby-plugin-react-helmet": "^4.0.0", - "gatsby-plugin-theme-ui": "^0.3.0", - "react-helmet": "^6.0.0", - "theme-ui": "^0.3.1" + "@theme-ui/mdx": "^0.15.0", + "@theme-ui/presets": "^0.15.0", + "gatsby-plugin-theme-ui": "^0.15.0", + "theme-ui": "^0.15.0" }, "keywords": [ "gatsby", diff --git a/plop-templates/theme-core-parent/seo.tsx.hbs b/plop-templates/theme-core-parent/seo.tsx.hbs index 62ed5f369..aeff83c94 100644 --- a/plop-templates/theme-core-parent/seo.tsx.hbs +++ b/plop-templates/theme-core-parent/seo.tsx.hbs @@ -1,5 +1,5 @@ import React from "react" -import { Helmet } from "react-helmet" +import { withPrefix } from "gatsby" import useSiteMetadata from "../hooks/use-site-metadata" type Props = { @@ -10,7 +10,7 @@ type Props = { children?: React.ReactNode } -const SEO = ({ title = ``, description = ``, pathname = ``, image = ``, children = null }: Props) => { +export const Seo = ({ title = ``, description = ``, pathname = ``, image = ``, children = null }: Props) => { const site = useSiteMetadata() const { @@ -18,20 +18,19 @@ const SEO = ({ title = ``, description = ``, pathname = ``, image = ``, children siteTitleAlt: defaultTitle, siteUrl, siteDescription: defaultDescription, - siteLanguage, siteImage: defaultImage, author, } = site const seo = { - title: title || defaultTitle, + title: title ? `${title} | ${siteTitle}` : defaultTitle, description: description || defaultDescription, url: `${siteUrl}${pathname || ``}`, image: `${siteUrl}${image || defaultImage}`, } return ( - - + <> + {seo.title} @@ -48,12 +47,10 @@ const SEO = ({ title = ``, description = ``, pathname = ``, image = ``, children - - - + + + {children} - + ) } - -export default SEO diff --git a/plop-templates/theme-core-parent/theme-ui.js.hbs b/plop-templates/theme-core-parent/theme-ui.js.hbs index f6975b993..0485b344a 100644 --- a/plop-templates/theme-core-parent/theme-ui.js.hbs +++ b/plop-templates/theme-core-parent/theme-ui.js.hbs @@ -2,8 +2,10 @@ import { merge } from "theme-ui" import { tailwind } from "@theme-ui/presets" const theme = merge(tailwind, { - initialColorModeName: `light`, - useCustomProperties: true, + config: { + initialColorModeName: `light`, + useColorSchemeMediaQuery: `system`, + }, colors: { primary: tailwind.colors.pink[7], secondary: tailwind.colors.indigo[6], diff --git a/plop-templates/theme-core-parent/use-site-metadata.tsx.hbs b/plop-templates/theme-core-parent/use-site-metadata.tsx.hbs index 14dfb7f78..362e4ac42 100644 --- a/plop-templates/theme-core-parent/use-site-metadata.tsx.hbs +++ b/plop-templates/theme-core-parent/use-site-metadata.tsx.hbs @@ -8,7 +8,6 @@ type Props = { siteHeadline: string siteUrl: string siteDescription: string - siteLanguage: string siteImage: string author: string [key: string]: unknown @@ -26,7 +25,6 @@ const useSiteMetadata = () => { siteHeadline siteUrl siteDescription - siteLanguage siteImage author } diff --git a/plop-templates/theme-core/homepage-query.tsx.hbs b/plop-templates/theme-core/homepage-query.tsx.hbs index cfc8ceaf6..07e19c410 100644 --- a/plop-templates/theme-core/homepage-query.tsx.hbs +++ b/plop-templates/theme-core/homepage-query.tsx.hbs @@ -1,8 +1,10 @@ import { graphql } from "gatsby" -import HomepageComponent from "../components/homepage" +import HomepageComponent, { Head } from "../components/homepage" export default HomepageComponent +export { Head } + export const query = graphql` query { ...queryGoesHere diff --git a/plop-templates/theme-core/homepage.tsx.hbs b/plop-templates/theme-core/homepage.tsx.hbs index 2767fb2ab..905225b64 100644 --- a/plop-templates/theme-core/homepage.tsx.hbs +++ b/plop-templates/theme-core/homepage.tsx.hbs @@ -2,4 +2,6 @@ import React from "react" export default function Homepage({ data }: { data: any }) { return
    {JSON.stringify(data, null, 2)}
    -} \ No newline at end of file +} + +export const Head = () => Homepage \ No newline at end of file diff --git a/plop-templates/theme-core/package.json.hbs b/plop-templates/theme-core/package.json.hbs index 0dce98eee..b38298371 100755 --- a/plop-templates/theme-core/package.json.hbs +++ b/plop-templates/theme-core/package.json.hbs @@ -15,14 +15,14 @@ "clean": "gatsby clean" }, "peerDependencies": { - "gatsby": "^3.0.0", - "react": "^17.1.0", - "react-dom": "^17.1.0" + "gatsby": "^4.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "dependencies": { - "gatsby-plugin-sharp": "^3.0.0", - "gatsby-source-filesystem": "^3.0.0", - "gatsby-transformer-sharp": "^3.0.0" + "gatsby-plugin-sharp": "^4.0.0", + "gatsby-source-filesystem": "^4.0.0", + "gatsby-transformer-sharp": "^4.0.0" }, "keywords": [ "gatsby", diff --git a/plop-templates/theme/README.md.hbs b/plop-templates/theme/README.md.hbs index 71dbdeeeb..f7de2e211 100755 --- a/plop-templates/theme/README.md.hbs +++ b/plop-templates/theme/README.md.hbs @@ -48,10 +48,10 @@ npm install @lekoarts/gatsby-theme-{{kebabCase name}} ### Install as a starter -This will generate a new site that pre-configures use of the theme. +This will generate a new site that pre-configures the theme including example content and additional plugins. ```sh -gatsby new {{kebabCase name}} LekoArts/{{kebabCase starter-name}} +npx gatsby new {{kebabCase starter-name}} https://github.com/LekoArts/{{kebabCase starter-name}} ``` [**View the starter's code**](https://github.com/LekoArts/{{kebabCase starter-name}}) @@ -99,8 +99,6 @@ module.exports = { siteUrl: `https://{{kebabCase name}}.lekoarts.de`, // Used for SEO siteDescription: `TODO`, - // Will be set on the html tag - siteLanguage: `en`, // Used for og:image and must be placed inside the `static` folder siteImage: `/banner.jpg`, // Twitter Handle diff --git a/plop-templates/theme/gatsby-config.js.hbs b/plop-templates/theme/gatsby-config.js.hbs index cfd51746d..ed3088528 100644 --- a/plop-templates/theme/gatsby-config.js.hbs +++ b/plop-templates/theme/gatsby-config.js.hbs @@ -5,12 +5,10 @@ module.exports = (themeOptions) => ({ siteHeadline: `{{readme-name}} - Gatsby Theme from @lekoarts`, siteUrl: `https://{{kebabCase name}}.lekoarts.de`, siteDescription: `Stub description for {{kebabCase name}}`, - siteLanguage: `en`, siteImage: `/banner.jpg`, author: `@lekoarts_de`, }, plugins: [ - `gatsby-plugin-react-helmet`, `gatsby-plugin-theme-ui`, ], }) diff --git a/plop-templates/theme/gatsby-ssr.js.hbs b/plop-templates/theme/gatsby-ssr.js.hbs new file mode 100644 index 000000000..1a0b17ccc --- /dev/null +++ b/plop-templates/theme/gatsby-ssr.js.hbs @@ -0,0 +1,3 @@ +exports.onRenderBody = ({ setHtmlAttributes }) => { + setHtmlAttributes({ lang: `en` }) +} diff --git a/plop-templates/theme/package.json.hbs b/plop-templates/theme/package.json.hbs index 8f4b3a0d4..ab6d4b77e 100755 --- a/plop-templates/theme/package.json.hbs +++ b/plop-templates/theme/package.json.hbs @@ -15,16 +15,15 @@ "clean": "gatsby clean" }, "peerDependencies": { - "gatsby": "^3.0.0", - "react": "^17.1.0", - "react-dom": "^17.1.0" + "gatsby": "^4.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "dependencies": { - "@theme-ui/presets": "^0.3.0", - "gatsby-plugin-react-helmet": "^3.3.2", - "gatsby-plugin-theme-ui": "^0.3.0", - "react-helmet": "^6.0.0", - "theme-ui": "^0.3.1" + "@theme-ui/mdx": "^0.15.0", + "@theme-ui/presets": "^0.15.0", + "gatsby-plugin-theme-ui": "^0.15.0", + "theme-ui": "^0.15.0" }, "keywords": [ "gatsby", diff --git a/plop-templates/theme/seo.tsx.hbs b/plop-templates/theme/seo.tsx.hbs index 8e891c084..90918ee32 100644 --- a/plop-templates/theme/seo.tsx.hbs +++ b/plop-templates/theme/seo.tsx.hbs @@ -1,5 +1,5 @@ import React from "react" -import { Helmet } from "react-helmet" +import { withPrefix } from "gatsby" import useSiteMetadata from "../hooks/use-site-metadata" type Props = { @@ -10,7 +10,7 @@ type Props = { children?: React.ReactNode } -const SEO = ({ title = ``, description = ``, pathname = ``, image = ``, children = null }: Props) => { +export const Seo = ({ title = ``, description = ``, pathname = ``, image = ``, children = null }: Props) => { const site = useSiteMetadata() const { @@ -18,20 +18,19 @@ const SEO = ({ title = ``, description = ``, pathname = ``, image = ``, children siteTitleAlt: defaultTitle, siteUrl, siteDescription: defaultDescription, - siteLanguage, siteImage: defaultImage, author, } = site const seo = { - title: title || defaultTitle, + title: title ? `${title} | ${siteTitle}` : defaultTitle, description: description || defaultDescription, url: `${siteUrl}${pathname || ``}`, image: `${siteUrl}${image || defaultImage}`, } return ( - - + <> + {seo.title} @@ -48,12 +47,10 @@ const SEO = ({ title = ``, description = ``, pathname = ``, image = ``, children - - - + + + {children} - + ) } - -export default SEO diff --git a/plop-templates/theme/theme-ui.js.hbs b/plop-templates/theme/theme-ui.js.hbs index b73d8a238..4f2da1f75 100755 --- a/plop-templates/theme/theme-ui.js.hbs +++ b/plop-templates/theme/theme-ui.js.hbs @@ -2,9 +2,9 @@ import { merge } from "theme-ui" import { tailwind } from "@theme-ui/presets" const theme = merge(tailwind, { - initialColorModeName: `light`, config: { - useCustomProperties: true, + initialColorModeName: `light`, + useColorSchemeMediaQuery: `system`, }, colors: { primary: tailwind.colors.pink[7], diff --git a/plop-templates/theme/use-site-metadata.tsx.hbs b/plop-templates/theme/use-site-metadata.tsx.hbs index 14dfb7f78..362e4ac42 100644 --- a/plop-templates/theme/use-site-metadata.tsx.hbs +++ b/plop-templates/theme/use-site-metadata.tsx.hbs @@ -8,7 +8,6 @@ type Props = { siteHeadline: string siteUrl: string siteDescription: string - siteLanguage: string siteImage: string author: string [key: string]: unknown @@ -26,7 +25,6 @@ const useSiteMetadata = () => { siteHeadline siteUrl siteDescription - siteLanguage siteImage author } diff --git a/plopfile.mjs b/plopfile.mjs index b57720c5c..b5f665146 100644 --- a/plopfile.mjs +++ b/plopfile.mjs @@ -27,6 +27,11 @@ const themeActions = [ path: `themes/gatsby-theme-{{kebabCase name}}/gatsby-config.js`, templateFile: `plop-templates/theme/gatsby-config.js.hbs`, }, + { + type: `add`, + path: `themes/gatsby-theme-{{kebabCase name}}/gatsby-ssr.js`, + templateFile: `plop-templates/theme/gatsby-ssr.js.hbs`, + }, { type: `add`, path: `themes/gatsby-theme-{{kebabCase name}}/index.js`, @@ -118,6 +123,11 @@ const themeCoreParentActions = [ path: `themes/gatsby-theme-{{kebabCase name}}/gatsby-config.js`, templateFile: `plop-templates/theme-core-parent/gatsby-config.js.hbs`, }, + { + type: `add`, + path: `themes/gatsby-theme-{{kebabCase name}}/gatsby-ssr.js`, + templateFile: `plop-templates/theme-core-parent/gatsby-ssr.js.hbs`, + }, { type: `add`, path: `themes/gatsby-theme-{{kebabCase name}}/src/@lekoarts/gatsby-theme-{{kebabCase name}}-core/components/homepage.tsx`, @@ -163,13 +173,13 @@ const themeCoreParentActions = [ const exampleActions = [ { type: `add`, - path: `examples/{{kebabCase name}}/gatsby-config.js`, - templateFile: `plop-templates/example/gatsby-config.js.hbs`, + path: `examples/{{kebabCase name}}/gatsby-config.ts`, + templateFile: `plop-templates/example/gatsby-config.ts.hbs`, }, { type: `add`, - path: `examples/{{kebabCase name}}/src/pages/index.js`, - templateFile: `plop-templates/example/index-page.js.hbs`, + path: `examples/{{kebabCase name}}/src/pages/index.tsx`, + templateFile: `plop-templates/example/index-page.tsx.hbs`, }, { type: `add`, diff --git a/themes/gatsby-theme-cara/README.md b/themes/gatsby-theme-cara/README.md index 7ff232bb7..9d5ddc42e 100755 --- a/themes/gatsby-theme-cara/README.md +++ b/themes/gatsby-theme-cara/README.md @@ -51,10 +51,10 @@ npm install @lekoarts/gatsby-theme-cara ### Install as a starter -This will generate a new site (with the folder name "cara") that pre-configures use of the theme including example content and additional plugins. +This will generate a new site that pre-configures the theme including example content and additional plugins. ```sh -gatsby new cara LekoArts/gatsby-starter-portfolio-cara +npx gatsby new gatsby-starter-portfolio-cara https://github.com/LekoArts/gatsby-starter-portfolio-cara ``` [**View the starter's code**](https://github.com/LekoArts/gatsby-starter-portfolio-cara) @@ -103,8 +103,6 @@ module.exports = { siteUrl: `https://cara.lekoarts.de`, // Used for SEO siteDescription: `Playful and Colorful One-Page portfolio featuring Parallax effects and animations`, - // Will be set on the tag - siteLanguage: `en`, // Used for og:image and must be placed inside the `static` folder siteImage: `/banner.jpg`, // Twitter Handle diff --git a/themes/gatsby-theme-cara/gatsby-config.js b/themes/gatsby-theme-cara/gatsby-config.js index ddd04b1d4..210b1c023 100755 --- a/themes/gatsby-theme-cara/gatsby-config.js +++ b/themes/gatsby-theme-cara/gatsby-config.js @@ -5,7 +5,6 @@ module.exports = ({ basePath = `/`, mdx = true }) => ({ siteHeadline: `Cara - Gatsby Theme from @lekoarts`, siteUrl: `https://cara.lekoarts.de`, siteDescription: `Playful and Colorful One-Page portfolio featuring Parallax effects and animations`, - siteLanguage: `en`, siteImage: `/banner.jpg`, author: `@lekoarts_de`, basePath, @@ -18,13 +17,17 @@ module.exports = ({ basePath = `/`, mdx = true }) => ({ path: `${__dirname}/src/sections`, }, }, - mdx && { - resolve: `gatsby-plugin-mdx`, + { + resolve: `gatsby-source-filesystem`, options: { - lessBabel: true, + name: `theme-overrides`, + path: `./src/@lekoarts/gatsby-theme-cara`, }, }, - `gatsby-plugin-react-helmet`, + mdx && { + resolve: `gatsby-plugin-mdx`, + options: {}, + }, `gatsby-plugin-theme-ui`, ].filter(Boolean), }) diff --git a/themes/gatsby-theme-cara/gatsby-ssr.js b/themes/gatsby-theme-cara/gatsby-ssr.js new file mode 100644 index 000000000..e3c066bd9 --- /dev/null +++ b/themes/gatsby-theme-cara/gatsby-ssr.js @@ -0,0 +1,5 @@ +import React from "react" + +export const onRenderBody = ({ setHeadComponents }) => { + setHeadComponents([]) +} diff --git a/themes/gatsby-theme-cara/package.json b/themes/gatsby-theme-cara/package.json index ef8d527cb..77bd6fe46 100755 --- a/themes/gatsby-theme-cara/package.json +++ b/themes/gatsby-theme-cara/package.json @@ -16,20 +16,20 @@ }, "peerDependencies": { "gatsby": "^4.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "dependencies": { - "@mdx-js/mdx": "^1.6.22", - "@react-spring/parallax": "^9.5.2", - "@react-spring/web": "^9.5.2", - "@theme-ui/presets": "^0.11.1", - "gatsby-plugin-mdx": "^3.20.0", - "gatsby-plugin-react-helmet": "^5.22.0", - "gatsby-plugin-theme-ui": "^0.11.1", - "gatsby-source-filesystem": "^4.22.0", - "react-helmet": "^6.1.0", - "theme-ui": "^0.11.1" + "@emotion/react": "^11.10.4", + "@mdx-js/react": "^2.1.3", + "@react-spring/parallax": "^9.5.5", + "@react-spring/web": "^9.5.5", + "@theme-ui/mdx": "^0.15.1", + "@theme-ui/presets": "^0.15.1", + "gatsby-plugin-mdx": "^4.3.0", + "gatsby-plugin-theme-ui": "^0.15.1", + "gatsby-source-filesystem": "^4.24.0", + "theme-ui": "^0.15.1" }, "keywords": [ "gatsby", diff --git a/themes/gatsby-theme-cara/src/components/about.tsx b/themes/gatsby-theme-cara/src/components/about.tsx index 297295b4c..0eb67067c 100755 --- a/themes/gatsby-theme-cara/src/components/about.tsx +++ b/themes/gatsby-theme-cara/src/components/about.tsx @@ -4,8 +4,7 @@ import Inner from "../elements/inner" import Content from "../elements/content" import Svg from "./svg" import { UpDown, UpDownWide } from "../styles/animations" -// @ts-ignore -import AboutMDX from "../sections/about" +import AboutMDX from "../sections/about.mdx" const About = ({ offset, factor = 1 }: { offset: number; factor?: number }) => (
    diff --git a/themes/gatsby-theme-cara/src/components/contact.tsx b/themes/gatsby-theme-cara/src/components/contact.tsx index 0db1c379c..ee9ec3f51 100755 --- a/themes/gatsby-theme-cara/src/components/contact.tsx +++ b/themes/gatsby-theme-cara/src/components/contact.tsx @@ -6,8 +6,7 @@ import Content from "../elements/content" import Svg from "./svg" import { UpDown, UpDownWide, waveAnimation } from "../styles/animations" import Footer from "./footer" -// @ts-ignore -import ContactMDX from "../sections/contact" +import ContactMDX from "../sections/contact.mdx" const Contact = ({ offset, factor = 1 }: { offset: number; factor?: number }) => (
    diff --git a/themes/gatsby-theme-cara/src/components/hero.tsx b/themes/gatsby-theme-cara/src/components/hero.tsx index 3bcf88a65..f8627d58b 100755 --- a/themes/gatsby-theme-cara/src/components/hero.tsx +++ b/themes/gatsby-theme-cara/src/components/hero.tsx @@ -5,14 +5,13 @@ import Inner from "../elements/inner" import Content from "../elements/content" import Svg from "./svg" import { UpDown, UpDownWide } from "../styles/animations" -// @ts-ignore -import Intro from "../sections/intro" +import Intro from "../sections/intro.mdx" const Hero = ({ offset, factor = 1 }: { offset: number; factor?: number }) => (
    - + diff --git a/themes/gatsby-theme-cara/src/components/layout.tsx b/themes/gatsby-theme-cara/src/components/layout.tsx index dfab2df00..6408b6f78 100755 --- a/themes/gatsby-theme-cara/src/components/layout.tsx +++ b/themes/gatsby-theme-cara/src/components/layout.tsx @@ -1,7 +1,8 @@ import * as React from "react" import { get } from "theme-ui" +import { MDXProvider } from "@mdx-js/react" import { Global } from "@emotion/react" -import SEO from "./seo" +import MdxComponents from "./mdx-components" type LayoutProps = { children: React.ReactNode; className?: string } @@ -38,8 +39,9 @@ const Layout = ({ children, className = `` }: LayoutProps) => ( }, })} /> - -
    {children}
    + +
    {children}
    +
    ) diff --git a/themes/gatsby-theme-cara/src/components/mdx-components.tsx b/themes/gatsby-theme-cara/src/components/mdx-components.tsx new file mode 100644 index 000000000..cfe128f3c --- /dev/null +++ b/themes/gatsby-theme-cara/src/components/mdx-components.tsx @@ -0,0 +1,12 @@ +import * as React from "react" +import ProjectCard from "./project-card" + +const MdxComponents = { + ProjectCard: ({ link, title, bg, children, ...props }: any) => ( + + {children} + + ), +} + +export default MdxComponents diff --git a/themes/gatsby-theme-cara/src/components/project-card.tsx b/themes/gatsby-theme-cara/src/components/project-card.tsx index f662dd6ca..a2e699730 100755 --- a/themes/gatsby-theme-cara/src/components/project-card.tsx +++ b/themes/gatsby-theme-cara/src/components/project-card.tsx @@ -31,7 +31,19 @@ const ProjectCard = ({ link, title, children, bg }: ProjectCardProps) => ( }, }} > -
    {children}
    +
    + {children} +
    (
    diff --git a/themes/gatsby-theme-cara/src/components/seo.tsx b/themes/gatsby-theme-cara/src/components/seo.tsx index 9d236b664..89d6869ed 100755 --- a/themes/gatsby-theme-cara/src/components/seo.tsx +++ b/themes/gatsby-theme-cara/src/components/seo.tsx @@ -1,5 +1,4 @@ import * as React from "react" -import { Helmet } from "react-helmet" import { withPrefix } from "gatsby" import useSiteMetadata from "../hooks/use-site-metadata" @@ -11,7 +10,7 @@ type Props = { children?: React.ReactNode } -const SEO = ({ title = ``, description = ``, pathname = ``, image = ``, children = null }: Props) => { +const Seo = ({ title = ``, description = ``, pathname = ``, image = ``, children = null }: Props) => { const site = useSiteMetadata() const { @@ -19,20 +18,19 @@ const SEO = ({ title = ``, description = ``, pathname = ``, image = ``, children siteTitleAlt: defaultTitle, siteUrl, siteDescription: defaultDescription, - siteLanguage, siteImage: defaultImage, author, } = site const seo = { - title: title || defaultTitle, + title: title ? `${title} | ${siteTitle}` : defaultTitle, description: description || defaultDescription, url: `${siteUrl}${pathname || ``}`, image: `${siteUrl}${image || defaultImage}`, } return ( - - + <> + {seo.title} @@ -53,8 +51,8 @@ const SEO = ({ title = ``, description = ``, pathname = ``, image = ``, children {children} - + ) } -export default SEO +export default Seo diff --git a/themes/gatsby-theme-cara/src/components/svg.tsx b/themes/gatsby-theme-cara/src/components/svg.tsx index 562346c42..8e1d02da9 100755 --- a/themes/gatsby-theme-cara/src/components/svg.tsx +++ b/themes/gatsby-theme-cara/src/components/svg.tsx @@ -1,84 +1,29 @@ /** @jsx jsx */ -import * as React from "react" import { jsx } from "theme-ui" import { hidden } from "../styles/utils" -const icons = { - triangle: { - shape: ( - - ), - viewBox: `0 0 30 30`, - }, - circle: { - shape: ( - - ), - viewBox: `0 0 30 30`, - }, - arrowUp: { - shape: ( - - - {` `} - - - ), - viewBox: `0 0 30 42`, - }, - upDown: { - shape: ( - - - - - ), - viewBox: `0 0 30 44.58`, - }, - box: { - shape: ( - - ), - viewBox: `0 0 30 30`, - }, - hexa: { - shape: ( - - ), - viewBox: `0 0 30 30`, - }, - cross: { - shape: ( - - ), - viewBox: `0 0 100 100`, - }, -} - type IconType = "triangle" | "circle" | "arrowUp" | "upDown" | "box" | "hexa" | "cross" type SVGProps = { stroke?: boolean color?: string | number | any - width: number + width: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12 | 16 | 20 | 24 | 32 | 40 | 48 | 56 | 64 | string icon: IconType left: string top: string hiddenMobile?: boolean } +const viewBox = { + triangle: `0 0 30 30`, + circle: `0 0 30 30`, + arrowUp: `0 0 30 42`, + upDown: `0 0 30 44.58`, + box: `0 0 30 30`, + hexa: `0 0 30 30`, + cross: `0 0 100 100`, +} + const Svg = ({ stroke = false, color = ``, width, icon, left, top, hiddenMobile = false }: SVGProps) => ( - {icons[icon].shape} + ) diff --git a/themes/gatsby-theme-cara/src/gatsby-plugin-theme-ui/components.js b/themes/gatsby-theme-cara/src/gatsby-plugin-theme-ui/components.js deleted file mode 100755 index 32fee253e..000000000 --- a/themes/gatsby-theme-cara/src/gatsby-plugin-theme-ui/components.js +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from "react" -import ProjectCard from "../components/project-card" - -const components = { - // eslint-disable-next-line react/display-name - ProjectCard: ({ link, title, bg, children, ...props }) => ( - - {children} - - ), -} - -export default components diff --git a/themes/gatsby-theme-cara/src/gatsby-plugin-theme-ui/index.js b/themes/gatsby-theme-cara/src/gatsby-plugin-theme-ui/index.js index 4bf4e38a3..72c2f017a 100755 --- a/themes/gatsby-theme-cara/src/gatsby-plugin-theme-ui/index.js +++ b/themes/gatsby-theme-cara/src/gatsby-plugin-theme-ui/index.js @@ -2,9 +2,9 @@ import { merge } from "theme-ui" import { tailwind } from "@theme-ui/presets" const theme = merge(tailwind, { - initialColorModeName: `dark`, config: { - useCustomProperties: true, + initialColorModeName: `dark`, + useColorSchemeMediaQuery: `system`, }, colors: { primary: tailwind.colors.orange[4], diff --git a/themes/gatsby-theme-cara/src/hooks/use-site-metadata.tsx b/themes/gatsby-theme-cara/src/hooks/use-site-metadata.tsx index 16b5d2f34..d9be295a4 100644 --- a/themes/gatsby-theme-cara/src/hooks/use-site-metadata.tsx +++ b/themes/gatsby-theme-cara/src/hooks/use-site-metadata.tsx @@ -8,7 +8,6 @@ type UseSiteMetadataProps = { siteHeadline: string siteUrl: string siteDescription: string - siteLanguage: string siteImage: string author: string [key: string]: unknown @@ -26,7 +25,6 @@ const useSiteMetadata = () => { siteHeadline siteUrl siteDescription - siteLanguage siteImage author } diff --git a/themes/gatsby-theme-cara/src/templates/cara.tsx b/themes/gatsby-theme-cara/src/templates/cara.tsx index 868941d79..27d4089ab 100755 --- a/themes/gatsby-theme-cara/src/templates/cara.tsx +++ b/themes/gatsby-theme-cara/src/templates/cara.tsx @@ -1,10 +1,12 @@ import * as React from "react" +import type { HeadFC } from "gatsby" import { Parallax } from "@react-spring/parallax" import Layout from "../components/layout" import Hero from "../components/hero" import Projects from "../components/projects" import About from "../components/about" import Contact from "../components/contact" +import Seo from "../components/seo" const Cara = () => ( @@ -18,3 +20,5 @@ const Cara = () => ( ) export default Cara + +export const Head: HeadFC = () => diff --git a/themes/gatsby-theme-emilia-core/gatsby-config.js b/themes/gatsby-theme-emilia-core/gatsby-config.js index bd4ab81d2..4063a4d9f 100755 --- a/themes/gatsby-theme-emilia-core/gatsby-config.js +++ b/themes/gatsby-theme-emilia-core/gatsby-config.js @@ -10,7 +10,6 @@ module.exports = (themeOptions) => { siteHeadline: `Emilia - Gatsby Theme from @lekoarts`, siteUrl: `https://emilia.lekoarts.de`, siteDescription: `Minimalistic portfolio/photography site with masonry grid, page transitions and big images. Themeable with Theme UI. Includes Light/Dark mode.`, - siteLanguage: `en`, siteImage: `/banner.jpg`, author: `@lekoarts_de`, basePath: options.basePath, @@ -31,12 +30,17 @@ module.exports = (themeOptions) => { path: options.assetsPath, }, }, - options.mdx && { - resolve: `gatsby-plugin-mdx`, + { + resolve: `gatsby-source-filesystem`, options: { - lessBabel: true, + name: `theme-overrides`, + path: `./src/@lekoarts`, }, }, + options.mdx && { + resolve: `gatsby-plugin-mdx`, + options: {}, + }, `gatsby-transformer-sharp`, options.sharp && { resolve: `gatsby-plugin-sharp`, diff --git a/themes/gatsby-theme-emilia-core/gatsby-node.js b/themes/gatsby-theme-emilia-core/gatsby-node.js index beec4704f..0cad89d2d 100755 --- a/themes/gatsby-theme-emilia-core/gatsby-node.js +++ b/themes/gatsby-theme-emilia-core/gatsby-node.js @@ -1,35 +1,21 @@ -const kebabCase = require(`lodash.kebabcase`) const path = require(`path`) +const { mdxResolverPassthrough, slugify } = require(`@lekoarts/themes-utils`) const withDefaults = require(`./utils/default-options`) -const mdxResolverPassthrough = (fieldName) => async (source, args, context, info) => { - const type = info.schema.getType(`Mdx`) - const mdxNode = context.nodeModel.getNodeById({ - id: source.parent, - }) - const resolver = type.getFields()[fieldName].resolve - const result = await resolver(mdxNode, args, context, info) - return result -} - // Create general interfaces that you could can use to leverage other data sources // The core theme sets up MDX as a type for the general interface -exports.createSchemaCustomization = ({ actions, schema }, themeOptions) => { +exports.createSchemaCustomization = ({ actions }, themeOptions) => { const { createTypes, createFieldExtension } = actions const { basePath } = withDefaults(themeOptions) - const slugify = (source) => { - const slug = source.slug ? source.slug : kebabCase(source.title) - - return `/${basePath}/${slug}`.replace(/\/\/+/g, `/`) - } - createFieldExtension({ name: `slugify`, extend() { return { - resolve: slugify, + resolve(source) { + return slugify(source, basePath) + }, } }, }) @@ -70,7 +56,7 @@ exports.createSchemaCustomization = ({ actions, schema }, themeOptions) => { areas: [String!]! cover: File! @fileByRelativePath excerpt(pruneLength: Int = 160): String! - body: String! + contentFilePath: String! } type MdxProject implements Node & Project { @@ -81,7 +67,7 @@ exports.createSchemaCustomization = ({ actions, schema }, themeOptions) => { areas: [String!]! cover: File! @fileByRelativePath excerpt(pruneLength: Int = 140): String! @mdxpassthrough(fieldName: "excerpt") - body: String! @mdxpassthrough(fieldName: "body") + contentFilePath: String! } type EmiliaConfig implements Node { @@ -122,6 +108,7 @@ exports.onCreateNode = ({ node, actions, getNode, createNodeId, createContentDig date: node.frontmatter.date, areas: node.frontmatter.areas, defer: node.frontmatter.defer, + contentFilePath: fileNode.absolutePath, } const mdxProjectId = createNodeId(`${node.id} >>> MdxProject`) @@ -200,13 +187,7 @@ exports.createPages = async ({ actions, graphql, reporter }, themeOptions) => { allProject(sort: { fields: date, order: DESC }) { nodes { slug - ... on MdxProject { - parent { - ... on Mdx { - fileAbsolutePath - } - } - } + contentFilePath title cover { childImageSharp { @@ -227,17 +208,15 @@ exports.createPages = async ({ actions, graphql, reporter }, themeOptions) => { const projects = result.data.allProject.nodes projects.forEach((project, index) => { - const { fileAbsolutePath } = project.parent - const next = index === 0 ? null : projects[index - 1] const prev = index === projects.length - 1 ? null : projects[index + 1] createPage({ path: project.slug, - component: projectTemplate, + component: `${projectTemplate}?__contentFilePath=${project.contentFilePath}`, context: { slug: project.slug, - absolutePathRegex: `/^${path.dirname(fileAbsolutePath)}/`, + absolutePathRegex: `/^${path.dirname(project.contentFilePath)}/`, prev, next, formatString, diff --git a/themes/gatsby-theme-emilia-core/package.json b/themes/gatsby-theme-emilia-core/package.json index 84b0166f3..542e34688 100755 --- a/themes/gatsby-theme-emilia-core/package.json +++ b/themes/gatsby-theme-emilia-core/package.json @@ -16,17 +16,16 @@ }, "peerDependencies": { "gatsby": "^4.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "dependencies": { - "@mdx-js/mdx": "^1.6.22", - "@mdx-js/react": "^1.6.22", - "gatsby-plugin-mdx": "^3.20.0", - "gatsby-plugin-sharp": "^4.20.0", - "gatsby-source-filesystem": "^4.20.0", - "gatsby-transformer-sharp": "^4.20.0", - "lodash.kebabcase": "^4.1.1" + "@lekoarts/themes-utils": "^0.0.1", + "@mdx-js/react": "^2.1.3", + "gatsby-plugin-mdx": "^4.3.0", + "gatsby-plugin-sharp": "^4.24.0", + "gatsby-source-filesystem": "^4.24.0", + "gatsby-transformer-sharp": "^4.24.0" }, "keywords": [ "gatsby", diff --git a/themes/gatsby-theme-emilia-core/src/components/project.tsx b/themes/gatsby-theme-emilia-core/src/components/project.tsx index 134fd3346..3c6326165 100755 --- a/themes/gatsby-theme-emilia-core/src/components/project.tsx +++ b/themes/gatsby-theme-emilia-core/src/components/project.tsx @@ -1,5 +1,12 @@ import * as React from "react" -export default function Project({ data }: { data: any }) { - return
    {JSON.stringify(data, null, 2)}
    +export default function Project({ data, children }: { data: any; children: any }) { + return ( +
    +
    {JSON.stringify(data, null, 2)}
    + {children} +
    + ) } + +export const Head = () => Project diff --git a/themes/gatsby-theme-emilia-core/src/components/projects.tsx b/themes/gatsby-theme-emilia-core/src/components/projects.tsx index e4d5b6298..a1b34ed82 100755 --- a/themes/gatsby-theme-emilia-core/src/components/projects.tsx +++ b/themes/gatsby-theme-emilia-core/src/components/projects.tsx @@ -3,3 +3,5 @@ import * as React from "react" export default function Projects({ data }: { data: any }) { return
    {JSON.stringify(data, null, 2)}
    } + +export const Head = () => Projects diff --git a/themes/gatsby-theme-emilia-core/src/templates/project-query.tsx b/themes/gatsby-theme-emilia-core/src/templates/project-query.tsx index eb76d5977..341ce977a 100755 --- a/themes/gatsby-theme-emilia-core/src/templates/project-query.tsx +++ b/themes/gatsby-theme-emilia-core/src/templates/project-query.tsx @@ -1,8 +1,10 @@ import { graphql } from "gatsby" -import ProjectComponent from "../components/project" +import ProjectComponent, { Head } from "../components/project" export default ProjectComponent +export { Head } + export const query = graphql` query ($slug: String!, $absolutePathRegex: String!, $formatString: String!) { images: allFile( @@ -20,7 +22,6 @@ export const query = graphql` } } project(slug: { eq: $slug }) { - body excerpt date(formatString: $formatString) slug diff --git a/themes/gatsby-theme-emilia-core/src/templates/projects-query.tsx b/themes/gatsby-theme-emilia-core/src/templates/projects-query.tsx index 0f03cb80f..d1968ddcf 100755 --- a/themes/gatsby-theme-emilia-core/src/templates/projects-query.tsx +++ b/themes/gatsby-theme-emilia-core/src/templates/projects-query.tsx @@ -1,8 +1,10 @@ import { graphql } from "gatsby" -import ProjectsComponent from "../components/projects" +import ProjectsComponent, { Head } from "../components/projects" export default ProjectsComponent +export { Head } + export const query = graphql` query { allProject(sort: { fields: date, order: DESC }) { diff --git a/themes/gatsby-theme-emilia/README.md b/themes/gatsby-theme-emilia/README.md index 38255ed49..1d5563b96 100755 --- a/themes/gatsby-theme-emilia/README.md +++ b/themes/gatsby-theme-emilia/README.md @@ -52,10 +52,10 @@ npm install @lekoarts/gatsby-theme-emilia ### Install as a starter -This will generate a new site that pre-configures use of the theme. +This will generate a new site that pre-configures the theme including example content and additional plugins. ```sh -gatsby new emilia LekoArts/gatsby-starter-portfolio-emilia +npx gatsby new gatsby-starter-portfolio-emilia https://github.com/LekoArts/gatsby-starter-portfolio-emilia ``` [**View the starter's code**](https://github.com/LekoArts/gatsby-starter-portfolio-emilia) @@ -119,8 +119,6 @@ module.exports = { siteUrl: `https://emilia.lekoarts.de`, // Used for SEO siteDescription: `Minimalistic portfolio/photography site with masonry grid, page transitions and big images. Themeable with Theme UI. Includes Light/Dark mode.`, - // Will be set on the tag - siteLanguage: `en`, // Used for og:image and must be placed inside the `static` folder siteImage: `/banner.jpg`, // Twitter Handle diff --git a/themes/gatsby-theme-emilia/gatsby-config.js b/themes/gatsby-theme-emilia/gatsby-config.js index 45fd50adf..b29c25136 100755 --- a/themes/gatsby-theme-emilia/gatsby-config.js +++ b/themes/gatsby-theme-emilia/gatsby-config.js @@ -4,7 +4,13 @@ module.exports = (options) => ({ resolve: `@lekoarts/gatsby-theme-emilia-core`, options, }, - `gatsby-plugin-react-helmet`, + { + resolve: `gatsby-source-filesystem`, + options: { + name: `texts`, + path: `${__dirname}/src/texts`, + }, + }, `gatsby-plugin-image`, `gatsby-plugin-theme-ui`, ], diff --git a/themes/gatsby-theme-emilia/gatsby-ssr.js b/themes/gatsby-theme-emilia/gatsby-ssr.js new file mode 100644 index 000000000..e3c066bd9 --- /dev/null +++ b/themes/gatsby-theme-emilia/gatsby-ssr.js @@ -0,0 +1,5 @@ +import React from "react" + +export const onRenderBody = ({ setHeadComponents }) => { + setHeadComponents([]) +} diff --git a/themes/gatsby-theme-emilia/package.json b/themes/gatsby-theme-emilia/package.json index 54e3ed248..1ae1cbc9a 100755 --- a/themes/gatsby-theme-emilia/package.json +++ b/themes/gatsby-theme-emilia/package.json @@ -16,19 +16,19 @@ }, "peerDependencies": { "gatsby": "^4.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "dependencies": { + "@emotion/react": "^11.10.4", "@lekoarts/gatsby-theme-emilia-core": "^3.0.12", - "@theme-ui/presets": "^0.11.1", - "gatsby-plugin-image": "^2.20.0", - "gatsby-plugin-react-helmet": "^5.20.0", - "gatsby-plugin-theme-ui": "^0.11.1", + "@theme-ui/mdx": "^0.15.1", + "@theme-ui/presets": "^0.15.1", + "gatsby-plugin-image": "^2.24.0", + "gatsby-plugin-theme-ui": "^0.15.1", "polished": "^4.2.2", - "react-helmet": "^6.1.0", - "react-spring": "^9.5.2", - "theme-ui": "^0.11.1" + "react-spring": "^9.5.5", + "theme-ui": "^0.15.1" }, "keywords": [ "gatsby", diff --git a/themes/gatsby-theme-emilia/src/@lekoarts/gatsby-theme-emilia-core/components/project.tsx b/themes/gatsby-theme-emilia/src/@lekoarts/gatsby-theme-emilia-core/components/project.tsx index 3e5c01940..0bf6db086 100755 --- a/themes/gatsby-theme-emilia/src/@lekoarts/gatsby-theme-emilia-core/components/project.tsx +++ b/themes/gatsby-theme-emilia/src/@lekoarts/gatsby-theme-emilia-core/components/project.tsx @@ -1,19 +1,9 @@ +import type { PageProps } from "gatsby" import * as React from "react" -import Project from "../../../components/project" +import Project, { Head, EmiliaProjectProps, EmiliaProjectPageContext } from "../../../components/project" -type Props = { - data: { - project: any - images: any - [key: string]: any - } - pageContext: { - prev: any - next: any - } - [key: string]: any -} - -export default function EmiliaCoreProject({ ...props }: Props) { +export default function EmiliaCoreProject({ ...props }: PageProps) { return } + +export { Head } diff --git a/themes/gatsby-theme-emilia/src/@lekoarts/gatsby-theme-emilia-core/components/projects.tsx b/themes/gatsby-theme-emilia/src/@lekoarts/gatsby-theme-emilia-core/components/projects.tsx index 75e6f93e3..eb33791b0 100755 --- a/themes/gatsby-theme-emilia/src/@lekoarts/gatsby-theme-emilia-core/components/projects.tsx +++ b/themes/gatsby-theme-emilia/src/@lekoarts/gatsby-theme-emilia-core/components/projects.tsx @@ -1,5 +1,5 @@ import * as React from "react" -import Projects from "../../../components/projects" +import Projects, { Head } from "../../../components/projects" type Props = { data: { @@ -16,3 +16,5 @@ export default function EmiliaCoreProjects({ ...props }: Props) { return } + +export { Head } diff --git a/themes/gatsby-theme-emilia/src/assets/bg-pattern.tsx b/themes/gatsby-theme-emilia/src/assets/bg-pattern.tsx deleted file mode 100755 index 86d93d873..000000000 --- a/themes/gatsby-theme-emilia/src/assets/bg-pattern.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import * as React from "react" - -const BGPattern = () => ( - - - - - - - - - - - - - - - - - -) - -export default BGPattern diff --git a/themes/gatsby-theme-emilia/src/assets/left-arrow.tsx b/themes/gatsby-theme-emilia/src/assets/left-arrow.tsx deleted file mode 100755 index 80665fbb0..000000000 --- a/themes/gatsby-theme-emilia/src/assets/left-arrow.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from "react" - -const LeftArrow = () => ( - - - -) - -export default LeftArrow diff --git a/themes/gatsby-theme-emilia/src/assets/location.tsx b/themes/gatsby-theme-emilia/src/assets/location.tsx deleted file mode 100755 index e8836fec7..000000000 --- a/themes/gatsby-theme-emilia/src/assets/location.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from "react" - -const Location = () => ( - - - - -) - -export default Location diff --git a/themes/gatsby-theme-emilia/src/components/card.tsx b/themes/gatsby-theme-emilia/src/components/card.tsx index 942f4d7a1..7f5894a03 100755 --- a/themes/gatsby-theme-emilia/src/components/card.tsx +++ b/themes/gatsby-theme-emilia/src/components/card.tsx @@ -13,6 +13,7 @@ type CardProps = { } } title: string + contentFilePath?: string } overlay?: string shadow?: string[] diff --git a/themes/gatsby-theme-emilia/src/components/footer.tsx b/themes/gatsby-theme-emilia/src/components/footer.tsx index 66d701e36..39aab0fee 100755 --- a/themes/gatsby-theme-emilia/src/components/footer.tsx +++ b/themes/gatsby-theme-emilia/src/components/footer.tsx @@ -3,8 +3,7 @@ import { Box, jsx, Container, Flex, Link, useColorMode } from "theme-ui" import useEmiliaConfig from "../hooks/use-emilia-config" import SocialMediaList from "./social-media-list" import ColorModeToggle from "./colormode-toggle" -// @ts-ignore -import AboutMeMDX from "../texts/about-me" +import AboutMeMDX from "../texts/about-me.mdx" const Footer = () => { const { showThemeAuthor } = useEmiliaConfig() diff --git a/themes/gatsby-theme-emilia/src/components/header-background.tsx b/themes/gatsby-theme-emilia/src/components/header-background.tsx index 30ed73bf2..e2f7fe4ce 100755 --- a/themes/gatsby-theme-emilia/src/components/header-background.tsx +++ b/themes/gatsby-theme-emilia/src/components/header-background.tsx @@ -1,7 +1,7 @@ /** @jsx jsx */ import * as React from "react" import { jsx, useColorMode } from "theme-ui" -import BGPattern from "../assets/bg-pattern" +import Svg from "./svg" const HeaderBackground = () => { const [colorMode] = useColorMode() @@ -19,13 +19,9 @@ const HeaderBackground = () => { width: `100%`, height: `100%`, color: `backgroundPattern`, - svg: { - height: `100%`, - width: `100%`, - }, }} > - +
    - +
    {description && (
    - {description} + {description}
    )} diff --git a/themes/gatsby-theme-emilia/src/components/header.tsx b/themes/gatsby-theme-emilia/src/components/header.tsx index 816c79a20..15ecaf8ec 100755 --- a/themes/gatsby-theme-emilia/src/components/header.tsx +++ b/themes/gatsby-theme-emilia/src/components/header.tsx @@ -5,8 +5,8 @@ import { useStaticQuery, graphql } from "gatsby" import { GatsbyImage, IGatsbyImageData } from "gatsby-plugin-image" import useEmiliaConfig from "../hooks/use-emilia-config" import HeaderBackground from "./header-background" -import Location from "../assets/location" import SocialMediaList from "./social-media-list" +import Svg from "./svg" type AvatarStaticQuery = { file: { @@ -90,19 +90,22 @@ const Header = () => { - {location} + + {` `} + {location}
    diff --git a/themes/gatsby-theme-emilia/src/components/layout.tsx b/themes/gatsby-theme-emilia/src/components/layout.tsx index 68fd409e9..c8b62bcf4 100755 --- a/themes/gatsby-theme-emilia/src/components/layout.tsx +++ b/themes/gatsby-theme-emilia/src/components/layout.tsx @@ -2,7 +2,6 @@ import * as React from "react" import { get } from "theme-ui" import { Global } from "@emotion/react" import Footer from "./footer" -import SEO from "./seo" type LayoutProps = { children: React.ReactNode } @@ -38,7 +37,6 @@ const Layout = ({ children }: LayoutProps) => ( }, })} /> - {children}