Is it possible to use nested folders in gridsome when using the source-filesystem plugin?

331 views Asked by At

My desired content folder structure is as follows:

- content (directory)
-- home.md

-- trip_A (directory)
--- intro.md
--- day_1.md
--- day_2.md

-- trip_B (directory)
--- intro.md
--- day_1.md

I would ideally like to define this as a single "source" for the @gridsome/source-filesystem plugin so that the addition of future sub-folders are automatically populated in the source.

However, it appears that I may have to manually specify a separate @gridsome/source-filesystem source for each of the sub-folders? Is this correct, or is there a workaround of sorts?

For example:

  • How do I create a generic source for all trip posts (regardless of trip A, B, C or, in future, trip D) that uses a typeName (i.e. template page) of type Trip but hosts each of these pages at their respective parent directories, e.g. /tripA/day_1.html, /tripB/day_1.html etc? The config seems to take a single pathPrefix unless there is a way to use a dynamic wild card route?
  • How do I use different types? Here it seems to make sense to create a separate source-filesystem entry with a different typeName, unless there is another way to do this?
2

There are 2 answers

0
James Carter On BEST ANSWER

I found that the simplest solution to this problem is to manually assign the path in the Templates part of the gridsome config using a function

IE, for this plugin setup...

var plugins = [
 {
    use: '@gridsome/source-filesystem',
    options: {
      path: '**/*.md',
      baseDir: 'temp/docs',
      typeName: 'Doc'
    }
  }
];

and this function to generate the path...

function slugify(node) {
  var text = node.title;
  console.log(node);  
  var text = text.toString().toLowerCase()
    .replace(/\s+/g, '-')           // Replace spaces with -
    .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
    .replace(/\-\-+/g, '-')         // Replace multiple - with single -
    .replace(/^-+/, '')             // Trim - from start of text
    .replace(/-+$/, '');            // Trim - from end of text
    return  node.fileInfo.directory + '/' + text;
}

and this Gridsome config that references the function in the templates object...

var gridsomeConfig = {
  siteName: siteName,
  icon: {
    favicon: favicon,
    touchicon: favicon
  },
  plugins: plugins,
  templates: {
    Doc:
      (node) => {
        return `/docs/${slugify(node)}/`
      }    
  }
}

and given some markdown files in various subdirectories, i.e. /api and /ui...

You will get content of type Doc at /docs/ui, /docs/api, etc. With the need for only one template (GraphQL type -- meaning same query for all docs).

2
mrfrogger On

What have you tried in your Gridsome config? Something like the following should collect all the files in the content directory and any of its subfolders:

{
   use: '@gridsome/source-filesystem',
   options: {
      path: './content/**/*.md',
      typeName: 'Post',  
   }
}

If you add a trip_C in future it will be included in the collection automatically.

Alternatively, you can use a single asterisk in the glob pattern (path: 'content/*/*.md') if you don't want to scan subfolders recursively.

This works because you've nested everything in content. It's also possible to specify a list of patterns in the path field which might work if you want to combine files from multiple top-level directories together in a single collection.

Does that help?