bitclust-core 1.2.6 → 1.6.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/Gemfile +3 -0
- data/README.md +65 -0
- data/Rakefile +32 -0
- data/data/bitclust/catalog/ja_JP.UTF-8 +19 -1
- data/data/bitclust/searchpage/index.html +90 -0
- data/data/bitclust/template/class +69 -8
- data/data/bitclust/template/function +2 -2
- data/data/bitclust/template/layout +11 -3
- data/data/bitclust/template/method +2 -2
- data/data/bitclust/template/search +1 -1
- data/data/bitclust/template.epub/class +22 -1
- data/data/bitclust/template.epub/function +2 -2
- data/data/bitclust/template.epub/layout +1 -3
- data/data/bitclust/template.epub/method +2 -2
- data/data/bitclust/template.lillia/class +26 -5
- data/data/bitclust/template.lillia/layout +1 -3
- data/data/bitclust/template.lillia/method +2 -2
- data/data/bitclust/template.offline/class +49 -5
- data/data/bitclust/template.offline/function +2 -2
- data/data/bitclust/template.offline/layout +27 -3
- data/data/bitclust/template.offline/method +2 -2
- data/lib/bitclust/app.rb +17 -17
- data/lib/bitclust/capi_converter.rb +20 -0
- data/lib/bitclust/classentry.rb +68 -17
- data/lib/bitclust/compat.rb +3 -2
- data/lib/bitclust/completion.rb +59 -27
- data/lib/bitclust/crossrubyutils.rb +9 -5
- data/lib/bitclust/database.rb +29 -8
- data/lib/bitclust/doc_converter.rb +63 -0
- data/lib/bitclust/docentry.rb +2 -1
- data/lib/bitclust/entity_splitter.rb +221 -0
- data/lib/bitclust/entry.rb +48 -7
- data/lib/bitclust/exception.rb +1 -0
- data/lib/bitclust/functiondatabase.rb +14 -1
- data/lib/bitclust/functionentry.rb +6 -1
- data/lib/bitclust/functionreferenceparser.rb +5 -4
- data/lib/bitclust/generators/epub.rb +11 -3
- data/lib/bitclust/htmlutils.rb +2 -1
- data/lib/bitclust/include_graph.rb +375 -0
- data/lib/bitclust/include_pruner.rb +144 -0
- data/lib/bitclust/interface.rb +2 -1
- data/lib/bitclust/libraryentry.rb +9 -7
- data/lib/bitclust/lineinput.rb +8 -5
- data/lib/bitclust/link_checker.rb +179 -0
- data/lib/bitclust/markdown_bridge.rb +186 -0
- data/lib/bitclust/markdown_orchestrator.rb +267 -0
- data/lib/bitclust/markdown_to_rrd.rb +824 -0
- data/lib/bitclust/markdown_tree.rb +217 -0
- data/lib/bitclust/mdcompiler.rb +883 -0
- data/lib/bitclust/mdparser.rb +347 -0
- data/lib/bitclust/messagecatalog.rb +4 -3
- data/lib/bitclust/method_since_calculator.rb +117 -0
- data/lib/bitclust/methoddatabase.rb +125 -14
- data/lib/bitclust/methodentry.rb +130 -7
- data/lib/bitclust/methodid.rb +13 -11
- data/lib/bitclust/methodsignature.rb +11 -4
- data/lib/bitclust/nameutils.rb +42 -22
- data/lib/bitclust/parseutils.rb +1 -0
- data/lib/bitclust/preprocessor.rb +70 -32
- data/lib/bitclust/progress_bar.rb +1 -0
- data/lib/bitclust/rdcompiler.rb +197 -96
- data/lib/bitclust/refsdatabase.rb +24 -8
- data/lib/bitclust/reloadable_request_handler.rb +72 -0
- data/lib/bitclust/requesthandler.rb +22 -16
- data/lib/bitclust/ridatabase.rb +11 -4
- data/lib/bitclust/rrd_to_markdown.rb +925 -0
- data/lib/bitclust/rrdparser.rb +197 -30
- data/lib/bitclust/runner.rb +18 -2
- data/lib/bitclust/screen.rb +81 -11
- data/lib/bitclust/search_index_generator.rb +288 -0
- data/lib/bitclust/searcher.rb +72 -22
- data/lib/bitclust/server.rb +6 -1
- data/lib/bitclust/silent_progress_bar.rb +1 -0
- data/lib/bitclust/simplesearcher.rb +25 -12
- data/lib/bitclust/subcommand.rb +8 -1
- data/lib/bitclust/subcommands/ancestors_command.rb +10 -2
- data/lib/bitclust/subcommands/checklink_command.rb +54 -0
- data/lib/bitclust/subcommands/chm_command.rb +16 -7
- data/lib/bitclust/subcommands/classes_command.rb +6 -0
- data/lib/bitclust/subcommands/epub_command.rb +1 -0
- data/lib/bitclust/subcommands/extract_command.rb +6 -0
- data/lib/bitclust/subcommands/htmlfile_command.rb +22 -7
- data/lib/bitclust/subcommands/init_command.rb +5 -1
- data/lib/bitclust/subcommands/list_command.rb +13 -4
- data/lib/bitclust/subcommands/lookup_command.rb +29 -9
- data/lib/bitclust/subcommands/methods_command.rb +11 -2
- data/lib/bitclust/subcommands/methodsince_command.rb +80 -0
- data/lib/bitclust/subcommands/preproc_command.rb +6 -0
- data/lib/bitclust/subcommands/property_command.rb +3 -1
- data/lib/bitclust/subcommands/query_command.rb +1 -0
- data/lib/bitclust/subcommands/searchpage_command.rb +102 -0
- data/lib/bitclust/subcommands/server_command.rb +16 -10
- data/lib/bitclust/subcommands/setup_command.rb +25 -10
- data/lib/bitclust/subcommands/statichtml_command.rb +132 -6
- data/lib/bitclust/subcommands/update_command.rb +111 -2
- data/lib/bitclust/syntax_highlighter.rb +52 -5
- data/lib/bitclust/textutils.rb +4 -3
- data/lib/bitclust/version.rb +2 -1
- data/lib/bitclust/version_badges.rb +90 -0
- data/lib/bitclust/whole_file_gate.rb +137 -0
- data/lib/bitclust.rb +1 -0
- data/test/test_app.rb +269 -0
- data/test/test_bitclust.rb +2 -0
- data/test/test_capi_converter.rb +91 -0
- data/test/test_class_screen.rb +413 -0
- data/test/test_copy_doc_md.rb +53 -0
- data/test/test_doc_converter.rb +78 -0
- data/test/test_entity_splitter.rb +231 -0
- data/test/test_entry.rb +207 -2
- data/test/test_eol_warning.rb +43 -0
- data/test/test_functionreferenceparser.rb +11 -0
- data/test/test_include_graph.rb +640 -0
- data/test/test_include_pruner.rb +133 -0
- data/test/test_link_checker.rb +114 -0
- data/test/test_lookup_command.rb +135 -0
- data/test/test_markdown_bridge.rb +217 -0
- data/test/test_markdown_orchestrator.rb +478 -0
- data/test/test_markdown_to_rrd.rb +757 -0
- data/test/test_markdown_tree.rb +369 -0
- data/test/test_mdcompiler.rb +1276 -0
- data/test/test_mdparser.rb +538 -0
- data/test/test_method_screen.rb +166 -0
- data/test/test_method_since_calculator.rb +290 -0
- data/test/test_methoddatabase.rb +16 -0
- data/test/test_methodentry.rb +328 -0
- data/test/test_methodsignature.rb +3 -1
- data/test/test_methodsince_command.rb +168 -0
- data/test/test_nameutils.rb +22 -0
- data/test/test_preprocessor.rb +215 -0
- data/test/test_rdcompiler.rb +429 -27
- data/test/test_refsdatabase.rb +32 -0
- data/test/test_rrd_to_markdown.rb +968 -0
- data/test/test_rrdparser.rb +295 -2
- data/test/test_run_ruby_wasm.rb +54 -0
- data/test/test_run_worker_prelude.rb +83 -0
- data/test/test_runner.rb +51 -0
- data/test/test_search_index_generator.rb +513 -0
- data/test/test_search_screen.rb +48 -0
- data/test/test_searcher.rb +153 -0
- data/test/test_searchpage_command.rb +167 -0
- data/test/test_simplesearcher.rb +28 -0
- data/test/test_statichtml_command.rb +204 -0
- data/test/test_syntax_highlighter.rb +60 -0
- data/test/test_whole_file_gate.rb +175 -0
- data/theme/default/js/NOTICE +42 -0
- data/theme/default/js/run-worker.js +111 -0
- data/theme/default/js/run.js +350 -0
- data/theme/default/js/search_controller.js +134 -0
- data/theme/default/js/search_init.js +176 -0
- data/theme/default/js/search_navigation.js +110 -0
- data/theme/default/js/search_page.js +202 -0
- data/theme/default/js/search_ranker.js +244 -0
- data/theme/default/script.js +91 -18
- data/theme/default/search.css +149 -0
- data/theme/default/style.css +193 -21
- data/theme/default/syntax-highlight.css +8 -0
- data/theme/lillia/style.css +45 -1
- metadata +178 -21
- data/README +0 -32
data/lib/bitclust/rdcompiler.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#
|
|
2
3
|
# bitclust/rdcompiler.rb
|
|
3
4
|
#
|
|
@@ -13,6 +14,8 @@ require 'bitclust/htmlutils'
|
|
|
13
14
|
require 'bitclust/textutils'
|
|
14
15
|
require 'bitclust/messagecatalog'
|
|
15
16
|
require 'bitclust/syntax_highlighter'
|
|
17
|
+
require 'bitclust/version_badges'
|
|
18
|
+
require 'rouge'
|
|
16
19
|
require 'stringio'
|
|
17
20
|
|
|
18
21
|
module BitClust
|
|
@@ -23,17 +26,16 @@ module BitClust
|
|
|
23
26
|
include HTMLUtils
|
|
24
27
|
include TextUtils
|
|
25
28
|
include Translatable
|
|
29
|
+
include VersionBadges
|
|
26
30
|
|
|
27
31
|
def initialize(urlmapper, hlevel = 1, opt = {})
|
|
28
32
|
@urlmapper = urlmapper
|
|
29
33
|
@catalog = opt[:catalog]
|
|
30
34
|
@hlevel = hlevel
|
|
31
35
|
@type = nil
|
|
32
|
-
@library = nil
|
|
33
|
-
@class = nil
|
|
34
36
|
@method = nil
|
|
35
37
|
@option = opt.dup
|
|
36
|
-
init_message_catalog(@catalog)
|
|
38
|
+
init_message_catalog(@catalog || MessageCatalog.new({}, 'C'))
|
|
37
39
|
end
|
|
38
40
|
|
|
39
41
|
def compile(src)
|
|
@@ -79,10 +81,10 @@ module BitClust
|
|
|
79
81
|
when /\A---/
|
|
80
82
|
entry_chunk
|
|
81
83
|
when /\A=+/
|
|
82
|
-
headline @f.gets
|
|
84
|
+
headline @f.gets || raise
|
|
83
85
|
when /\A(\s+)\*\s/, /\A(\s+)\(\d+\)\s/
|
|
84
86
|
@item_stack = []
|
|
85
|
-
item_list($1.size)
|
|
87
|
+
item_list(($1 || raise).size)
|
|
86
88
|
raise "@item_stack should be empty. #{@item_stack.inspect}" unless @item_stack.empty?
|
|
87
89
|
when %r<\A//emlist(?:\[(?:[^\[\]]+?)?\]\[\w+?\])?\{>
|
|
88
90
|
emlist
|
|
@@ -90,8 +92,12 @@ module BitClust
|
|
|
90
92
|
dlist
|
|
91
93
|
when /\A\s+\S/
|
|
92
94
|
list
|
|
95
|
+
when /\A@see\b/
|
|
96
|
+
# findings#1: doc/lib ページの @see もメソッドエントリと同じく
|
|
97
|
+
# SEE_ALSO として解釈する(従来は段落テキストだった)
|
|
98
|
+
see
|
|
93
99
|
else
|
|
94
|
-
if @f.peek
|
|
100
|
+
if @f.peek&.strip&.empty?
|
|
95
101
|
@f.gets
|
|
96
102
|
else
|
|
97
103
|
paragraph
|
|
@@ -106,23 +112,35 @@ module BitClust
|
|
|
106
112
|
end
|
|
107
113
|
end
|
|
108
114
|
|
|
115
|
+
# シグネチャ行に続くメソッド属性行({: ...}。直前のシグネチャ行に束縛)
|
|
116
|
+
METHOD_ATTRIBUTE_LINE_RE = /\A\{:.*\}[ \t]*$/
|
|
117
|
+
|
|
109
118
|
def entry_chunk
|
|
110
119
|
@out.puts '<dl>' if @option[:force]
|
|
111
120
|
first = true
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
121
|
+
attrs = [] #: Array[String]
|
|
122
|
+
while @f.next?
|
|
123
|
+
if /\A---/ =~ @f.peek
|
|
124
|
+
method_signature(@f.gets || raise, first)
|
|
125
|
+
first = false
|
|
126
|
+
elsif !first && METHOD_ATTRIBUTE_LINE_RE =~ @f.peek
|
|
127
|
+
# メソッド属性行は本文には描画しない(undef のみ後でメッセージ)
|
|
128
|
+
attrs.concat attribute_tokens(@f.gets)
|
|
129
|
+
else
|
|
130
|
+
break
|
|
131
|
+
end
|
|
115
132
|
end
|
|
116
|
-
props = {}
|
|
133
|
+
props = {} #: Hash[String?, String?]
|
|
117
134
|
@f.while_match(/\A:/) do |line|
|
|
118
135
|
k, v = line.sub(/\A:/, '').split(':', 2)
|
|
119
|
-
props[k
|
|
136
|
+
props[k&.strip] = v&.strip
|
|
120
137
|
end if @type == :method
|
|
121
138
|
@out.puts %Q(<dd class="#{@type.to_s}-description">)
|
|
139
|
+
undef_message if attrs.include?('undef')
|
|
122
140
|
while @f.next?
|
|
123
141
|
case @f.peek
|
|
124
142
|
when /\A===+/
|
|
125
|
-
headline @f.gets
|
|
143
|
+
headline @f.gets || raise
|
|
126
144
|
when /\A==?/
|
|
127
145
|
if @option[:force]
|
|
128
146
|
break
|
|
@@ -133,7 +151,7 @@ module BitClust
|
|
|
133
151
|
break
|
|
134
152
|
when /\A(\s+)\*\s/, /\A(\s+)\(\d+\)\s/
|
|
135
153
|
@item_stack = []
|
|
136
|
-
item_list($1.size)
|
|
154
|
+
item_list(($1 || raise).size)
|
|
137
155
|
raise "@item_stack should be empty. #{@item_stack.inspect}" unless @item_stack.empty?
|
|
138
156
|
when /\A:\s/
|
|
139
157
|
dlist
|
|
@@ -141,14 +159,16 @@ module BitClust
|
|
|
141
159
|
emlist
|
|
142
160
|
when /\A\s+\S/
|
|
143
161
|
list
|
|
144
|
-
when
|
|
162
|
+
when /\A@see\b/
|
|
163
|
+
# findings#3: 無アンカーの /@see/ は行の途中に @see を含む
|
|
164
|
+
# 本文行を吸ってしまう(@todo も同様)
|
|
145
165
|
see
|
|
146
|
-
when
|
|
166
|
+
when /\A@todo\b/
|
|
147
167
|
todo
|
|
148
168
|
when /\A@[a-z]/
|
|
149
169
|
entry_info
|
|
150
170
|
else
|
|
151
|
-
if @f.peek
|
|
171
|
+
if @f.peek&.strip&.empty?
|
|
152
172
|
@f.gets
|
|
153
173
|
else
|
|
154
174
|
entry_paragraph
|
|
@@ -160,9 +180,9 @@ module BitClust
|
|
|
160
180
|
end
|
|
161
181
|
|
|
162
182
|
def headline(line)
|
|
163
|
-
level = @hlevel + (line.slice(/\A=+/).
|
|
183
|
+
level = @hlevel + (line.slice(/\A=+/)&.size.to_i - 3)
|
|
164
184
|
label = line.sub(/\A=+(\[a:(.*?)\])?/, '').strip
|
|
165
|
-
frag = $2 if $2 and not $2.empty?
|
|
185
|
+
frag = $2 if $2 and not ($2 || raise).empty?
|
|
166
186
|
line h(level, escape_html(label), frag)
|
|
167
187
|
end
|
|
168
188
|
|
|
@@ -171,7 +191,9 @@ module BitClust
|
|
|
171
191
|
"<h#{level} #{name}>#{label}</h#{level}>"
|
|
172
192
|
end
|
|
173
193
|
|
|
174
|
-
|
|
194
|
+
ITEM_RE = /\A(\s+)(?:\*\s|\(\d+\))/
|
|
195
|
+
|
|
196
|
+
def item_list(level = 0)
|
|
175
197
|
open_tag = nil
|
|
176
198
|
close_tag = nil
|
|
177
199
|
case @f.peek
|
|
@@ -182,11 +204,9 @@ module BitClust
|
|
|
182
204
|
open_tag = "<ol>"
|
|
183
205
|
close_tag = "</ol>"
|
|
184
206
|
end
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
end
|
|
189
|
-
@f.while_match(/\A(\s+)(?:\*\s|\(\d+\))/) do |line|
|
|
207
|
+
line open_tag
|
|
208
|
+
@item_stack.push(close_tag)
|
|
209
|
+
@f.while_match(ITEM_RE) do |line|
|
|
190
210
|
string "<li>"
|
|
191
211
|
@item_stack.push("</li>")
|
|
192
212
|
string compile_text(line.sub(/\A(\s+)(?:\*|\(\d+\))/, '').strip)
|
|
@@ -195,15 +215,14 @@ module BitClust
|
|
|
195
215
|
nl
|
|
196
216
|
string compile_text(cont.strip)
|
|
197
217
|
end
|
|
218
|
+
end
|
|
219
|
+
if (m = ITEM_RE.match(@f.peek)) && level < (m[1] || raise).size
|
|
220
|
+
item_list(($1 || raise).size)
|
|
198
221
|
line @item_stack.pop # current level li
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
line @item_stack.pop # current level ul or ol
|
|
202
|
-
elsif /\A(\s+)(?:\*\s|\(\d+\))/ =~ @f.peek and level > $1.size
|
|
222
|
+
break if ITEM_RE =~ @f.peek and level > ($1 || raise).size
|
|
223
|
+
elsif m && level > (m[1] || raise).size
|
|
203
224
|
line @item_stack.pop # current level li
|
|
204
|
-
|
|
205
|
-
line @item_stack.pop # previous level li
|
|
206
|
-
item_list($1.size, false)
|
|
225
|
+
break
|
|
207
226
|
else
|
|
208
227
|
line @item_stack.pop # current level li
|
|
209
228
|
end
|
|
@@ -256,8 +275,8 @@ module BitClust
|
|
|
256
275
|
line '</dd>'
|
|
257
276
|
end
|
|
258
277
|
|
|
259
|
-
def dt(s)
|
|
260
|
-
"<dt>#{s}</dt>"
|
|
278
|
+
def dt(s, id = nil)
|
|
279
|
+
id ? %Q(<dt id="#{escape_html(id)}">#{s}</dt>) : "<dt>#{s}</dt>"
|
|
261
280
|
end
|
|
262
281
|
|
|
263
282
|
def stop_on_syntax_error?
|
|
@@ -265,31 +284,48 @@ module BitClust
|
|
|
265
284
|
@option[:stop_on_syntax_error]
|
|
266
285
|
end
|
|
267
286
|
|
|
287
|
+
# lang 指定付きコードブロックのハイライト HTML を返す。
|
|
288
|
+
# ruby(rb などの Rouge 上の alias を含む)は構文チェックを兼ねる
|
|
289
|
+
# Ripper ベースの SyntaxHighlighter、その他の言語は Rouge を使う。
|
|
290
|
+
# Rouge が知らない言語はエスケープのみ(従来この経路と ruby の構文
|
|
291
|
+
# エラー時フォールバックはエスケープされずに出力されていたのを修正)。
|
|
292
|
+
# invalid: true(md の ```ruby invalid)は構文として完全でないコードの
|
|
293
|
+
# 印で、Ripper の構文チェックをせず Rouge の lexer で色付けする(#251)
|
|
294
|
+
def highlight_source(src, lang, caption, invalid: false)
|
|
295
|
+
lexer = ::Rouge::Lexer.find(lang)
|
|
296
|
+
if lexer && lexer.tag == 'ruby' && !invalid
|
|
297
|
+
begin
|
|
298
|
+
filename = (caption&.size || 0) > 2 ? caption : @f.name or raise
|
|
299
|
+
BitClust::SyntaxHighlighter.new(src, filename).highlight
|
|
300
|
+
rescue BitClust::SyntaxHighlighter::Error => ex
|
|
301
|
+
$stderr.puts ex.message
|
|
302
|
+
exit(false) if stop_on_syntax_error?
|
|
303
|
+
escape_html(src)
|
|
304
|
+
end
|
|
305
|
+
elsif lexer
|
|
306
|
+
::Rouge::Formatters::HTML.new.format(lexer.lex(src))
|
|
307
|
+
else
|
|
308
|
+
escape_html(src)
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
|
|
268
312
|
def emlist
|
|
269
313
|
command = @f.gets
|
|
270
314
|
if %r!\A//emlist\[(?<caption>[^\[\]]+?)?\]\[(?<lang>\w+?)\]! =~ command
|
|
271
|
-
|
|
315
|
+
# @type var caption: String?
|
|
316
|
+
# @type var lang: String
|
|
317
|
+
# caption は pre 内の absolute 配置ではなく、pre の上に密着した
|
|
318
|
+
# タブとして描画する(pre 内だと編集・貼り付けで先頭行と重なる)
|
|
272
319
|
line "<span class=\"caption\">#{escape_html(caption)}</span>" if caption
|
|
273
|
-
|
|
274
|
-
|
|
320
|
+
# <code> の直後に改行を入れると pre の内容の先頭に余計な空行として
|
|
321
|
+
# 表示される(pre 開始タグ直後の改行と違いブラウザは無視しない)
|
|
322
|
+
# ため、コード本体は <code> に直接続ける(#254)
|
|
323
|
+
string "<pre class=\"highlight #{lang}\"><code>"
|
|
324
|
+
src = +""
|
|
275
325
|
@f.until_terminator(%r<\A//\}>) do |line|
|
|
276
326
|
src << line
|
|
277
327
|
end
|
|
278
|
-
|
|
279
|
-
begin
|
|
280
|
-
filename = (caption&.size || 0) > 2 ? caption : @f.name
|
|
281
|
-
string BitClust::SyntaxHighlighter.new(src, filename).highlight
|
|
282
|
-
rescue BitClust::SyntaxHighlighter::Error => ex
|
|
283
|
-
$stderr.puts ex.message
|
|
284
|
-
if stop_on_syntax_error?
|
|
285
|
-
exit(false)
|
|
286
|
-
else
|
|
287
|
-
string src
|
|
288
|
-
end
|
|
289
|
-
end
|
|
290
|
-
else
|
|
291
|
-
string src
|
|
292
|
-
end
|
|
328
|
+
string highlight_source(src, lang, caption)
|
|
293
329
|
line '</code></pre>'
|
|
294
330
|
else
|
|
295
331
|
line '<pre>'
|
|
@@ -302,7 +338,7 @@ module BitClust
|
|
|
302
338
|
|
|
303
339
|
def list
|
|
304
340
|
lines = unindent_block(canonicalize(@f.break(/\A\S/)))
|
|
305
|
-
while lines.last
|
|
341
|
+
while lines.last&.empty?
|
|
306
342
|
lines.pop
|
|
307
343
|
end
|
|
308
344
|
line '<pre>'
|
|
@@ -327,7 +363,7 @@ module BitClust
|
|
|
327
363
|
end
|
|
328
364
|
|
|
329
365
|
def see
|
|
330
|
-
header = @f.gets
|
|
366
|
+
header = @f.gets or raise
|
|
331
367
|
header.slice!(/\A\@\w+/)
|
|
332
368
|
body = [header] + @f.span(/\A\s+\S/)
|
|
333
369
|
line '<p>'
|
|
@@ -336,7 +372,7 @@ module BitClust
|
|
|
336
372
|
end
|
|
337
373
|
|
|
338
374
|
def todo
|
|
339
|
-
header = @f.gets
|
|
375
|
+
header = @f.gets or raise
|
|
340
376
|
header.slice!(/\A\@\w+/)
|
|
341
377
|
body = header
|
|
342
378
|
line '<p class="todo">'
|
|
@@ -344,12 +380,25 @@ module BitClust
|
|
|
344
380
|
line '</p>'
|
|
345
381
|
end
|
|
346
382
|
|
|
383
|
+
def attribute_tokens(attr_line)
|
|
384
|
+
(attr_line || '')[/\A\{:(.*)\}/, 1].to_s.strip.split(/\s+/)
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
# {: undef} 属性付きエントリのメッセージ。ページを見に来た人向け
|
|
388
|
+
# (statichtml は undefined エントリを skip するので server 等の動的経路用)。
|
|
389
|
+
# nomethod は説明が本文に書かれている前提のマーカーなので何も描画しない
|
|
390
|
+
def undef_message
|
|
391
|
+
line '<p>'
|
|
392
|
+
line 'このメソッドは定義されていません。'
|
|
393
|
+
line '</p>'
|
|
394
|
+
end
|
|
395
|
+
|
|
347
396
|
def entry_info
|
|
348
397
|
line '<dl>'
|
|
349
398
|
while @f.next? and /\A\@(?!see)\w+|\A$/ =~ @f.peek
|
|
350
|
-
header = @f.gets
|
|
399
|
+
header = @f.gets or raise
|
|
351
400
|
next if /\A$/ =~ header
|
|
352
|
-
cmd = header.slice!(/\A\@\w+/)
|
|
401
|
+
cmd = header.slice!(/\A\@\w+/) or raise
|
|
353
402
|
@f.ungets(header)
|
|
354
403
|
case cmd
|
|
355
404
|
when '@param', '@arg'
|
|
@@ -385,9 +434,10 @@ module BitClust
|
|
|
385
434
|
string %Q(<dt class="method-heading")
|
|
386
435
|
string %Q( id="#{@method.index_id}") if first
|
|
387
436
|
string '><code>'
|
|
388
|
-
string @method.klass.name + @method.
|
|
437
|
+
string @method.klass.name + @method.display_typemark if @opt
|
|
389
438
|
string escape_html(sig.friendly_string)
|
|
390
439
|
string '</code>'
|
|
440
|
+
string heading_version_badges(@method, sig.name, first) if @method
|
|
391
441
|
if first
|
|
392
442
|
string '<span class="permalink">['
|
|
393
443
|
string a_href(@urlmapper.method_url(methodid2specstring(@method.id)), "permalink")
|
|
@@ -395,7 +445,9 @@ module BitClust
|
|
|
395
445
|
string rdoc_link(@method.id, @option[:database].properties["version"])
|
|
396
446
|
if @option[:edit_base_url] && @method.source_location
|
|
397
447
|
string ']['
|
|
398
|
-
|
|
448
|
+
# @type var urlmapper: ::BitClust::Subcommands::StatichtmlCommand::URLMapperEx
|
|
449
|
+
urlmapper = _ = @urlmapper
|
|
450
|
+
string a_href(urlmapper.edit_url(@method.source_location), 'edit')
|
|
399
451
|
end
|
|
400
452
|
string ']</span>'
|
|
401
453
|
end
|
|
@@ -406,54 +458,68 @@ module BitClust
|
|
|
406
458
|
end
|
|
407
459
|
|
|
408
460
|
BracketLink = /\[\[[\w-]+?:[!-~]+?(?:\[\] )?\]\]/n
|
|
461
|
+
# BitClust には ISO/JIS へのリンク機能がないため、[[ISO:8601]]/[[JIS:X 0301]] は
|
|
462
|
+
# リンクにせず平文で表示する (rurema/bitclust#236)。引数に空白を含む JIS も拾う。
|
|
463
|
+
StandardRef = /\[\[(?:ISO|JIS):[!-~][!-~ ]*?\]\]/n
|
|
409
464
|
NeedESC = /[&"<>]/
|
|
410
465
|
|
|
411
466
|
def compile_text(str)
|
|
412
467
|
escape_table = HTMLUtils::ESC
|
|
413
|
-
str.gsub(/(#{NeedESC})|(#{BracketLink})/o) {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
elsif tok = $
|
|
468
|
+
str.gsub(/(#{NeedESC})|(#{StandardRef})|(#{BracketLink})/o) {
|
|
469
|
+
# @type var char: '&' | '"' | '<' | '>'
|
|
470
|
+
if char = _ = $1 then escape_table[char]
|
|
471
|
+
elsif tok = $2 then standard_ref(tok[2..-3] || raise)
|
|
472
|
+
elsif tok = $3 then bracket_link(tok[2..-3] || raise)
|
|
417
473
|
else
|
|
418
474
|
raise 'must not happen'
|
|
419
475
|
end
|
|
420
476
|
}
|
|
421
477
|
end
|
|
422
478
|
|
|
479
|
+
def standard_ref(link)
|
|
480
|
+
# 例: "ISO:8601" -> "ISO 8601", "JIS:X 0301" -> "JIS X 0301"
|
|
481
|
+
type, _arg = link.split(':', 2)
|
|
482
|
+
arg = _arg&.strip or raise
|
|
483
|
+
escape_html("#{type} #{arg}")
|
|
484
|
+
end
|
|
485
|
+
|
|
423
486
|
def bracket_link(link, label = nil, frag = nil)
|
|
424
487
|
type, _arg = link.split(':', 2)
|
|
425
|
-
arg = _arg
|
|
488
|
+
arg = _arg&.rstrip or raise
|
|
489
|
+
# link_checker(bitclust/link_checker.rb)が指定されているときは
|
|
490
|
+
# 参照を検証用に記録する。描画には影響しない
|
|
491
|
+
@option[:link_checker]&.note_ref(type || raise, arg)
|
|
426
492
|
case type
|
|
427
493
|
when 'lib'
|
|
428
494
|
protect(link) {
|
|
429
495
|
case arg
|
|
430
496
|
when '/', '_index'
|
|
431
|
-
label = '
|
|
497
|
+
label = _('Library Index')
|
|
432
498
|
when '_builtin'
|
|
433
|
-
label = 'Builtin
|
|
499
|
+
label = _('Builtin Library')
|
|
434
500
|
end
|
|
435
501
|
library_link(arg, label, frag)
|
|
436
502
|
}
|
|
437
503
|
when 'c'
|
|
438
504
|
protect(link) { class_link(arg, label, frag) }
|
|
439
505
|
when 'm'
|
|
440
|
-
protect(link) { method_link(complete_spec(arg), label || arg, frag) }
|
|
506
|
+
protect(link) { method_link(complete_spec(arg), label || display_spec(arg), frag) }
|
|
441
507
|
when 'f'
|
|
442
508
|
protect(link) {
|
|
443
509
|
case arg
|
|
444
510
|
when '/', '_index'
|
|
445
|
-
arg, label = '', '
|
|
511
|
+
arg, label = '', _('Function Index')
|
|
446
512
|
end
|
|
447
513
|
function_link(arg, label || arg, frag)
|
|
448
514
|
}
|
|
449
515
|
when 'd'
|
|
450
516
|
protect(link) { document_link(arg, label, frag) }
|
|
451
517
|
when 'ref'
|
|
452
|
-
protect(link) { reference_link(arg) }
|
|
518
|
+
protect(link) { reference_link(arg, label) }
|
|
453
519
|
when 'url'
|
|
454
520
|
direct_url(arg)
|
|
455
521
|
when 'man'
|
|
456
|
-
man_link(arg)
|
|
522
|
+
man_link(arg, label)
|
|
457
523
|
when 'rfc', 'RFC'
|
|
458
524
|
rfc_link(arg)
|
|
459
525
|
when 'ruby-list', 'ruby-dev', 'ruby-ext', 'ruby-talk', 'ruby-core'
|
|
@@ -475,37 +541,51 @@ module BitClust
|
|
|
475
541
|
%Q(<a class="external" href="#{escape_html(url)}">#{escape_html(url)}</a>)
|
|
476
542
|
end
|
|
477
543
|
|
|
478
|
-
|
|
544
|
+
# label はラベル付き参照(MDCompiler#ref_md_link)からの表示テキスト
|
|
545
|
+
# 上書き。指定時は refs テーブルからのセクションラベル計算を行わない
|
|
546
|
+
def reference_link(arg, label = nil)
|
|
479
547
|
case arg
|
|
480
|
-
when /(\w+):(.*)\#(
|
|
548
|
+
when /(\w+):(.*)\#([-\w]+)\z/
|
|
549
|
+
# @type var type: String
|
|
550
|
+
# @type var name: String
|
|
551
|
+
# @type var frag: String
|
|
481
552
|
type, name, frag = $1, $2, $3
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
553
|
+
unless label
|
|
554
|
+
# @type var title: String
|
|
555
|
+
# @type var t: String
|
|
556
|
+
# @type var id: String
|
|
557
|
+
case type
|
|
558
|
+
when 'lib'
|
|
559
|
+
title, t, id = name, LibraryEntry.type_id.to_s, name
|
|
560
|
+
when 'c'
|
|
561
|
+
title, t, id = name, ClassEntry.type_id.to_s, name
|
|
562
|
+
when 'm'
|
|
563
|
+
# 表示側(title)のみ display_spec で畳む。id は refs テーブルの
|
|
564
|
+
# キーなので記載どおり(bitclust#282)
|
|
565
|
+
title, t, id = display_spec(name), MethodEntry.type_id.to_s, name
|
|
566
|
+
when 'd'
|
|
567
|
+
title, t, id = @option[:database].get_doc(name).title, DocEntry.type_id.to_s, name
|
|
568
|
+
else
|
|
569
|
+
raise "must not happen"
|
|
570
|
+
end
|
|
571
|
+
label = @option[:database].refs[t, id, frag]
|
|
572
|
+
label = title + '/' + label if label and name
|
|
493
573
|
end
|
|
494
|
-
label = @option[:database].refs[t, id, frag]
|
|
495
|
-
label = title + '/' + label if label and name
|
|
496
574
|
bracket_link("#{type}:#{name}", label, frag)
|
|
497
|
-
when /\A(
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
575
|
+
when /\A([-\w]+)\z/
|
|
576
|
+
frag = $1 || raise
|
|
577
|
+
unless label
|
|
578
|
+
e = @option[:entry]
|
|
579
|
+
type = e.type_id.to_s
|
|
580
|
+
label = @option[:database].refs[type, e.name, frag] || frag
|
|
581
|
+
end
|
|
502
582
|
a_href('#' + frag, label)
|
|
503
583
|
else
|
|
504
584
|
raise "must not happen"
|
|
505
585
|
end
|
|
506
586
|
end
|
|
507
587
|
|
|
508
|
-
BLADE_URL = '
|
|
588
|
+
BLADE_URL = 'https://blade.ruby-lang.org/%s/%s'
|
|
509
589
|
|
|
510
590
|
def blade_link(ml, num)
|
|
511
591
|
url = sprintf(BLADE_URL, ml, num)
|
|
@@ -543,10 +623,12 @@ module BitClust
|
|
|
543
623
|
end
|
|
544
624
|
end
|
|
545
625
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
626
|
+
# label はラベル付き参照(MDCompiler#ref_md_link)からの表示テキスト
|
|
627
|
+
# 上書き。リンクにできない spec ではラベルをプレーン表示に使う
|
|
628
|
+
def man_link(spec, label = nil)
|
|
629
|
+
m = /([\w\.\/]+)\((\w+)\)/.match(spec) or return escape_html(label || spec)
|
|
630
|
+
url = man_url(m[2], escape_html(m[1] || raise)) or return escape_html(label || spec)
|
|
631
|
+
%Q(<a class="external" href="#{escape_html(url)}">#{escape_html(label || "#{m[1]}(#{m[2]})")}</a>)
|
|
550
632
|
end
|
|
551
633
|
|
|
552
634
|
BUGS_URL = "https://bugs.ruby-lang.org/issues/%s"
|
|
@@ -558,8 +640,14 @@ module BitClust
|
|
|
558
640
|
|
|
559
641
|
def rdoc_url(method_id, version)
|
|
560
642
|
cname, tmark, mname, _libname = methodid2specparts(method_id)
|
|
561
|
-
|
|
562
|
-
|
|
643
|
+
cname = cname.split(".").first || raise
|
|
644
|
+
# rdoc は Kernel のモジュール関数(rb_define_global_function 由来)を
|
|
645
|
+
# private インスタンスメソッドとして掲載しているため i にする
|
|
646
|
+
if typemark2char(tmark) == 'i' || (cname == "Kernel" && tmark == '.#')
|
|
647
|
+
tchar = 'i'
|
|
648
|
+
else
|
|
649
|
+
tchar = 'c'
|
|
650
|
+
end
|
|
563
651
|
cname = cname.gsub('::', '/')
|
|
564
652
|
id = "method-#{tchar}-#{encodename_rdocurl(mname)}"
|
|
565
653
|
|
|
@@ -579,6 +667,19 @@ module BitClust
|
|
|
579
667
|
end
|
|
580
668
|
end
|
|
581
669
|
|
|
670
|
+
# bitclust#282: [[m:...]] のデフォルトラベル(参照の記載文字列)は表示
|
|
671
|
+
# 専用なので、module function の ".#" は DB バージョンが 4.0 以降なら
|
|
672
|
+
# "?." で表示する(#250/#277 の display_typemark と同じ選択規則。
|
|
673
|
+
# Markdown ソースの [m:Kernel?.x] も inline 復元時に ".#" へ正規化されて
|
|
674
|
+
# ここに来るため、どちらの表記で書かれていても見出し表記と一致する)。
|
|
675
|
+
# spec・URL・アンカーキーは不変。明示ラベル(label 引数)には触れない
|
|
676
|
+
def display_spec(spec)
|
|
677
|
+
return spec unless spec.include?('.#')
|
|
678
|
+
db = @option[:database]
|
|
679
|
+
version = db ? db.propget('version') : nil
|
|
680
|
+
spec.sub('.#', NameUtils.display_typemark('.#', version))
|
|
681
|
+
end
|
|
682
|
+
|
|
582
683
|
def seems_code(text)
|
|
583
684
|
# FIXME
|
|
584
685
|
escape_html(text)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#
|
|
2
3
|
# bitclust/refsdatabase.rb
|
|
3
4
|
#
|
|
@@ -11,17 +12,21 @@ module BitClust
|
|
|
11
12
|
class RefsDatabase
|
|
12
13
|
def self.load(src)
|
|
13
14
|
if src.respond_to?(:to_str)
|
|
15
|
+
# @type var src: _ToStr
|
|
14
16
|
buf = fopen(src.to_str, 'r:UTF-8'){|f| f.read}
|
|
15
17
|
elsif src.respond_to?(:to_io)
|
|
18
|
+
# @type var src: _ToIO
|
|
16
19
|
buf = src.to_io.read
|
|
17
20
|
else
|
|
21
|
+
# @type var src: _Reader
|
|
18
22
|
buf = src.read
|
|
19
23
|
end
|
|
20
24
|
|
|
21
25
|
refs = self.new
|
|
22
|
-
buf
|
|
26
|
+
buf&.each_line{|l|
|
|
23
27
|
if /((?:\\,|[^,])+),((?:\\,|[^,])+),((?:\\,|[^,])+),((?:\\,|[^,])+)\n/ =~ l
|
|
24
|
-
type, id, linkid, desc = [$1, $2, $3, $4].map{|e| e
|
|
28
|
+
type, id, linkid, desc = [$1, $2, $3, $4].map{|e| e&.gsub(/\\(.)/){|s| $1 == ',' ? ',' : s } }
|
|
29
|
+
type || raise; id || raise; linkid || raise; desc || raise
|
|
25
30
|
refs[type, id, linkid] = desc
|
|
26
31
|
end
|
|
27
32
|
}
|
|
@@ -42,15 +47,18 @@ module BitClust
|
|
|
42
47
|
|
|
43
48
|
def save(s)
|
|
44
49
|
if s.respond_to?(:to_str)
|
|
50
|
+
# @type var s: _ToStr
|
|
45
51
|
path = s.to_str
|
|
46
52
|
io = fopen(path, 'w:UTF-8')
|
|
47
53
|
elsif s.respond_to?(:to_io)
|
|
54
|
+
# @type var s: _ToIO
|
|
48
55
|
io = s.to_io
|
|
49
56
|
else
|
|
50
57
|
io = s
|
|
51
58
|
end
|
|
59
|
+
# @type var io: IO
|
|
52
60
|
|
|
53
|
-
@h.each{|k, v|
|
|
61
|
+
@h.sort.each{|k, v|
|
|
54
62
|
io.write( [k, v].flatten.map{|e| e.gsub(/,/, '\\,') }.join(',') + "\n" )
|
|
55
63
|
}
|
|
56
64
|
io.close
|
|
@@ -58,11 +66,19 @@ module BitClust
|
|
|
58
66
|
|
|
59
67
|
def extract(entry)
|
|
60
68
|
entry.source.each_line{|l|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
69
|
+
anchor, label =
|
|
70
|
+
if /\A={1,6}\[a:([-\w]+)\] *(.*)/ =~ l
|
|
71
|
+
[$1, $2]
|
|
72
|
+
elsif /\A\#{1,6} +(.*?) *\{#([-\w]+)\}\s*\z/ =~ l
|
|
73
|
+
# md ソース: 「### 見出し {#anchor}」形式(M3 ネイティブパース)。
|
|
74
|
+
# ラベルは rd 表示形へ戻す(\` エスケープ解除等。pattern_matching)
|
|
75
|
+
Kernel.require 'bitclust/markdown_to_rrd'
|
|
76
|
+
[$2, ::BitClust::MarkdownToRRD.restore_description($1 || raise)]
|
|
77
|
+
end
|
|
78
|
+
next unless anchor
|
|
79
|
+
entry.labels.each{|name|
|
|
80
|
+
self[entry.class.type_id, name, anchor || raise] = label || raise
|
|
81
|
+
}
|
|
66
82
|
}
|
|
67
83
|
end
|
|
68
84
|
end
|