GithubHelp home page GithubHelp logo

pauliescanlon / gatsby-mdx-routes Goto Github PK

View Code? Open in Web Editor NEW
15.0 3.0 3.0 4.21 MB

A Gatsby mdx plugin to create navigation menus for your .mdx files 🚌

Home Page: https://gatsby-mdx-routes.netlify.com/

JavaScript 19.00% TypeScript 81.00%

gatsby-mdx-routes's Introduction

npm (scoped)

npm

NPM

gatsby-mdx-routes

gatsby-mdx-routes is a plugin that exposes links to .mdx files sourced from src/pages.

This plugin aims to separate the data from the ui, which means the styling of your navigation is up to you.

πŸ‘οΈ Preview

πŸš€ Getting started

Install

npm install @pauliescanlon/gatsby-mdx-routes

Setup

To source .mdx files from src/pages you'll need gatsby-source-filesystem and gatsby-plugin-mdx installed.

Your gatsby-config should look something like this...

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `pages`,
        path: `${__dirname}/src/pages/`,
      },
    },
    {
      resolve: `gatsby-plugin-mdx`,
      options: {
        defaultLayouts: {
          default: `${__dirname}/src/layouts/layout.js`,
        },
      },
    },
  ],
}

If that's all setup you'll now need to add @pauliescanlon/gatsby-mdx-routes as a plugin of gatsby-plugin-mdx πŸ˜…

module.exports = {
  {
    resolve: `gatsby-plugin-mdx`,
    options: {
      defaultLayouts: {
        default: `${__dirname}/src/layouts/layout.js`,
      },
      plugins: [`@pauliescanlon/gatsby-mdx-routes`],
    },
  },
}

Using the defaultLayouts from gatsby-plugin-mdx allows you to create one file that will be repeated across pages.

This is where we'll add MdxRoutes.

MdxRoutes

MdxRoutes returns two arrays, routes which is a flat array and menus which is created recursively and contains a menu array.

You will probably use one or the other, not both.

routes

The routes array returns two object keys, one is the actual route to the file in question (slug), the other is the navigationLabel from frontmatter

Key Description
slug Route to .mdx file
navigationLabel navigationLabel extracted from frontmatter

src/pages/a-page.mdx

frontmatter

---
navigationLabel: Page Title
---

src/layouts/layout.js

import React, { Fragment } from "react"
import { Link } from "gatsby"

import { MdxRoutes } from "@pauliescanlon/gatsby-mdx-routes"

export default ({ children }) => (
  <Fragment>
    <nav>
      <MdxRoutes>
        {(routes, _) => (
          <ul>
            {routes.map((route, index) => (
              <li key={index}>
                <Link to={route.slug}>{route.navigationLabel}</Link>
              </li>
            ))}
          </ul>
        )}
      </MdxRoutes>
    </nav>
    <main>{children}</main>
  </Fragment>
)

menus

The menus array also returns the two object keys mentioned above, it also returns the following

Key Description
slug Route to .mdx file
navigationLabel navigationLabel extracted from frontmatter
id key to use in recursive function
parent string to determine parent
menu array of routes grouped by parent
paths internal array to use in recursive function

The menus array is constructed by looking at the file paths on disk and determining what depth a file lives. This is calculated by the amount of forward slashes in the slug

To create the menus array MdxRoutes will mirror the directory structure in your project

your project

└─ src
    └─ pages
        └─ other-pages
            └─ some-other-page.mdx
        β”œβ”€ sub-pages
            β”œβ”€ sub-page-items
              β”œβ”€ sub-page-items-again
                └─ sub-page-item-again-1.mdx
              └─ sub-page-item-1.mdx
            └─ sub-page-1.mdx
        β”œβ”€ about.mdx
        β”œβ”€ contact.mdx
        └─ index.mdx

To use the menus array you'll also need a recursive Tree function to create your navigation list.

Watch out for the conditional slug, we need this to determine if the object key is a parent or an actual route to a file.

src/layouts/layout.js

import React, { Fragment } from "react"
import { Link } from "gatsby"

import { MdxRoutes } from "@pauliescanlon/gatsby-mdx-routes"

const Tree = ({ menus }) => {
  const createTree = menus => {
    return (
      <ul>
        {menus.map(route => (
          <li key={route.navigationLabel}>
            {route.slug ? (
              <Link to={route.slug}>
                {route.navigationLabel}
                {route.menu && createTree(route.menu)}
              </Link>
            ) : (
              <span>
                {route.navigationLabel}
                {route.menu && createTree(route.menu)}
              </span>
            )}
          </li>
        ))}
      </ul>
    )
  }

  return createTree(menus, null)
}

export default ({ children }) => (
  <Fragment>
    <nav>
      <MdxRoutes>{(_, menus) => <Tree menus={menus} />}</MdxRoutes>
    </nav>
    <main>{children}</main>
  </Fragment>
)

props

Prop Type Required Description
navigationOrder Array[string] no A reference array to order by

navigationOrder

By passing in an array of strings MdxRoutes can use this to sort the returned routes or menus array, otherwise everything is just returned alphabetically in an ascending order based on the slug, with the index ("/") being first in the list.

