|
7 months ago | |
---|---|---|
.github/workflows | 2 years ago | |
.yarn/releases | 2 years ago | |
src | 7 months ago | |
test | 7 months ago | |
.gitignore | 1 year ago | |
.yarnrc.yml | 1 year ago | |
README.md | 7 months ago | |
jam-my-stack.sublime-project | 2 years ago | |
jest.config.js | 2 years ago | |
package-lock.json | 2 years ago | |
package.json | 7 months ago | |
yarn.lock | 9 months ago |
README.md
jam-my-stack 🥞
A set of simple IndieWeb Jamstack publishing syndication tools
Published at https://www.npmjs.com/package/jam-my-stack
These simple scripts enrich your Jamstack-site by adding/manipulating/whatever (meta)data, such as extra posts, indexing, and so forth. A primary example of these tools in action is my own site https://brainbaking.com - inspect how it's used at https://git.brainbaking.com/wgroeneveld/brainbaking
Are you looking for a way to receive webmentions? See https://git.brainbaking.com/wgroeneveld/go-jamming !
The tools
Usage:
yarn add jam-my-stack
const { mastodon, goodreads } = require('jam-my-stack')
1. Mastodon
1.1 parseFeed
An async function that parses your Fediverse-compatible feed (Mastodon/Pleroma/...) and converts entries to .md
Markdown files for your Jamstack to enjoy.
Usage example:
await mastodon.parseFeed({
notesdir: `${__dirname}/content/notes`,
url: "https://chat.brainbaking.com/users/wouter/feed",
utcOffset: 60,
titleCount: 50,
titlePrefix: "Note: "
})
Options and their default values:
utcOffset
:60
(= GMT+1, that's where I am!) (in minutes, see day.js docstitleCount
:50
. Will add "..." and trim if title length bigger.titlePrefix
:""
. Will add before title (e.g. "Note: ")ignoreReplies
:false
. If true, will not processin-reply-to
items.
Note that this does not delete the notes dir with every call. It simply checks if there isn't already a file with the same name (based on the publication date), and adds one if not.
Example feed entry:
<entry>
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
<id>https://chat.brainbaking.com/objects/77a3ecfb-47e1-4d7a-a24a-8b779d80a8ac</id>
<title>I pulled the Google plug and installed LineageOS: https://brainbaking.com/post/2021/03/getting-ri...</title>
<content type="html">I pulled the Google plug and installed LineageOS: <a href="https://brainbaking.com/post/2021/03/getting-rid-of-tracking-using-lineageos/" rel="ugc">https://brainbaking.com/post/2021/03/getting-rid-of-tracking-using-lineageos/</a> Very impressed so far! Also rely on my own CalDAV server to replace GCalendar. Any others here running <a class="hashtag" data-tag="lineageos" href="https://chat.brainbaking.com/tag/lineageos" rel="tag ugc">#lineageos</a> for privacy reasons?</content>
<published>2021-03-01T19:03:35.273023Z</published>
<updated>2021-03-01T19:03:35.273023Z</updated>
<ostatus:conversation ref="https://chat.brainbaking.com/contexts/ff9aa62e-3357-41ad-951d-15f6ad506424">
https://chat.brainbaking.com/contexts/ff9aa62e-3357-41ad-951d-15f6ad506424
</ostatus:conversation>
<link href="https://chat.brainbaking.com/contexts/ff9aa62e-3357-41ad-951d-15f6ad506424" rel="ostatus:conversation"/>
<summary></summary>
<link type="application/atom+xml" href='https://chat.brainbaking.com/objects/77a3ecfb-47e1-4d7a-a24a-8b779d80a8ac' rel="self"/>
<link type="text/html" href='https://chat.brainbaking.com/objects/77a3ecfb-47e1-4d7a-a24a-8b779d80a8ac' rel="alternate"/>
<category term="lineageos"></category>
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://chat.brainbaking.com/users/wouter"/>
</entry>
This generates the file 01h20m03s35.md
(it assumes UTC times in the feed and adjusts according to specified utcOffset
, such as GMT+1 in this example), with contents:
---
source: "https://chat.brainbaking.com/objects/77a3ecfb-47e1-4d7a-a24a-8b779d80a8ac"
title: "I pulled the Google plug and installed LineageOS: https://brainbaking.com/post/2021/03/getting-ri..."
date: "2021-03-01T19:03:35"
---
I pulled the Google plug and installed LineageOS: <a href="https://brainbaking.com/post/2021/03/getting-rid-of-tracking-using-lineageos/" rel="ugc">https://brainbaking.com/post/2021/03/getting-rid-of-tracking-using-lineageos/</a> Very impressed so far! Also rely on my own CalDAV server to replace GCalendar. Any others here running <a class="hashtag" data-tag="lineageos" href="https://chat.brainbaking.com/tag/lineageos" rel="tag ugc">#lineageos</a> for privacy reasons?
See implementation for more details and features.
Also parsers:
<link rel="enclosure"/>
image types (seerender-enclosures.ejs
) ejs template, that is appended to the Markdown file if any are found. Styling is up to you...... @https://blah.com/blie hi there
- this is a in-reply-to toot which addscontext
frontmatter, so your html renderer can use the correct IndieWeb classes. This should also enable webmention sending since you mention the URL. If you "at" a valid Mastodon user, it will automatically do this.
2. Goodreads
2.1 createWidget
An async function that reads and modifies Goodreads JS widget embed code, converting low-res book covers to hi-res ones if possible. This omits possible Goodread cookies and cross-domain mishaps.
Usage example:
const widget = await goodreads.createWidget("https://www.goodreads.com/review/grid_widget/5451893.Wouter's%20bookshelf:%20read?cover_size=medium&hide_link=&hide_title=&num_books=12&order=d&shelf=read&sort=date_added&widget_id=1496758344")
await fsp.writeFile(`${__dirname}/static/js/goodreads.js`, widget, 'utf-8')
3. Lunr
As of version 1.0.30
, Lunr functionality was removed in favor of https://pagefind.app/
With Pagefind, there's no need to integrate it into jam-my-stack, greatly simplifying things and reducing the index file size.
4. Howlongtobeat
4.1 howlong
Adds https://howlongtobeat.com/ game length (MainGame
) and an ID to your front matter (keys howlongtobeat_id
and howlongtobeat_hrs
), provided you first added a property called game_name
. (This gets substituted).
It also downloads a thumbnail of the cover image as cover.jpg
in the same relative directory as the source article if you provided the dir as an option. The downloaded thumbnail is automatically optimized for the web using mogrify
(this will emit a warning if you do not have ImageMagick installed locally).
So, Frontmatter like this:
---
title: Diablo 3 my Review
game_name: Diablo 3
---
Gets subsituted by something like this:
---
title: Diablo 3 my Review
howlongtobeat_id: 62129
howlongtobeat_hrs: 20.5
---
In your Hugo template, add a link to https://howlongtobeat.com/game?id={howlongtobeat_id}
and you're all set!
Usage example:
await howlong({
postDir: `${__dirname}/content`,
downloadDir: `${__dirname}/static`)
It will print out games and metadata it found.
Suppose the above diablo-3.md
lives in content/games/switch/diablo-3
, then a cover.jpg
will be automatically downloaded in static/games/switch/diablo-3/
and that directory will be created if not yet existing.
Working example: https://jefklakscodex.com/games/diablo-3/ (on the left side). Check out the Hugo template to use the properties at https://git.brainbaking.com/wgroeneveld/jefklakscodex.
5. Webmentions
In cooperation with https://git.brainbaking.com/wgroeneveld/go-jamming
5.1 getWebmentions
Calls the get webmention endpoint, sorts by date, adds metadata such as relative date (relativeTarget
, property), and returns data. Could be written in a data
folder for Hugo to parse, for example.
Parameters: first domain
, second the config for the endpoint and token. Usage example:
await getWebmentions("brainbaking.com", {
endpoint: 'https://jam.brainbaking.com',
token: 'lol'
})
5.1 send
Calls the set webmention endpoint using a PUT
. Based on the RSS feed, see the go-jamming README.
Same as getWebmentions
.
6. YouTube
Thanks to ideas from rubenerd.com and his video.sh script. This downloads a thumbnail using youtube-dl
, smacks a play button on it using convert
, and stores that in the specified folder. Use in conjunction with a Hugo shortcode to get rid of YouTube's iframes!
This method will fail if you do not have ImageMagick installed locally.
Usage example:
await download({
postDir: 'somewhere/posts',
downloadDir: 'static/youtube-thumbs',
overlayImg: 'playbtn.png'
})
It scans all .md
files in the posts dir for {{< youtube xxx >}}
shortcodes.