qiita-markdown 0.14.0 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of qiita-markdown might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +5 -4
- data/lib/qiita/markdown.rb +1 -0
- data/lib/qiita/markdown/filters/external_link.rb +41 -0
- data/lib/qiita/markdown/filters/sanitize.rb +1 -0
- data/lib/qiita/markdown/processor.rb +1 -0
- data/lib/qiita/markdown/summary_processor.rb +1 -0
- data/lib/qiita/markdown/version.rb +1 -1
- data/qiita-markdown.gemspec +1 -0
- data/spec/qiita/markdown/processor_spec.rb +140 -8
- data/spec/qiita/markdown/summary_processor_spec.rb +6 -6
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aeafaca650b98a99a00e0735bde849f99faff1fb
|
4
|
+
data.tar.gz: 2911b685bc654da88a608ba1ee7c4636027c9a40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 019f1dd78735350a0e5c43f0c869fc3656ae858aaeec5d659b9eab64a1d040f3e0685a26313facb6fa750b526aecf676ad5b874aca06a49e18867fa384a60030
|
7
|
+
data.tar.gz: 26232bd99bac696a6eb05cd37054a53c0227773db46f78f0406abc63f0076d1b84ad06ca0058d53d8d2dcb18a4fbc5966f3f867f1f49f7d50f65f8d2eacbe7ff
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -15,7 +15,7 @@ Qiita-specified markdown processor.
|
|
15
15
|
Qiita::Markdown::Processor provides markdown rendering logic.
|
16
16
|
|
17
17
|
```ruby
|
18
|
-
processor = Qiita::Markdown::Processor.new
|
18
|
+
processor = Qiita::Markdown::Processor.new(hostname: "example.com")
|
19
19
|
processor.call(markdown)
|
20
20
|
# => {
|
21
21
|
# codes: [
|
@@ -38,7 +38,7 @@ Qiita::Markdown is built on [jch/html-pipeline](https://github.com/jch/html-pipe
|
|
38
38
|
Add your favorite html-pipeline-compatible filters.
|
39
39
|
|
40
40
|
```ruby
|
41
|
-
processor = Qiita::Markdown::Processor.new
|
41
|
+
processor = Qiita::Markdown::Processor.new(hostname: "example.com")
|
42
42
|
processor.filters << HTML::Pipeline::ImageMaxWidthFilter
|
43
43
|
processor.call(text)
|
44
44
|
```
|
@@ -55,13 +55,14 @@ processor.call(text)
|
|
55
55
|
:emoji_names - A list of allowed emoji names. (Array<String>)
|
56
56
|
:emoji_url_generator - #call'able object that accepts emoji name as argument and returns emoji image URL. (#call)
|
57
57
|
The original implementation is used when the generator returned a falsey value.
|
58
|
+
:hostname - FQDN. Used to check whether or not each URL of `href` attributes is external site. (String)
|
58
59
|
:language_aliases - Alias table for some language names. (Hash)
|
59
60
|
:rule - Sanitization rule table. (Hash)
|
60
61
|
:script - A flag to allow to embed script element. (Boolean)
|
61
62
|
```
|
62
63
|
|
63
64
|
```ruby
|
64
|
-
processor = Qiita::Markdown::Processor.new(asset_root: "http://example.com/assets")
|
65
|
+
processor = Qiita::Markdown::Processor.new(asset_root: "http://example.com/assets", hostname: "example.com")
|
65
66
|
processor.call(text)
|
66
67
|
```
|
67
68
|
|
@@ -87,6 +88,6 @@ SummaryProcessor accepts the following context in addition to the Processor's co
|
|
87
88
|
```
|
88
89
|
|
89
90
|
```ruby
|
90
|
-
processor = Qiita::Markdown::SummaryProcessor.new(truncate: { length: 80 })
|
91
|
+
processor = Qiita::Markdown::SummaryProcessor.new(truncate: { length: 80 }, hostname: "example.com")
|
91
92
|
processor.call(text)
|
92
93
|
```
|
data/lib/qiita/markdown.rb
CHANGED
@@ -10,6 +10,7 @@ require "sanitize"
|
|
10
10
|
require "qiita/markdown/filters/checkbox"
|
11
11
|
require "qiita/markdown/filters/code"
|
12
12
|
require "qiita/markdown/filters/emoji"
|
13
|
+
require "qiita/markdown/filters/external_link"
|
13
14
|
require "qiita/markdown/filters/footnote"
|
14
15
|
require "qiita/markdown/filters/greenmat"
|
15
16
|
require "qiita/markdown/filters/group_mention"
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "addressable/uri"
|
2
|
+
|
3
|
+
module Qiita
|
4
|
+
module Markdown
|
5
|
+
module Filters
|
6
|
+
class ExternalLink < HTML::Pipeline::Filter
|
7
|
+
def call
|
8
|
+
doc.search("a").each do |anchor|
|
9
|
+
next unless anchor["href"]
|
10
|
+
href = anchor["href"].strip
|
11
|
+
href_host = host_of(href)
|
12
|
+
next unless href_host
|
13
|
+
if href_host != hostname
|
14
|
+
anchor["rel"] = "nofollow"
|
15
|
+
anchor["target"] = "_blank"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
doc
|
20
|
+
end
|
21
|
+
|
22
|
+
def validate
|
23
|
+
needs :hostname
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def host_of(url)
|
29
|
+
uri = Addressable::URI.parse(url)
|
30
|
+
uri.host
|
31
|
+
rescue Addressable::URI::InvalidURIError
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def hostname
|
36
|
+
context[:hostname]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/qiita-markdown.gemspec
CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_dependency "pygments.rb"
|
26
26
|
spec.add_dependency "greenmat", ">= 3.2.0.2", "< 4"
|
27
27
|
spec.add_dependency "sanitize"
|
28
|
+
spec.add_dependency "addressable"
|
28
29
|
spec.add_development_dependency "activesupport", "4.2.6"
|
29
30
|
spec.add_development_dependency "benchmark-ips", "~> 1.2"
|
30
31
|
spec.add_development_dependency "bundler", "~> 1.7"
|
@@ -7,7 +7,7 @@ describe Qiita::Markdown::Processor do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
let(:context) do
|
10
|
-
{}
|
10
|
+
{ hostname: "example.com" }
|
11
11
|
end
|
12
12
|
|
13
13
|
let(:markdown) do
|
@@ -482,7 +482,7 @@ describe Qiita::Markdown::Processor do
|
|
482
482
|
|
483
483
|
it "replaces it with preferred link and updates :mentioned_groups" do
|
484
484
|
is_expected.to eq <<-EOS.strip_heredoc
|
485
|
-
<p><a href="https://alice.example.com/groups/bob">@alice/bob</a></p>
|
485
|
+
<p><a href="https://alice.example.com/groups/bob" rel="nofollow" target="_blank">@alice/bob</a></p>
|
486
486
|
EOS
|
487
487
|
expect(result[:mentioned_groups]).to eq [{
|
488
488
|
group_url_name: "bob",
|
@@ -517,13 +517,13 @@ describe Qiita::Markdown::Processor do
|
|
517
517
|
|
518
518
|
context "with raw URL" do
|
519
519
|
let(:markdown) do
|
520
|
-
"http://
|
520
|
+
"http://example.com/search?q=日本語"
|
521
521
|
end
|
522
522
|
|
523
523
|
it "creates link for that with .autolink class" do
|
524
524
|
should eq(
|
525
|
-
'<p><a href="http://
|
526
|
-
"http://
|
525
|
+
'<p><a href="http://example.com/search?q=%E6%97%A5%E6%9C%AC%E8%AA%9E" class="autolink">' \
|
526
|
+
"http://example.com/search?q=日本語</a></p>\n"
|
527
527
|
)
|
528
528
|
end
|
529
529
|
end
|
@@ -745,7 +745,7 @@ describe Qiita::Markdown::Processor do
|
|
745
745
|
|
746
746
|
it "generates footnotes elements" do
|
747
747
|
should eq <<-EOS.strip_heredoc
|
748
|
-
<p><sup id="fnref1"><a href="#fn1" title="test">1</a></sup></p>
|
748
|
+
<p><sup id="fnref1"><a href="#fn1" rel="footnote" title="test">1</a></sup></p>
|
749
749
|
|
750
750
|
<div class="footnotes">
|
751
751
|
<hr>
|
@@ -764,13 +764,13 @@ describe Qiita::Markdown::Processor do
|
|
764
764
|
context "with manually written link inside of <sup> tag" do
|
765
765
|
let(:markdown) do
|
766
766
|
<<-EOS.strip_heredoc
|
767
|
-
<sup>[
|
767
|
+
<sup>[Example](http://example.com/)</sup>
|
768
768
|
EOS
|
769
769
|
end
|
770
770
|
|
771
771
|
it "does not confuse the structure with automatically generated footnote reference" do
|
772
772
|
should eq <<-EOS.strip_heredoc
|
773
|
-
<p><sup><a href="http://
|
773
|
+
<p><sup><a href="http://example.com/">Example</a></sup></p>
|
774
774
|
EOS
|
775
775
|
end
|
776
776
|
end
|
@@ -847,5 +847,137 @@ describe Qiita::Markdown::Processor do
|
|
847
847
|
)
|
848
848
|
end
|
849
849
|
end
|
850
|
+
|
851
|
+
context "with internal URL" do
|
852
|
+
let(:markdown) do
|
853
|
+
"http://qiita.com/?a=b"
|
854
|
+
end
|
855
|
+
|
856
|
+
let(:context) do
|
857
|
+
{ hostname: "qiita.com" }
|
858
|
+
end
|
859
|
+
|
860
|
+
it "creates link which does not have rel='nofollow' and target='_blank'" do
|
861
|
+
should eq(
|
862
|
+
'<p><a href="http://qiita.com/?a=b" class="autolink">' \
|
863
|
+
"http://qiita.com/?a=b</a></p>\n"
|
864
|
+
)
|
865
|
+
end
|
866
|
+
end
|
867
|
+
|
868
|
+
context "with external URL" do
|
869
|
+
let(:markdown) do
|
870
|
+
"http://external.com/?a=b"
|
871
|
+
end
|
872
|
+
|
873
|
+
let(:context) do
|
874
|
+
{ hostname: "qiita.com" }
|
875
|
+
end
|
876
|
+
|
877
|
+
it "creates link which has rel='nofollow' and target='_blank'" do
|
878
|
+
should eq(
|
879
|
+
'<p><a href="http://external.com/?a=b" class="autolink" rel="nofollow" target="_blank">' \
|
880
|
+
"http://external.com/?a=b</a></p>\n"
|
881
|
+
)
|
882
|
+
end
|
883
|
+
end
|
884
|
+
|
885
|
+
context "with internal anchor tag" do
|
886
|
+
let(:markdown) do
|
887
|
+
'<a href="http://qiita.com/?a=b">foobar</a>'
|
888
|
+
end
|
889
|
+
|
890
|
+
let(:context) do
|
891
|
+
{ hostname: "qiita.com" }
|
892
|
+
end
|
893
|
+
|
894
|
+
it "creates link which does not have rel='nofollow' and target='_blank'" do
|
895
|
+
should eq(
|
896
|
+
"<p><a href=\"http://qiita.com/?a=b\">foobar</a></p>\n"
|
897
|
+
)
|
898
|
+
end
|
899
|
+
end
|
900
|
+
|
901
|
+
context "with external anchor tag" do
|
902
|
+
let(:markdown) do
|
903
|
+
'<a href="http://external.com/?a=b">foobar</a>'
|
904
|
+
end
|
905
|
+
|
906
|
+
let(:context) do
|
907
|
+
{ hostname: "qiita.com" }
|
908
|
+
end
|
909
|
+
|
910
|
+
it "creates link which has rel='nofollow' and target='_blank'" do
|
911
|
+
should eq(
|
912
|
+
"<p><a href=\"http://external.com/?a=b\" rel=\"nofollow\" target=\"_blank\">foobar</a></p>\n"
|
913
|
+
)
|
914
|
+
end
|
915
|
+
end
|
916
|
+
|
917
|
+
context "with external URL which ends with the hostname parameter" do
|
918
|
+
let(:markdown) do
|
919
|
+
"http://qqqqqqiita.com/?a=b"
|
920
|
+
end
|
921
|
+
|
922
|
+
let(:context) do
|
923
|
+
{ hostname: "qiita.com" }
|
924
|
+
end
|
925
|
+
|
926
|
+
it "creates link which has rel='nofollow' and target='_blank'" do
|
927
|
+
should eq(
|
928
|
+
'<p><a href="http://qqqqqqiita.com/?a=b" class="autolink" rel="nofollow" target="_blank">' \
|
929
|
+
"http://qqqqqqiita.com/?a=b</a></p>\n"
|
930
|
+
)
|
931
|
+
end
|
932
|
+
end
|
933
|
+
|
934
|
+
context "with external anchor tag which ends with the hostname parameter" do
|
935
|
+
let(:markdown) do
|
936
|
+
'<a href="http://qqqqqqiita.com/?a=b">foobar</a>'
|
937
|
+
end
|
938
|
+
|
939
|
+
let(:context) do
|
940
|
+
{ hostname: "qiita.com" }
|
941
|
+
end
|
942
|
+
|
943
|
+
it "creates link which has rel='nofollow' and target='_blank'" do
|
944
|
+
should eq(
|
945
|
+
"<p><a href=\"http://qqqqqqiita.com/?a=b\" rel=\"nofollow\" target=\"_blank\">foobar</a></p>\n"
|
946
|
+
)
|
947
|
+
end
|
948
|
+
end
|
949
|
+
|
950
|
+
context "with sub-domain URL of hostname parameter" do
|
951
|
+
let(:markdown) do
|
952
|
+
"http://sub.qiita.com/?a=b"
|
953
|
+
end
|
954
|
+
|
955
|
+
let(:context) do
|
956
|
+
{ hostname: "qiita.com" }
|
957
|
+
end
|
958
|
+
|
959
|
+
it "creates link which has rel='nofollow' and target='_blank'" do
|
960
|
+
should eq(
|
961
|
+
'<p><a href="http://sub.qiita.com/?a=b" class="autolink" rel="nofollow" target="_blank">' \
|
962
|
+
"http://sub.qiita.com/?a=b</a></p>\n"
|
963
|
+
)
|
964
|
+
end
|
965
|
+
end
|
966
|
+
|
967
|
+
context "with external anchor tag which has rel attribute" do
|
968
|
+
let(:markdown) do
|
969
|
+
'<a href="http://external.com/?a=b" rel="url">foobar</a>'
|
970
|
+
end
|
971
|
+
|
972
|
+
let(:context) do
|
973
|
+
{ hostname: "qiita.com" }
|
974
|
+
end
|
975
|
+
|
976
|
+
it "creates link which has rel='nofollow' and target='_blank', and rel value is overwritten" do
|
977
|
+
should eq(
|
978
|
+
"<p><a href=\"http://external.com/?a=b\" rel=\"nofollow\" target=\"_blank\">foobar</a></p>\n"
|
979
|
+
)
|
980
|
+
end
|
981
|
+
end
|
850
982
|
end
|
851
983
|
end
|
@@ -7,7 +7,7 @@ describe Qiita::Markdown::SummaryProcessor do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
let(:context) do
|
10
|
-
{}
|
10
|
+
{ hostname: "example.com" }
|
11
11
|
end
|
12
12
|
|
13
13
|
let(:markdown) do
|
@@ -185,17 +185,17 @@ describe Qiita::Markdown::SummaryProcessor do
|
|
185
185
|
|
186
186
|
context "with a long document consisting of nested elements" do
|
187
187
|
before do
|
188
|
-
context[:truncate] = { length:
|
188
|
+
context[:truncate] = { length: 12 }
|
189
189
|
end
|
190
190
|
|
191
191
|
let(:markdown) do
|
192
192
|
<<-EOS.strip_heredoc
|
193
|
-
_[
|
193
|
+
_[Example](http://example.com/) is **a technical knowledge sharing and collaboration platform for programmers**._
|
194
194
|
EOS
|
195
195
|
end
|
196
196
|
|
197
197
|
it "truncates it while honoring the document structure" do
|
198
|
-
should eq '<em><a href="http://
|
198
|
+
should eq '<em><a href="http://example.com/">Example</a> is <strong>…</strong></em>'
|
199
199
|
end
|
200
200
|
end
|
201
201
|
|
@@ -206,13 +206,13 @@ describe Qiita::Markdown::SummaryProcessor do
|
|
206
206
|
|
207
207
|
let(:markdown) do
|
208
208
|
<<-EOS.strip_heredoc
|
209
|
-
**12** 4 [ 6](http://
|
209
|
+
**12** 4 [ 6](http://example.com/)_7
|
210
210
|
9_ 123
|
211
211
|
EOS
|
212
212
|
end
|
213
213
|
|
214
214
|
it "truncates it while counting the consecutive whilespaces as one" do
|
215
|
-
should eq "<strong>12</strong> 4 <a href=\"http://
|
215
|
+
should eq "<strong>12</strong> 4 <a href=\"http://example.com/\"> 6</a><em>7\n9</em>…"
|
216
216
|
end
|
217
217
|
end
|
218
218
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qiita-markdown
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryo Nakamura
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gemoji
|
@@ -114,6 +114,20 @@ dependencies:
|
|
114
114
|
- - ">="
|
115
115
|
- !ruby/object:Gem::Version
|
116
116
|
version: '0'
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: addressable
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
type: :runtime
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
117
131
|
- !ruby/object:Gem::Dependency
|
118
132
|
name: activesupport
|
119
133
|
requirement: !ruby/object:Gem::Requirement
|
@@ -250,6 +264,7 @@ files:
|
|
250
264
|
- lib/qiita/markdown/filters/checkbox.rb
|
251
265
|
- lib/qiita/markdown/filters/code.rb
|
252
266
|
- lib/qiita/markdown/filters/emoji.rb
|
267
|
+
- lib/qiita/markdown/filters/external_link.rb
|
253
268
|
- lib/qiita/markdown/filters/footnote.rb
|
254
269
|
- lib/qiita/markdown/filters/greenmat.rb
|
255
270
|
- lib/qiita/markdown/filters/group_mention.rb
|
@@ -301,4 +316,3 @@ test_files:
|
|
301
316
|
- spec/qiita/markdown/processor_spec.rb
|
302
317
|
- spec/qiita/markdown/summary_processor_spec.rb
|
303
318
|
- spec/spec_helper.rb
|
304
|
-
has_rdoc:
|