jekyll_aspec 1.0.1 → 1.0.2
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/.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
|