Skip to Content Skip to Search

# Action Text Markdown Conversion

Converts an HTML fragment into a Markdown string. Used by ‘ActionText::Content#to_markdown` and `ActionText::Fragment#to_markdown` to produce Markdown representations of rich text.

Example: ‘<h1>Release Notes</h1>` => `# Release Notes`, a markdown heading.

Note that this converter escapes text nodes so it won’t render as markdown.

Example: ‘<p># Release Notes</p>` => `# Release Notes`, not a heading.

Methods
E
F
M
N
R

Instance Public methods

escape_markdown_text(text)

Backslash-escapes CommonMark metacharacters in ‘text` so they are treated as literal characters by Markdown renderers.

MarkdownConversion.escape_markdown_text("**Important**")
# => "\\*\\*Important\\*\\*"
# File actiontext/lib/action_text/markdown_conversion.rb, line 92
def escape_markdown_text(text)
  text.gsub(MARKDOWN_METACHARACTERS) { |c| "\\#{c}" }
end

fragment_by_unwrapping_raw_markdown_tags(fragment)

Returns a copy of ‘fragment` with `<action-text-markdown>` elements replaced by their children, leaving the text to be escaped like any other.

render_attachment wraps already-rendered Markdown in that element so node_to_markdown emits it without escaping. Only Action Text may do that, so ActionText::Content unwraps the element while canonicalizing: anything carrying it at that point came from outside the framework.

# File actiontext/lib/action_text/markdown_conversion.rb, line 44
def fragment_by_unwrapping_raw_markdown_tags(fragment)
  ActionText::Fragment.wrap(fragment).update do |source|
    source.css(RAW_MARKDOWN_TAG_NAME).each do |node|
      node.replace(node.children)
    end
  end
end

Returns a Markdown link: ‘[title](url)`.

Escapes metacharacters in ‘title`, and percent-encodes characters in `url` that would break the link syntax.

MarkdownConversion.markdown_link("photo", "https://example.com/photo_(large).png")
# => "[photo](https://example.com/photo_%28large%29.png)"

Pass ‘image: true` to produce an image link (`![title](url)`).

MarkdownConversion.markdown_link("photo", "https://example.com/photo.png", image: true)
# => "![photo](https://example.com/photo.png)"

If the URI scheme is not allowed (per ‘Rails::HTML::Sanitizer.allowed_uri?`), returns the escaped title wrapped in escaped brackets (`[title]`).

MarkdownConversion.markdown_link("click", "javascript:alert(1)")
# => "\\[click\\]"

node_to_markdown(node)

Converts a Nokogiri HTML ‘node` into a Markdown string.

node = Nokogiri::HTML4.fragment("<p>Hello <strong>world</strong></p>")
MarkdownConversion.node_to_markdown(node) # => "Hello **world**"

NOTE: text inside ‘<action-text-markdown>` elements is emitted without escaping, so this method is not safe for untrusted content. Convert user-supplied markup through ActionText::Content, which strips those elements while canonicalizing.

# File actiontext/lib/action_text/markdown_conversion.rb, line 31
def node_to_markdown(node)
  BottomUpReducer.new(node).reduce do |n, child_values|
    markdown_for_node(n, child_values)
  end.strip
end

render_attachment(attachment, attachment_links: false)

Returns an element holding ‘attachment`’s Markdown, for ‘ActionText::Content#to_markdown` to substitute in place of the attachment. node_to_markdown emits the element’s text verbatim rather than escaping it as ordinary Markdown source.

# File actiontext/lib/action_text/markdown_conversion.rb, line 55
def render_attachment(attachment, attachment_links: false)
  ActionText::HtmlConversion.create_element(RAW_MARKDOWN_TAG_NAME).tap do |node|
    node.content = attachment.to_markdown(attachment_links: attachment_links)
  end
end