gatsby-image-plugin - Node process "SIGABRT"error - javascript

I'm having issues with graphql when trying to use gatsby-plugin-image. My node process crashes with error "SIGABRT" which indicates some kind of critical node memory threshold has been reached.
As per the docs I have tried using graphql page queries, and useStaticQuery within a hook component.
The images folder is in src at root, and only has around 150 images in it.
I'm struggling to find any docs or examples of best practice for working with dynamic GatsbyImage as I'd like to pass the image as a prop.. can anyone shed any light on this? It seems width and or layout properties are required for the graphql query, as reducing the width of each image right down to 100 sometimes lets the process run and build complete. But it is intermittent, and crashes sometimes.
example page query:
export const Images = graphql
query {
allFile(filter: { extension: { regex: "/(jpg)|(jpeg)|(png)/" }, relativeDirectory: { regex: "/(events)/" } }) {
edges {
node {
id
base
name
relativePath
childImageSharp {
gatsbyImageData(width: 100, placeholder: BLURRED, formats: [AUTO, WEBP, AVIF])
}
}
}
}
}
;
example staticQuery:
const images = useStaticQuery(graphql
query {
allFile(filter: { extension: { regex: "/(jpg)|(jpeg)|(png)/" }, relativeDirectory: { regex: "/(events)/" } }) {
edges {
node {
id
base
name
relativePath
childImageSharp {
gatsbyImageData(width: 100, placeholder: BLURRED, formats: [AUTO, WEBP, AVIF])
}
}
}
}
}
);

Related

Matching query images with JSON variable in Gatsby

So, I have a JSON file that has info I'm pulling into my React project. One of those fields is an image keyword. I want to use that to call images in a "show" folder where promo images can be dumped.
thisYear.json
{
"title": "Rope",
"author": "Patrick Hamilton",
"image": "rope",
},{
"title": "I Hate Hamlet",
"author": "Paul Rudnick",
"image": "iHateHamlet",
}
]
I made a query that is grabbing the images from said "show" folder to the jsx file
{
allFile(filter: {relativeDirectory: {eq: "shows"}}) {
edges {
node {
id
name
childImageSharp {
gatsbyImageData(placeholder: DOMINANT_COLOR)
}
}
}
}
}
I've tried to write some functions that compare the name properties, but I just can't seem to write anything that works. I'm not grasping something here and I just don't know what it is.
The showImage is passed in while I'm mapping through my JSON file and comparing with imageData, which is the query data. The console log is showing the right names being compared, so I know it's passing through. it's just not passing that data to the GatsbyImage.
function findImage(showImage) {
imageData.map((image) => {
console.log(image.node.name + ' vs ' + showImage)
if (image.node.name == showImage) {
/**if the image name == our show image name, we return that image data */
return data.file.childImageSharp.gatsbyImageData
}
})
return
}
My git repository is here if it helps:
https://github.com/TheComeBackGuy/TKD-Gatsby
Well, I figured out what I was doing wrong. I wasn't returning the answer to the root of the function. I'm sure a more experienced person could write it cleaner, but here's what I used.
export default function FindImage(queryArray, showImage) {
let returnStatement = null
queryArray.map((images) => {
if (images.node.name == showImage) {
console.log(showImage + ' vs ' + images.node.name)
console.log(images.node.childImageSharp.gatsbyImageData)
returnStatement = images.node.childImageSharp.gatsbyImageData
}
})
return returnStatement
}

Formatting cells with the Google Sheets API (v4)

