Replies: 4 comments 6 replies
-
|
Hhmm, I'm not sure what the format of the WordPress REST API response is, but I'd probably start by creating a custom collection in your .eleventy.js config file using Biggest issue I can imagine is that the format of the 11ty collection data and exported WordPress data will be very different, so you might want to normalize the data a bit and keep the minimum amount of data like: date, title, excerpt, url, etc. so that the format of the object is consistent. |
Beta Was this translation helpful? Give feedback.
-
|
So, after a week tweaking and learning 11ty and playing around, I have a clearer idea of what I was trying to achieve when I asked the question: how do I merge the tags from WordPress posts and use them like tags in .md files? Here are some details for reference about the process and in case people are trying to achieve something similar: First of all to simplify the process I added a function in my WordPress theme to ease the process of getting tags info: WordPress posts contain only tags IDs and this means you have to also grab the API response for tags and match IDs with names etc... For now I went for a simpler way: I added a field in the API to output an array of tags names from WordPress: /* PHP in my wp-themes/mytheme/functions.php */
// Ajouter une nouvelle entrée dans la REST API
// https://developer.wordpress.org/reference/functions/register_rest_field/
// https://imranhsayed.medium.com/add-custom-field-to-wordpress-rest-api-35c63c6dfff4
add_action( 'rest_api_init', 'gk_add_custom_fields' );
function gk_add_custom_fields() {
register_rest_field(
'post',
'tags_names', //New Field Name in JSON RESPONSEs
array(
'get_callback' => 'gk_get_custom_fields', // custom function name
'update_callback' => null,
'schema' => null,
)
);
}
function gk_get_custom_fields( $object, $field_name, $request ) {
// grab all tags for this post
$tags_objects = get_the_tags($object['id']);
$tags_names = [];
// return an array of this posts' tags' names only
foreach ($tags_objects as $tag) {
$tags_names[] = $tag->name;
}
return $tags_names;
};Then I grab the posts using a script (something similar to this) with a subtlety: I'm building two files, one is the response from the API, the other one is a simpler .json file only containing the data I want, formatted in a way similar to how 11ty organizes data (I think): // script in grabWP.js
#!/usr/bin/env node
const fs = require("node:fs/promises");
const axios = require("axios");
grabWP();
async function grabWP() {
// write content of fetched pages into a posts_full.json file
const posts_full = await fetchPages();
await fs.writeFile("_data/posts_full.json", JSON.stringify(posts_full));
console.log(`Done! ${posts_full.length} full posts written to posts_full.json`);
// iterate through this first file and build an array from the only info I nee:
// (id, title, date, tag names (from a custom field created earlier in the WordPress theme, slug, content, etc.))
const posts_simple = [];
posts_full.forEach(post => {
var arr = {
"id": post.id,
"title": post.title.rendered,
"date": post.date,
"tags": post.tags_names,
"slug": post.slug,
"content": post.content.rendered
};
posts_simple.push(arr);
});
// create another file from this data
fs.writeFile("_data/posts.json", JSON.stringify(posts_simple));
}
async function fetchPages(page = 1) {
const res = [];
let totalPages = 1;
do {
console.log(`Fetching page ${page}/${totalPages}`);
const { data, headers } = await axios.get("https://www.geeks-curiosity.net/wp-json/wp/v2/posts", {params: {per_page:50, page}});
res.push(data);
totalPages = headers['x-wp-totalpages'];
page += 1;
} while (page <= totalPages);
return res.flat();
}I end up with a nice file containing only the necessary infos from my posts from WordPress . This posts.json is used to create pages like // post.njk
---
pagination:
data: posts
size: 1
alias: posts
permalink: "posts/{{ posts.slug }}/"
layout: default
---
{# The ids used here are from the posts.json, a simplified array of WP data generated by grabWP.js #}
<h1>{{ posts.title | safe }}</h1>
<span class="">🏷️ Tags :
{% for tag in posts.tags %}
<a href="/tag/{{ tag | safe | slug }}">{{ tag | safe }}</a>
{% endfor %}
</span>
<div class="mainContent">
{{ posts.content | safe }}
</div>In the same spirit I've also made a Now. I'm struggling with a 11ty subtlety. How should I do to merge the tags from the I tried changing this in many ways but to no effect, it still produces only an array of tags from markdown files, I did not manage to add the item.tags from my posts.json file // .eleventy.js
eleventyConfig.addCollection("tagList", function(collection) {
let tagSet = new Set();
collection.getAll().forEach(item => {
// gather all tags from every note
(item.data.tags || []).forEach(tag => tagSet.add(tag));
});
return filterTagList([...tagSet]);
});For reference here is the template tags.njk that generates the tag pages // tags.njk
---
layout: default
pagination:
data: collections
size: 1
alias: tag
permalink: /tags/{{ tag }}/
---
<h1>Étiquette: « {{ tag }} »</h1>
<ul>
{% set taglist = collections[ tag ] %}
{% for p in taglist | sort(false, false, 'data.title') %}
<li data-tags="{{ p.data.tags }}"><a href="{{ p.url }}">{{ p.data.title }}</a></li>
{% endfor %}
</ul> |
Beta Was this translation helpful? Give feedback.
-
|
Essentially I suppose my question boils down to: how do you merge two collections into one, one data set coming from a JSON file (REST API) and the other one coming from a series of mardown files with frontmatter. Once I figure that out I can either create a common feed for merged data, and/or have 11ty grab tags and other info from both collections, etc.. Thanks in advance to anyone that can guide me in the right direction. |
Beta Was this translation helpful? Give feedback.
-
|
OK, I ran your fetch script and tried to get a basic version working locally using your WP JSON endpoint. // src/posts.11tydata.js
module.exports = {
pagination: {
data: "posts",
size: 1,
alias: "post",
addAllPagesToCollections: true,
},
permalink: "posts/{{ post.slug }}/",
eleventyComputed: {
tags: ({post}) => post.tags,
title: ({post}) => post.title,
},
// layout: "default",
};And then modified the front matter of src/posts.njk: ---
# src/posts.njk
## see ./posts.11tydata.js
---Then I think you run into the problem where dynamically set Here's my rough .eleventy.js config file: // .eleventy.js
module.exports = function (eleventyConfig) {
const posts = require("./src/_data/posts.json");
// Create a tag list for our dynamically set tags via src/_data/posts.json.
const postsTagList = posts.reduce((acc, post) => {
(post.tags || []).forEach(tag => acc.add(tag));
return acc;
}, new Set());
for (const t of [...postsTagList]) {
eleventyConfig.addCollection(t, function (collection) {
return collection.getFilteredByTag(t);
});
}
...
};So we manually create collections based on the dynamically set find www/tags/**/index.html | sort -f | pbcopy
# Feels like a weird URL
www/tags/2001 l'Odyssée de l'espace/index.html
...
# Space in URL path.
www/tags/2K Games/index.html
...
# `@` in URL path.
www/tags/@Atlanta/index.html
# Note /AC/DC/ has extra folder "depth" to `/` in tag name.
www/tags/AC/DC/index.html
# More escaping stuff.
www/tags/AD&amp;D/index.html
www/tags/adaptation jeu vidéo au cinéma/index.html
...
# Note "metal" and "Métal", when I used `|slugify` filter, these conflicted and threw permalink errors.
www/tags/metal/index.html
www/tags/Métal/index.html
...> eleventy
[11ty] Wrote 622 files in 0.24 seconds (0.4ms each, v1.0.2) |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Is it possible to compose a single feed of posts but that are coming from two different sources?
In my specific case I would have a json file coming from WordPress REST API and mardown files stored locally. Is there a way to combine the two in a chronological order for example?
I'm new to 11ty and any examples or similar project you know of would be welcome. Thanks!
Beta Was this translation helpful? Give feedback.
All reactions