<MdxRoutes navigationOrder={["Contact", "About", "Home", "Sub Page"]}>
  {(routes, menus) => (
    <ul>
      {routes.map((route, index) => (
        <li key={index}>
          <Link to={route.slug}>{route.navigationLabel}</Link>
        </li>
      ))}
    </ul>
  )}
</MdxRoutes>

If you're using gatsby-mdx-routes in your project i'd love to hear from you @pauliescanlon

ko-fi

gatsby-mdx-routes's People

Contributors

pauliescanlon avatar spences10 avatar

Stargazers

Jrson avatar  avatar Guy Barnard avatar Tristan Remy avatar  avatar Piotr Monwid-Olechnowicz avatar Eric Howey avatar Tom Hermans avatar Muescha avatar Chad Lee avatar Ryosuke avatar Gareth Andrew avatar Ionut Cirja avatar Adrian Oprea avatar Federico Zivolo avatar

Watchers

James Cloos avatar  avatar  avatar

gatsby-mdx-routes's Issues

Duplicate menus

It appears that when used in a theme there's a duplications in the menus object if there's more than one directory with nested mdx files

Add changelog

While we’re still very much pre minor or major release others might find it helpful to see breaking changes.

Between 0.01 and 0.0.2 there’s already been a remaining of the return values and there probably will be again. Best to keep a note is these changes to avoid confusing others

Provide frontmatter data?

Right now I don't understand how am I supposed to render a menu with proper titles for each menu option. If the plugin provided the page frontmatter data, it would be easy to get the title from it.

Add support for weight/order frontmatter field (or custom frontmatter fields)

I have a script that takes the routes generated by this plugin, and sorts them. I would like to use a sort or weight frontmatter field to give hints to my script on how to sort the routes, but right now only slug and navigationLabel are exposed.

Would you mind adding support for sort or weight, or maybe a way to define custom frontmatter fields to expose?

GraphQL "fields" and "navigationLabel" Query Error

Seems like a nice idea for a library. Only issue is I can't get it working and get a GraphQL query error on first use:

There was an error in your GraphQL query:

Cannot query field "fields" on type "Mdx".

If you don't expect "fields" to exist on the type "Mdx" it is most likely a typo.
However, if you expect "fields" to exist there are a couple of solutions to common problems:

- If you added a new data source and/or changed something inside gatsby-node.js/gatsby-config.js, please try a restart of your development server
- The field might be accessible in another subfield, please try your query in GraphiQL and use the GraphiQL explorer to see which fields you can query and what shape they have
- You want to optionally use your field "fields" and right now it is not used anywhere. Therefore Gatsby can't infer the type and add it to the GraphQL schema. A quick fix is to add at least one entry with that field ("dummy content")

It is recommended to explicitly type your GraphQL schema if you want to use optional fields. This way you don't have to add the mentioned "dummy content". Visit our docs to learn how you can define the schema for "Mdx":
https://www.gatsbyjs.org/docs/schema-customization/#creating-type-definitions

File: /Users/user/gatsby-project/node_modules/@pauliescanlon/gatsby-mdx-routes/components/MdxRoutes/MdxRoutes.js

There was an error in your GraphQL query:

Cannot query field "navigationLabel" on type "MdxFrontmatter".

If you don't expect "navigationLabel" to exist on the type "MdxFrontmatter" it is most likely a typo.
However, if you expect "navigationLabel" to exist there are a couple of solutions to common problems:

- If you added a new data source and/or changed something inside gatsby-node.js/gatsby-config.js, please try a restart of your development server
- The field might be accessible in another subfield, please try your query in GraphiQL and use the GraphiQL explorer to see which fields you can query and what shape they have
- You want to optionally use your field "navigationLabel" and right now it is not used anywhere. Therefore Gatsby can't infer the type and add it to the GraphQL schema. A quick fix is to add at least one entry with that field ("dummy content")

It is recommended to explicitly type your GraphQL schema if you want to use optional fields. This way you don't have to add the mentioned "dummy content". Visit our docs to learn how you can define the schema for "MdxFrontmatter":
https://www.gatsbyjs.org/docs/schema-customization/#creating-type-definitions

File: /Users/user/gatsby-project/node_modules/@pauliescanlon/gatsby-mdx-routes/components/MdxRoutes/MdxRoutes.js

Perhaps I need navigationLabel in the front matter of all my MDX files? Still, would be good to have it not break when this wasn't the case.

The other strange thing is that I continue to get this error even after I've removed your plugin from my gastby-config.js file. To get my project back to a fit state I had to remove your library from my package.json, delete all node_modules and yarn.locks and then re-install everything.

Generate hyperlink for sub-menu parent folder

This issue is a follow up to the question on this tweet.

Adding an index.mdx file inside a sub-menu folder should make that folder an hyperlink.

Take the following folder and file structure:

|-- src
    |-- pages
        |-- other-pages
           |-- some-other-page.mdx
        |-- yet-another-pages
           |-- index.mdx
           |-- yet-another-page.mdx
        |-- about.mdx
        |-- contact.mdx
        |-- index.mdx

The following menu should be rendered:

other pages (no link)
    some other page (link to: /other-pages/some-other-page)
yet another pages (link to: /yet-another-pages)
    yet another page (link to: /yet-another-pages/yet-another-page)
about (link to: /about)
contact (link to: /contact)
home (link to: /home)

Take special not to the 3rd line in the above code.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.