diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 28d65a02..b2ab81c3 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,17 +1,5 @@ version: 2 updates: - - package-ecosystem: bundler - directory: "/" - schedule: - interval: weekly - open-pull-requests-limit: 10 - allow: - - dependency-type: direct - - dependency-type: indirect - groups: - ruby: - patterns: - - "*" - package-ecosystem: "npm" directory: "/" schedule: diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 09f40c47..0d1c67ad 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -24,12 +24,6 @@ jobs: node-version: "22" cache: "npm" - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: 3.4 - bundler-cache: true - - name: Install dependencies run: npm ci diff --git a/.rubocop.yml b/.rubocop.yml deleted file mode 100644 index f7cf9277..00000000 --- a/.rubocop.yml +++ /dev/null @@ -1,8 +0,0 @@ -AllCops: - NewCops: enable - TargetRubyVersion: 3.4 - DisplayCopNames: true - -Style/DoubleNegation: - Exclude: - - bin/data-update diff --git a/AGENTS.md b/AGENTS.md index ae1250b8..e0381b04 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,14 +9,13 @@ What this repo owns: - docs content and navigation under `src/content/docs/` - docs-specific components and styling under `src/components/` -- feed-directory presentation and client behavior -- generated docs data consumed by the site (`src/data/configs.json`) +- feed-directory presentation and client behavior (`FeedDirectory.astro`, `feed-directory.js`) What this repo does not own: - runtime extractor behavior and CLI semantics (`html2rss/`) -- web API behavior and OpenAPI generation (`html2rss-web/`) -- feed YAML catalog definitions (`html2rss-configs/`) +- catalog metadata, YAML configs, or catalog serialization (`html2rss-configs/` β†’ `Html2rss::Configs::Catalog`) +- catalog HTTP API (`html2rss-web/` β†’ `GET /api/v1/configs`) When docs describe behavior from other repos, treat those repos as source-of-truth and update docs to match them. @@ -30,40 +29,41 @@ Before substantial edits, state cross-repo context in your notes: Common contracts: -- Feed directory data comes from `html2rss-configs` via `bin/data-update`. +- Feed Directory browse data comes from `{instance}/api/v1/configs` on a running `html2rss-web` instance (see OpenAPI in `html2rss-web`). +- Instance URL persistence: default public instance, `#!url=` hash deep link from the web app, and browser localStorage (see `feed-directory.js`). +- Deep link from `html2rss-web`: `https://html2rss.github.io/feed-directory/#!url={encodedInstanceUrl}` must keep working. +- Catalog metadata in YAML (`directory.title`, `directory.summary`, `directory.topics`) is authored in `html2rss-configs` only. - Ruby gem docs should match `html2rss` behavior and CLI output. - Web application docs should match `html2rss-web` behavior and published OpenAPI. If a cross-repo behavior changed but upstream is not updated yet, document the gap clearly instead of inventing new behavior. -## Generated Artifacts +## Feed Directory (agent maintenance) -Treat `src/data/configs.json` as generated. +- The browse UI is a **thin client**: fetch catalog JSON from the active instance, render rows client-side, build RSS links from each entry's `path`. +- Do not reintroduce `bin/data-update`, `src/data/configs.json`, or a `html2rss-configs` gem dependency in this repo. +- Wire shape v1 is defined in `html2rss-web` request specs and OpenAPI (`catalog_version`, `parameters.schema`, `parameters.defaults`). +- When the instance is unreachable or returns `404` with `catalog_disabled`, show an error state β€” no static fallback list. -- Do not hand-edit it. -- Regenerate with repo-native commands: - - `make update` - - or `bin/data-update` (after dependencies are installed) -- `bin/data-update` reads packaged configs (from `html2rss-configs`) and writes `src/data/configs.json`. +## Generated Artifacts -If a change only affects generated data, include the source change rationale in the PR description. +This repo has no generated catalog data. Do not add a packaged-config snapshot back into the docs build. ## Build, Test, and Dev Commands Run commands from `html2rss.github.io/`: -- `make setup` installs dependencies and refreshes generated data +- `make setup` installs npm dependencies - `make dev` runs Astro locally - `make build` builds production output - `make lint` checks formatting - `make lintfix` applies formatting fixes -- `make update` refreshes feed-directory data from packaged configs Preferred verification flow for docs/content changes: 1. Run targeted check(s) first (`make lint` or `make build`). 2. Run the broader check set before PR (`make lint` and `make build`). -3. If feed directory or config references changed, run `make update` and verify resulting diffs. +3. For feed-directory UI changes, spot-check against a running instance with catalog enabled (`GET /api/v1/configs` returns entries). ## Docs Authoring Rules diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 0e904547..00000000 --- a/Gemfile +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -source 'https://rubygems.org' - -gem 'html2rss', '~> 0.26' -gem 'html2rss-configs', git: 'https://github.com/html2rss/html2rss-configs.git' diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 702593e1..00000000 --- a/Gemfile.lock +++ /dev/null @@ -1,140 +0,0 @@ -GIT - remote: https://github.com/html2rss/html2rss-configs.git - revision: b7434d6687394cef758677f8b40cdf55a684a6b7 - specs: - html2rss-configs (0.2.0) - html2rss - -GEM - remote: https://rubygems.org/ - specs: - addressable (2.9.0) - public_suffix (>= 2.0.2, < 8.0) - bigdecimal (4.1.2) - brotli (0.8.0) - concurrent-ruby (1.3.8) - crass (1.0.7) - dry-configurable (1.4.0) - dry-core (~> 1.0) - zeitwerk (~> 2.6) - dry-core (1.2.0) - concurrent-ruby (~> 1.0) - logger - zeitwerk (~> 2.6) - dry-inflector (1.3.1) - dry-initializer (3.2.0) - dry-logic (1.6.0) - bigdecimal - concurrent-ruby (~> 1.0) - dry-core (~> 1.1) - zeitwerk (~> 2.6) - dry-schema (1.16.0) - concurrent-ruby (~> 1.0) - dry-configurable (~> 1.0, >= 1.0.1) - dry-core (~> 1.1) - dry-initializer (~> 3.2) - dry-logic (~> 1.6) - dry-types (~> 1.9, >= 1.9.1) - zeitwerk (~> 2.6) - dry-types (1.9.1) - bigdecimal (>= 3.0) - concurrent-ruby (~> 1.0) - dry-core (~> 1.0) - dry-inflector (~> 1.0) - dry-logic (~> 1.4) - zeitwerk (~> 2.6) - dry-validation (1.11.1) - concurrent-ruby (~> 1.0) - dry-core (~> 1.1) - dry-initializer (~> 3.2) - dry-schema (~> 1.14) - zeitwerk (~> 2.6) - faraday (2.14.3) - faraday-net_http (>= 2.0, < 3.5) - json - logger - faraday-follow_redirects (0.5.0) - faraday (>= 1, < 3) - faraday-gzip (3.1.0) - faraday (>= 2.0, < 3) - zlib (~> 3.0) - faraday-net_http (3.4.4) - net-http (~> 0.5) - hana (1.3.7) - html2rss (0.26.0) - addressable (~> 2.7) - brotli - dry-validation - faraday (> 2.0.1, < 3.0) - faraday-follow_redirects - faraday-gzip (~> 3) - kramdown - mcp (~> 1.0) - mime-types (> 3.0) - nokogiri (>= 1.10, < 2.0) - rack (~> 3.0) - rackup (~> 2.0) - regexp_parser - reverse_markdown (~> 3.0) - rss - sanitize - thor - tzinfo - webrick (~> 1.9) - zeitwerk - json (2.21.2) - json_schemer (2.5.0) - bigdecimal - hana (~> 1.3) - regexp_parser (~> 2.0) - simpleidn (~> 0.2) - kramdown (2.5.2) - rexml (>= 3.4.4) - logger (1.7.0) - mcp (1.2.0) - json_schemer (>= 2.4) - mime-types (3.7.0) - logger - mime-types-data (~> 3.2025, >= 3.2025.0507) - mime-types-data (3.2026.0701) - net-http (0.9.1) - uri (>= 0.11.1) - nokogiri (1.19.4-arm64-darwin) - racc (~> 1.4) - nokogiri (1.19.4-x86_64-linux-gnu) - racc (~> 1.4) - public_suffix (7.0.5) - racc (1.8.1) - rack (3.2.7) - rackup (2.3.1) - rack (>= 3) - regexp_parser (2.12.0) - reverse_markdown (3.0.2) - nokogiri - rexml (3.4.4) - rss (0.3.3) - rexml - sanitize (7.0.0) - crass (~> 1.0.2) - nokogiri (>= 1.16.8) - simpleidn (0.2.3) - thor (1.5.0) - tzinfo (2.0.6) - concurrent-ruby (~> 1.0) - uri (1.1.1) - webrick (1.9.2) - zeitwerk (2.8.3) - zlib (3.2.3) - -PLATFORMS - arm64-darwin-23 - arm64-darwin-24 - arm64-darwin-25 - x86_64-linux - -DEPENDENCIES - html2rss (~> 0.26) - html2rss-configs! - -BUNDLED WITH - 4.0.9 diff --git a/Makefile b/Makefile index f809ba7c..401598b1 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,7 @@ -default: setup clean lintfix dev +default: setup lint dev setup: npm ci - bundle check || bundle - make update dev: npm run dev @@ -26,7 +24,3 @@ lintfix: clean: find . -type d -empty -delete find . -type f -empty -delete - -update: - bundle update html2rss-configs - bin/data-update diff --git a/README.md b/README.md index 773adb1a..8d0a40cc 100644 --- a/README.md +++ b/README.md @@ -8,35 +8,34 @@ website. ### Prerequisites - Node.js (for Astro) -- Ruby (for data updates) ### Quick Setup ```bash -# Install dependencies and refresh generated feed data +# Install dependencies make setup # Start the local Astro development server make dev ``` +Feed Directory browse data comes from a running `html2rss-web` instance (`GET /api/v1/configs`). For local feed-directory testing, run an instance (for example from `html2rss-web`) and point the directory UI at it. + ### πŸ’» Try in Browser You can develop html2rss directly in your browser using GitHub Codespaces: [Open in GitHub Codespaces](https://github.com/codespaces/new?repo=html2rss/html2rss.github.io) -The Codespace provides a cloud development environment with Node.js and Ruby pre-installed. Run `make setup` to install dependencies and get started! +The Codespace provides a cloud development environment with Node.js pre-installed. Run `make setup` to install dependencies and get started! ### Available Commands -- `make setup` - Install dependencies and refresh generated feed data +- `make setup` - Install npm dependencies - `make dev` - Start Astro development server - `make build` - Build for production - `make preview` - Preview production build -- `make build-full` - Update data and build for production - `make lintfix` - Fix code formatting -- `make update` - Update feed data ## 🌐 Community & Resources diff --git a/bin/data-update b/bin/data-update deleted file mode 100755 index 618e09c6..00000000 --- a/bin/data-update +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true - -require 'rubygems' -require 'bundler/setup' - -require 'fileutils' -require 'html2rss' -require 'html2rss/configs' -require 'uri' -require 'yaml' -require 'json' - -file_names = Html2rss::Configs.file_names.sort - -def extract_default_parameters(parameters) - return {} unless parameters.is_a?(Hash) - - parameters.each_with_object({}) do |(param_name, param_config), defaults| - defaults[param_name] = param_config['default'] if param_config.is_a?(Hash) && param_config['default'] - end -end - -def valid_url(url) - !!URI(url) -rescue StandardError - false -end - -def string_formatting_references(string) - string.to_s.scan(/%[{<](\w+)[>}](\w)?/).to_h.transform_values do |value| - case value - when 'i', 'd', 'u' - Numeric - else - String - end - end -end - -output = file_names.map do |file_name| - config = YAML.safe_load(File.open(file_name), symbolize_names: false) - - file_name_splits = file_name.split('/') - - # Extract default parameter values from the parameters section - default_parameters = extract_default_parameters(config['parameters']) - - { - 'domain' => file_name_splits[-2..-2].join, - 'name' => File.basename(file_name_splits[-1..].join, '.*'), - 'valid_channel_url' => valid_url(config['channel']['url']), - 'url_parameters' => string_formatting_references(config['channel']['url']), - 'default_parameters' => default_parameters, - 'channel' => config['channel'], - 'directory' => config['directory'] - } -end - -config_file = File.join(__dir__, '..', 'src/data/configs.json') -FileUtils.touch config_file - -json_content = JSON.pretty_generate(output) - -File.write(config_file, json_content) diff --git a/package.json b/package.json index 94a3c027..dbfe04f7 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,7 @@ "build": "astro build", "preview": "astro preview", "astro": "astro", - "update-data": "ruby bin/data-update", - "build:full": "npm run update-data && npm run build", + "build:full": "npm run build", "lint": "prettier --check .", "lintfix": "prettier --write ." }, diff --git a/src/components/FeedDirectory.astro b/src/components/FeedDirectory.astro index fcb4ff1a..679788db 100644 --- a/src/components/FeedDirectory.astro +++ b/src/components/FeedDirectory.astro @@ -1,42 +1,10 @@ --- -import { configs } from "../data/loadConfigs"; import { Icon } from "@astrojs/starlight/components"; - -const feedCount = configs.length; - -function formatDefaultParameters(defaultParameters: Record = {}) { - return Object.entries(defaultParameters) - .filter(([, value]) => value) - .map(([key, value]) => `${key}=${value}`) - .join(", "); -} - -const availableTopics = [...new Set(configs.flatMap((config) => config.directory?.topics || []))].sort( - (a, b) => a.localeCompare(b), -); - -const availableLanguages = [ - ...new Set( - configs - .map((config) => config.channel?.language) - .filter((language): language is string => Boolean(language)), - ), -].sort((a, b) => a.localeCompare(b)); - -const staticFeedUrls = configs.map((config) => ({ - ...config, - staticFeedUrl: "#", - defaultSummary: formatDefaultParameters(config.default_parameters), - sourceSummary: config.channel?.url - ?.replace(/^https?:\/\//, "") - .replace(/^www\./, "") - .replace(/\/$/, ""), - topics: config.directory?.topics || [], - language: config.channel?.language || "", -})); ---
+ +
@@ -56,7 +24,7 @@ const staticFeedUrls = configs.map((config) => ({

Search across - {feedCount} + 0 ready-to-use feeds

@@ -64,15 +32,7 @@ const staticFeedUrls = configs.map((config) => ({

Topics

-
- { - availableTopics.map((topic) => ( - - )) - } -
+
@@ -85,11 +45,10 @@ const staticFeedUrls = configs.map((config) => ({ aria-label="Filter by language" > - {availableLanguages.map((language) => )}
- +
@@ -108,7 +67,7 @@ const staticFeedUrls = configs.map((config) => ({ -
+ -
- { - staticFeedUrls.map((config, index) => ( -
-
-
-

{config.sourceSummary || `${config.domain}/${config.name}`}

- - -
- -
- {config.defaultSummary ? ( -

Defaults: {config.defaultSummary}

- ) : ( -
-
- - {Object.keys(config.url_parameters || {}).length > 0 && ( - - )} -
- )) - } -
+
- +