diff --git a/app/assets/images/reddit-icon.svg b/app/assets/images/reddit-icon.svg new file mode 100644 index 000000000..524c15d52 --- /dev/null +++ b/app/assets/images/reddit-icon.svg @@ -0,0 +1 @@ + diff --git a/app/assets/stylesheets/ltags/LiquidTags.scss b/app/assets/stylesheets/ltags/LiquidTags.scss index 1cb633022..f8ef04748 100644 --- a/app/assets/stylesheets/ltags/LiquidTags.scss +++ b/app/assets/stylesheets/ltags/LiquidTags.scss @@ -14,3 +14,4 @@ @import 'ListingTag'; @import 'StackexchangeTag'; @import 'WikipediaTag'; +@import 'RedditTag'; diff --git a/app/assets/stylesheets/ltags/RedditTag.scss b/app/assets/stylesheets/ltags/RedditTag.scss new file mode 100644 index 000000000..91684fd57 --- /dev/null +++ b/app/assets/stylesheets/ltags/RedditTag.scss @@ -0,0 +1,98 @@ +@import 'variables'; + +.ltag__reddit--container { + max-width: 620px; + border: 1px solid $light-medium-gray; + border-radius: 3px; + box-shadow: $shadow; + margin:1.1em auto 1.30em; + padding: 10px; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !important; + overflow: hidden; + + .ltag__reddit--title-container { + border-bottom: 1px solid #eaecef; + display: flex; + flex-direction: column; + + header { + display: flex; + justify-content: space-between; + + .ltag__reddit--title { + h1 { + margin-left: 5px; + margin-bottom: 0; + margin-top: 8px; + font-size: 1.4em; + padding-bottom: 0; + + img { + height: 40px; + width: 40px; + display: inline-block; + vertical-align: -9px; + } + } + } + + .ltag__reddit--post-metadata { + font-size: 0.6em; + + span { + display: inline-block; + padding: 7px 6px; + margin-left: 6px; + } + } + } + } + + .ltag__reddit--body { + padding: 1em 0.5em; + max-height: calc(21vw + 165px); + overflow: hidden; + + @media screen and (min-width: 430px) { + max-height: calc(20vw + 153px); + } + @media screen and (min-width: 800px) { + max-height: 310px; + } + + h1,h2,h3,h4,h5,h6 { + font-weight: 500 !important; + } + + p { + margin-top: 0px; + padding: 0px; + margin-bottom: 15px; + font-size: 1.1rem; + } + } + + .ltag__reddit--btn--container { + padding: 0.1em 0 1.15em; + z-index: 100; + text-align: center; + position: relative; + box-shadow: 0px 0px 60px 42px #fff; + } + + .ltag__reddit--btn { + color: #0366d6; + background-color: #f1f8ff; + border-radius: 3px; + line-height: 20px; + padding: 0.25em 1.2em; + opacity: 0.9; + font-weight: bold; + border: 1px solid #0366d6; + font-size: 0.75em; + + &:hover { + opacity: 1; + } + } +} diff --git a/app/liquid_tags/reddit_tag.rb b/app/liquid_tags/reddit_tag.rb new file mode 100644 index 000000000..b385b686c --- /dev/null +++ b/app/liquid_tags/reddit_tag.rb @@ -0,0 +1,73 @@ +class RedditTag < LiquidTagBase + include ActionView::Helpers::SanitizeHelper + + PARTIAL = "liquids/reddit".freeze + URL_REGEXP = /\Ahttps\:\/\/(www.)?reddit.com/.freeze + + def initialize(_tag_name, url, _tokens) + @url = ActionController::Base.helpers.strip_tags(url).strip + @reddit_content = parse_url + end + + def render(_context) + ActionController::Base.new.render_to_string( + partial: PARTIAL, + locals: { + author: @reddit_content[:author], + title: @reddit_content[:title], + post_url: @reddit_content[:post_url], + created_at: @reddit_content[:created_at], + post_hint: @reddit_content[:post_hint], + image_url: @reddit_content[:image_url], + thumbnail: @reddit_content[:thumbnail], + html_text: @reddit_content[:selftext_html], + markdown_text: @reddit_content[:selftext] + }, + ) + end + + private + + def parse_url + validate_url + + # Requests to Reddit require a custom `User-Agent` header to prevent 429 errors + json = HTTParty.get("#{@url}.json", headers: { "User-Agent" => "#{ApplicationConfig['COMMUNITY_NAME']} (#{URL.url})" }) + + # The JSON response is an array with two items. + # The first one is the post itself, the second one are the comments + data = json.first["data"]["children"][0]["data"] + + { + author: data["author"], + title: data["title"], + post_url: @url, + created_at: Time.zone.at(data["created_utc"]).strftime("%b %e '%y"), + post_hint: data["post_hint"], + image_url: data["url"], + thumbnail: data["thumbnail"], + selftext: parse_markdown_content(data["selftext"]), + selftext_html: data["selftext_html"] + } + end + + def parse_markdown_content(content) + markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTMLRouge, REDCARPET_CONFIG) + text = markdown.render(content) + + sanitize(HTML_Truncator.truncate(text, 60)) + end + + def validate_url + return true if valid_url?(@url.delete(" ")) && (@url =~ URL_REGEXP)&.zero? + + raise StandardError, "Invalid Reddit link: #{@url}" + end + + def valid_url?(url) + url = URI.parse(url) + url.is_a?(URI::HTTP) + end +end + +Liquid::Template.register_tag("reddit", RedditTag) diff --git a/app/views/liquids/_reddit.html.erb b/app/views/liquids/_reddit.html.erb new file mode 100644 index 000000000..7c78f5b20 --- /dev/null +++ b/app/views/liquids/_reddit.html.erb @@ -0,0 +1,32 @@ +
+ <% if post_hint == 'image' %>
+
+ <% else %>
+ <%= markdown_text %>
+ <% end %>
+
All you need is the Asciinema id:
{% asciinema 239367 %}
+
+ Enter the full URL of the post you want to embed
+
+{% reddit https://www.reddit.com/r/aww/comments/ag3s4b/ive_waited_28_years_to_finally_havr_my_first_pet %}
+
+
To parse Liquid tags as code, simply wrap it with a single backtick or triple backticks.
`{% mytag %}{{ site.SOMETHING }}{% endmytag %}`