qiita-markdown 0.15.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -1
- data/README.md +2 -0
- data/lib/qiita/markdown.rb +1 -0
- data/lib/qiita/markdown/base_processor.rb +42 -0
- data/lib/qiita/markdown/filters/external_link.rb +1 -1
- data/lib/qiita/markdown/filters/greenmat.rb +9 -1
- data/lib/qiita/markdown/filters/sanitize.rb +2 -0
- data/lib/qiita/markdown/processor.rb +19 -41
- data/lib/qiita/markdown/summary_processor.rb +19 -14
- data/lib/qiita/markdown/version.rb +1 -1
- data/spec/qiita/markdown/processor_spec.rb +34 -15
- data/spec/qiita/markdown/summary_processor_spec.rb +15 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 739494b992f30301e63c329ca71f822ef80bd67a
|
|
4
|
+
data.tar.gz: 6f925bef2e51205cec9f663e71ddae50ef6d2097
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f002a9b803ff192b9139c8060dde2116e945aec2aec1fd9f02e3a09d45ad85c5654a7fdf8f2f7b31bd44a9f48293c693506d4b0cbeca15c9d41a2d4ae66cadf9
|
|
7
|
+
data.tar.gz: b718ef753796afa29aaed9dc72122a0bc88daa33db71cceea242ffe8192ff4f6238766e54ebe0f91821ebff7680b231457ce200ff7f6a0f3c38bb2936192d4af
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
## 0.16.0
|
|
2
|
+
- Add rel=noopener to all external a tags
|
|
3
|
+
- Support HTML5 `<details>` and `<summary>` elements
|
|
4
|
+
- Enable to change settings for footnotes
|
|
5
|
+
|
|
1
6
|
## 0.15.0
|
|
2
|
-
- Append rel=nofollow and target=_blank to
|
|
7
|
+
- Append `rel=nofollow` and `target=_blank` to `a` tags for external link
|
|
3
8
|
|
|
4
9
|
## 0.14.0
|
|
5
10
|
- Add some attributes to mentions for rendering hovercard
|
data/README.md
CHANGED
|
@@ -57,6 +57,8 @@ processor.call(text)
|
|
|
57
57
|
The original implementation is used when the generator returned a falsey value.
|
|
58
58
|
:hostname - FQDN. Used to check whether or not each URL of `href` attributes is external site. (String)
|
|
59
59
|
:language_aliases - Alias table for some language names. (Hash)
|
|
60
|
+
:markdown - A hash for enabling / disabling optional Markdown syntax. (Hash)
|
|
61
|
+
Currently only :footnotes (default: true) is supported.
|
|
60
62
|
:rule - Sanitization rule table. (Hash)
|
|
61
63
|
:script - A flag to allow to embed script element. (Boolean)
|
|
62
64
|
```
|
data/lib/qiita/markdown.rb
CHANGED
|
@@ -23,6 +23,7 @@ require "qiita/markdown/filters/truncate"
|
|
|
23
23
|
require "qiita/markdown/greenmat/heading_rendering"
|
|
24
24
|
require "qiita/markdown/greenmat/html_renderer"
|
|
25
25
|
require "qiita/markdown/greenmat/html_toc_renderer"
|
|
26
|
+
require "qiita/markdown/base_processor"
|
|
26
27
|
require "qiita/markdown/processor"
|
|
27
28
|
require "qiita/markdown/summary_processor"
|
|
28
29
|
require "qiita/markdown/version"
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Qiita
|
|
2
|
+
module Markdown
|
|
3
|
+
# An abstract base processor for rendering a Markdown document.
|
|
4
|
+
class BaseProcessor
|
|
5
|
+
# @return [Hash] the default context for HTML::Pipeline
|
|
6
|
+
def self.default_context
|
|
7
|
+
raise NotImplementedError
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# @return [Array<Class>] the default HTML::Pipeline filter classes
|
|
11
|
+
def self.default_fiters
|
|
12
|
+
raise NotImplementedError
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @param [Hash] context Optional context for HTML::Pipeline.
|
|
16
|
+
def initialize(context = {})
|
|
17
|
+
@context = self.class.default_context.merge(context)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Converts Markdown text into HTML string with extracted metadata.
|
|
21
|
+
#
|
|
22
|
+
# @param [String] input Markdown text.
|
|
23
|
+
# @param [Hash] context Optional context merged into default context.
|
|
24
|
+
# @return [Hash] Process result.
|
|
25
|
+
# @example
|
|
26
|
+
# Qiita::Markdown::Processor.new.call(markdown) #=> {
|
|
27
|
+
# codes: [...],
|
|
28
|
+
# mentioned_usernames: [...],
|
|
29
|
+
# output: "...",
|
|
30
|
+
# }
|
|
31
|
+
def call(input, context = {})
|
|
32
|
+
HTML::Pipeline.new(filters, @context).call(input, context)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @note Modify filters if you want.
|
|
36
|
+
# @return [Array<HTML::Pipeline::Filter>]
|
|
37
|
+
def filters
|
|
38
|
+
@filters ||= self.class.default_filters
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -2,6 +2,10 @@ module Qiita
|
|
|
2
2
|
module Markdown
|
|
3
3
|
module Filters
|
|
4
4
|
class Greenmat < HTML::Pipeline::TextFilter
|
|
5
|
+
DEFAULT_OPTIONS = {
|
|
6
|
+
footnotes: true,
|
|
7
|
+
}.freeze
|
|
8
|
+
|
|
5
9
|
# @return [Nokogiri::HTML::DocumentFragment]
|
|
6
10
|
def call
|
|
7
11
|
Nokogiri::HTML.fragment(greenmat.render(@text))
|
|
@@ -16,13 +20,17 @@ module Qiita
|
|
|
16
20
|
Qiita::Markdown::Greenmat::HTMLRenderer.new(hard_wrap: true, with_toc_data: true),
|
|
17
21
|
autolink: true,
|
|
18
22
|
fenced_code_blocks: true,
|
|
19
|
-
footnotes:
|
|
23
|
+
footnotes: options[:footnotes],
|
|
20
24
|
no_intra_emphasis: true,
|
|
21
25
|
no_mention_emphasis: true,
|
|
22
26
|
strikethrough: true,
|
|
23
27
|
tables: true,
|
|
24
28
|
)
|
|
25
29
|
end
|
|
30
|
+
|
|
31
|
+
def options
|
|
32
|
+
@options ||= DEFAULT_OPTIONS.merge(context[:markdown] || {})
|
|
33
|
+
end
|
|
26
34
|
end
|
|
27
35
|
end
|
|
28
36
|
end
|
|
@@ -1,48 +1,26 @@
|
|
|
1
1
|
module Qiita
|
|
2
2
|
module Markdown
|
|
3
|
-
class Processor
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
DEFAULT_FILTERS = [
|
|
9
|
-
Filters::Greenmat,
|
|
10
|
-
Filters::ImageLink,
|
|
11
|
-
Filters::Footnote,
|
|
12
|
-
Filters::Code,
|
|
13
|
-
Filters::Checkbox,
|
|
14
|
-
Filters::Emoji,
|
|
15
|
-
Filters::SyntaxHighlight,
|
|
16
|
-
Filters::Mention,
|
|
17
|
-
Filters::GroupMention,
|
|
18
|
-
Filters::ExternalLink,
|
|
19
|
-
Filters::Sanitize,
|
|
20
|
-
]
|
|
21
|
-
|
|
22
|
-
# @param [Hash] context Optional context for HTML::Pipeline.
|
|
23
|
-
def initialize(context = {})
|
|
24
|
-
@context = DEFAULT_CONTEXT.merge(context)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Converts Markdown text into HTML string with extracted metadata.
|
|
28
|
-
#
|
|
29
|
-
# @param [String] input Markdown text.
|
|
30
|
-
# @param [Hash] context Optional context merged into default context.
|
|
31
|
-
# @return [Hash] Process result.
|
|
32
|
-
# @example
|
|
33
|
-
# Qiita::Markdown::Processor.new.call(markdown) #=> {
|
|
34
|
-
# codes: [...],
|
|
35
|
-
# mentioned_usernames: [...],
|
|
36
|
-
# output: "...",
|
|
37
|
-
# }
|
|
38
|
-
def call(input, context = {})
|
|
39
|
-
HTML::Pipeline.new(filters, @context).call(input, context)
|
|
3
|
+
class Processor < BaseProcessor
|
|
4
|
+
def self.default_context
|
|
5
|
+
{
|
|
6
|
+
asset_root: "/images",
|
|
7
|
+
}
|
|
40
8
|
end
|
|
41
9
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
10
|
+
def self.default_filters
|
|
11
|
+
[
|
|
12
|
+
Filters::Greenmat,
|
|
13
|
+
Filters::ImageLink,
|
|
14
|
+
Filters::Footnote,
|
|
15
|
+
Filters::Code,
|
|
16
|
+
Filters::Checkbox,
|
|
17
|
+
Filters::Emoji,
|
|
18
|
+
Filters::SyntaxHighlight,
|
|
19
|
+
Filters::Mention,
|
|
20
|
+
Filters::GroupMention,
|
|
21
|
+
Filters::ExternalLink,
|
|
22
|
+
Filters::Sanitize,
|
|
23
|
+
]
|
|
46
24
|
end
|
|
47
25
|
end
|
|
48
26
|
end
|
|
@@ -3,21 +3,26 @@ module Qiita
|
|
|
3
3
|
# A processor for rendering a summary of markdown document. This simplifies
|
|
4
4
|
# a document by removing complex markups and also truncates it to a
|
|
5
5
|
# specific length without breaking the document structure.
|
|
6
|
-
class SummaryProcessor <
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
]
|
|
6
|
+
class SummaryProcessor < BaseProcessor
|
|
7
|
+
def self.default_context
|
|
8
|
+
{
|
|
9
|
+
asset_root: "/images",
|
|
10
|
+
markdown: {
|
|
11
|
+
footnotes: false,
|
|
12
|
+
},
|
|
13
|
+
}
|
|
14
|
+
end
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
def self.default_filters
|
|
17
|
+
[
|
|
18
|
+
Filters::Greenmat,
|
|
19
|
+
Filters::Simplify,
|
|
20
|
+
Filters::Emoji,
|
|
21
|
+
Filters::Mention,
|
|
22
|
+
Filters::ExternalLink,
|
|
23
|
+
Filters::Sanitize,
|
|
24
|
+
Filters::Truncate,
|
|
25
|
+
]
|
|
21
26
|
end
|
|
22
27
|
end
|
|
23
28
|
end
|
|
@@ -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" rel="nofollow" target="_blank">@alice/bob</a></p>
|
|
485
|
+
<p><a href="https://alice.example.com/groups/bob" rel="nofollow noopener" target="_blank">@alice/bob</a></p>
|
|
486
486
|
EOS
|
|
487
487
|
expect(result[:mentioned_groups]).to eq [{
|
|
488
488
|
group_url_name: "bob",
|
|
@@ -789,6 +789,25 @@ describe Qiita::Markdown::Processor do
|
|
|
789
789
|
end
|
|
790
790
|
end
|
|
791
791
|
|
|
792
|
+
context "with markdown: { footnotes: false } context" do
|
|
793
|
+
before do
|
|
794
|
+
context[:markdown] = { footnotes: false }
|
|
795
|
+
end
|
|
796
|
+
|
|
797
|
+
let(:markdown) do
|
|
798
|
+
<<-EOS.strip_heredoc
|
|
799
|
+
[^1]
|
|
800
|
+
[^1]: test
|
|
801
|
+
EOS
|
|
802
|
+
end
|
|
803
|
+
|
|
804
|
+
it "does not generate footnote elements" do
|
|
805
|
+
should eq <<-EOS.strip_heredoc
|
|
806
|
+
<p><a href="test">^1</a></p>
|
|
807
|
+
EOS
|
|
808
|
+
end
|
|
809
|
+
end
|
|
810
|
+
|
|
792
811
|
context "with data-attributes" do
|
|
793
812
|
let(:markdown) do
|
|
794
813
|
<<-EOS.strip_heredoc
|
|
@@ -857,7 +876,7 @@ describe Qiita::Markdown::Processor do
|
|
|
857
876
|
{ hostname: "qiita.com" }
|
|
858
877
|
end
|
|
859
878
|
|
|
860
|
-
it "creates link which does not have rel='nofollow' and target='_blank'" do
|
|
879
|
+
it "creates link which does not have rel='nofollow noopener' and target='_blank'" do
|
|
861
880
|
should eq(
|
|
862
881
|
'<p><a href="http://qiita.com/?a=b" class="autolink">' \
|
|
863
882
|
"http://qiita.com/?a=b</a></p>\n"
|
|
@@ -874,9 +893,9 @@ describe Qiita::Markdown::Processor do
|
|
|
874
893
|
{ hostname: "qiita.com" }
|
|
875
894
|
end
|
|
876
895
|
|
|
877
|
-
it "creates link which has rel='nofollow' and target='_blank'" do
|
|
896
|
+
it "creates link which has rel='nofollow noopener' and target='_blank'" do
|
|
878
897
|
should eq(
|
|
879
|
-
'<p><a href="http://external.com/?a=b" class="autolink" rel="nofollow" target="_blank">' \
|
|
898
|
+
'<p><a href="http://external.com/?a=b" class="autolink" rel="nofollow noopener" target="_blank">' \
|
|
880
899
|
"http://external.com/?a=b</a></p>\n"
|
|
881
900
|
)
|
|
882
901
|
end
|
|
@@ -891,7 +910,7 @@ describe Qiita::Markdown::Processor do
|
|
|
891
910
|
{ hostname: "qiita.com" }
|
|
892
911
|
end
|
|
893
912
|
|
|
894
|
-
it "creates link which does not have rel='nofollow' and target='_blank'" do
|
|
913
|
+
it "creates link which does not have rel='nofollow noopener' and target='_blank'" do
|
|
895
914
|
should eq(
|
|
896
915
|
"<p><a href=\"http://qiita.com/?a=b\">foobar</a></p>\n"
|
|
897
916
|
)
|
|
@@ -907,9 +926,9 @@ describe Qiita::Markdown::Processor do
|
|
|
907
926
|
{ hostname: "qiita.com" }
|
|
908
927
|
end
|
|
909
928
|
|
|
910
|
-
it "creates link which has rel='nofollow' and target='_blank'" do
|
|
929
|
+
it "creates link which has rel='nofollow noopener' and target='_blank'" do
|
|
911
930
|
should eq(
|
|
912
|
-
"<p><a href=\"http://external.com/?a=b\" rel=\"nofollow\" target=\"_blank\">foobar</a></p>\n"
|
|
931
|
+
"<p><a href=\"http://external.com/?a=b\" rel=\"nofollow noopener\" target=\"_blank\">foobar</a></p>\n"
|
|
913
932
|
)
|
|
914
933
|
end
|
|
915
934
|
end
|
|
@@ -923,9 +942,9 @@ describe Qiita::Markdown::Processor do
|
|
|
923
942
|
{ hostname: "qiita.com" }
|
|
924
943
|
end
|
|
925
944
|
|
|
926
|
-
it "creates link which has rel='nofollow' and target='_blank'" do
|
|
945
|
+
it "creates link which has rel='nofollow noopener' and target='_blank'" do
|
|
927
946
|
should eq(
|
|
928
|
-
'<p><a href="http://qqqqqqiita.com/?a=b" class="autolink" rel="nofollow" target="_blank">' \
|
|
947
|
+
'<p><a href="http://qqqqqqiita.com/?a=b" class="autolink" rel="nofollow noopener" target="_blank">' \
|
|
929
948
|
"http://qqqqqqiita.com/?a=b</a></p>\n"
|
|
930
949
|
)
|
|
931
950
|
end
|
|
@@ -940,9 +959,9 @@ describe Qiita::Markdown::Processor do
|
|
|
940
959
|
{ hostname: "qiita.com" }
|
|
941
960
|
end
|
|
942
961
|
|
|
943
|
-
it "creates link which has rel='nofollow' and target='_blank'" do
|
|
962
|
+
it "creates link which has rel='nofollow noopener' and target='_blank'" do
|
|
944
963
|
should eq(
|
|
945
|
-
"<p><a href=\"http://qqqqqqiita.com/?a=b\" rel=\"nofollow\" target=\"_blank\">foobar</a></p>\n"
|
|
964
|
+
"<p><a href=\"http://qqqqqqiita.com/?a=b\" rel=\"nofollow noopener\" target=\"_blank\">foobar</a></p>\n"
|
|
946
965
|
)
|
|
947
966
|
end
|
|
948
967
|
end
|
|
@@ -956,9 +975,9 @@ describe Qiita::Markdown::Processor do
|
|
|
956
975
|
{ hostname: "qiita.com" }
|
|
957
976
|
end
|
|
958
977
|
|
|
959
|
-
it "creates link which has rel='nofollow' and target='_blank'" do
|
|
978
|
+
it "creates link which has rel='nofollow noopener' and target='_blank'" do
|
|
960
979
|
should eq(
|
|
961
|
-
'<p><a href="http://sub.qiita.com/?a=b" class="autolink" rel="nofollow" target="_blank">' \
|
|
980
|
+
'<p><a href="http://sub.qiita.com/?a=b" class="autolink" rel="nofollow noopener" target="_blank">' \
|
|
962
981
|
"http://sub.qiita.com/?a=b</a></p>\n"
|
|
963
982
|
)
|
|
964
983
|
end
|
|
@@ -973,9 +992,9 @@ describe Qiita::Markdown::Processor do
|
|
|
973
992
|
{ hostname: "qiita.com" }
|
|
974
993
|
end
|
|
975
994
|
|
|
976
|
-
it "creates link which has rel='nofollow' and target='_blank', and rel value is overwritten" do
|
|
995
|
+
it "creates link which has rel='nofollow noopener' and target='_blank', and rel value is overwritten" do
|
|
977
996
|
should eq(
|
|
978
|
-
"<p><a href=\"http://external.com/?a=b\" rel=\"nofollow\" target=\"_blank\">foobar</a></p>\n"
|
|
997
|
+
"<p><a href=\"http://external.com/?a=b\" rel=\"nofollow noopener\" target=\"_blank\">foobar</a></p>\n"
|
|
979
998
|
)
|
|
980
999
|
end
|
|
981
1000
|
end
|
|
@@ -243,5 +243,20 @@ describe Qiita::Markdown::SummaryProcessor do
|
|
|
243
243
|
should eq %{<a href="/alice" class="user-mention js-hovercard" title="alice" data-hovercard-target-type="user" data-hovercard-target-name="alice">@alice</a>\n}
|
|
244
244
|
end
|
|
245
245
|
end
|
|
246
|
+
|
|
247
|
+
context "with footenote syntax" do
|
|
248
|
+
let(:markdown) do
|
|
249
|
+
<<-EOS.strip_heredoc
|
|
250
|
+
[^1]
|
|
251
|
+
[^1]: test
|
|
252
|
+
EOS
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it "does not generate footnote elements by default" do
|
|
256
|
+
should eq <<-EOS.strip_heredoc
|
|
257
|
+
<a href="test">^1</a>
|
|
258
|
+
EOS
|
|
259
|
+
end
|
|
260
|
+
end
|
|
246
261
|
end
|
|
247
262
|
end
|
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.16.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-
|
|
11
|
+
date: 2016-09-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: gemoji
|
|
@@ -261,6 +261,7 @@ files:
|
|
|
261
261
|
- benchmark/sample.md
|
|
262
262
|
- lib/qiita-markdown.rb
|
|
263
263
|
- lib/qiita/markdown.rb
|
|
264
|
+
- lib/qiita/markdown/base_processor.rb
|
|
264
265
|
- lib/qiita/markdown/filters/checkbox.rb
|
|
265
266
|
- lib/qiita/markdown/filters/code.rb
|
|
266
267
|
- lib/qiita/markdown/filters/emoji.rb
|