Skip to content

Add PublishMarkdown plugin for writing feeds as Markdown documents - #134

Merged
id774 merged 1 commit into
masterfrom
claude/markdown-first-output-29mjsc
Aug 14, 2026
Merged

Add PublishMarkdown plugin for writing feeds as Markdown documents#134
id774 merged 1 commit into
masterfrom
claude/markdown-first-output-29mjsc

Conversation

@id774

@id774 id774 commented Aug 14, 2026

Copy link
Copy Markdown
Owner

Summary

Introduces PublishMarkdown, a new publishing plugin that serializes the feed pipeline as a Markdown document, writing to either a file or standard output. This enables Recipes to produce human-readable, version-control-friendly output without requiring external services or credentials.

Key Changes

  • New plugin: PublishMarkdown (plugins/publish/markdown.rb)

    • Renders each feed item as a Markdown section with level-2 ATX heading
    • Extracts metadata fields (Link, Date, Author, Comments, Source, Enclosure) as bullet points
    • Converts HTML in descriptions/content_encoded to plain text using Nokogiri
    • Supports writing to file (with append/overwrite modes) or standard output
    • Creates missing parent directories automatically
    • Handles Unicode content correctly
    • Produces deterministic, byte-for-byte identical output across runs
  • Comprehensive test suite (spec/plugins/publish/markdown_spec.rb)

    • 232 lines of specs covering document structure, HTML handling, file I/O, Unicode support
    • Tests metadata extraction, body text normalization, empty pipelines
    • Validates append/overwrite modes and file creation behavior
  • Documentation updates

    • Extended doc/PLUGINS.md section 6.7 with detailed PublishMarkdown specification
    • Added doc/BASIC_DESIGN.md section explaining the Publish boundary and pipeline serialization
    • Added doc/DEPLOYMENT.md section on publishing to Markdown with operational guidance
    • Updated doc/REQUIREMENTS.md sections 10.1-10.2 on output and publication formats
    • Updated doc/POLICY.md to clarify that format conversion is a Publish plugin responsibility
  • Example configuration (config/feed2markdown.yml)

    • New scaffold example demonstrating a complete feed-to-Markdown workflow
    • Shows integration with SubscriptionFeed, FilterIgnore, FilterSort, and StorePermalink
  • README updates

    • Updated example to use PublishMarkdown instead of PublishConsole
    • Added explanation of Markdown as the standard publication format
    • Updated plugin count from 44 to 45

Implementation Details

  • HTML-to-text conversion: Reduces markup to plain text rather than translating to Markdown, avoiding a large library dependency. Scripts are removed, block elements become paragraph breaks, <br> becomes line breaks, and entities are decoded.

  • Whitespace normalization: Handles line ending conversion, trailing whitespace removal, and blank line collapsing. Text from markup also has indentation stripped to prevent Markdown code block interpretation.

  • Metadata handling: Supports both string and element-based fields (source.content, enclosure.url) from parsed feeds. URLs are wrapped as autolinks (<url>) for both rendering and grep compatibility.

  • Deterministic output: Date formatting uses the item's own timezone without conversion, ensuring identical output across machines. Empty pipelines produce no file output.

  • File handling: Appends by default (suitable for cron jobs building a journal), with optional overwrite mode. Empty runs don't create or modify files.

https://claude.ai/code/session_016JMWCNj1qYTpsxJA9t72uA

Automatic Ruby collects from many sources into one composable pipeline, and
what a run leaves behind is the Recipe's choice. Add the exit that needs
nothing outside the machine: a Markdown document, readable by a person,
processable with ordinary tools, keepable in version control, and usable as
input to another program.

Requirements and design come first, and the implementation follows them.
doc/REQUIREMENTS.md states that publishing a portable document is a primary
use, names Markdown as the standard publication format for it, and records
that an output format is never a second pipeline representation.
doc/BASIC_DESIGN.md places PublishMarkdown at the Publish boundary as a
serializer, keeping Markdown out of the framework, out of the pipeline value
and out of any implicit step. doc/PLUGINS.md specifies what it writes.

Nothing existing changes meaning: the pipeline value keeps its shape, RSS and
Atom remain input formats, SubscriptionFeed is untouched, no Recipe gains a
plugin it did not name, and framework core is not modified.

- plugins/publish/markdown.rb: a level-2 heading per item, a metadata list of
  the fields the item carries, content_encoded before description, HTML
  reduced to text with nokogiri rather than translated, deterministic output,
  and file and mode settings; the pipeline is returned unchanged.
- spec/plugins/publish/markdown_spec.rb: 25 examples, no network, no
  credential, file examples confined to a temporary directory.
- config/feed2markdown.yml: collect, filter, de-duplicate, append to a file.
- README, DEPLOYMENT and VERSIONS updated, and the plugin counts raised to
  forty-five, twenty-three of them Supported.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016JMWCNj1qYTpsxJA9t72uA
@id774
id774 merged commit d78f699 into master Aug 14, 2026
0 of 6 checks passed
@id774
id774 deleted the claude/markdown-first-output-29mjsc branch August 14, 2026 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants