giblish 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/README.adoc +32 -11
- data/Rakefile +3 -1
- data/giblish.gemspec +1 -1
- data/lib/giblish-search.rb +444 -0
- data/lib/giblish/buildgraph.rb +1 -1
- data/lib/giblish/buildindex.rb +58 -31
- data/lib/giblish/cmdline.rb +27 -0
- data/lib/giblish/core.rb +66 -7
- data/lib/giblish/docid.rb +3 -27
- data/lib/giblish/docinfo.rb +32 -17
- data/lib/giblish/indexheadings.rb +163 -0
- data/lib/giblish/utils.rb +59 -3
- data/lib/giblish/version.rb +1 -1
- metadata +7 -6
@@ -0,0 +1,163 @@
|
|
1
|
+
require "json"
|
2
|
+
require "pathname"
|
3
|
+
require "asciidoctor"
|
4
|
+
require "asciidoctor/extensions"
|
5
|
+
require_relative "./utils"
|
6
|
+
|
7
|
+
module Giblish
|
8
|
+
|
9
|
+
# This hook is called by Asciidoctor once for each document _before_
|
10
|
+
# Asciidoctor processes the adoc content.
|
11
|
+
#
|
12
|
+
# It indexes all headings found in all documents in the tree.
|
13
|
+
# The resulting index can be serialized to a JSON file file
|
14
|
+
# with the following format:
|
15
|
+
#
|
16
|
+
# {
|
17
|
+
# file_infos : [{
|
18
|
+
# filepath : filepath_1,
|
19
|
+
# title : Title,
|
20
|
+
# sections : [{
|
21
|
+
# id : section_id_1,
|
22
|
+
# title : section_title_1,
|
23
|
+
# line_no : line_no
|
24
|
+
# },
|
25
|
+
# {
|
26
|
+
# id : section_id_1,
|
27
|
+
# title : section_title_1,
|
28
|
+
# line_no : line_no
|
29
|
+
# },
|
30
|
+
# ...
|
31
|
+
# ]
|
32
|
+
# },
|
33
|
+
# {
|
34
|
+
# filepath : filepath_1,
|
35
|
+
# ...
|
36
|
+
# }]
|
37
|
+
# }
|
38
|
+
class IndexHeadings < Asciidoctor::Extensions::Preprocessor
|
39
|
+
|
40
|
+
# Use a class-global heading_index dict since asciidoctor creates a new instance
|
41
|
+
# of this class for each processed file
|
42
|
+
@heading_index = {"file_infos" => []}
|
43
|
+
|
44
|
+
class << self
|
45
|
+
def heading_index
|
46
|
+
@heading_index
|
47
|
+
end
|
48
|
+
|
49
|
+
def clear_index
|
50
|
+
@heading_index = {"file_infos" => []}
|
51
|
+
end
|
52
|
+
|
53
|
+
# write the index to a file in dst_dir and remove the base_dir
|
54
|
+
# part of the path for each filename
|
55
|
+
def serialize(dst_dir, base_dir = "")
|
56
|
+
dst_dir = Pathname.new(dst_dir) unless dst_dir.respond_to?(:join)
|
57
|
+
base_dir = Pathname.new(base_dir) unless base_dir.respond_to?(:join)
|
58
|
+
|
59
|
+
if base_dir.to_s.empty?
|
60
|
+
heading_index
|
61
|
+
else
|
62
|
+
# remove the base_dir part of the file path
|
63
|
+
heading_index["file_infos"].each do |file_info|
|
64
|
+
file_info["filepath"] = Pathname.new(file_info["filepath"])
|
65
|
+
.relative_path_from(base_dir)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
Giblog.logger.info { "writing json to #{dst_dir.join("heading_index.json").to_s}" }
|
70
|
+
File.open(dst_dir.join("heading_index.json").to_s,"w") do |f|
|
71
|
+
f.write(heading_index.to_json)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def process(document, reader)
|
77
|
+
# Add doc as a source dependency for doc ids
|
78
|
+
src_path = document.attributes["docfile"]
|
79
|
+
|
80
|
+
# Note: the nil check is there to prevent us adding generated
|
81
|
+
# asciidoc docs that does not exist in the file system (e.g. the
|
82
|
+
# generated index pages). This is a bit hackish and should maybe be
|
83
|
+
# done differently
|
84
|
+
return if src_path.nil?
|
85
|
+
|
86
|
+
# get the title from thw raw text (asciidoctor has not yet
|
87
|
+
# processed the text)
|
88
|
+
title = find_title reader.lines
|
89
|
+
|
90
|
+
# Index all headings in the doc
|
91
|
+
Giblog.logger.debug { "indexing headings in #{src_path}" }
|
92
|
+
sections = []
|
93
|
+
file_info_hash = {
|
94
|
+
"filepath" => src_path,
|
95
|
+
"title" => title,
|
96
|
+
"sections" => sections
|
97
|
+
}
|
98
|
+
|
99
|
+
# build the 'sections' array
|
100
|
+
line_no = 1
|
101
|
+
regex = Regexp.new(/^=+\s+(.*)$/)
|
102
|
+
reader.lines.each do |line|
|
103
|
+
m = regex.match(line)
|
104
|
+
if m
|
105
|
+
# We found a heading, index it
|
106
|
+
section = { "id" => get_unique_id(file_info_hash, m[1]) }
|
107
|
+
section["title"] = m[1].strip
|
108
|
+
section["line_no"] = line_no
|
109
|
+
sections << section
|
110
|
+
end
|
111
|
+
line_no += 1
|
112
|
+
end
|
113
|
+
|
114
|
+
heading_index["file_infos"] << file_info_hash
|
115
|
+
reader
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def find_title(lines)
|
121
|
+
title = "No title Found!"
|
122
|
+
Giblish.process_header_lines(lines) do |line|
|
123
|
+
m = /^=+(.*)$/.match(line)
|
124
|
+
if m
|
125
|
+
# We found a decent title
|
126
|
+
title = m[1].strip
|
127
|
+
end
|
128
|
+
end
|
129
|
+
title
|
130
|
+
end
|
131
|
+
|
132
|
+
def get_unique_id(doc_heading_dict, heading_str)
|
133
|
+
id_base = Giblish.to_valid_id(heading_str)
|
134
|
+
return id_base if !doc_heading_dict.key? id_base
|
135
|
+
|
136
|
+
# handle the case with several sections with the same name
|
137
|
+
idx = 1
|
138
|
+
heading_id = ""
|
139
|
+
loop do
|
140
|
+
idx += 1
|
141
|
+
heading_id = "#{id_base}_#{idx}"
|
142
|
+
# some code here
|
143
|
+
break unless doc_heading_dict.key? heading_id
|
144
|
+
end
|
145
|
+
return heading_id
|
146
|
+
end
|
147
|
+
|
148
|
+
# Helper method to shorten calls to the heading_index from instance methods
|
149
|
+
def heading_index
|
150
|
+
self.class.heading_index
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
# Helper method to register the docid preprocessor extension with
|
156
|
+
# the asciidoctor engine.
|
157
|
+
def register_index_heading_extension
|
158
|
+
Asciidoctor::Extensions.register do
|
159
|
+
preprocessor IndexHeadings
|
160
|
+
end
|
161
|
+
end
|
162
|
+
module_function :register_index_heading_extension
|
163
|
+
end
|
data/lib/giblish/utils.rb
CHANGED
@@ -38,12 +38,16 @@ module Giblish
|
|
38
38
|
# tree
|
39
39
|
# resource_dir - a string or pathname with the directory containing
|
40
40
|
# resources
|
41
|
-
def initialize(src_root, dst_root, resource_dir = nil)
|
41
|
+
def initialize(src_root, dst_root, resource_dir = nil, web_root = false)
|
42
42
|
# Make sure that the source root exists in the file system
|
43
43
|
@src_root_abs = Pathname.new(src_root).realpath
|
44
44
|
self.dst_root_abs = dst_root
|
45
|
+
|
45
46
|
# Make sure that the resource dir exists if user gives a path to it
|
46
47
|
resource_dir && (@resource_dir_abs = Pathname.new(resource_dir).realpath)
|
48
|
+
|
49
|
+
# Set web root if given by user
|
50
|
+
@web_root_abs = web_root ? Pathname.new(web_root) : nil
|
47
51
|
end
|
48
52
|
|
49
53
|
def dst_root_abs=(dst_root)
|
@@ -67,6 +71,13 @@ module Giblish
|
|
67
71
|
src_abs.relative_path_from(@src_root_abs)
|
68
72
|
end
|
69
73
|
|
74
|
+
def reldir_from_web_root(in_path)
|
75
|
+
p = in_path.is_a?(Pathname) ? in_path : Pathname.new(in_path)
|
76
|
+
return p if @web_root_abs.nil?
|
77
|
+
|
78
|
+
p.relative_path_from(@web_root_abs)
|
79
|
+
end
|
80
|
+
|
70
81
|
def adoc_output_file(infile_path, extension)
|
71
82
|
# Get absolute source dir path
|
72
83
|
src_dir_abs = self.class.closest_dir infile_path
|
@@ -152,6 +163,50 @@ module Giblish
|
|
152
163
|
end
|
153
164
|
end
|
154
165
|
|
166
|
+
# Helper method that provides the user with a way of processing only the
|
167
|
+
# lines within the asciidoc header block.
|
168
|
+
# The user must return nil to get the next line.
|
169
|
+
#
|
170
|
+
# ex:
|
171
|
+
# process_header_lines(file_path) do |line|
|
172
|
+
# if line == "Quack!"
|
173
|
+
# puts "Donald!"
|
174
|
+
# 1
|
175
|
+
# else
|
176
|
+
# nil
|
177
|
+
# end
|
178
|
+
# end
|
179
|
+
def process_header_lines(lines)
|
180
|
+
state = "before_header"
|
181
|
+
lines.each do |line|
|
182
|
+
case state
|
183
|
+
when "before_header" then (state = "in_header" if line =~ /^[=+]^.*$/ || yield(line))
|
184
|
+
when "in_header" then (state = "done" if line =~ /^\s*$/ || yield(line))
|
185
|
+
when "done" then break
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
module_function :process_header_lines
|
190
|
+
|
191
|
+
# Helper method that provides the user with a way of processing only the
|
192
|
+
# lines within the asciidoc header block.
|
193
|
+
# The user must return nil to get the next line.
|
194
|
+
#
|
195
|
+
# ex:
|
196
|
+
# process_header_lines_from_file(file_path) do |line|
|
197
|
+
# if line == "Quack!"
|
198
|
+
# puts "Donald!"
|
199
|
+
# 1
|
200
|
+
# else
|
201
|
+
# nil
|
202
|
+
# end
|
203
|
+
# end
|
204
|
+
def process_header_lines_from_file(path)
|
205
|
+
lines = File.readlines(path)
|
206
|
+
process_header_lines(lines,&Proc.new)
|
207
|
+
end
|
208
|
+
module_function :process_header_lines_from_file
|
209
|
+
|
155
210
|
# runs the supplied block but redirect stderr to a string
|
156
211
|
# returns the string containing stderr contents
|
157
212
|
def with_captured_stderr
|
@@ -166,8 +221,9 @@ module Giblish
|
|
166
221
|
|
167
222
|
# transforms strings to valid asciidoctor id strings
|
168
223
|
def to_valid_id(input_str)
|
169
|
-
id_str = "_#{input_str.downcase}"
|
170
|
-
id_str.gsub(%r{[^a-z0-9]+},"_")
|
224
|
+
id_str = "_#{input_str.strip.downcase}"
|
225
|
+
id_str.gsub!(%r{[^a-z0-9]+},"_")
|
226
|
+
id_str.chomp('_')
|
171
227
|
end
|
172
228
|
module_function :to_valid_id
|
173
229
|
|
data/lib/giblish/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: giblish
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anders Rillbert
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -61,7 +61,7 @@ dependencies:
|
|
61
61
|
version: '1.5'
|
62
62
|
- - ">="
|
63
63
|
- !ruby/object:Gem::Version
|
64
|
-
version: 1.5.
|
64
|
+
version: 1.5.8
|
65
65
|
type: :runtime
|
66
66
|
prerelease: false
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -71,7 +71,7 @@ dependencies:
|
|
71
71
|
version: '1.5'
|
72
72
|
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: 1.5.
|
74
|
+
version: 1.5.8
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: asciidoctor-diagram
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -169,6 +169,7 @@ files:
|
|
169
169
|
- data/testdocs/wellformed/source_highlighting/highlight_source.adoc
|
170
170
|
- exe/giblish
|
171
171
|
- giblish.gemspec
|
172
|
+
- lib/giblish-search.rb
|
172
173
|
- lib/giblish.rb
|
173
174
|
- lib/giblish/application.rb
|
174
175
|
- lib/giblish/buildgraph.rb
|
@@ -179,6 +180,7 @@ files:
|
|
179
180
|
- lib/giblish/docid.rb
|
180
181
|
- lib/giblish/docinfo.rb
|
181
182
|
- lib/giblish/gititf.rb
|
183
|
+
- lib/giblish/indexheadings.rb
|
182
184
|
- lib/giblish/pathtree.rb
|
183
185
|
- lib/giblish/utils.rb
|
184
186
|
- lib/giblish/version.rb
|
@@ -210,8 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
210
212
|
- !ruby/object:Gem::Version
|
211
213
|
version: '0'
|
212
214
|
requirements: []
|
213
|
-
|
214
|
-
rubygems_version: 2.7.6
|
215
|
+
rubygems_version: 3.0.1
|
215
216
|
signing_key:
|
216
217
|
specification_version: 4
|
217
218
|
summary: A tool for publishing asciidoc docs stored in git repos
|