Skip to content

Commit

Permalink
[gatsby-source-medium] Add Medium Source (#1907)
Browse files Browse the repository at this point in the history
* Add gatsby-source-medium Plugin

* Fix package name in README

* Improve README

* Remove unnecessary attributes

* Add User <-> Post GraphQL Links

* Add Medium Example Page

* Fix typo
  • Loading branch information
deniaz authored and KyleAMathews committed Sep 4, 2017
1 parent 05d63f2 commit 8b9567d
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 0 deletions.
8 changes: 8 additions & 0 deletions examples/using-medium/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"env": {
"browser": true
},
"globals": {
"graphql": false
}
}
5 changes: 5 additions & 0 deletions examples/using-medium/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Using Medium

https://using-medium.gatsbyjs.org

Gatsby example site that shows how to use the gatsby-source-medium plugin.
13 changes: 13 additions & 0 deletions examples/using-medium/gatsby-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = {
siteMetadata: {
title: `Using Medium`,
},
plugins: [
{
resolve: `gatsby-source-medium`,
options: {
username: `smartive`,
},
},
],
}
18 changes: 18 additions & 0 deletions examples/using-medium/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "gatsby-example-using-medmium",
"private": true,
"version": "1.0.0",
"description": "Gatsby example site that shows how to use the Medium source plugin",
"main": "index.js",
"author": "Robert Vogt <robert@smartive.ch>",
"license": "MIT",
"dependencies": {
"gatsby": "latest",
"gatsby-link": "latest"
},
"keywords": ["gatsby"],
"scripts": {
"develop": "gatsby develop",
"build": "gatsby build"
}
}
13 changes: 13 additions & 0 deletions examples/using-medium/src/layouts/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react"

export const DefaultLayout = props => (
<div>
<h1>Example showing Medium posts</h1>

<main>
{props.children()}
</main>
</div>
)

export default DefaultLayout
48 changes: 48 additions & 0 deletions examples/using-medium/src/pages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from "react"

const mediumCDNUrl = `https://cdn-images-1.medium.com/max/150/`

const IndexPage = ({ data }) => {
const posts = data.allMediumPost.edges

return (
<main>
{posts.map(post =>
<article key={post.node.id}>
<h2>
{post.node.title}
</h2>
<h3>
by {post.node.author.name}
</h3>
<img src={`${mediumCDNUrl}/${post.node.virtuals.previewImage.imageId}`} alt={post.node.title} width="150" />
</article>
)}
</main>
)
}

IndexPage.propTypes

export default IndexPage

export const pageQuery = graphql`
query IndexQuery {
allMediumPost(limit: 5, sort: { fields: [createdAt], order: DESC }) {
edges {
node {
id
title
author {
name
}
virtuals {
previewImage {
imageId
}
}
}
}
}
}
`
59 changes: 59 additions & 0 deletions packages/gatsby-source-medium/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# gatsby-source-medium

Source plugin for pulling data into Gatsby from an unofficial Medium JSON
endpoint. Unfortunately the JSON endpoint does not provide the complete stories,
but only previews. If you need the complete stories, you might have a look at
something like [gatsby-source-rss](https://github.com/jondubin/gatsby-source-rss).

## Install

`npm install --save gatsby-source-medium`

## How to use

```javascript
// In your gatsby-config.js
plugins: [
{
resolve: `gatsby-source-medium`,
options: {
username: `username/publication`
}
}
]
```

## How to query

You can query nodes created from Medium like the following:

```graphql

query StoriesQuery {
allMediumPost(sort: { fields: [createdAt], order: DESC }) {
edges {
node {
id
title
creatorId
slug
uniqueSlug
virtuals {
subtitle
previewImage {
imageId
}
}
}
}
}
allMediumUser {
edges {
node {
id
name
}
}
}
}
```
65 changes: 65 additions & 0 deletions packages/gatsby-source-medium/gatsby-node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const axios = require(`axios`)
const crypto = require(`crypto`)

const fetch = username => {
const url = `https://medium.com/${username}/latest?format=json`
return axios.get(url)
}

const prefix = `])}while(1);</x>`

const strip = payload => payload.replace(prefix, ``)

exports.sourceNodes = async ({ boundActionCreators }, { username }) => {
const { createNode } = boundActionCreators

try {
const result = await fetch(username)
const json = JSON.parse(strip(result.data))

const { posts } = json.payload
const collectionKeys = Object.keys(json.payload.references.Collection)
const userKeys = Object.keys(json.payload.references.User)

const importableResources = [
userKeys.map(key => json.payload.references.User[key]),
posts,
collectionKeys.map(key => json.payload.references.Collection[key]),
]

const resources = Array.prototype.concat(...importableResources)
resources.map(resource => {
const digest = crypto.createHash(`md5`).update(JSON.stringify(resource)).digest(`hex`)

const links =
resource.type === `Post`
? {
author___NODE: resource.creatorId,
}
: resource.type === `User`
? {
posts___NODE: posts.filter(post => post.creatorId === resource.userId).map(post => post.id),
}
: {}

const node = Object.assign(
resource,
{
id: resource.id ? resource.id : resource.userId,
parent: `__SOURCE__`,
children: [],
internal: {
type: `Medium${resource.type}`,
contentDigest: digest,
},
},
links
)

createNode(node)
})
} catch (error) {
console.error(error)
process.exit(1)
}
}
10 changes: 10 additions & 0 deletions packages/gatsby-source-medium/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "gatsby-source-medium",
"version": "1.0.0",
"description": "Gatsby source plugin for building websites using Medium as a data source",
"author": "Robert Vogt <robert@smartive.ch>",
"license": "MIT",
"dependencies": {
"axios": "^0.16.2"
}
}

0 comments on commit 8b9567d

Please sign in to comment.