Yet another rss reader

For Reviewers

Building Raton has been tested using MacOS Big Sur 11.4 and requires Node.js 15.5.1, yarn version 1.22.10, any recent version of bash (version GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin20) is shipped with Big Sur and used) and jq version jq-1.6.

To install the dependencies: yarn install To build the extension: ./bin/release

Feed Article Sanitization

In ./src/components/article_browser/ArticleBrowser.svelte you might see the line:

{@html $selectedArticle.content}

Which is Sveltes way of basically doing element.innerHTML = stuff; While normally potentially dangerous, this content is pre-sanitized during the fetching and processing of feeds, in ./src/lib/feeds/transforms/sanitizer.ts using the DOMPurify package.

Development

Raton is built with mainly: Typescript and Svelte. TailwindCSS is used for most styling, Prettier is used for formatting, Rollup for bundling. Storage of articles is done with Dexie and IndexedDB, parsing is with some hand-rolled parsers in lib/feeds.

Credits:

Setup

An asdf .tools-versions file is provided with the recommended node version. Dependencies are managed through yarn:

yarn install

Developing

Raton is built and bundled with Rollup as it provides the best experience with Svelte's own tools and produces the best bundles that keep Mozilla's linter happy compared to Parcel v2 and other bundlers.

The start:rollup command to have Rollup watch files and automatically rebuild:

yarn start:rollup

Additionally, Storybook is setup with the Svelte CSF format for documenting, previewing and rapidly developing components; Check out any of the .stories.svelte files for examples and run Storybook with:

yarn storybook

To kick off a full production grade build of the extension's JS and CSS into dist/, use the build:rollup command which will add some treeshaking and remove source maps, etc:

yarn build:rollup

A Note On Bundling Due to some limitiations with ES modules in Firefox (mainly in content scripts), Rollup builds each content script separately as IIFE's to avoid ESM . This comes with a few downsides in the content scripts, mainly the lack of proper support for dynamic import() statements and code splitting.

Known To Dos

(These should eventually be tracked in fossil better, but for now they're here.)

This list is mostly ordered generally by priority as I see it:

  • [X] Basic Feed Management
    • [X] Add feed
    • [X] Remove feed
    • These are working but the UX is a little wonky still
  • [-] Bulk article management (bulk read/unread at least)
    • Bulk mark as read is working
  • [X] OPML Import/Export
    • Working but probably bug filled
  • [X] Explicit refresh of articles and fetching feeds
  • [X] Refresh of article list
    • maybe some "load new articles" indicator to not have a jarring experience?
    • Somewhat done, could be hooked up automatically
    • need to see about keeping the scroll at the same location
  • [X] Keyboard shortcuts
  • [-] Settings panels
    • [X] General Settings
    • Preferred locale?
      • Don't have additional locales yet, so this doesn't make much sense for now
    • [X] Configurable keyboard shortcuts
    • [X] Credits Panel
    • [ ] Tutorial/Help panels
    • [X] Update News panel
    • Something like? Keep a Changelog
  • [-] Documentation on building and reviewing
  • [ ] Guess I should write some tests or something

    • AVA and ESM seem to not agree so there is a custom tsconfig to handle tests :/
  • [X] Debugging tools

    • DB exporter/importer
  • [x] Storybook document the various components for easier development/styling work

    • Work in progress as components get written but this is setup and working
  • [x] Article read/unread functionality

  • [x] Feeds in sidebar, view articles on a per feed basis

    • [x] Unread badges/chips
  • [X] Limited loading of chunks of articles within a virtualized list

  • [x] Better build script that walks through the steps to ensure things are correctly setup and ready to go for a new version

Road Map Features

  • [ ] Bug reporting with sentry or similar

    • Need a privacy statement and explanation on what data is captured
  • [ ] Renaming/editing feed titles

  • [ ] Dark mode support

  • [ ] Advanced importing to be able to select which feeds from the import to subscribe to

  • [ ] Feed organization with "folders"

  • [ ] Advanced filtering and sorting of articles (filter by unread, sort by title, sort by date fetched)

  • [ ] Feedback system

    • Like VS Codes: :) or :( emoji and a free form text input?
    • Where to send feedback?
    • Could just redirect to the forum in fossil or something

Known Bugs

Ideas

These need to be fleshed out a bit before they're ready to be ditched or moved to the roadmap as new features.

  • Custom Branding?

  • Custom fetch interval?

    • Over-ridable per feed
  • Command palette style interface for switching feeds quickly

  • Tooling to convert a markdown changelog to something that's usable in the release notes section

  • Tooling to automatically make the credits page for libraries used?

  • Details on the feed management page for geeks and nerds

    • Total items stored
    • subscribed on
    • feed type
    • image/additional channel details
    • last checked on
  • Better feedback for (un)subscribing to feeds?

  • Article & Feed search

  • Alternative article list views

  • Staring articles (to avoid deleting and being able to find them later)

  • Deleting/hiding articles

  • Specialized handling of lobst.rs and hackernews feeds to have tabs for "Article in an iframe" and "comments in an iframe" ?

    • Maybe some sort of plugin setup for custom handling of different feeds
    • This is somewhat done where comment links show up in the article viewer
  • Notifications for new items from all or specific feeds

  • Pruning of feed articles after X time

  • Feed Discovery Page action

    • Could just open the app to /manage/add?url= for starters
  • Configurable color schemes

Testing

This bit is a mess, fair warning. Tests make use of AVA as the runner and assertion library.

Unit

yarn test:unit

These are the fastest and should be covering more of the business logic. General rule of thumb is if business logic is living in a component file that makes it hard to unit test: move it out into it's own function/module.

Resources:

Integration

yarn test:integration

Spins up JSDom environments for each context to test general integration between them without needing the full browser. These environments also include mocking of the browser api and some other helpful tooling. Check out tests/integration/setup.ts for more information.

Resources:

System

yarn test:system

Spins up a full browser instance to test the extension extensions behavior; These are extremely slow, however, and should be limited to E2E unless logical. Check out tests/system/setup.ts for more information.

A couple of helpers are provided as well:

async switchToBrowserChrome(geckodriver) - Switchs the selenium web driver to control the browser chrome async switchToBrowserContent(geckodriver) - Switchs the selenium web driver to control the current window/tab's content. Needed for navigations and for interacting with the content script UI async navigateTo(geckodriver, path) - Navigates the browser and sets the selenium web driver to controlling the browser chrome. Handles relative paths from tests/system/pages/ to help test the content scripts against various page set ups. async takeScreenshot(geckodriver) - Takes a screenshot of the window and saves it to ./screenshot-<date>.png

Resources:

Production Builds

Pretty simple, first ensure that you've updated the release notes:

  • Release notes are currently in ./src/components/settings/release_notes as a svelte component per version
  • Make sure it's pulled in and rendering in ./src/components/settings/ReleaseNotes.svelte
  • Increment the version in package.json to the correct new version matching the release notes

When all done, run:

./bin/release

This will build the extension in production mode, and produce the AMO ready zip in web-ext-artifacts/raton-<version>.zip.