From 66379b32f0b4bb94a22fb216a453cd7020e3dfe0 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 10 Mar 2026 19:41:48 +0000 Subject: [PATCH 1/5] Add table tag passthrough support and fix quote trailing newlines - Add AST classes Table, TableRow, TableCell (passthrough: strip wrapper tags, preserve cell content for Discourse which has no table syntax) - Register table/tr/td/th handlers in BBCode handler registry - Register passthrough renderer tags in Discourse TagLibrary - Append \n\n after named [quote] blocks to ensure paragraph separation - Add unit specs for Table/TableRow/TableCell AST classes - Add TagLibrary registration tests for all three table classes - Pin table system tests to exact eq outputs; add empty/whitespace-cell edge cases Made-with: Cursor --- lib/markbridge/ast.rb | 1 + lib/markbridge/ast/table.rb | 14 +++++++ .../parsers/bbcode/handler_registry.rb | 8 ++++ .../renderers/discourse/tag_library.rb | 9 +++++ .../renderers/discourse/tags/quote_tag.rb | 7 ++-- spec/system/bbcode_to_markdown_spec.rb | 32 ++++++++++++++++ spec/unit/markbridge/ast/table_spec.rb | 37 +++++++++++++++++++ .../renderers/discourse/tag_library_spec.rb | 12 ++++++ .../discourse/tags/quote_tag_spec.rb | 4 +- 9 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 lib/markbridge/ast/table.rb create mode 100644 spec/unit/markbridge/ast/table_spec.rb diff --git a/lib/markbridge/ast.rb b/lib/markbridge/ast.rb index a0a3cb1..42a7a49 100644 --- a/lib/markbridge/ast.rb +++ b/lib/markbridge/ast.rb @@ -25,6 +25,7 @@ require_relative "ast/strikethrough" require_relative "ast/subscript" require_relative "ast/superscript" +require_relative "ast/table" require_relative "ast/text" require_relative "ast/markdown_text" require_relative "ast/underline" diff --git a/lib/markbridge/ast/table.rb b/lib/markbridge/ast/table.rb new file mode 100644 index 0000000..2ea3587 --- /dev/null +++ b/lib/markbridge/ast/table.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Markbridge + module AST + class Table < Element + end + + class TableRow < Element + end + + class TableCell < Element + end + end +end diff --git a/lib/markbridge/parsers/bbcode/handler_registry.rb b/lib/markbridge/parsers/bbcode/handler_registry.rb index 56e0c25..595b86a 100644 --- a/lib/markbridge/parsers/bbcode/handler_registry.rb +++ b/lib/markbridge/parsers/bbcode/handler_registry.rb @@ -132,6 +132,14 @@ def self.default(closing_strategy: nil) registry.register(%w[list ul ol ulist olist], Handlers::ListHandler.new) registry.register(%w[* li .], Handlers::ListItemHandler.new) + # Table handlers (passthrough: strip wrapper tags, preserve cell content) + registry.register("table", Handlers::SimpleHandler.new(AST::Table, auto_closeable: true)) + registry.register("tr", Handlers::SimpleHandler.new(AST::TableRow, auto_closeable: true)) + registry.register( + %w[td th], + Handlers::SimpleHandler.new(AST::TableCell, auto_closeable: true), + ) + # Set the closing strategy registry.closing_strategy = closing_strategy || default_closing_strategy(registry) diff --git a/lib/markbridge/renderers/discourse/tag_library.rb b/lib/markbridge/renderers/discourse/tag_library.rb index f716eaf..61da6df 100644 --- a/lib/markbridge/renderers/discourse/tag_library.rb +++ b/lib/markbridge/renderers/discourse/tag_library.rb @@ -59,6 +59,15 @@ def self.default library.register AST::LineBreak, Tags::LineBreakTag.new library.register AST::HorizontalRule, Tags::HorizontalRuleTag.new + # Table tags: passthrough — strip wrapper tags, preserve cell content + passthrough = + Tag.new do |element, interface| + interface.render_children(element, context: interface.with_parent(element)) + end + library.register AST::Table, passthrough + library.register AST::TableRow, passthrough + library.register AST::TableCell, passthrough + library end end diff --git a/lib/markbridge/renderers/discourse/tags/quote_tag.rb b/lib/markbridge/renderers/discourse/tags/quote_tag.rb index de1c568..b490ddc 100644 --- a/lib/markbridge/renderers/discourse/tags/quote_tag.rb +++ b/lib/markbridge/renderers/discourse/tags/quote_tag.rb @@ -15,13 +15,12 @@ def render(element, interface) # Format: [quote="username, post:123, topic:456"]content[/quote] if element.post && element.topic && element.username # Full Discourse quote with context - "[quote=\"#{element.username}, post:#{element.post}, topic:#{element.topic}\"]\n#{content}\n[/quote]" + "[quote=\"#{element.username}, post:#{element.post}, topic:#{element.topic}\"]\n#{content}\n[/quote]\n\n" elsif element.author # Quote with author attribution only - "[quote=\"#{element.author}\"]\n#{content}\n[/quote]" + "[quote=\"#{element.author}\"]\n#{content}\n[/quote]\n\n" else - # Plain quote - could use Markdown blockquote or BBCode - # Using Markdown blockquote for plain quotes + # Plain Markdown blockquote — no trailing \n\n needed; surrounding paragraph context handles spacing content.split("\n").map { |line| "> #{line}" }.join("\n") end end diff --git a/spec/system/bbcode_to_markdown_spec.rb b/spec/system/bbcode_to_markdown_spec.rb index 1bf6f88..1f8251b 100644 --- a/spec/system/bbcode_to_markdown_spec.rb +++ b/spec/system/bbcode_to_markdown_spec.rb @@ -508,4 +508,36 @@ expect(result).to eq(expected) end end + + describe "table tags" do + it "strips [TABLE][TR][TD] wrapper tags and preserves cell content" do + bbcode = "[TABLE][TR][TD]cell content[/TD][/TR][/TABLE]" + expect(Markbridge.bbcode_to_markdown(bbcode)).to eq("cell content") + end + + it "preserves content from multiple cells" do + bbcode = "[TABLE][TR][TD]first[/TD][TD]second[/TD][/TR][/TABLE]" + expect(Markbridge.bbcode_to_markdown(bbcode)).to eq("firstsecond") + end + + it "strips [TH] header cells and preserves content" do + bbcode = "[TABLE][TR][TH]Header[/TH][/TR][TR][TD]value[/TD][/TR][/TABLE]" + expect(Markbridge.bbcode_to_markdown(bbcode)).to eq("Headervalue") + end + + it "preserves formatted content inside table cells" do + bbcode = "[TABLE][TR][TD][B]bold cell[/B][/TD][/TR][/TABLE]" + expect(Markbridge.bbcode_to_markdown(bbcode)).to eq("**bold cell**") + end + + it "handles empty cells" do + bbcode = "[TABLE][TR][TD][/TD][/TR][/TABLE]" + expect(Markbridge.bbcode_to_markdown(bbcode)).to eq("") + end + + it "handles whitespace-only cells" do + bbcode = "[TABLE][TR][TD] [/TD][/TR][/TABLE]" + expect(Markbridge.bbcode_to_markdown(bbcode)).to eq("") + end + end end diff --git a/spec/unit/markbridge/ast/table_spec.rb b/spec/unit/markbridge/ast/table_spec.rb new file mode 100644 index 0000000..b1bf686 --- /dev/null +++ b/spec/unit/markbridge/ast/table_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +RSpec.describe Markbridge::AST::Table do + it "is an Element" do + expect(described_class.new).to be_a(Markbridge::AST::Element) + end + + it "can have children" do + table = described_class.new + table << Markbridge::AST::TableRow.new + expect(table.children.size).to eq(1) + end +end + +RSpec.describe Markbridge::AST::TableRow do + it "is an Element" do + expect(described_class.new).to be_a(Markbridge::AST::Element) + end + + it "can have children" do + row = described_class.new + row << Markbridge::AST::TableCell.new + expect(row.children.size).to eq(1) + end +end + +RSpec.describe Markbridge::AST::TableCell do + it "is an Element" do + expect(described_class.new).to be_a(Markbridge::AST::Element) + end + + it "can have children" do + cell = described_class.new + cell << Markbridge::AST::Text.new("content") + expect(cell.children.size).to eq(1) + end +end diff --git a/spec/unit/markbridge/renderers/discourse/tag_library_spec.rb b/spec/unit/markbridge/renderers/discourse/tag_library_spec.rb index 8e0f743..f815871 100644 --- a/spec/unit/markbridge/renderers/discourse/tag_library_spec.rb +++ b/spec/unit/markbridge/renderers/discourse/tag_library_spec.rb @@ -81,6 +81,18 @@ expect(default_library[Markbridge::AST::HorizontalRule]).not_to be_nil end + it "registers Table tag" do + expect(default_library[Markbridge::AST::Table]).not_to be_nil + end + + it "registers TableRow tag" do + expect(default_library[Markbridge::AST::TableRow]).not_to be_nil + end + + it "registers TableCell tag" do + expect(default_library[Markbridge::AST::TableCell]).not_to be_nil + end + it "renders bold correctly" do bold = Markbridge::AST::Bold.new bold << Markbridge::AST::Text.new("text") diff --git a/spec/unit/markbridge/renderers/discourse/tags/quote_tag_spec.rb b/spec/unit/markbridge/renderers/discourse/tags/quote_tag_spec.rb index 4c9806a..92a104a 100644 --- a/spec/unit/markbridge/renderers/discourse/tags/quote_tag_spec.rb +++ b/spec/unit/markbridge/renderers/discourse/tags/quote_tag_spec.rb @@ -20,7 +20,7 @@ element << Markbridge::AST::Text.new("This is a quote") result = tag.render(element, interface) - expect(result).to eq("[quote=\"John\"]\nThis is a quote\n[/quote]") + expect(result).to eq("[quote=\"John\"]\nThis is a quote\n[/quote]\n\n") end it "renders quote with full Discourse context" do @@ -28,7 +28,7 @@ element << Markbridge::AST::Text.new("This is a quote") result = tag.render(element, interface) - expect(result).to eq("[quote=\"john, post:123, topic:456\"]\nThis is a quote\n[/quote]") + expect(result).to eq("[quote=\"john, post:123, topic:456\"]\nThis is a quote\n[/quote]\n\n") end it "renders multi-line plain quote with blockquote syntax" do From 75ce539d5ee48b208198de5b7c2c5752b87b4d79 Mon Sep 17 00:00:00 2001 From: Ruben Oussoren Date: Thu, 2 Apr 2026 14:09:43 +0000 Subject: [PATCH 2/5] Add [IMG2] BBCode handler for vBulletin 5 enhanced image tags Parse [IMG2=JSON]{'src':'...'}[/IMG2] tags by extracting the src URL from the JSON payload and producing AST::Image nodes. Also handles bare [IMG2]url[/IMG2] without JSON. Includes unit and integration tests. --- lib/markbridge/parsers/bbcode.rb | 1 + .../parsers/bbcode/handler_registry.rb | 3 + .../parsers/bbcode/handlers/img2_handler.rb | 58 ++++++ .../bbcode/handlers/img2_handler_spec.rb | 167 ++++++++++++++++++ 4 files changed, 229 insertions(+) create mode 100644 lib/markbridge/parsers/bbcode/handlers/img2_handler.rb create mode 100644 spec/unit/markbridge/parsers/bbcode/handlers/img2_handler_spec.rb diff --git a/lib/markbridge/parsers/bbcode.rb b/lib/markbridge/parsers/bbcode.rb index 7216687..14b9b71 100644 --- a/lib/markbridge/parsers/bbcode.rb +++ b/lib/markbridge/parsers/bbcode.rb @@ -28,6 +28,7 @@ require_relative "bbcode/handlers/color_handler" require_relative "bbcode/handlers/email_handler" require_relative "bbcode/handlers/image_handler" +require_relative "bbcode/handlers/img2_handler" require_relative "bbcode/handlers/list_handler" require_relative "bbcode/handlers/list_item_handler" require_relative "bbcode/handlers/quote_handler" diff --git a/lib/markbridge/parsers/bbcode/handler_registry.rb b/lib/markbridge/parsers/bbcode/handler_registry.rb index 595b86a..29c5502 100644 --- a/lib/markbridge/parsers/bbcode/handler_registry.rb +++ b/lib/markbridge/parsers/bbcode/handler_registry.rb @@ -100,6 +100,9 @@ def self.default(closing_strategy: nil) # Image handler registry.register("img", Handlers::ImageHandler.new) + # IMG2 handler (vBulletin 5 enhanced image) + registry.register("img2", Handlers::Img2Handler.new) + # Attachment handler registry.register(%w[attach attachment], Handlers::AttachmentHandler.new) diff --git a/lib/markbridge/parsers/bbcode/handlers/img2_handler.rb b/lib/markbridge/parsers/bbcode/handlers/img2_handler.rb new file mode 100644 index 0000000..f28268d --- /dev/null +++ b/lib/markbridge/parsers/bbcode/handlers/img2_handler.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +module Markbridge + module Parsers + module BBCode + module Handlers + # Handler for vBulletin 5 [IMG2] tags. + # + # Supports: + # - [IMG2=JSON]{"src":"http://example.com/image.png",...}[/IMG2] + # - [IMG2]http://example.com/image.png[/IMG2] + class Img2Handler < BaseHandler + def initialize(collector: RawContentCollector.new) + @collector = collector + @element_class = AST::Image + end + + def on_open(token:, context:, registry:, tokens: nil) + content = collect_content(token:, tokens:) + return unless content + + src = extract_src(token, content.strip) + return if src.nil? || src.empty? + + context.add_child(AST::Image.new(src: src)) + end + + def on_close(token:, context:, registry:, tokens: nil) + context.add_child(AST::Text.new(token.source)) + end + + attr_reader :element_class + + private + + def collect_content(token:, tokens:) + return unless tokens + return unless closing_tag_ahead?(token.tag, tokens) + + @collector.collect(token.tag, tokens).content + end + + def closing_tag_ahead?(tag, tokens) + tokens.peek_ahead(100).any? { |t| t.is_a?(TagEndToken) && t.tag == tag } + end + + def extract_src(token, content) + if token.attrs[:option]&.downcase == "json" && content.start_with?("{") + $1 if content =~ /"src"\s*:\s*"([^"]+)"/ + else + content + end + end + end + end + end + end +end diff --git a/spec/unit/markbridge/parsers/bbcode/handlers/img2_handler_spec.rb b/spec/unit/markbridge/parsers/bbcode/handlers/img2_handler_spec.rb new file mode 100644 index 0000000..17b7113 --- /dev/null +++ b/spec/unit/markbridge/parsers/bbcode/handlers/img2_handler_spec.rb @@ -0,0 +1,167 @@ +# frozen_string_literal: true + +RSpec.describe Markbridge::Parsers::BBCode::Handlers::Img2Handler do + let(:handler) { described_class.new } + let(:document) { Markbridge::AST::Document.new } + let(:registry) { Markbridge::Parsers::BBCode::HandlerRegistry.new } + let(:context) { Markbridge::Parsers::BBCode::ParserState.new(document) } + + class MockScanner + def initialize(tokens) + @tokens = tokens + @index = 0 + end + + def next_token + return nil if @index >= @tokens.length + + token = @tokens[@index] + @index += 1 + token + end + end + + def make_scanner(tokens) + Markbridge::Parsers::BBCode::PeekableEnumerator.new(MockScanner.new(tokens)) + end + + def text_token(text, pos: 0) + Markbridge::Parsers::BBCode::TextToken.new(text:, pos:) + end + + def start_token(tag: "img2", attrs: {}, source: "[IMG2]", pos: 0) + Markbridge::Parsers::BBCode::TagStartToken.new(tag:, attrs:, pos:, source:) + end + + def end_token(tag: "img2", source: "[/IMG2]", pos: 0) + Markbridge::Parsers::BBCode::TagEndToken.new(tag:, pos:, source:) + end + + describe "#on_open" do + it "extracts src from JSON body with HTTP URL" do + token = start_token(attrs: { option: "JSON" }, source: "[IMG2=JSON]") + json = '{"data-align":"none","data-size":"full","src":"http://example.com/image.png"}' + scanner = make_scanner([text_token(json), end_token]) + + handler.on_open(token:, context:, registry:, tokens: scanner) + + image = document.children.first + expect(image).to be_a(Markbridge::AST::Image) + expect(image.src).to eq("http://example.com/image.png") + end + + it "extracts src from JSON body with HTTPS URL" do + token = start_token(attrs: { option: "JSON" }, source: "[IMG2=JSON]") + json = '{"data-align":"none","src":"https://forums.example.com/core/image.jpg"}' + scanner = make_scanner([text_token(json), end_token]) + + handler.on_open(token:, context:, registry:, tokens: scanner) + + image = document.children.first + expect(image).to be_a(Markbridge::AST::Image) + expect(image.src).to eq("https://forums.example.com/core/image.jpg") + end + + it "produces nothing when JSON body has no src field" do + token = start_token(attrs: { option: "JSON" }, source: "[IMG2=JSON]") + json = '{"data-align":"none","data-size":"full"}' + scanner = make_scanner([text_token(json), end_token]) + + handler.on_open(token:, context:, registry:, tokens: scanner) + + expect(document.children).to be_empty + end + + it "produces nothing when JSON src is empty" do + token = start_token(attrs: { option: "JSON" }, source: "[IMG2=JSON]") + json = '{"src":""}' + scanner = make_scanner([text_token(json), end_token]) + + handler.on_open(token:, context:, registry:, tokens: scanner) + + expect(document.children).to be_empty + end + + it "handles bare [IMG2]url[/IMG2] without JSON option" do + token = start_token(attrs: {}, source: "[IMG2]") + scanner = make_scanner([text_token("https://example.com/photo.jpg"), end_token]) + + handler.on_open(token:, context:, registry:, tokens: scanner) + + image = document.children.first + expect(image).to be_a(Markbridge::AST::Image) + expect(image.src).to eq("https://example.com/photo.jpg") + end + + it "handles case-insensitive JSON option" do + token = start_token(attrs: { option: "json" }, source: "[IMG2=json]") + json = '{"src":"http://example.com/img.png"}' + scanner = make_scanner([text_token(json), end_token]) + + handler.on_open(token:, context:, registry:, tokens: scanner) + + image = document.children.first + expect(image).to be_a(Markbridge::AST::Image) + expect(image.src).to eq("http://example.com/img.png") + end + + it "produces nothing when there is no closing tag" do + token = start_token(attrs: { option: "JSON" }, source: "[IMG2=JSON]") + scanner = make_scanner([text_token("some content")]) + + handler.on_open(token:, context:, registry:, tokens: scanner) + + expect(document.children).to be_empty + end + + it "handles JSON with escaped slashes in src" do + token = start_token(attrs: { option: "JSON" }, source: "[IMG2=JSON]") + json = '{"src":"http:\/\/example.com\/path\/image.png"}' + scanner = make_scanner([text_token(json), end_token]) + + handler.on_open(token:, context:, registry:, tokens: scanner) + + image = document.children.first + expect(image).to be_a(Markbridge::AST::Image) + expect(image.src).to eq("http:\\/\\/example.com\\/path\\/image.png") + end + end + + describe "#on_close" do + it "emits orphaned close tag as text" do + token = end_token(source: "[/IMG2]") + + handler.on_close(token:, context:, registry:) + + text = document.children.first + expect(text).to be_a(Markbridge::AST::Text) + expect(text.value).to eq("[/IMG2]") + end + end + + describe "end-to-end via Markbridge.bbcode_to_markdown" do + it "converts [IMG2=JSON] with HTTP src to image markdown" do + input = '[IMG2=JSON]{"data-align":"none","data-size":"full","src":"http://example.com/image.png"}[/IMG2]' + result = Markbridge.bbcode_to_markdown(input) + expect(result).to eq("![](http://example.com/image.png)") + end + + it "converts bare [IMG2] to image markdown" do + input = "[IMG2]http://example.com/photo.jpg[/IMG2]" + result = Markbridge.bbcode_to_markdown(input) + expect(result).to eq("![](http://example.com/photo.jpg)") + end + + it "strips [IMG2=JSON] with no src" do + input = 'Hello [IMG2=JSON]{"data-align":"none"}[/IMG2] world' + result = Markbridge.bbcode_to_markdown(input) + expect(result).to eq("Hello world") + end + + it "converts [IMG2=JSON] inline with surrounding text" do + input = 'Before [IMG2=JSON]{"src":"http://example.com/img.png"}[/IMG2] after' + result = Markbridge.bbcode_to_markdown(input) + expect(result).to eq("Before ![](http://example.com/img.png) after") + end + end +end From 160bf0c634c5b9a227a40136210cbd7179528da7 Mon Sep 17 00:00:00 2001 From: Ruben Oussoren Date: Thu, 2 Apr 2026 14:14:56 +0000 Subject: [PATCH 3/5] Fix CI: RuboCop hash syntax, img2 spec typo, and missing Table in ASTPresenter - Use Ruby 3.1+ hash shorthand in Img2Handler (src: instead of src: src) - Fix img2_handler_spec to use AST::Text#text instead of nonexistent #value - Add Table to ASTPresenter's CATEGORY_MAP and ICON_MAP --- lib/markbridge/parsers/bbcode/handlers/img2_handler.rb | 2 +- playground/ast_presenter.rb | 2 ++ .../markbridge/parsers/bbcode/handlers/img2_handler_spec.rb | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/markbridge/parsers/bbcode/handlers/img2_handler.rb b/lib/markbridge/parsers/bbcode/handlers/img2_handler.rb index f28268d..9857be1 100644 --- a/lib/markbridge/parsers/bbcode/handlers/img2_handler.rb +++ b/lib/markbridge/parsers/bbcode/handlers/img2_handler.rb @@ -22,7 +22,7 @@ def on_open(token:, context:, registry:, tokens: nil) src = extract_src(token, content.strip) return if src.nil? || src.empty? - context.add_child(AST::Image.new(src: src)) + context.add_child(AST::Image.new(src:)) end def on_close(token:, context:, registry:, tokens: nil) diff --git a/playground/ast_presenter.rb b/playground/ast_presenter.rb index 06c69a7..0038ab9 100644 --- a/playground/ast_presenter.rb +++ b/playground/ast_presenter.rb @@ -30,6 +30,7 @@ class ASTPresenter "Subscript" => "formatting", "Superscript" => "formatting", "Text" => "text", + "Table" => "block", "Underline" => "formatting", "Upload" => "media", "Url" => "link", @@ -62,6 +63,7 @@ class ASTPresenter "Subscript" => "subscript", "Superscript" => "superscript", "Text" => "textCursor", + "Table" => "table", "Underline" => "underline", "Upload" => "upload", "Url" => "link", diff --git a/spec/unit/markbridge/parsers/bbcode/handlers/img2_handler_spec.rb b/spec/unit/markbridge/parsers/bbcode/handlers/img2_handler_spec.rb index 17b7113..96e23bf 100644 --- a/spec/unit/markbridge/parsers/bbcode/handlers/img2_handler_spec.rb +++ b/spec/unit/markbridge/parsers/bbcode/handlers/img2_handler_spec.rb @@ -135,7 +135,7 @@ def end_token(tag: "img2", source: "[/IMG2]", pos: 0) text = document.children.first expect(text).to be_a(Markbridge::AST::Text) - expect(text.value).to eq("[/IMG2]") + expect(text.text).to eq("[/IMG2]") end end From d7248948d5eec4f15453064f891a32258b11da5f Mon Sep 17 00:00:00 2001 From: Ruben Oussoren Date: Thu, 2 Apr 2026 14:17:00 +0000 Subject: [PATCH 4/5] Add Table, TableRow, and TableCell to ASTPresenter maps --- playground/ast_presenter.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/playground/ast_presenter.rb b/playground/ast_presenter.rb index 0038ab9..184353a 100644 --- a/playground/ast_presenter.rb +++ b/playground/ast_presenter.rb @@ -31,6 +31,8 @@ class ASTPresenter "Superscript" => "formatting", "Text" => "text", "Table" => "block", + "TableRow" => "block", + "TableCell" => "block", "Underline" => "formatting", "Upload" => "media", "Url" => "link", @@ -64,6 +66,8 @@ class ASTPresenter "Superscript" => "superscript", "Text" => "textCursor", "Table" => "table", + "TableRow" => "tableRow", + "TableCell" => "tableCell", "Underline" => "underline", "Upload" => "upload", "Url" => "link", From d4613bbb177280e22734610ea1aedc9a15e979c0 Mon Sep 17 00:00:00 2001 From: Ruben Oussoren Date: Thu, 2 Apr 2026 14:20:46 +0000 Subject: [PATCH 5/5] Fix stree line length in img2_handler_spec --- .../markbridge/parsers/bbcode/handlers/img2_handler_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/unit/markbridge/parsers/bbcode/handlers/img2_handler_spec.rb b/spec/unit/markbridge/parsers/bbcode/handlers/img2_handler_spec.rb index 96e23bf..872c79c 100644 --- a/spec/unit/markbridge/parsers/bbcode/handlers/img2_handler_spec.rb +++ b/spec/unit/markbridge/parsers/bbcode/handlers/img2_handler_spec.rb @@ -141,7 +141,8 @@ def end_token(tag: "img2", source: "[/IMG2]", pos: 0) describe "end-to-end via Markbridge.bbcode_to_markdown" do it "converts [IMG2=JSON] with HTTP src to image markdown" do - input = '[IMG2=JSON]{"data-align":"none","data-size":"full","src":"http://example.com/image.png"}[/IMG2]' + input = + '[IMG2=JSON]{"data-align":"none","data-size":"full","src":"http://example.com/image.png"}[/IMG2]' result = Markbridge.bbcode_to_markdown(input) expect(result).to eq("![](http://example.com/image.png)") end