Skip to content

Minor improvements#5

Merged
AlexR1712 merged 9 commits intomainfrom
claude/add-instagram-support-AQq6t
May 5, 2026
Merged

Minor improvements#5
AlexR1712 merged 9 commits intomainfrom
claude/add-instagram-support-AQq6t

Conversation

@AlexR1712
Copy link
Copy Markdown
Contributor

No description provided.

claude and others added 9 commits May 5, 2026 22:05
Instagram has no native rich-text formatting in any of its surfaces, so
the new renderer substitutes ASCII letters and digits with characters from
Unicode's Mathematical Alphanumeric Symbols block (sans-serif bold for
**bold**, sans-serif italic for *italic*, monospace for `code`,
combining U+0336 for ~~strike~~). Headers, blockquotes, code blocks,
tables, lists, links, and task lists all map to Instagram-paste-friendly
output that survives copy/paste into captions, bios, comments, and DMs.

A new UnicodeStyler helper encapsulates the codepoint mapping so it can
be reused if other future platforms adopt the same approach. The
MarkdownConverter::toInstagram() facade mirrors the existing
toSlack/toWhatsApp shape; 2,200 (caption length) is documented as the
typical maxLength.
TextChunker may exceed maxLength by up to 50 chars to land on a safe
breakpoint instead of breaking mid-word. This was discovered the hard
way during Instagram-renderer verification — assertions of `<=
maxLength` failed by 6 chars on a 2,200-char caption test until the
overshoot was accounted for. Documents the contract in both the README
FAQ and the MAX_CHUNK_OVERSHOOT constant.
Every renderer was running preg_replace('/!/', '', $content) to strip
the '!' that LinkParser::formatImage() prepended to image markdown.
That stripped legitimate exclamation marks from prose too — 'Hello!'
became 'Hello'. Pushing the strip up into LinkParser solves both:

  - LinkParser::formatImage() now emits 'alt (url)' (no leading '!').
  - Every renderer drops its 'preg_replace(/!/, ...)' line.
  - Image rendering is unchanged because no renderer differentiated
    images from links anyway — they all rendered both as the platform's
    native link form.

Adds two new feature tests covering both directions: '!' is stripped
from image markdown, and '!' survives in plain prose, on all five
platforms.
Previously every renderer's renderBlockquote() returned its prefix
('> ', '💬 ', '❝ ❞') around raw block content, so '> use **bold**'
emerged as '> use **bold**' literally. Now blockquote content goes
through the same inline pipeline as paragraphs:

  - Parser applies LinkParser + StyleParser to blockquote content
    (matching what parseBuffer() already does for paragraphs).
  - Each renderer's renderBlockquote() pipes through renderParagraph()
    so bold/italic/strike/code/link transformations all apply.

Adds five per-platform tests covering bold/italic/strike/code inside
quotes plus a cross-platform link-in-quote test.

Note: a pre-existing non-greedy bug in convertLinks across all
renderers means "See [link](url)" still includes "See" in the link's
display text; this commit does not address that — it's tracked
separately and surfaces today regardless of blockquote handling.
Pins the rendered output of a single representative LLM-style Markdown
document (headers, bold, italic, strikethrough, highlight, inline
code, code block, table, blockquote, horizontal rule, task list,
bullet list, link, image, emoji, plain prose with !) for every
platform. Any cross-cutting refactor that changes any renderer's
output will produce a byte-level diff here, making intentional changes
explicit and accidental changes loud.

Snapshots live in tests/Fixtures/ and are regeneratable from the doc
header in SnapshotTest.php.

These snapshots intentionally capture two pre-existing rendering
quirks I noticed during verification (link prefix swallowing in
convertLinks; adjacent-link merging in Telegram) so they're locked in
and visible. Fixing either of those will deliberately update the
relevant snapshot and tell us exactly what changed.
The same renderBlock() match expression was duplicated verbatim across
five concrete renderers (Telegram, WhatsApp, Discord, Slack,
Instagram). Lifts it into AbstractRenderer along with sensible
default implementations of every leaf method (renderParagraph,
renderHeader, renderCodeBlock, renderTable, renderBlockquote,
renderHorizontalRule). Each concrete renderer now overrides only the
leaf methods it cares about — adding a new platform means writing
formatting rules, not boilerplate.

Net deletion: ~60 lines of duplicated dispatch. The new snapshot
tests in tests/Feature/SnapshotTest.php confirm byte-identical output
for every platform, so the refactor is verifiably behavior-preserving.

The README's "Custom Renderer" example (which overrides renderBlock
directly) still works because renderBlock is concrete-with-default
rather than final, and the leaf methods now have non-throwing default
implementations.
@AlexR1712 AlexR1712 merged commit 623375e into main May 5, 2026
1 check passed
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