jekyll_aspec 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/.travis.yml +1 -1
- data/Gemfile +2 -2
- data/Gemfile.lock +1 -1
- data/README.md +10 -10
- data/Rakefile +8 -1
- data/bin/console +3 -3
- data/jekyll_aspec.gemspec +18 -18
- data/lib/extensions/autoxrefs.rb +103 -5
- data/lib/extensions/html_postprocessor.rb +1 -2
- data/lib/extensions/inline_callout_macro.rb +1 -1
- data/lib/extensions/inline_cwiki_macro.rb +8 -5
- data/lib/extensions/inline_repo_macro.rb +29 -23
- data/lib/extensions/inline_task_macro.rb +2 -2
- data/lib/extensions/replace_regex.rb +0 -3
- data/lib/extensions/req_refs.rb +32 -47
- data/lib/extensions/requirement_appendix.rb +116 -0
- data/lib/extensions/requirement_block.rb +45 -50
- data/lib/extensions/todo_block.rb +10 -16
- data/lib/extensions/utils/block.rb +21 -11
- data/lib/extensions/utils/labels.rb +9 -9
- data/lib/jekyll_aspec.rb +11 -20
- data/lib/jekyll_aspec/version.rb +2 -2
- metadata +9 -14
- data/docs/inline-task.adoc +0 -34
- data/docs/requirement-block.adoc +0 -56
- data/docs/todo-block.adoc +0 -48
- data/lib/extensions/req_preprocessor.rb +0 -23
- data/lib/extensions/requirement_block_macro.rb +0 -28
- data/lib/extensions/utils/req_macro_walker.rb +0 -110
- data/lib/extensions/utils/xref_helper.rb +0 -122
@@ -14,9 +14,9 @@ Extensions.register do
|
|
14
14
|
|
15
15
|
process do |parent, target, attrs|
|
16
16
|
pattern = parent.document.attr 'task-pattern'
|
17
|
-
if pattern.nil?
|
17
|
+
if pattern.nil?
|
18
18
|
warn "asciidoctor: WARNING: Attribue 'task-pattern' for inline task macro not defined"
|
19
|
-
pattern =
|
19
|
+
pattern = 'unknown'
|
20
20
|
end
|
21
21
|
url = pattern % target
|
22
22
|
|
@@ -1,8 +1,5 @@
|
|
1
|
-
# Used by Jekyll during conversion
|
2
1
|
module Jekyll
|
3
|
-
# A Liquid Template Filter for using regular expressions
|
4
2
|
module RegexFilter
|
5
|
-
# Simple replacement
|
6
3
|
def replace_regex(input, regex_string, replace_string)
|
7
4
|
regex = Regexp.new regex_string
|
8
5
|
input.gsub regex, replace_string
|
data/lib/extensions/req_refs.rb
CHANGED
@@ -2,30 +2,21 @@ require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'
|
|
2
2
|
|
3
3
|
include ::Asciidoctor
|
4
4
|
|
5
|
-
#
|
6
|
-
|
7
|
-
# @todo Don't do this
|
5
|
+
# Find all Adoc Files
|
8
6
|
adoc_files = Dir.glob('**/*.adoc')
|
9
|
-
|
10
|
-
|
11
|
-
exts = '(\.adoc|\.md|\.html)'
|
12
|
-
|
7
|
+
exts = "(\.adoc|\.md|\.html)"
|
8
|
+
# make some empty vars globally available
|
13
9
|
rpath = nil
|
14
10
|
rtext = nil
|
15
|
-
orphan = false
|
16
|
-
|
17
11
|
reqs = []
|
18
12
|
inc_reqs = []
|
19
|
-
com_reqs = []
|
20
13
|
incs = []
|
21
14
|
xrefs = []
|
22
|
-
|
23
15
|
xref_base = ''
|
24
16
|
|
25
|
-
|
26
|
-
|
17
|
+
# Retrieve this via document attribute
|
18
|
+
docsdir = '_docs'
|
27
19
|
|
28
|
-
# @todo called helper method here
|
29
20
|
def trim(s)
|
30
21
|
s.gsub!(/_docs\//, '')
|
31
22
|
s.gsub!(/(\.adoc|\.md|\.html)/, '')
|
@@ -38,8 +29,6 @@ adoc_files.each do |file_name|
|
|
38
29
|
File.read(file_name).each_line do |li|
|
39
30
|
lc += 1
|
40
31
|
|
41
|
-
incommentblock ^= true if li[blockrx]
|
42
|
-
commented = true if li[linerx]
|
43
32
|
inc = true if li[/published: false/]
|
44
33
|
|
45
34
|
# Match Requirement Blocks [req,ABC-123,version=n]
|
@@ -50,9 +39,7 @@ adoc_files.each do |file_name|
|
|
50
39
|
path = path.sub!(/#{exts}/, '')
|
51
40
|
item = [rid, li.chop, path, file_name, lc]
|
52
41
|
|
53
|
-
if
|
54
|
-
com_reqs.push item
|
55
|
-
elsif inc
|
42
|
+
if inc
|
56
43
|
inc_reqs.push item
|
57
44
|
else
|
58
45
|
reqs.push item
|
@@ -94,52 +81,50 @@ end
|
|
94
81
|
# Sort (in-place) by numberic ID
|
95
82
|
reqs.sort_by!(&:first)
|
96
83
|
|
97
|
-
#
|
84
|
+
# Preprocessor that strips the << tags - NOTE: may break conversion if line ends with >>
|
85
|
+
Extensions.register do
|
86
|
+
preprocessor do
|
87
|
+
process do |_document, reader|
|
88
|
+
Reader.new reader.readlines.map { |li|
|
89
|
+
if li[/\<\<Req-.+?\>\>/]
|
90
|
+
openb = li.match(/(\<\<)Req-.+?\>\>/).captures[0]
|
91
|
+
closeb = li.match(/\<\<Req-.+?(\>\>)/).captures[0]
|
92
|
+
li.gsub!(/#{openb}/, ' ')
|
93
|
+
li.gsub!(/#{closeb}/, ' ')
|
94
|
+
else
|
95
|
+
li
|
96
|
+
end
|
97
|
+
}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
98
102
|
Extensions.register do
|
99
103
|
inline_macro do
|
100
|
-
named :
|
104
|
+
named :reqlink
|
101
105
|
|
102
106
|
# Regex-based, will match "See Req-ROPR-123 for..."
|
103
|
-
# Will also match <<Req-ROPR-123>>
|
104
|
-
# @todo this is a heavy-handed approach to matching all
|
105
|
-
# xrefs. Find a better way to autolink xrefs that doesn't involved the
|
106
|
-
# use of the req-preprocessor
|
107
107
|
match /(Req-\w+-?\d+)/
|
108
108
|
|
109
109
|
# match id with Req-\w+-?(\d+)
|
110
110
|
process do |parent, target|
|
111
111
|
t = target.sub(/^Req-\w+-?/, '')
|
112
112
|
|
113
|
-
orphan = true if reqs.empty?
|
114
|
-
|
115
113
|
reqs.each do |id, text, path, _file_name, _line|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
rtext = rtext.gsub(/,version=\d\]$/, '')
|
122
|
-
break
|
123
|
-
else
|
124
|
-
orphan = true
|
125
|
-
end
|
114
|
+
next unless id == t
|
115
|
+
rpath = path
|
116
|
+
rtext = text.gsub(/\A\[req,id=/, '')
|
117
|
+
rtext = rtext.gsub(/,version=\d\]$/, '')
|
118
|
+
break
|
126
119
|
end
|
127
120
|
|
128
121
|
link = target.sub(/^Req-/, '')
|
129
122
|
xref_base = (parent.document.attr 'xref-base')
|
130
123
|
uri = "#{xref_base}/#{rpath}/index.html##{link}"
|
131
|
-
o = ' <span class
|
124
|
+
o = ' <span class="label label-info">'
|
132
125
|
c = ' </span>'
|
133
126
|
|
134
|
-
|
135
|
-
# docfile = parent.document.attr 'docname'
|
136
|
-
# warn %(asciidoctor: WARNING: #{name || node.node_name} orphaned #{target} in #{docfile})
|
137
|
-
(create_pass_block parent, %(<strong>#{target}</strong>), {},
|
138
|
-
content_model: :raw).convert
|
139
|
-
else
|
140
|
-
(create_anchor parent, %(#{o} Req. #{rtext} #{c}),
|
141
|
-
type: :link, target: uri).convert
|
142
|
-
end
|
127
|
+
(create_anchor parent, %(#{o} Req. #{rtext} #{c}), type: :link, target: uri).convert
|
143
128
|
end
|
144
129
|
end
|
145
130
|
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'asciidoctor'
|
2
|
+
require 'asciidoctor/extensions'
|
3
|
+
|
4
|
+
exts = "(\.adoc|\.md|\.html)"
|
5
|
+
docsdir = '_docs'
|
6
|
+
|
7
|
+
title = nil
|
8
|
+
chapter = nil
|
9
|
+
doctitle = nil
|
10
|
+
|
11
|
+
reqs = []
|
12
|
+
rows = []
|
13
|
+
# For commented requirements
|
14
|
+
coms = []
|
15
|
+
|
16
|
+
# For includes
|
17
|
+
inc_reqs = []
|
18
|
+
incs = []
|
19
|
+
|
20
|
+
CommentBlockRx = %r(^\/{4,}$)
|
21
|
+
CommentLineRx = %r{^//(?=[^/]|$)}
|
22
|
+
|
23
|
+
def trim(s)
|
24
|
+
s.gsub!(/_docs\//, '')
|
25
|
+
s.gsub!(/(\.adoc|\.md|\.html)/, '')
|
26
|
+
end
|
27
|
+
|
28
|
+
adoc_files = Dir.glob('**/*.adoc')
|
29
|
+
adoc_files.sort!
|
30
|
+
adoc_files.each do |f|
|
31
|
+
inc = false
|
32
|
+
commented = false
|
33
|
+
|
34
|
+
File.read(f).each_line do |li|
|
35
|
+
incommentblock ^= true if li[CommentBlockRx]
|
36
|
+
commented = true if li[CommentLineRx]
|
37
|
+
inc = true if li[/published: false/]
|
38
|
+
|
39
|
+
doctitle = /(?<=title:\s).+/.match(li) if li[/^title:\s+\w.+/]
|
40
|
+
chapter = /(?<=chapter:\s).+/.match(li) if li[/^chapter:\s+\w.+/]
|
41
|
+
|
42
|
+
if li[/\[\s*req\s*,\s*id\s*=\s*\w+-?[0-9]+\s*,.*/]
|
43
|
+
title.sub!(/^\./, '')
|
44
|
+
req = [li.chop, f, title, chapter, doctitle]
|
45
|
+
|
46
|
+
if commented || incommentblock
|
47
|
+
coms.push(req)
|
48
|
+
elsif inc
|
49
|
+
inc_reqs.push(req)
|
50
|
+
else
|
51
|
+
reqs.push(req)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Collect all includes
|
55
|
+
elsif li[/^include::.+.adoc\[\]/]
|
56
|
+
|
57
|
+
inc_file = li.chop.match(/(?<=^include::).+.adoc(?=\[\])/i).to_s
|
58
|
+
path = inc_file.sub(/^#{docsdir}\//, '')
|
59
|
+
path = path.sub(/#{exts}/, '')
|
60
|
+
parent = f
|
61
|
+
item = [inc_file, path, parent]
|
62
|
+
incs.push item
|
63
|
+
|
64
|
+
end
|
65
|
+
title = li
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Sort included reqs and correct the path to the parent (including doc)
|
70
|
+
# Push this back into 'normal' requirements array for regular processing
|
71
|
+
inc_reqs.each do |l, f, title, chapter, doctitle|
|
72
|
+
incs.each do |incfile, _incpath, parent|
|
73
|
+
if f == incfile
|
74
|
+
item = [l, parent, title, chapter, doctitle]
|
75
|
+
reqs.push item
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
reqs.uniq!
|
81
|
+
|
82
|
+
i = 0
|
83
|
+
reqs.each do |req, f, title, chapter, doctitle|
|
84
|
+
i += 1
|
85
|
+
|
86
|
+
id = /[^,]*\s*id\s*=\s*(\w+-?[0-9]+)\s*,.*/.match(req)[1]
|
87
|
+
version = /(?<=version=)\d+/.match(req)
|
88
|
+
|
89
|
+
f.gsub!(/^_docs\//, '')
|
90
|
+
f.gsub!(/.adoc$/, '')
|
91
|
+
|
92
|
+
link = "#{f}/index##{id}"
|
93
|
+
ref = "<a class=\"link\" href=\"#{link}\"><emphasis role=\"strong\">#{title}</emphasis> </a>"
|
94
|
+
breadcrumb = "<a href=\"#{f}\">#{chapter} / #{doctitle}</a>"
|
95
|
+
row = "<tr> <th scope=\"row\">#{i}</th> <td>#{id}</td><td>#{version}</td> <td>#{ref}</td> <td>#{breadcrumb}</td> </tr>"
|
96
|
+
|
97
|
+
rows.push(row)
|
98
|
+
end
|
99
|
+
|
100
|
+
Asciidoctor::Extensions.register do
|
101
|
+
block_macro :requirements do
|
102
|
+
process do |parent, _target, _attrs|
|
103
|
+
content = %(<h2 id="requirements"><a class="anchor" href="#requirements"></a><a class="link" href="#requirements">Requirements</a></h2>
|
104
|
+
<div class="panel panel-default"> <div class="panel-heading"><h4>Requirements</h4></div>
|
105
|
+
<table class="table"> <thead> <tr>
|
106
|
+
<th>#</th> <th>ID</th><th>Version</th> <th>Title</th> <th>Document</th>
|
107
|
+
</tr> </thead>
|
108
|
+
<tbody>
|
109
|
+
#{rows.join}
|
110
|
+
</tbody>
|
111
|
+
</table> </div>)
|
112
|
+
|
113
|
+
create_pass_block parent, content, {}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -1,56 +1,51 @@
|
|
1
|
-
require
|
1
|
+
require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'
|
2
2
|
|
3
3
|
include ::Asciidoctor
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
5
|
+
Extensions.register do
|
6
|
+
block do
|
7
|
+
named :req
|
8
|
+
on_contexts :open, :paragraph, :example, :listing, :sidebar, :pass
|
9
|
+
name_positional_attributes 'number', 'version'
|
10
|
+
|
11
|
+
process do |parent, reader, attrs|
|
12
|
+
# Add pass characters here to prevent html character replacements for < > tags
|
13
|
+
pass = '+++'
|
14
|
+
attrs['name'] = 'requirement'
|
15
|
+
attrs['caption'] = 'Requirement: '
|
16
|
+
id = attrs['id']
|
17
|
+
nl = ''
|
18
|
+
|
19
|
+
begin
|
20
|
+
# downcase the title and replace spaces with underscores.
|
21
|
+
# Also replacing special HTML entities:
|
22
|
+
# " = "
|
23
|
+
# & = &
|
24
|
+
downcased_title = attrs['title'].downcase.tr(' ', '_').gsub('"', '"')
|
25
|
+
san_title = attrs['title'].gsub(/&/, '&')
|
26
|
+
rescue Exception => msg
|
27
|
+
puts msg
|
28
|
+
# If no title exists on the Req block, throw an exception
|
29
|
+
puts '[ERROR] Requirement block title missing'
|
30
|
+
end
|
31
|
+
|
32
|
+
alt = %(
|
33
|
+
<div class=\"panel panel-primary\">
|
34
|
+
<div class=\"panel-heading\">
|
35
|
+
<h3 class=\"panel-title\">
|
36
|
+
<a class=\"anchor\" href=\"##{id}\"></a>
|
37
|
+
<a class=\"link\" href=\"##{id}\"><emphasis role=\"strong\">Requirement: #{id}:</emphasis> #{san_title} </a> (ver. #{attrs['version']})
|
38
|
+
</h3>
|
39
|
+
</div>
|
40
|
+
<div class=\"panel-body\">)
|
41
|
+
|
42
|
+
close = '</div></div>'
|
43
|
+
|
44
|
+
# concatenate all generated lines and prepend before the original content
|
45
|
+
concat_lines = reader.lines.unshift(pass, alt, pass, nl)
|
46
|
+
concat_lines.push(nl, pass, close, pass)
|
47
|
+
|
48
|
+
create_block parent, :admonition, concat_lines, attrs, content_model: :compound
|
35
49
|
end
|
36
|
-
|
37
|
-
alt = %(
|
38
|
-
<div class=\"panel panel-primary\">
|
39
|
-
<div class=\"panel-heading\">
|
40
|
-
<h3 class=\"panel-title\">
|
41
|
-
<a class=\"anchor\" href=\"##{id}\"></a>
|
42
|
-
<a class=\"link\" href=\"##{id}\"><emphasis role=\"strong\">Requirement: #{id}:</emphasis> #{san_title} </a> (ver. #{attrs['version']})
|
43
|
-
</h3>
|
44
|
-
</div>
|
45
|
-
<div class=\"panel-body\">)
|
46
|
-
|
47
|
-
close = "</div></div>"
|
48
|
-
|
49
|
-
# concatenate all generated lines and prepend before the original content
|
50
|
-
concat_lines = reader.lines.unshift(pass, alt, pass, nl)
|
51
|
-
concat_lines.push(nl, pass, close, pass)
|
52
|
-
|
53
|
-
# @todo use a regular pass block in this instance
|
54
|
-
create_block parent, :admonition, concat_lines, attrs, content_model: :compound
|
55
50
|
end
|
56
51
|
end
|
@@ -1,22 +1,16 @@
|
|
1
|
-
require
|
1
|
+
require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'
|
2
2
|
|
3
3
|
include ::Asciidoctor
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# --
|
10
|
-
class TodoBlock < Extensions::BlockProcessor
|
11
|
-
use_dsl
|
12
|
-
named :TODO
|
13
|
-
on_contexts :open, :paragraph, :example, :listing, :sidebar, :pass
|
5
|
+
Extensions.register do
|
6
|
+
block do
|
7
|
+
named :TODO
|
8
|
+
on_contexts :open, :paragraph, :example, :listing, :sidebar, :pass
|
14
9
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
create_block parent, :admonition, reader.lines, attrs, content_model: :compound
|
10
|
+
process do |parent, reader, attrs|
|
11
|
+
attrs['name'] = 'todo'
|
12
|
+
attrs['caption'] = 'Todo'
|
13
|
+
create_block parent, :admonition, reader.lines, attrs, content_model: :compound
|
14
|
+
end
|
21
15
|
end
|
22
16
|
end
|
@@ -4,23 +4,33 @@
|
|
4
4
|
module Context
|
5
5
|
# @param attributes [Array] attributes passed by the inline macro
|
6
6
|
# @param target [String] the target text
|
7
|
-
# @param
|
7
|
+
# @param pattern [String] the target url
|
8
8
|
# @param label [String] an optional status label, used to display if a task/issue is open or closed
|
9
|
-
# @return [String] the raw HTML to be included in the target document
|
10
|
-
def self.format(attributes, target,
|
9
|
+
# @return [String] the raw HTML to be included in the target document
|
10
|
+
def self.format(attributes, target, pattern, label)
|
11
11
|
block = false
|
12
|
-
block = true if attributes.key?
|
12
|
+
block = true if attributes.key? 'block'
|
13
13
|
|
14
14
|
if target[0] == "\:"
|
15
15
|
block = true
|
16
|
-
target[0] =
|
16
|
+
target[0] = ''
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
url = "#{pattern}/#{target}"
|
20
|
+
|
21
|
+
html = if block
|
22
|
+
if pattern == 'unknown'
|
23
|
+
"<div style=\"float:right;padding-left:0.1em;\"><span class=\"label label-#{label}\" data-toggle=\"tooltip\" title=\"Missing config\">#{target}</span></div>"
|
24
|
+
else
|
25
|
+
"<div style=\"float:right;padding-left:0.1em;\"><a href=\"#{url}\"><span class=\"label label-#{label}\">#{target}</span></a></div>"
|
26
|
+
end
|
27
|
+
else
|
28
|
+
if pattern == 'unknown'
|
29
|
+
"<span class=\"label label-#{label}\" data-toggle=\"tooltip\" title=\"Missing config\">#{target}</span>"
|
30
|
+
else
|
31
|
+
"<a href=\"#{url}\"><span class=\"label label-#{label}\">#{target}</span></a>"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
html
|
25
35
|
end
|
26
36
|
end
|