I'm using the Google Sheets API (v4) to create/update spreadsheets programmatically and have run into the following issue:
As per the documentation (https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/cells#CellFormat), I'm setting the number format to CURRENCY; this will correctly display the number as a numeric value with a ¥ sign at the front (Japanese locale). However, it does not seem to actually select the "Currency" option on the formats dropdown, and more importantly, does NOT reflect the specified format when downloading the spreadsheet (e.g. as an .xlsx file).
This is different from selecting the 'Currency' option manually (via the UI), in which case values are correctly displayed once downloaded.
Here's the relevant section of code:
import { google, sheets_v4 } from 'googleapis';
const sheetsApi = google.sheets({
version: 'v4',
auth: await this.getAuthClient(),
});
await sheetsApi.spreadsheets
.batchUpdate({
spreadsheetId: resource,
requestBody: {
requests: [
{
updateSpreadsheetProperties: {
fields: 'locale',
properties: {
locale: 'ja',
},
},
},
...,
{
repeatCell: {
fields: 'userEnteredFormat.numberFormat',
cell: {
userEnteredFormat: {
numberFormat: { type: 'CURRENCY' },
},
},
},
},
],
},
})
.catch((error) => {
console.log(error);
});
I've also tried settings the pattern (tried few different ones), but haven't been able to actually set the cell format, despite the value being displayed as such.
Probably a simple mistake, but I've been stuck on this for a while.. any help would be greatly appreciated!
In that case, I thought that the property of pattern might be required to be set. So in this case, how about modifying your request of repeatCell as follows?
Modified request:
{
"repeatCell": {
"range": {,,,}, // Please set range.
"cell": {
"userEnteredFormat": {
"numberFormat": {
"type": "CURRENCY",
"pattern": "[$¥-411]#,##0.00" // <--- Added
}
}
},
"fields": "userEnteredFormat.numberFormat" // or "fields": "userEnteredFormat"
}
}
Note:
In my environment, when above modified request is used for the batchUpdate method, I could confirm that "Currency" was checked.
References:
RepeatCellRequest- NumberFormat

How to create a single Gatsby Page to show and filter all blog posts by tag/category

Hello i'm building a blog using Gatsby and Netlify CMS. I started off from the gatsby-starter-netlify-cms template.
I have the /blog page where i currently display all posts and also a list of all the tags.
When user clicks on a tag, it is currently redirected to the tags/name-of-tag page, where a list of all posts tagged like that is displayed.
What i want instead is to directly filter the list on the /blog page.
This way i'll have only one page to display and filter blog posts by tag (and possibly by term search).
So the tag links should redirect to /blog?tag-name or something like that.
I'm not sure how to tell Gatsby to create a single page with possibility to inject a filter value in order to pass it to the page query..
This is how /tags/ pages are created currently:
// Tag pages:
let tags = []
// Iterate through each post, putting all found tags into `tags`
posts.forEach((edge) => {
if (_.get(edge, `node.frontmatter.tags`)) {
tags = tags.concat(edge.node.frontmatter.tags)
}
})
// Eliminate duplicate tags
tags = _.uniq(tags)
// Make tag pages
tags.forEach((tag) => {
const tagPath = `/tags/${_.kebabCase(tag)}/`
createPage({
path: tagPath,
component: path.resolve(`src/templates/tags.js`),
context: {
tag,
},
})
})
This is my blog page query (the one i want to be able to filter by tag):
export const blogPageQuery = graphql`
query BlogPageTemplate {
markdownRemark(frontmatter: { templateKey: { eq: "blog-page" } }) {
frontmatter {
image {
childImageSharp {
fluid(maxWidth: 2048, quality: 80) {
...GatsbyImageSharpFluid
}
}
}
heading
subheading
}
}
allMarkdownRemark(
sort: { order: DESC, fields: [frontmatter___date] }
filter: { frontmatter: { templateKey: { eq: "blog-post" } } }
) {
edges {
node {
id
fields {
slug
}
excerpt(pruneLength: 180)
frontmatter {
date(formatString: "MMMM DD, YYYY")
title
description
featuredpost
featuredimage {
childImageSharp {
fluid(quality: 50, maxWidth: 512) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
}
}
`
I'm not sure how to tell Gatsby to create a single page with
possibility to inject a filter value in order to pass it to the page
query.
You can't. The only way to filter data in a page query is by passing data using the context. Like you are doing in with the tags page:
createPage({
path: tagPath,
component: path.resolve(`src/templates/tags.js`),
context: {
tag,
},
})
The easiest and native approach is to use the /tag/tag-name page, which is intended to filter by tag name, otherwise, you will need to get the URL parameter and using it in a JavaScript filter function to filter all the data from the page query. Since you are missing the rendering part of your blog page... Something like this approach should work:
const BlogTemplate=({ data }){
if(typeof window !== "undefined"){
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const urlTag= urlParams.get('tag');
const filteredPosts= data.allMarkdownRemark.edges.node.filter(node=> node.frontmatter.tag.includes(urlTag))
const loopData= urlParams.has('tag') ? filteredPosts : data
}
return loopData.allMarkdownRemark.edges.node.map(node=> <h1 key={node.title}>{node.title}</h1>)
}
Note: of course, adapt it to your needs but get the idea.
Note also that you will need to wrap all your window logic in the typeof window !== "undefined" condition, since in the SSR window (and other global objects) are not available.
The key part is to use wether use data or your filteredPosts depending on the existance of the URL parameter, so if it exists, you will need to filter the data otherwise, you need to use the "default" data (unfiltered).
It's difficult to guess how the code will behave but the idea relies on changing your iterable data depending on the URL, use some hooks if needed.
According to your query, it seems that your blogs don't contain any tag field in the blog template query so you will need to add it to allow the filter loop to work.
Once the code is working, you will need to add the proper controls to avoid the code-breaking when some field is missing, but the idea and the path to follow is this.

Vue.js Dynamic Image paths after compiling/runtime

I am having a problem setting dynamic image paths with Vue.js. I am using the Vue-Cli to build the project.
I believe the issue is caused because I am referencing image paths dynamically after runtime. Normally it seems the references to my ./assets/ folder are converted into ./img/ after runtime. Since I am changing the url dynamically after load the paths don't appear to work/load. Country is initially set via a store getters but is then v-modeled from a language select dropdown, where the values correspond the the url suffix.
<div id="flag-container" :style="{ backgroundImage: `url(${src})` }"></div>
computed: {
src(){
return `./assets/flags/flag-${this.country}.png`;
}
},
data() {
return {
country: this.$store.getters.language
}
}
Inspector shows url change is implemented.
Any recommendation on the best solution for this?
Using webpack require context and beforeMount, I was able to store the images in base64 format inside an object. I stored the object and accessed it with a dynamic key. Thanks Max for leading me to the right documentation.
export default {
beforeMount() {
var that = this;
function importAll(r) {
r.keys().forEach((key) => (that.imgCache[key] = r(key)));
}
importAll(require.context("../assets/flags/", true, /\.png$/));
},
computed: {
src() {
var key = `./flag-${this.country}.png`,
url = this.imgCache[key];
return url;
},
},
};
Don't use
data() {
return {
country: this.$store.getters.language
}
}
as it will stop being reactive to store changes. Use computed property
<div id="flag-container" :style="{ backgroundImage: `url(${src})` }"></div>
computed: {
src(){
return `./assets/flags/flag-${this.country}.png`;
},
country() {
return this.$store.getters.language
}
},

Elasticsearch setting up stemming and analyzer questions

I'm using ES with my node server via the package "elasticsearch": "12.1.3".
I do bulk inserts of my documents. Excerpt:
var body = [];
_.each(rows, function(doc) {
body.push({
update: {
_index: 'mytest',
_type: 'mydoc',
_id: doc.id,
_retry_on_conflict: 3
}
});
body.push({
doc: doc,
doc_as_upsert: true
});
});
client.bulk({
body: body
}, ...
On demand, to individually update documents, I have this in place:
client.index({
index: 'mytest',
type: 'mydoc',
id: doc.id,
body: doc.body
}, ...);
Everything works as expected so far. Now I'm trying to add basic 'light_english' stemming.
Looking at the Docs here
and for the JS package here
I want certain fields in my document to be "fuzzy" matched, therefore I think stemming is the way to go?
It is not clear to me how I would set this up.
Assuming I use the example settings from the link above, would this be the right way to do it:
client.cluster.putSettings({
"settings": {
"analysis": {
"filter": {
"no_stem": {
"type": "keyword_marker",
"keywords": [ "skies" ]
}
},
"analyzer": {
"my_english": {
"tokenizer": "standard",
"filter": [
"lowercase",
"no_stem",
"porter_stem"
]
}
}
}
}
});
And would this then work permanently for my two code examples above, if applied once?
Bonus question: What would be a good default analyzer plugin (or settings) I can use? My main goal is that searches for example: "Günther" would also match "gunther" and vice versa.
Might it be better to do this manually before inserting/updating documents, so that strings are lower-cased, diacritics removed etc.?

Categories

Resources