feat(markdown): add ids to headers (#713)

* feat(markdown): add anchors for headers

* Fix markdown anchors impl and spec

* Fixes tests for markdown anchors

* Use name for anchors instead of IDs

* Fix approval file

* Remove emojis in links and hyphenate only spaces
This commit is contained in:
Gabriel Lebec 2018-11-20 18:17:07 -05:00 committed by Ben Halpern
parent 5ee5c931fc
commit 1e2749be24
9 changed files with 81 additions and 86 deletions

View file

@ -38,6 +38,7 @@ gem "delayed_job_active_record", "~> 4.1"
gem "devise", "~> 4.5"
gem "draper", "~> 3.0"
gem "email_validator", "~> 1.6"
gem "emoji_regex", "~> 1.0"
gem "envied", "~> 0.9"
gem "fastly", "~> 1.15"
gem "fastly-rails", "~> 0.8"

View file

@ -261,6 +261,7 @@ GEM
http_parser.rb (~> 0.6.0)
email_validator (1.6.0)
activemodel
emoji_regex (1.0.1)
envied (0.9.1)
coercible (~> 1.0)
thor (~> 0.15)
@ -936,6 +937,7 @@ DEPENDENCIES
devise (~> 4.5)
draper (~> 3.0)
email_validator (~> 1.6)
emoji_regex (~> 1.0)
envied (~> 0.9)
factory_bot_rails (~> 4.11)
fake_stripe (~> 0.2)

View file

@ -312,6 +312,12 @@ header{
code{
color:$sky-blue;
}
&.anchor{
padding-top: 50px;
margin-top: -50px;
-webkit-background-clip: content-box;
background-clip: content-box;
}
}
h1,h2,h3,h4,h5,h6{
font-family: $helvetica;

View file

@ -561,6 +561,14 @@ a.header-link{
margin-left:0%;
overflow-x:auto;
}
a{
&.anchor{
padding-top: 50px;
margin-top: -50px;
-webkit-background-clip: content-box;
background-clip: content-box;
}
}
}
.icon-img{
height:16px;

View file

@ -15,6 +15,23 @@ module Redcarpet
end
%(<a href="#{link}"#{link_attributes}>#{content}</a>)
end
def header(title, header_number)
anchor_link = remove_emoji_and_hyphenate(title)
<<~HEREDOC
<h#{header_number}>
<a name="#{anchor_link}" href="##{anchor_link}" class="anchor">
</a>
#{title}
</h#{header_number}>
HEREDOC
end
private
def remove_emoji_and_hyphenate(string)
string.downcase.gsub(EmojiRegex::Regex, "").strip.gsub(/\s/, "-")
end
end
end
end

View file

@ -27,7 +27,7 @@ describe "Using the editor" do
page.evaluate_script("window.onbeforeunload = function(){}")
end
it "fill out form with ruch content and click preview" do
it "fill out form with rich content and click preview" do
fill_markdown_with(read_from_file(raw_text))
page.execute_script("window.scrollTo(0, -100000)")
find("button#previewbutt").click

View file

@ -210,82 +210,5 @@ RSpec.describe Comment, type: :model do
end
end
# describe "::StreamRails::Activity(notification callbacks)" do
# before do
# StreamRails.enabled = true
# allow(StreamNotifier).to receive(:new).and_call_original
# end
# after { StreamRails.enabled = false }
# context "when a comment without ancestor is created" do
# let(:test_comment) { build(:comment, commentable_id: article.id) }
# before { allow(test_comment).to receive(:send_email_notification).and_call_original }
# it "notifies the author" do
# test_comment.save!
# expect(StreamNotifier).to have_received(:new).at_least(:once)
# end
# it "does not notify author if self is author" do
# test_comment.user = user
# test_comment.save
# expect(StreamNotifier).not_to have_received(:new).with(user.id)
# expect(test_comment).not_to have_received :send_email_notification
# end
# it "does not notify anybody else" do
# test_comment.save
# expect(StreamNotifier).not_to have_received(:new).with(test_comment.user_id)
# end
# end
# context "when a comment with ancestor is created" do
# let(:nest_comment_1) { create(:comment, commentable_id: article.id) }
# let(:nest_comment_2) do
# create(:comment, parent_id: nest_comment_1.id, commentable_id: article.id)
# end
# let(:author_comment) do
# create(:comment, parent_id: nest_comment_2.id,
# commentable_id: article.id, user_id: user.id)
# end
# let(:nest_comments_authors) { [nest_comment_1.user_id, nest_comment_2.user_id] }
# before do
# StreamRails.enabled = false
# nest_comments_authors # this needs to be evoked before StreamRails is enabled
# StreamRails.enabled = true
# end
# it "notifies all the ancestors" do
# create(:comment, parent_id: nest_comment_2.id, commentable_id: article.id)
# nest_comments_authors.each do |id|
# expect(StreamNotifier).to have_received(:new).with(id).at_least(:once)
# end
# end
# it "does not notifies the author" do
# create(:comment, parent_id: nest_comment_2.id, commentable_id: article.id)
# expect(StreamNotifier).not_to have_received(:new).with(user.id)
# end
# it "notifies all ancestors even if the author is among them" do
# create(:comment, parent_id: author_comment.id, commentable_id: article.id)
# nest_comments_authors.push(user.id).each do |id|
# expect(StreamNotifier).to have_received(:new).with(id).at_least(:once)
# end
# end
# it "does not notify self if self is among the ancestors" do
# me = create(:user)
# test_comment = create(:comment, parent_id: author_comment.id, commentable_id: article.id, user_id: me.id)
# create(:comment, parent_id: author_comment.id, commentable_id: article.id, user_id: me.id)
# allow(test_comment).to receive(:send_email_notification).and_call_original
# expect(StreamNotifier).not_to have_received(:new).with(me.id)
# expect(test_comment).not_to have_received(:send_email_notification)
# end
# end
# end
end
# rubocop:enable RSpec/ExampleLength, RSpec/MultipleExpectations

View file

@ -1,16 +1,52 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body><h1>h1</h1>
<body><h1>
<a name="h1" href="#h1" class="anchor" id="h1">
</a>
h1
</h1>
<h2>h2</h2>
<h2>
<a name="h2" href="#h2" class="anchor" id="h2">
</a>
h2
</h2>
<h3>h3</h3>
<h3>
<a name="h3" href="#h3" class="anchor" id="h3">
</a>
h3
</h3>
<h4>h4</h4>
<h4>
<a name="h4" href="#h4" class="anchor" id="h4">
</a>
h4
</h4>
<h5>h5</h5>
<h5>
<a name="h5" href="#h5" class="anchor" id="h5">
</a>
h5
</h5>
<h6>h6</h6>
<h6>
<a name="h6" href="#h6" class="anchor" id="h6">
</a>
h6
</h6>
<h1>
<a name="multiword-heading" href="#multiword-heading" class="anchor" id="multiword-heading">
</a>
multiword heading
</h1>
<h1>
<a name="%F0%9F%98%8E-emoji-heading" href="#%F0%9F%98%8E-emoji-heading" class="anchor" id="%F0%9F%98%8E-emoji-heading">
</a>
😎 emoji heading
</h1>
<p><em>italic</em> <em>italic</em><br /><strong>bold</strong> <strong>bold</strong><br /><em>You <strong>can</strong> combine them</em><br /><strong>asterisks and <em>underscores</em></strong></p>

View file

@ -1,8 +1,8 @@
---
title: This is a test
published: false
description:
tags:
description:
tags:
---
# h1
@ -11,6 +11,8 @@ tags:
#### h4
##### h5
###### h6
# multiword heading
# &#128526; emoji heading
*italic* _italic_
**bold** __bold__