Skip to content

Commit 266faac

Browse files
Allow rich text for Developer#bio (joemasilotti#638)
* add concern to handle Developer#bio rich text rendering * use Developer#rich_text_bio in show page * test Developers::RichText concern * use custom renderer * run check * remove custom markdown renderer * update test to ignore MD links and images * updated CHANGELOG * add Markdown supported text * update doc link and changelog type * add option for plaintext renderer * use plain_text_bio in card component * run check * Line up comments with options; tweak CHANGELOG * Disable highlighted markdown, it's too agressive Co-authored-by: Joe Masilotti <[email protected]>
1 parent f8c1cb7 commit 266faac

File tree

8 files changed

+115
-2
lines changed

8 files changed

+115
-2
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
## September
66

7+
* September 15 - Allow rich text for developer bios #638 @rayhanw
78
* September 15 - Show "Featured" badge in search results #642
89
* September 14 - Only ever send one Celebration Promotion email #617 @sarvaiyanidhi
910
* September 13 - Impersonate users directly from `/admin/users` #627 @KarlHeitmann

app/components/developers/card_component.html.erb

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<% end %>
2323

2424
<div class="mt-2 text-sm sm:text-base text-gray-700 space-y-4">
25-
<p class="line-clamp-3 break-words"><%= strip_tags bio %></p>
25+
<p class="line-clamp-3 break-words"><%= developer.plain_text_bio %></p>
2626
</div>
2727
</div>
2828
<% end %>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
module Developers
2+
module RichText
3+
require "redcarpet/render_strip"
4+
5+
def rich_text_bio
6+
@rich_text_bio ||= markdown.render(bio).strip
7+
end
8+
9+
def plain_text_bio
10+
@plain_text_bio ||= plain_text_markdown.render(bio).strip
11+
end
12+
13+
private
14+
15+
# https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
16+
MARKDOWN_OPTIONS = {
17+
disable_indented_code_blocks: true,
18+
fenced_code_blocks: true,
19+
highlight: false,
20+
strikethrough: true,
21+
superscript: true,
22+
underline: true
23+
}.freeze
24+
25+
# https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch
26+
RENDER_OPTIONS = {
27+
filter_html: true,
28+
hard_wrap: true,
29+
no_images: true,
30+
no_links: true,
31+
no_styles: true
32+
}.freeze
33+
34+
def renderer
35+
@renderer ||= Redcarpet::Render::HTML.new(RENDER_OPTIONS)
36+
end
37+
38+
def markdown
39+
@markdown ||= Redcarpet::Markdown.new(renderer, MARKDOWN_OPTIONS)
40+
end
41+
42+
def plain_text_renderer
43+
@plain_text_renderer ||= Redcarpet::Render::StripDown
44+
end
45+
46+
def plain_text_markdown
47+
@plain_text_markdown ||= Redcarpet::Markdown.new(plain_text_renderer, MARKDOWN_OPTIONS)
48+
end
49+
end
50+
end

app/models/developer.rb

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ class Developer < ApplicationRecord
22
include Availability
33
include Avatarable
44
include Developers::Notifications
5+
include Developers::RichText
56
include HasSocialProfiles
67
include PersonName
78
include PgSearch::Model

app/views/developers/_form.html.erb

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
<li class="mt-1"><%= t(".bio.examples.help") %></li>
126126
<li class="mt-1"><%= t(".bio.examples.unique") %></li>
127127
</ul>
128+
129+
<p class="mt-4 text-sm text-gray-500"><%= t(".bio.markdown") %></p>
128130
</div>
129131
</div>
130132

app/views/developers/show.html.erb

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
<div class="py-3 lg:pt-6 lg:pb-0">
3737
<h2 class="sr-only"><%= t(".description") %></h2>
3838
<div class="prose max-w-prose">
39-
<%= simple_format(strip_tags(@developer.bio)) %>
39+
<%== @developer.rich_text_bio %>
4040
</div>
4141
</div>
4242
</div>

config/locales/en.yml

+1
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ en:
287287
title: Example topics
288288
unique: Your unique skills that make you awesome
289289
help_text: Personally identifiable information will be removed.
290+
markdown: Markdown is supported but links and images are removed.
290291
title: Bio
291292
creating: Creating...
292293
loading: Loading...
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
require "test_helper"
2+
3+
class Developers::RichTextTest < ActiveSupport::TestCase
4+
test "#rich_text_bio parses bio correctly" do
5+
developer = developers(:one)
6+
bio = <<~MD
7+
# H1
8+
This is _underlined_
9+
`Inline code block`
10+
MD
11+
developer.update!(bio:)
12+
13+
assert_match(/<h1>H1<\/h1>/, developer.rich_text_bio)
14+
assert_match "This is <u>underlined</u>", developer.rich_text_bio
15+
assert_match "<code>Inline code block</code>", developer.rich_text_bio
16+
end
17+
18+
test "#rich_text_bio disallows manually written HTML tags" do
19+
developer = developers(:one)
20+
bio = <<~MD
21+
<h1>Hello world</h1>
22+
MD
23+
developer.update!(bio:)
24+
25+
assert_no_match(/<h1>Hello world<\/h1>/, developer.rich_text_bio)
26+
assert_match(/<p>Hello world<\/p>/, developer.rich_text_bio)
27+
end
28+
29+
test "#rich_text_bio ignores links" do
30+
developer = developers(:one)
31+
bio = <<~MD
32+
[Text](https://example.com)
33+
MD
34+
developer.update!(bio:)
35+
36+
assert_equal developer.rich_text_bio, "<p>[Text](https://example.com)</p>"
37+
end
38+
39+
test "#rich_text_bio ignores images" do
40+
developer = developers(:one)
41+
bio = <<~MD
42+
![Image](https://example.com)
43+
MD
44+
developer.update!(bio:)
45+
46+
assert_equal developer.rich_text_bio, "<p>![Image](https://example.com)</p>"
47+
end
48+
49+
test "#plain_text_bio strips to plaintext" do
50+
developer = developers(:one)
51+
bio = <<~MD
52+
**hi** _bye_
53+
MD
54+
developer.update!(bio:)
55+
56+
assert_equal developer.plain_text_bio, "hi bye"
57+
end
58+
end

0 commit comments

Comments
 (0)