npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@mathieuloutre/spike-contentful

v2.2.0

Published

Contentful CMS plugin for spike

Downloads

4

Readme

Spike Contentful Plugin

npm tests dependencies coverage

Contentful CMS plugin for spike

Note: This project is in early development, and versioning is a little different. Read this for more details.

Why should you care?

If you're using Contentful and would like to pull your data for compilation into a spike static site, this will help you out.

Installation

npm install spike-contentful -S

Usage

This is a standard webpack plugin, but is built for and intended to be used with spike. You can include it in your spike project as such:

// app.js
const Contentful = require('spike-contentful')
const htmlStandards = require('reshape-standard')
const locals = {}

module.exports = {
  plugins: [
    new Contentful({
      addDataTo: locals,
      accessToken: 'xxx',
      spaceId: 'xxx',
      contentTypes: [
        {
          name: 'posts',
          id: '633fTeiMaxxxxxxxxx'
        },
        {
          name: 'authors',
          id: '223gTahLaxxxxxxxxx'
        }
      ]
    })
  ],
  reshape: htmlStandards({ locals: () => locals })
}

At a minimum, the spike-contentful plugin requires both name and id for contentTypes. The name corresponds with how you'd like to access it in your templates. The id is found listed under "Identifier" by logging into Contentful and clicking "APIs" then "Content model explorer".

Since Spike uses reshape, you can use a variety of different plugins to expose local variables to your html. We are using reshape along with spike html standards here because it's the plugin provided in spike's default template, and also is currently the only plugin that provides the ability to run complex loops through objects.

In order to pass the data correctly, you must pass spike-contentful an object, which it will load the data onto when the compile begins under a contentful key. If you also pass the same object to whatever reshape plugin you are using in whatever manner it requires to make the data available in your html templates, the data will be present on that object before they start compiling. This is a slightly unconventional pattern for Javascript libraries, but in this situation it allows for maximum flexibility and convenience.

Once included, it will expose a contentful local to your jade files, which you can use to iterate through your content types. Based on the example above, the posts content type will be accessible through contentful.posts, as such:

// a template file
ul
  each(loop='post of contentful.posts')
    li {{ JSON.stringify(post) }}

For the sugar-free

<ul>
	<each loop="post of contentful.blog">
		<li>{{ JSON.stringify(post) }}</li>
	</each>
</ul>

Filters

Limit

To limit the number of results for a given content type:

new Contentful({
  addDataTo: locals,
  accessToken: 'xxx',
  spaceId: 'xxx',
  contentTypes: [
    {
      name: 'posts',
      id: '633fTeiMaxxxxxxxxx',
      filters: {
        limit: 10
      }
    }
  ]
})

Order

To order results of a given content type:

new Contentful({
  addDataTo: locals,
  accessToken: 'xxx',
  spaceId: 'xxx',
  contentTypes: [
    {
      name: 'posts',
      id: '633fTeiMaxxxxxxxxx',
      filters: {
        limit: 10,
        order: 'sys.createdAt'
      }
    }
  ]
})

Transforms

Contentful returns a lot of associated data and, as a result, we include a way to clean it up. You also have the ability to pass your own custom transform option to each content type allowing you to transform the data however you like before it's sent to your views.

new Contentful({
  addDataTo: locals,
  accessToken: 'xxx',
  spaceId: 'xxx',
  contentTypes: [
    {
      name: 'posts',
      id: '633fTeiMaxxxxxxxxx',
      transform: (post) => {
        // do your transformation here...
        return post
      }
    }
  ]
})

This plugin ships with a default transform function that will run some basic cleanup. However, be warned that the transform will enter an infinite loop and crash if there are circular references within the data, which is not an uncommon occurance, so please be very careful utilizing this transform. To enable our default transform, you can pass true as such:

new Contentful({
  addDataTo: locals,
  accessToken: 'xxx',
  spaceId: 'xxx',
  contentTypes: [
    {
      name: 'posts',
      id: '633fTeiMaxxxxxxxxx',
      transform: true
    }
  ]
})

If you'd like to use our default transform outside of the library, this is also available as an export. For example, you could include it and use it with client-side JS responses.

const Contentful = require('spike-contentful')
console.log(Contentful.transform)

Templates

Using the template option allows you to write objects returned from Contentful to single page templates. For example, if you are trying to render a blog as static, you might want each post returned from the API to be rendered as a single page by itself.

The template option is an object with path and output keys. The path is an absolute or relative path to a template to be used to render each item, and output is a function with the currently iterated item as a parameter, which should return a string representing a path relative to the project root where the single view should be rendered. For example:

new Contentful({
  addDataTo: locals,
  accessToken: 'xxx',
  spaceId: 'xxx',
  contentTypes: [{
    name: 'posts',
    id: '633fTeiMaxxxxxxxxx',
    template: {
      path: 'templates/post.html',
      output: (post) => { return `posts/${post.id}.html` }
    }
  }]
})

Your template must use the item variable as seen below. Also note that this feature will not work if your template is ignored by spike.

<p>{{item.title}}</p>

JSON Output

Finally, if you'd like to have the output written locally to a JSON file so that it's cached locally, you can pass the name of the file, resolved relative to your project's output, as a json option to the plugin. For example:

new Contentful({
  addDataTo: locals,
  accessToken: 'xxx',
  spaceId: 'xxx',
  contentTypes: [{
    name: 'posts',
    id: '633fTeiMaxxxxxxxxx'
  }],
  json: 'data.json'
})

You may also choose to have the ouput written specifically for any content type :

new Contentful({
  addDataTo: locals,
  accessToken: 'xxx',
  spaceId: 'xxx',
  contentTypes: [
    {
      name: 'posts',
      id: '633fTeiMaxxxxxxxxx',
      // JSON output expected for this content type
      json: 'posts.json'
    },
    {
      name: 'press',
      id: '4Em9bQeIQxxxxxxxxx'
      // No JSON output needed for this content type
    }
  ],
  // Save all content types data in one file
  json: 'alldata.json'
})

Aggressive Refresh

By default, this plugin will only fetch data once when you start your watcher, for development speed purposes. This means that if you change your data, you will have to restart the watcher to pick up the changes. If you are in a phase where you are making frequent data changes and would like a more aggressive updating strategy, you can set the aggressiveRefresh option to true, and your dreams will come true. However, note that this will slow down your local development, as it will fetch and link all entires every time you save a file, so it's only recommended for temporary use.

Testing

To run the tests locally, you'll need to add a test/.env with your name and token values:

  • cp test/.env.sample test/.env
  • accessToken is derived from "APIs" > "Content Delivery API Keys" in the Contentful admin section.
  • spaceId is also derived from "APIs" > "Content Delivery API Keys" in the Contentful admin section.

License & Contributing