Last active
June 16, 2021 17:39
-
-
Save hungmi/adc35a9fab2064fc434fb951df9eec80 to your computer and use it in GitHub Desktop.
Rails ActionText: support prism syntax highlight code blocks. And transform <action-text-attachment/> to <img/> to work with any frontend.
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
# lib/action_text_parser.rb | |
# require 'action_text_parser' in application.rb | |
class ActionTextParser | |
def self.run(action_text_record) | |
html = action_text_record.body.to_html | |
nodes = Nokogiri::HTML::DocumentFragment.parse html | |
nodes = self.parse_attachments(nodes) | |
nodes = self.parse_code(nodes) | |
nodes.to_html | |
end | |
def self.parse_attachments(nodes) | |
# transform every <action-text-attachment/> to <img/> | |
nodes.css('action-text-attachment').map do |attachment| | |
src = attachment.attributes['url'].value | |
width = attachment.attributes['width'].value | |
height = attachment.attributes['height'].value | |
alt = attachment.attributes['caption'].try(:value) || attachment.attributes['filename'].try(:value) | |
attachment.swap("<img src='#{src}' width='#{width}' height='#{height}' alt='#{alt}' title='#{alt}' />") | |
end | |
nodes | |
end | |
def self.parse_code(nodes) | |
# transform <pre>...</pre> to "<pre><code class='#{lang-xxx}'>...</code></pre>" | |
nodes.css('pre').map do |pre| | |
lang_class = pre.content.split("\n")[-1].strip | |
if lang_class.present? && lang_class[/lang\-*/].present? | |
pre.swap("<pre><code class='#{lang_class}'>#{pre.content.strip.gsub(lang_class, '')}</code></pre>") | |
end | |
end | |
nodes | |
end | |
end |
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
class Api::V1::PostsController < ApplicationController | |
def show | |
@post = Post.find_by_id(params[:id]) | |
if @post | |
render json: { content_html: ActionTextParser.run(@post.content) } | |
end | |
end | |
end |
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
<!-- /posts/show.html.erb --> | |
<link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/themes/prism-okaidia.min.css" rel="stylesheet" /> | |
<link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/plugins/line-numbers/prism-line-numbers.min.css" rel="stylesheet" /> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/components/prism-core.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/plugins/autoloader/prism-autoloader.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/plugins/line-numbers/prism-line-numbers.min.js"></script> | |
<%= raw ActionTextParser.run @post.content %> |
Nice! Glad to see my post could be helpful to someone else. Thanks for tagging.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is inspired by a post of @ajessee.
After implement this, we can use Trix to write some code:

And the frontend will show
