diff --git a/.env.sample b/.env.sample new file mode 100644 index 00000000..dea7201b --- /dev/null +++ b/.env.sample @@ -0,0 +1 @@ +GITHUB_TOKEN=your_token diff --git a/README.md b/README.md index c711aeaa..303af3a0 100644 --- a/README.md +++ b/README.md @@ -13,15 +13,15 @@

-## Table of Contents +--- -- [Table of Contents](#table-of-contents) - [🎉 Features](#-features) - [🎆 EXIF extraction](#-exif-extraction) - [💰 Cryptocurrency donation via Web3/MetaMask](#-cryptocurrency-donation-via-web3metamask) - [🔍 Search](#-search) - [🕸 Related Posts](#-related-posts) - [🐝 Coinhive](#-coinhive) + - [📝 GitHub changelog rendering](#-github-changelog-rendering) - [🏆 SEO component](#-seo-component) - [📈 Matomo (formerly Piwik) analytics tracking](#-matomo-formerly-piwik-analytics-tracking) - [gatsby-redirect-from](#gatsby-redirect-from) @@ -112,6 +112,26 @@ If you want to know how this works, have a look at the respective component unde - [`src/components/atoms/Coinhive.jsx`](src/components/atoms/Coinhive.jsx) +### 📝 GitHub changelog rendering + +Adds ability to show contents of a changelog, rendered from a `CHANGELOG.md` on GitHub from the given repository. The use case is to enhance release posts about projects hosted on GitHub. Makes use of the GitHub GraphQL API via [gatsby-source-graphql](https://www.gatsbyjs.org/packages/gatsby-source-graphql/). + +Adding this to a post's YAML frontmatter: + +```yaml +changelog: gatsby-plugin-matomo +``` + +will render this at the end of the post: + +screen shot 2018-11-21 at 23 03 38 + +See it live on [Matomo plugin for Gatsby](https://kremalicious.com/gatsby-plugin-matomo#changelog). + +If you want to know how this works, have a look at the respective component under + +- [`src/components/atoms/Changelog.jsx`](src/components/atoms/Changelog.jsx) + ### 🏆 SEO component Includes a SEO component which automatically switches all required `meta` tags for search engines, Twitter Cards, and Facebook OpenGraph tags based on the browsed route/page. @@ -159,6 +179,11 @@ Then install dependencies and start everything up: ```bash npm i + +# GITHUB_TOKEN is required for some parts +cp .env.sample .env +vi .env + npm start ``` diff --git a/content/posts/2018-11-01-gatsby-plugin-matomo/index.md b/content/posts/2018-11-01-gatsby-plugin-matomo/index.md index de9495ff..5480f9ee 100644 --- a/content/posts/2018-11-01-gatsby-plugin-matomo/index.md +++ b/content/posts/2018-11-01-gatsby-plugin-matomo/index.md @@ -4,6 +4,7 @@ date: 2018-11-01T19:08:00.367Z title: Matomo plugin for Gatsby image: gatsby-plugin-matomo-teaser.png +changelog: gatsby-plugin-matomo tags: - goodies diff --git a/gatsby-config.js b/gatsby-config.js index 999b86e0..81a603a6 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -1,3 +1,15 @@ +require('dotenv').config() + +if (!process.env.GITHUB_TOKEN) { + // eslint-disable-next-line + console.warn(` + + ⚠️ A GitHub token is required to build some parts of the blog. + ⚠️ Check the README https://github.com/kremalicious/blog#-development. + + `) +} + const path = require('path') const siteConfig = require('./config') @@ -37,6 +49,20 @@ module.exports = { path: path.join(__dirname, 'src', 'images') } }, + { + resolve: 'gatsby-source-graphql', + options: { + typeName: 'GitHub', + fieldName: 'github', + url: 'https://api.github.com/graphql', + headers: { + Authorization: `bearer ${process.env.GITHUB_TOKEN}` + }, + // Additional options to pass to node-fetch + fetchOptions: {}, + refetchInterval: 300 // 5 min. + } + }, 'gatsby-plugin-sharp', 'gatsby-transformer-sharp', { diff --git a/package.json b/package.json index 3d35ae56..fbb5cb94 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "gatsby-remark-images": "^3.0.0", "gatsby-remark-smartypants": "^2.0.6", "gatsby-source-filesystem": "^2.0.8", + "gatsby-source-graphql": "^2.0.6", "gatsby-transformer-remark": "^2.1.12", "gatsby-transformer-sharp": "^2.1.8", "graphql": "^0.13.2", @@ -74,6 +75,8 @@ "react-qr-svg": "^2.1.0", "react-time": "^4.3.0", "react-transition-group": "^2.5.0", + "remark": "^10.0.1", + "remark-react": "^4.0.3", "slugify": "^1.3.3", "web3": "^1.0.0-beta.36" }, diff --git a/src/components/Post/PostContent.jsx b/src/components/Post/PostContent.jsx index 9b3bf3c8..f4022f4c 100644 --- a/src/components/Post/PostContent.jsx +++ b/src/components/Post/PostContent.jsx @@ -1,12 +1,13 @@ -import React from 'react' +import React, { Fragment } from 'react' import PropTypes from 'prop-types' +import Changelog from '../atoms/Changelog' // Remove lead paragraph from content const PostContent = ({ post }) => { - let content const separator = '' + const changelog = post.frontmatter.changelog - content = post.html + let content = post.html if (post.frontmatter.type === 'post') { if (content.includes(separator)) { @@ -17,7 +18,12 @@ const PostContent = ({ post }) => { } } - return
+ return ( + +
+ {changelog && } + + ) } PostContent.propTypes = { diff --git a/src/components/atoms/Changelog.jsx b/src/components/atoms/Changelog.jsx new file mode 100644 index 00000000..671a7555 --- /dev/null +++ b/src/components/atoms/Changelog.jsx @@ -0,0 +1,86 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { StaticQuery, graphql } from 'gatsby' +import remark from 'remark' +import remarkReact from 'remark-react' +import styles from './Changelog.module.scss' + +const queryGithub = graphql` + query GitHubReposInfo { + github { + viewer { + repositories(first: 100, privacy: PUBLIC, isFork: false) { + edges { + node { + name + url + owner { + login + } + object(expression: "master:CHANGELOG.md") { + id + ... on GitHub_Blob { + text + } + } + } + } + } + } + } + } +` + +const Changelog = ({ repo }) => ( + { + const repositoriesGitHub = data.github.viewer.repositories.edges + + let repoFilteredArray = repositoriesGitHub + .map(({ node }) => { + if (node.name === repo) return node + }) + .filter(n => n) + + const repoMatch = repoFilteredArray[0] + const { object, url, owner } = repoMatch + + if (repoMatch === undefined || object === undefined) return null + + const changelogHtml = + object && + remark() + .use(remarkReact) + .processSync(object.text).contents + + const filePathUrl = `${url}/tree/master/CHANGELOG.md` + const filePathDisplay = `${owner.login}/${repo}:CHANGELOG.md` + + return ( +
+

+ Changelog +

+
+ {changelogHtml} +

+ + sourced from{' '} + + {filePathDisplay} + + +

+
+
+ ) + }} + /> +) + +Changelog.propTypes = { + repo: PropTypes.string.isRequired +} + +export default Changelog diff --git a/src/components/atoms/Changelog.module.scss b/src/components/atoms/Changelog.module.scss new file mode 100644 index 00000000..97e4ba7b --- /dev/null +++ b/src/components/atoms/Changelog.module.scss @@ -0,0 +1,68 @@ +@import 'variables'; + +.changelogTitle { + margin-bottom: 0; +} + +.changelogContent { + padding-top: $spacer * 2; + padding-left: $spacer / 2; + margin-left: $spacer / 2; + border-left: 1px solid $brand-grey-dimmed; + + h2 { + position: relative; + + &::before { + content: ''; + width: .4rem; + height: .4rem; + border-radius: 50%; + display: inline-block; + background: $color-headings; + position: absolute; + left: -($spacer / 1.5); + top: $font-size-large / 3; + } + } + + h2, + h3 { + font-size: $font-size-large; + background: none; + padding: 0; + margin-left: 0; + margin-top: $spacer / 8; + margin-bottom: $spacer / $line-height; + } + + ul { + font-size: $font-size-small; + margin-left: $spacer / 8; + } +} + +.changelogSource { + font-size: $font-size-mini; + font-family: $font-family-base; + font-weight: $font-weight-base; + padding-top: $spacer / 2; + padding-bottom: $spacer / 2; + + &, + a { + color: $brand-grey-light; + } + + a { + margin-left: $spacer / 8; + + code { + font-size: ($font-size-mini * .9); + } + + &:hover { + color: $link-color; + } + } +} diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss index 670f9527..1b33b3c1 100644 --- a/src/styles/_variables.scss +++ b/src/styles/_variables.scss @@ -45,7 +45,7 @@ $font-size-root: 18px; $font-size-base: 1rem; $font-size-large: 1.15rem; -$font-size-small: .8rem; +$font-size-small: .85rem; $font-size-mini: .7rem; $font-size-h1: 2.5rem; diff --git a/src/templates/Post.jsx b/src/templates/Post.jsx index 3dce1bc9..b92074f4 100644 --- a/src/templates/Post.jsx +++ b/src/templates/Post.jsx @@ -112,6 +112,7 @@ export const pageQuery = graphql` style { publicURL } + changelog } fields { slug