From 24057c7d832fc925e48c891abc0f751753c43ac6 Mon Sep 17 00:00:00 2001
From: Matthias Kretschmann
Date: Wed, 21 Nov 2018 23:39:09 +0100
Subject: [PATCH] changelog component
---
.env.sample | 1 +
README.md | 29 ++++++-
.../2018-11-01-gatsby-plugin-matomo/index.md | 1 +
gatsby-config.js | 26 ++++++
package.json | 3 +
src/components/Post/PostContent.jsx | 14 ++-
src/components/atoms/Changelog.jsx | 86 +++++++++++++++++++
src/components/atoms/Changelog.module.scss | 68 +++++++++++++++
src/styles/_variables.scss | 2 +-
src/templates/Post.jsx | 1 +
10 files changed, 224 insertions(+), 7 deletions(-)
create mode 100644 .env.sample
create mode 100644 src/components/atoms/Changelog.jsx
create mode 100644 src/components/atoms/Changelog.module.scss
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:
+
+
+
+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.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