Irodr exposes window.userScript for user scripts (Greasemonkey, Violentmonkey, Tampermonkey, browser extensions).
See resources/userScript for examples.
Irodr dispatches userscript-init on window when the API is ready. Listen for it before using window.userScript.
window.addEventListener("userscript-init", (event) => {
// event.detail.userScript === window.userScript
});The focused item.
interface UserScriptActiveContent {
id: string;
author: string;
publishedDate: Date;
// Same as publishedDate when not updated
updatedDate: Date;
title: string;
body: { content: string };
url: string;
}The open feed.
interface UserScriptActiveSubscription {
title: string;
// The feed URL, or the site URL when the source has no feed URL (GitHub)
url: string;
iconUrl: string;
htmlUrl: string;
}Bind a shortcut, e.g. "n" or "shift+n". It replaces a default binding of the same keys, as in irodr 1.x.
Run the handlers bound to keys, e.g. triggerKey("j") moves to the next item.
The built-in actions by name, e.g. getDefaultActions()["move-next-content-item"]().
window.userScript.event.subscribe(event: string, handler: (content) => void): () => void
| Event | When |
|---|---|
SubscriptionContent::componentDidMount |
An item is rendered |
SubscriptionContent::componentDidUpdate |
A rendered item changes or is focused |
SubscriptionContent::componentWillUnmount |
An item is removed |
content has contentId, title, url, author, body (HTML), isFocus, publishedDate and updatedDate.
These class names and attributes are stable for user scripts:
| Selector | Element |
|---|---|
.SubscriptionContentsContainer |
The scrolling article view |
.SubscriptionContentsContainer-content |
An item, with data-content-id |
.SubscriptionContentsContainer-contentTitle |
An item's title |
.SubscriptionContentsContainer-contentBody |
An item's body |
.SubscriptionContentsContainer-contentFooter |
An item's footer (dates) |
.SubscriptionListContainer-item |
A feed, with data-feedid |
.ng-content |
Hides an item's content |
window.addEventListener("userscript-init", () => {
userScript.event.subscribe("SubscriptionContent::componentDidMount", (content) => {
const element = document.querySelector(`[data-content-id="${CSS.escape(content.contentId)}"]`);
if (element && /^PR:/.test(content.title)) {
element.querySelector(".SubscriptionContentsContainer-contentTitle").classList.add("ng-content");
element.querySelector(".SubscriptionContentsContainer-contentBody").setAttribute("hidden", "");
}
});
});Shift+T translates the focused item from English to Japanese with the browser's
Translator API. A user script can provide a translator instead:
window.irodrTranslator = {
async translateBatch(texts, sourceLanguage, targetLanguage) {
return texts; // translated texts, in the same order
}
};Irodr uses the Translator API first and the user script's translator when the Translator API is unavailable
(e.g. Firefox and Safari, or Chrome without the language pack). Translation starts at the paragraphs on screen and
continues as the article is scrolled: translateBatch receives about 300 characters of text at a time, and link
labels are translated in place so links keep working.
irodr-translate.user.js is a translator with Google Translate.
It calls translate.googleapis.com/translate_a/single, the unofficial endpoint that browser extensions such as
Traduzir-paginas-web use, through GM_xmlhttpRequest
because the endpoint does not allow CORS. The endpoint is not a documented API: Google may rate-limit or change it,
so use it at your own risk. Change CLIENT in the script when requests start failing with HTTP 429 or 403.