Gatsby - How to query for all YAML in a subfolder of src/data/ using GraphQL - reactjs

I'm trying to query for all YAML files in a subfolder of my data folder. I'm using gatsby-transformer-yaml to parse the YAML data. My filetree looks something like this:
content/
posts/
book1.md
book2.md
src/
data/
books/
quotes1.yaml
quotes2.yaml
templates/
booknote.tsx
According to the documentation, I should be able to make a query called allBooksYaml which would return all of the quotes in quote1.yaml and quote2.yaml. However, when I look at the GraphiQL playground, the only queries I can make are allQuote1Yaml and allQuote2Yaml. (1) Is this a bug? Or is something wrong with my setup?
The reason why I want to do this is so that I can filter the result of allBooksYaml with the title of the book and display the correct quotes for each page generated with the booknote.tsx template. If I don't do this, I think I would have to make an individual page/GraphQL query manually for each book note post I want to create. (2) Is there a better way to link data in a YAML file and the Markdown/Page component?
Thanks in advance!

According to the plugin's documentation, given:
module.exports = {
plugins: [
`gatsby-transformer-yaml`,
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/src/data/`,
},
},
],
}
Where the source folder ${__dirname}/src/data/ contains the .yaml files.
Having in mind also, that you can structure your folder to generate an array or a single object:
Array of Objects: Where each file represents a collection. (you probably want this one)
Single Object: Where each subfolder represents a collection; each file represents one “record”.
So, if your path is ./src/data/books you should be able to query for all books, but this will generate a specific node for all books (single object).
For the second question, I think the best optimal solution is to generate dynamically the pages using gatsby-node.js, querying all markdown books and there, send the title (or another unique field) to the template via context and filter there for each specific book, so your quotes will need to contain a field with an identifier that will match the book, mostly what you said but without the manual approach. Which, at the same time, is more or less a blog approach.
Further reference: https://www.gatsbyjs.com/docs/creating-and-modifying-pages/

You should be able to do just that by using the following config:
"gatsby-transformer-yaml",
{
resolve: "gatsby-source-filesystem",
options: {
path: `${__dirname}/src/data`,
},
},
"gatsby-transformer-yaml",
{
resolve: "gatsby-source-filesystem",
options: {
path: `${__dirname}/content`,
},
},

Related

Apollo Client readFragment with custom id (keyFields)

For ref, using "#apollo/client": "^3.5.5",
I've defined my typePolicies like so as suggested in docs:
HistoricalData: {
keyFields: ["variable", "workspace"],
fields:{...}
}
and when my cache is built, I am expecting my cacheId to be like
<__typename>:<id>:<id>
HistoricalData:${props.variable}:${props.workspace}`;
but instead, when I look in the Apollo cache, it's been created using the keyField names and the values in an object, such as
HistoricalData:{"variable":"GAS.TOTAL","workspace":"ABC"}
instead of
HistoricalData:GAS.TOTAL:ABC
so when I try to readFragment it returns null
client.readFragment({
id: `HistoricalData:${props.variable}:${props.workspace}`,
fragment: apolloGQL`fragment MyHistorical on Historical {
variable
workspace
}`})
It does actually return a value from the cache if I create my id in the structure that exists in the cache and readFragment using this.
Has anyone else noticed that Apollo client is not creating the cache id's in the structure that they describe in the docs?
After some research I came upon the correct way to handle this case. I know that you have already moved on, but just in case anyone else has the same problem in the future, here goes:
As described in the documentation for customizing the cache ID, the cache ID will be an stringified object, as you pointed out. It's not quite explicit in the documentation, but at this point in time it provides this nested example for a cache ID:
Book:{"title":"Fahrenheit 451","author":{"name":"Ray Bradbury"}}
But as users we don't have to preoccupy us with the format of this ID, because there's a helper for that, called cache.identify.
For your specific case, you could use something like this:
const identifiedId = cache.identify({
__typename: 'HistoricalData',
variable: 'GAS.TOTAL',
workspace: 'ABC'
});
cache.readFragment({
id: identifiedId,
fragment: apolloGQL`fragment MyHistorical on Historical {
variable
workspace
}`
});

gatsby-plugin-mdx with rehype-autolink-headers only working with wrap option

I am trying to get my site setup with Gatsby + MDX. I am looking at the documentation here and want to make use of the autolink-header-option. I have tried using the rehype and remark plugins for this, but I can only get the Rehype plugin to work and only with the wrap option. I would much prefer the GitHub (default) style with the link coming before the title.
I am using the below config in gatsby-config.js and cleared .cache and public after updating the file to be sure nothing was cached. Also I am not getting any errors, everything builds and runs successfully, there just is not any link to the headers.
{
resolve: `gatsby-plugin-mdx`,
options: {
rehypePlugins: [
// To pass options, use a 2-element array with the
// configuration in an object in the second element
require("rehype-autolink-headings"),
],
},
},
UPDATE
After trying multiple configurations, the way I was able to get it working as expected was with a different plugin config.
{
resolve: `gatsby-plugin-mdx`,
options: {
gatsbyRemarkPlugins: [ `gatsby-remark-autolink-headers` ],
plugins: [ `gatsby-remark-autolink-headers` ],
},
}
Both gatsbyRemarkPlugins and plugins are required as per: https://github.com/gatsbyjs/gatsby/issues/15486
The README for rehype-autolink-headings mentions that:
This package works with headings that have IDs. One way to add IDs to headings is by using remark-slug before this plugin.
Changing your config to the following should fix it:
{
resolve: `gatsby-plugin-mdx`,
options: {
rehypePlugins: [
require("rehype-slug"),
// To pass options, use a 2-element array with the
// configuration in an object in the second element
require("rehype-autolink-headings"),
],
},
},
In fact, the documentation you linked to has this additional require line as well, but it doesn't clarify what it is used for.

gatsby & graphql : filtering for a specific single image

I don't really understand graphql or gatsby that well but I believe all my images are loaded into graphql by putting this in my gatsby-config.js
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: path.join(__dirname, `src/assets/images`),
},
},
I am then trying to query a specific image which I can do with
query MyQuery {
allImageSharp(filter: {id: {eq: "7acfccd5-4aef-532b-8889-9d844ae2068b"}}) {
edges {
node {
sizes {
sizes
srcSet
src
aspectRatio
}
id
}
}
}
}
And this returns what I want, but the id that I have to enter for this query is 7acfccd5-4aef-532b-8889-9d844ae2068b. Is this id even going to stay the same if I put it in my code? Is there a way to set the id to something more sensical?
If I save my query to a variable data, it turns out that on Netlify data.allImageSharp.edges[0] is null, while locally this value will return what I need
I'm looking for the best way to query a single image. Not multiple images.
If I could set my own id's then I could query these.
Update
I found an example in the gatsby-source-filesystem documentation, but don't really know how to add it to my code
With this snippet:
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: path.join(__dirname, `src/assets/images`),
},
},
Basically you are telling your GraphQL schema that will find images in src/assets/images folder so you will be able to query all the content inside this folder via GraphQL. You are specifying the source for your data.
From gatsby-source-filesystem documentation:
The plugin creates File nodes from files. The various “transformer”
plugins can transform File nodes into various other types of data e.g.
gatsby-transformer-json transforms JSON files into JSON data nodes and
gatsby-transformer-remark transforms markdown files into
MarkdownRemark nodes from which you can query an HTML representation
of the markdown.
Answering your question, of course, you can filter and sort for any property or node that your image has, such as name, path, extension, etc. You may find a useful and autocompletion tool for your queries under /___graphql path when you run a gatsby develop command. This will help you to check out what parameters can be queried and filtered.
If you have an image with a path of src/images/exampleImage.jpg, you can query by the images name by querying using file rather than allImageSharp.
query HeaderQuery {
exampleImage: file(
extension: {eq: "jpg"},
name: {eq: "exampleImage"}
) {
childImageSharp {
fluid {
src
srcSet
sizes
srcSetWebp
}
}
}
}
You can also replace {extension: {eq: "jpg"} with {extension: {regex: "/(jpg)|(jpeg)|(png)/"} to query files of any extension type.

How do you change the name of the default export of a folder in React?

Naturally in React you can alias importing ./component/<name>/index.js as ./component/<name>.
Is there a way in Webpack to change the name of the file that is used as the default? In this case, changing the index.js to a different file name?
JavaScript and by extension Webpack only allows index.js files as default when a directory is used. However, when using Webpack it is possible to write a plugin tapping into a hook for before-existing-directory and return the file you require as index at build time.
Luckily, this plugin is already written directory-named-webpack-plugin.
var DirectoryNamedWebpackPlugin = require("directory-named-webpack-plugin");
resolve: {
plugins: [
new DirectoryNamedWebpackPlugin()
]
}
If there is a folder named foo, this makes webpack look for foo/foo.js instead of the default index file. It also supports a custom transform function, so you can choose the file that gets selected, but I would strongly advise against that as it can get confusing real fast.
Looks like I was just missing an object layer. I had:
plugins: [
new DirectoryNamedWebpackPlugin()
]
instead of:
resolve: {
plugins: [
new DirectoryNamedWebpackPlugin()
]
}

Semantic ui search module

I am using semantic ui search module, the content will be a remote JSON file, can make it work but no matter what i typed whether its found or not, i will show up the list from the JSON file.
script
$('.ui.search')
.search({
apiSettings: {
url: 'http://localhost/api/materialMaster.json'
},
fields: {
results : 'data',
title : 'matcode'
},
minCharacters : 2
})
;
JSON file format is
{"data":[{"matcode":"0A66244S1"},{"matcode":"200GD0S100150CM"}]}
See if this can help. I had this same problem and I solved using this instructions.
https://stackoverflow.com/a/32937262/5381965

Resources