Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.