Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[gatsby-source-medium] Add Medium Source #1907

Merged
merged 7 commits into from
Sep 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"
}
}