@dschau/gatsby-source-google-docs
v1.9.4
Published
Gatsby plugin to use Google Docs as a data source
Downloads
22
Maintainers
Readme
gatsby-source-google-docs
gatsby-source-google-docs
is a Gatsby plugin to use Google Docs as a data source.
- 🔥 No need for a CMS anymore.
- 🖋 Write your blog posts on Google Docs.
- 🗂 Organize your documents in one or multiple folder in Google Drive (trees allowed)
- 🤡 Add custom metadata fields to yours documents
It's that simple
Getting started
Download gatsby-source-google-docs
package
You can download gatsby-source-google-docs
from the NPM registry via the
npm
or yarn
commands
yarn add gatsby-source-google-docs
npm install gatsby-source-google-docs --save
Turn on the Google Docs API and set configuration
- Follow the Step 1: Turn ON the Google Docs API
- Turn ON the Google Drive API
- Get a
client_id
and aclient_secret
from the Google console. If you downloadedcredential.json
file, you can extract them from it - Get an
api_key
from the Google console - Fill the
gatsby-source-google-docs
gatsby config object.
More info can be found on the official Google Docs quickstart guide.
Generate a token file
Run gatsby develop
to generate a token file.
token_path
can be customized in the configuration object (config/token_path
).
Usage
Add the plugin to your configuration:
In your gatsby-node.js
file, configure the gatsby-source-google-docs
and the gatsby-transformer-remark
plugins:
module.exports = {
plugins: [
{
resolve: "gatsby-source-google-docs",
options: {
// Mandatory
// --------
foldersIds: ["FOLDER_ID_1", "FOLDER_ID_2"], // folders Ids can be found in Google Drive URLs
config: {
api_key: "YOUR_API_KEY",
client_id: "YOUR_CLIENT_ID",
client_secret: "YOUR_CLIENT_SECRET",
// Optional
// --------
token_path: "google-docs-token.json",
},
// Optional
// --------
fields: ["createdTime"], // https://developers.google.com/drive/api/v3/reference/files#resource
fieldsMapper: {createdTime: "date", name: "title"}, // To rename fields
fieldsDefault: {draft: false}, // To add default fields values
convertImgToNode: true, // To convert images to remote node files
},
},
// Use gatsby-transformer-remark to modify the generated markdown
// Not mandatary, but recommanded to be compliant with gatsby remark ecosystem
{
resolve: "gatsby-transformer-remark",
options: {
plugins: [],
},
},
],
}
Add an automatic slug generation
Modify your onCreateNode
function in your gatsby-node.js
to generate a slug
field:
exports.onCreateNode = ({node, actions}) => {
// You need to enable `gatsby-transformer-remark` to transform `GoogleDocs` type to `MarkdownRemark` type.
if (node.internal.type === `MarkdownRemark`) {
const customSlug = node.frontmatter.slug // If you add extra data `slug` with description field
actions.createNodeField({
name: `slug`,
node,
value: customSlug || node.frontmatter.path,
})
}
}
node.frontmatter.name
contains the title of the Google Doc
Create a post template
Create a src/templates/post.js
file where you will define your post template:
import React from "react"
const PostTemplate = ({data: {post}}) => (
<>
<h1>{post.frontmatter.name}</h1>
<p>{post.frontmatter.date}</p>
<div dangerouslySetInnerHTML={{__html: post.html}} />
</>
)
export default PostTemplate
// You need to enable `gatsby-transformer-remark` to query `markdownRemark`.
// If you don't use it, query `googleDocs`
// If you use convertImgToNode then add googleDocImages query
export const pageQuery = graphql`
query BlogPostBySlug($slug: String!) {
post: markdownRemark(fields: {slug: {eq: $slug}}) {
html
frontmatter {
name
date(formatString: "DD MMMM YYYY", locale: "fr")
}
}
googleDocImages: allFile(filter: {name: {glob: "google-doc-image-**"}}) {
edges {
node {
id
name
childImageSharp {
fluid {
base64
tracedSVG
aspectRatio
src
srcSet
srcWebp
srcSetWebp
sizes
originalImg
originalName
presentationWidth
presentationHeight
}
}
}
}
}
}
`
Create a page for each post
Use the createPages
API from gatsby in your gatsby-node.js
to create a page for each post.
const path = require("path")
// You need to enable `gatsby-transformer-remark` to query `allMarkdownRemark`.
// If you don't use it, query `allGoogleDocs`
exports.createPages = async ({graphql, actions}) =>
graphql(
`
{
allMarkdownRemark(
sort: {fields: [frontmatter___date], order: DESC}
) {
edges {
node {
fields {
slug
}
}
}
}
}
`
).then(result => {
if (result.errors) {
throw result.errors
}
result.data.allMarkdownRemark.edges.forEach((post, index) => {
actions.createPage({
path: post.node.fields.slug,
component: path.resolve(`./src/templates/post.js`),
context: {
slug: post.node.fields.slug,
},
})
})
})
Add extra data
If you need more data attached to your documents, fill the description field in Google Drive
with a JSON object:
{
"slug": "custom-url",
"date": "2019-01-01",
"author": "Yourself",
"category": "yourCageory",
"tags": ["tag1", "tag2"]
}
JSON will be transformed to YAML and added to your markdown frontmatter and ovveride the existing ones.
/!\ Do not use
id
,name
,description
or anyGoogle Docs
field you add to the configfields
option
If convertImgToNode is enabled. You will need to search the id in the HTML file and replace it with Gatsby image tag
Create a post template
Create a src/templates/post.js
file where you will define your post template:
import React from "react";
import Img from 'gatsby-image';
import parse from 'html-react-parser';
const PostTemplate = ({data: {post, googleDocImages}}) => {
//This is needed if convertImgToNode is enabled
const options = {
replace: (domNode) => {
const {
children,
} = domNode;
if (!children) return;
const hasImgTag = children.find(img => img.name === 'img');
if (hasImgTag) {
const {
attribs,
} = hasImgTag;
const {
src,
alt,
} = attribs;
return (
<Img
fluid={googleDocImages.edges.find(({ node }) => node.id === src).node.childImageSharp.fluid}
alt={alt}
className="ui fluid image"
/>
);
}
}
};
const htmlContent = parse(post.html, options);
return (
<>
<h1>{post.frontmatter.name}</h1>
<p>{post.frontmatter.date}</p>
<React.Fragment>
{htmlContent}
</React.Fragment>
</>
);
}
export default PostTemplate
// You need to enable `gatsby-transformer-remark` to query `markdownRemark`.
// If you don't use it, query `googleDocs`
// If you use convertImgToNode then add googleDocImages query
export const pageQuery = graphql`
query BlogPostBySlug($slug: String!) {
post: markdownRemark(fields: {slug: {eq: $slug}}) {
html
frontmatter {
name
date(formatString: "DD MMMM YYYY", locale: "fr")
}
}
googleDocImages: allFile(filter: {name: {glob: "google-doc-image-**"}}) {
edges {
node {
id
name
childImageSharp {
fluid {
base64
tracedSVG
aspectRatio
src
srcSet
srcWebp
srcSetWebp
sizes
originalImg
originalName
presentationWidth
presentationHeight
}
}
}
}
}
}
`
Contributing
- ⇄ Pull/Merge requests and ★ Stars are always welcome.
- For bugs and feature requests, please create an issue.
See CONTRIBUTING guidelines
Changelog
See CHANGELOG
License
This project is licensed under the MIT License - see the LICENCE file for details