bitclust-core 1.3.0 → 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 +48 -4
- 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 +16 -17
- data/lib/bitclust/capi_converter.rb +20 -0
- data/lib/bitclust/classentry.rb +67 -17
- data/lib/bitclust/compat.rb +2 -2
- data/lib/bitclust/completion.rb +58 -27
- data/lib/bitclust/crossrubyutils.rb +8 -5
- data/lib/bitclust/database.rb +28 -8
- data/lib/bitclust/doc_converter.rb +63 -0
- data/lib/bitclust/docentry.rb +1 -1
- data/lib/bitclust/entity_splitter.rb +221 -0
- data/lib/bitclust/entry.rb +47 -7
- data/lib/bitclust/functiondatabase.rb +13 -1
- data/lib/bitclust/functionentry.rb +5 -1
- data/lib/bitclust/functionreferenceparser.rb +4 -4
- data/lib/bitclust/generators/epub.rb +10 -3
- data/lib/bitclust/htmlutils.rb +1 -1
- data/lib/bitclust/include_graph.rb +375 -0
- data/lib/bitclust/include_pruner.rb +144 -0
- data/lib/bitclust/interface.rb +1 -1
- data/lib/bitclust/libraryentry.rb +8 -7
- data/lib/bitclust/lineinput.rb +7 -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 +3 -3
- data/lib/bitclust/method_since_calculator.rb +117 -0
- data/lib/bitclust/methoddatabase.rb +124 -14
- data/lib/bitclust/methodentry.rb +125 -7
- data/lib/bitclust/methodid.rb +12 -11
- data/lib/bitclust/methodsignature.rb +10 -4
- data/lib/bitclust/nameutils.rb +41 -22
- data/lib/bitclust/preprocessor.rb +66 -29
- data/lib/bitclust/rdcompiler.rb +195 -95
- data/lib/bitclust/refsdatabase.rb +23 -8
- data/lib/bitclust/reloadable_request_handler.rb +72 -0
- data/lib/bitclust/requesthandler.rb +21 -16
- data/lib/bitclust/ridatabase.rb +10 -4
- data/lib/bitclust/rrd_to_markdown.rb +925 -0
- data/lib/bitclust/rrdparser.rb +196 -30
- data/lib/bitclust/runner.rb +17 -2
- data/lib/bitclust/screen.rb +80 -11
- data/lib/bitclust/search_index_generator.rb +288 -0
- data/lib/bitclust/searcher.rb +69 -20
- data/lib/bitclust/simplesearcher.rb +24 -12
- data/lib/bitclust/subcommand.rb +7 -1
- data/lib/bitclust/subcommands/ancestors_command.rb +9 -2
- data/lib/bitclust/subcommands/checklink_command.rb +54 -0
- data/lib/bitclust/subcommands/chm_command.rb +15 -7
- data/lib/bitclust/subcommands/classes_command.rb +5 -0
- data/lib/bitclust/subcommands/extract_command.rb +5 -0
- data/lib/bitclust/subcommands/htmlfile_command.rb +21 -7
- data/lib/bitclust/subcommands/init_command.rb +4 -1
- data/lib/bitclust/subcommands/list_command.rb +12 -4
- data/lib/bitclust/subcommands/lookup_command.rb +28 -9
- data/lib/bitclust/subcommands/methods_command.rb +10 -2
- data/lib/bitclust/subcommands/methodsince_command.rb +80 -0
- data/lib/bitclust/subcommands/preproc_command.rb +5 -0
- data/lib/bitclust/subcommands/property_command.rb +2 -1
- data/lib/bitclust/subcommands/searchpage_command.rb +102 -0
- data/lib/bitclust/subcommands/server_command.rb +10 -8
- data/lib/bitclust/subcommands/setup_command.rb +24 -10
- data/lib/bitclust/subcommands/statichtml_command.rb +129 -6
- data/lib/bitclust/subcommands/update_command.rb +110 -2
- data/lib/bitclust/syntax_highlighter.rb +48 -4
- data/lib/bitclust/textutils.rb +3 -3
- data/lib/bitclust/version.rb +1 -1
- data/lib/bitclust/version_badges.rb +90 -0
- data/lib/bitclust/whole_file_gate.rb +137 -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 +401 -30
- 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 +132 -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 +161 -20
- data/README +0 -32
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test/unit'
|
|
4
|
+
require 'tmpdir'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
|
|
7
|
+
require 'bitclust/markdown_orchestrator'
|
|
8
|
+
require 'bitclust/markdown_to_rrd'
|
|
9
|
+
|
|
10
|
+
# MarkdownOrchestrator: RD ツリー → Markdown ツリー変換のクロスファイル方針を
|
|
11
|
+
# 1か所に束ねる(グラフ解析 → prune → 全体ゲート解除 → front matter 注入)。
|
|
12
|
+
# bin/rrd2md --graph と tools/md-roundtrip-check.rb --inject の共通実装。
|
|
13
|
+
#
|
|
14
|
+
# テストリスト:
|
|
15
|
+
# [x] member には library を注入し、root からは grouping include を prune、
|
|
16
|
+
# root には type: library を付ける
|
|
17
|
+
# [x] fragment include は温存される
|
|
18
|
+
# [x] 全体ゲート(常に真)は解除されて md にラッパーが残らない
|
|
19
|
+
# [x] LIBRARIES 由来のゲートとファイル全体ゲートは交差でマージされ二重にならない
|
|
20
|
+
# [x] reduce の rd と convert の md が MarkdownToRRD で一致(ラウンドトリップ期待値)
|
|
21
|
+
# [x] LIBRARIES 自体は変換対象外
|
|
22
|
+
class TestMarkdownOrchestrator < Test::Unit::TestCase
|
|
23
|
+
FILES = {
|
|
24
|
+
"LIBRARIES" => "foo\n\#@until 3.1\ngated\n\#@end\nx\nx/x\ncml\ngml\n",
|
|
25
|
+
"foo.rd" => "category Cat\n\n説明。\n\n\#@include(foo/Bar)\n\n\#@include(foo/frag)\n",
|
|
26
|
+
"foo/Bar" => "\#@since 1.9.1\n= class Bar < Object\n\nBar の説明。\n\#@end\n",
|
|
27
|
+
"foo/frag" => "断片。\n",
|
|
28
|
+
"gated.rd" => "\#@until 3.1\ngated ライブラリの説明。\n\#@end\n",
|
|
29
|
+
"x.rd" => "x の説明。\n\n\#@include(x/X)\n",
|
|
30
|
+
"x/X" => "= class X < Object\n\nX の説明。\n",
|
|
31
|
+
"x/x.rd" => "x/x の説明。\n",
|
|
32
|
+
# cmath 型: LIBRARIES にゲートは無いがファイル全体が #@since で包まれている
|
|
33
|
+
"cml.rd" => "\#@since 1.9.1\ncml の説明。\n\#@end\n",
|
|
34
|
+
# rubygems 型: 据え置きゲートの中にライブラリメタデータがある
|
|
35
|
+
"gml.rd" => "\#@since 1.9.1\nrequire foo\n\ngml の説明。\n\#@end\n",
|
|
36
|
+
}.freeze
|
|
37
|
+
|
|
38
|
+
def with_orchestrator(scope: nil)
|
|
39
|
+
Dir.mktmpdir do |dir|
|
|
40
|
+
FILES.each do |path, content|
|
|
41
|
+
full = File.join(dir, path)
|
|
42
|
+
FileUtils.mkdir_p(File.dirname(full))
|
|
43
|
+
File.write(full, content)
|
|
44
|
+
end
|
|
45
|
+
opts = scope ? { scope: scope } : {}
|
|
46
|
+
yield BitClust::MarkdownOrchestrator.new(dir, **opts)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def wide_scope
|
|
51
|
+
BitClust::IncludeGraph::Scope.new("1.8.7", "4.2")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_member_whole_file_gate_unwraps_to_entity_since_under_wide_scope
|
|
55
|
+
# メンバーの全体ゲートはエンティティ自身の存在ゲートなので front matter へ
|
|
56
|
+
# (旧世界でも include 先が空にプリプロセスされる=エンティティ不存在で等価)
|
|
57
|
+
with_orchestrator(scope: wide_scope) do |orch|
|
|
58
|
+
md = orch.convert("foo/Bar", FILES["foo/Bar"])
|
|
59
|
+
expected = <<~'MD'
|
|
60
|
+
---
|
|
61
|
+
library: foo
|
|
62
|
+
since: "1.9.1"
|
|
63
|
+
---
|
|
64
|
+
# class Bar < Object
|
|
65
|
+
|
|
66
|
+
Bar の説明。
|
|
67
|
+
MD
|
|
68
|
+
assert_equal expected, md
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_fragment_whole_file_gate_is_kept_in_body
|
|
73
|
+
# 断片(#@include 展開用、front matter を持てない)の全体ゲートは
|
|
74
|
+
# 常真でない限り据え置く。front matter を付けると include 展開の途中に
|
|
75
|
+
# `---` が現れてパースが壊れる(_builtin/Fiber.current の #@since 1.9.0)
|
|
76
|
+
files = {
|
|
77
|
+
"LIBRARIES" => "foo\n",
|
|
78
|
+
"foo.rd" => "説明。\n\n\#@include(foo/gfrag)\n",
|
|
79
|
+
"foo/gfrag" => "\#@since 1.9.1\n断片。\n\#@end\n",
|
|
80
|
+
}
|
|
81
|
+
with_files(files, scope: wide_scope) do |orch|
|
|
82
|
+
md = orch.convert("foo/gfrag", files["foo/gfrag"])
|
|
83
|
+
assert_equal "\#@since 1.9.1\n断片。\n\#@end\n", md
|
|
84
|
+
end
|
|
85
|
+
# デフォルトスコープでは常真 → 従来どおり解除される
|
|
86
|
+
with_files(files) do |orch|
|
|
87
|
+
md = orch.convert("foo/gfrag", files["foo/gfrag"])
|
|
88
|
+
assert_equal "断片。\n", md
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def with_files(files, scope: nil)
|
|
93
|
+
Dir.mktmpdir do |dir|
|
|
94
|
+
files.each do |path, content|
|
|
95
|
+
full = File.join(dir, path)
|
|
96
|
+
FileUtils.mkdir_p(File.dirname(full))
|
|
97
|
+
File.write(full, content)
|
|
98
|
+
end
|
|
99
|
+
opts = scope ? { scope: scope } : {}
|
|
100
|
+
yield BitClust::MarkdownOrchestrator.new(dir, **opts)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def test_kept_gate_library_metadata_moves_to_front_matter_with_gate
|
|
105
|
+
# rubygems 型: 据え置きゲートの中の require 等は、独立ゲートに分離した上で
|
|
106
|
+
# front matter 化する(native パースはメタデータを front matter からしか
|
|
107
|
+
# 読まないため)。本文はゲートのまま残る
|
|
108
|
+
with_orchestrator(scope: wide_scope) do |orch|
|
|
109
|
+
md = orch.convert("gml.rd", FILES["gml.rd"])
|
|
110
|
+
expected = <<~'MD'
|
|
111
|
+
---
|
|
112
|
+
type: library
|
|
113
|
+
require:
|
|
114
|
+
#@since 1.9.1
|
|
115
|
+
- foo
|
|
116
|
+
#@end
|
|
117
|
+
---
|
|
118
|
+
#@since 1.9.1
|
|
119
|
+
gml の説明。
|
|
120
|
+
#@end
|
|
121
|
+
MD
|
|
122
|
+
assert_equal expected, md
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def test_narrowing_whole_file_gate_on_library_root_is_kept_in_body
|
|
127
|
+
# cmath 型: ライブラリの存在は LIBRARIES が正(1.8.7 にも存在して内容が空)。
|
|
128
|
+
# LIBRARIES 由来ゲートより狭いファイル全体ゲートを front matter に解除すると
|
|
129
|
+
# 「ライブラリの存在」まで狭めてしまうので、据え置いて本文ゲートのまま残す
|
|
130
|
+
with_orchestrator(scope: wide_scope) do |orch|
|
|
131
|
+
md = orch.convert("cml.rd", FILES["cml.rd"])
|
|
132
|
+
expected = <<~'MD'
|
|
133
|
+
---
|
|
134
|
+
type: library
|
|
135
|
+
---
|
|
136
|
+
#@since 1.9.1
|
|
137
|
+
cml の説明。
|
|
138
|
+
#@end
|
|
139
|
+
MD
|
|
140
|
+
assert_equal expected, md
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def test_matching_whole_file_gate_still_unwraps_under_wide_scope
|
|
145
|
+
# LIBRARIES 由来のゲート(until 3.1)とファイル全体ゲートが一致する場合は
|
|
146
|
+
# 従来どおり解除して front matter に一本化する(fiber/set 型)
|
|
147
|
+
with_orchestrator(scope: wide_scope) do |orch|
|
|
148
|
+
md = orch.convert("gated.rd", FILES["gated.rd"])
|
|
149
|
+
expected = <<~'MD'
|
|
150
|
+
---
|
|
151
|
+
type: library
|
|
152
|
+
until: "3.1"
|
|
153
|
+
---
|
|
154
|
+
gated ライブラリの説明。
|
|
155
|
+
MD
|
|
156
|
+
assert_equal expected, md
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def test_root_conversion_prunes_groupings_and_marks_library
|
|
161
|
+
with_orchestrator do |orch|
|
|
162
|
+
md = orch.convert("foo.rd", FILES["foo.rd"])
|
|
163
|
+
expected = <<~MD
|
|
164
|
+
---
|
|
165
|
+
type: library
|
|
166
|
+
category: Cat
|
|
167
|
+
---
|
|
168
|
+
説明。
|
|
169
|
+
|
|
170
|
+
\#@include(foo/frag)
|
|
171
|
+
MD
|
|
172
|
+
assert_equal expected, md
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def test_member_conversion_injects_library_and_unwraps_vacuous_gate
|
|
177
|
+
with_orchestrator do |orch|
|
|
178
|
+
md = orch.convert("foo/Bar", FILES["foo/Bar"])
|
|
179
|
+
expected = <<~MD
|
|
180
|
+
---
|
|
181
|
+
library: foo
|
|
182
|
+
---
|
|
183
|
+
# class Bar < Object
|
|
184
|
+
|
|
185
|
+
Bar の説明。
|
|
186
|
+
MD
|
|
187
|
+
assert_equal expected, md
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def test_library_gate_from_libraries_and_file_wrap_merge_once
|
|
192
|
+
with_orchestrator do |orch|
|
|
193
|
+
md = orch.convert("gated.rd", FILES["gated.rd"])
|
|
194
|
+
expected = <<~MD
|
|
195
|
+
---
|
|
196
|
+
type: library
|
|
197
|
+
until: "3.1"
|
|
198
|
+
---
|
|
199
|
+
gated ライブラリの説明。
|
|
200
|
+
MD
|
|
201
|
+
assert_equal expected, md
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def test_reduce_matches_markdown_to_rrd_of_convert
|
|
206
|
+
with_orchestrator do |orch|
|
|
207
|
+
FILES.each_key do |path|
|
|
208
|
+
next unless orch.convert?(path)
|
|
209
|
+
rrd = FILES[path]
|
|
210
|
+
reduced, = orch.reduce(path, rrd)
|
|
211
|
+
assert_equal reduced, BitClust::MarkdownToRRD.convert(orch.convert(path, rrd)),
|
|
212
|
+
"roundtrip mismatch for #{path}"
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def test_libraries_file_is_not_converted
|
|
218
|
+
with_orchestrator do |orch|
|
|
219
|
+
assert_false orch.convert?("LIBRARIES")
|
|
220
|
+
assert_true orch.convert?("foo.rd")
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def test_entity_h1_without_space_is_normalized
|
|
225
|
+
# _builtin/Encoding の「=class Encoding」。RRDParser は受理するが
|
|
226
|
+
# 単一ファイル変換器は正規形「= class」のみ扱うため、reduce 段で正規化する
|
|
227
|
+
with_orchestrator do |orch|
|
|
228
|
+
rrd = "=class Enc\n\n説明。\n"
|
|
229
|
+
reduced, = orch.reduce("foo/Enc", rrd)
|
|
230
|
+
assert_equal "= class Enc\n\n説明。\n", reduced
|
|
231
|
+
assert_equal "# class Enc\n\n説明。\n", orch.convert("foo/Enc", rrd)
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# ---- reduce のヘッダ正規化 ----
|
|
236
|
+
# md→rd の再生成形(H1 直後に関係、末尾空白なし)に reduce 側を揃え、
|
|
237
|
+
# byte-exact ラウンドトリップを成立させる
|
|
238
|
+
|
|
239
|
+
def test_reduce_strips_leading_blank_after_resolution
|
|
240
|
+
# base64/Base64: 解決で先頭に空行が残るケース
|
|
241
|
+
with_orchestrator do |orch|
|
|
242
|
+
rrd = "\#@since 1.9.1\n\n= module B\n\#@else\n= module Old\n\#@end\n"
|
|
243
|
+
reduced, = orch.reduce("foo/Bar", rrd)
|
|
244
|
+
assert_equal "= module B\n", reduced
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def test_reduce_strips_trailing_space_on_relation_lines
|
|
249
|
+
# openssl/SSL__SSLSocket: 「include X 」の末尾スペース
|
|
250
|
+
with_orchestrator do |orch|
|
|
251
|
+
rrd = "= class A < Object\ninclude Foo \n\n説明。\n"
|
|
252
|
+
reduced, = orch.reduce("foo/Bar", rrd)
|
|
253
|
+
assert_equal "= class A < Object\ninclude Foo\n\n説明。\n", reduced
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def test_reduce_removes_blank_between_h1_and_relations
|
|
258
|
+
# _builtin/Integer 等: H1 と(gated)関係の間の空行
|
|
259
|
+
with_orchestrator do |orch|
|
|
260
|
+
rrd = "= class A < Object\n\ninclude Foo\n\n説明。\n"
|
|
261
|
+
reduced, = orch.reduce("foo/Bar", rrd)
|
|
262
|
+
assert_equal "= class A < Object\ninclude Foo\n\n説明。\n", reduced
|
|
263
|
+
|
|
264
|
+
rrd2 = "= class A < B\n\n\#@until 3.2\nalias F\n\#@end\n\n説明。\n"
|
|
265
|
+
reduced2, = orch.reduce("foo/Bar", rrd2)
|
|
266
|
+
assert_equal "= class A < B\n\#@until 3.2\nalias F\n\#@end\n\n説明。\n", reduced2
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def test_reduce_keeps_blank_after_h1_without_relations
|
|
271
|
+
with_orchestrator do |orch|
|
|
272
|
+
rrd = "= class A < Object\n\n説明。\n\#@since 3.0\n新しい。\n\#@end\n"
|
|
273
|
+
reduced, = orch.reduce("foo/Bar", rrd)
|
|
274
|
+
assert_equal rrd, reduced
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# ---- units: エンティティ分割(O3)----
|
|
279
|
+
# ヘッダ関係を持つマルチエンティティファイルはエンティティ単位に分割し、
|
|
280
|
+
# 関係を front matter に一元化する。関係なしの束ね(Errno 族等)は分割しない。
|
|
281
|
+
|
|
282
|
+
def test_units_split_relation_bearing_multi_entity_file
|
|
283
|
+
with_orchestrator do |orch|
|
|
284
|
+
rrd = "= class Conf < Object\ninclude Enumerable\n\n説明。\n\n" \
|
|
285
|
+
"= class Conf::Error < StandardError\nエラー。\n"
|
|
286
|
+
units = orch.units("foo/Bar", rrd)
|
|
287
|
+
assert_equal ["foo/Conf.md", "foo/Conf__Error.md"], units.map(&:path)
|
|
288
|
+
assert_equal <<~MD, orch.convert_unit(units[0])
|
|
289
|
+
---
|
|
290
|
+
library: foo
|
|
291
|
+
include:
|
|
292
|
+
- Enumerable
|
|
293
|
+
---
|
|
294
|
+
# class Conf < Object
|
|
295
|
+
|
|
296
|
+
説明。
|
|
297
|
+
|
|
298
|
+
MD
|
|
299
|
+
assert_equal <<~MD, orch.convert_unit(units[1])
|
|
300
|
+
---
|
|
301
|
+
library: foo
|
|
302
|
+
---
|
|
303
|
+
# class Conf::Error < StandardError
|
|
304
|
+
エラー。
|
|
305
|
+
MD
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def test_units_keep_relation_free_bundle_unsplit
|
|
310
|
+
with_orchestrator do |orch|
|
|
311
|
+
rrd = "= class E1 < StandardError\n説明1。\n\n= class E2 < StandardError\n説明2。\n"
|
|
312
|
+
units = orch.units("foo/Bar", rrd)
|
|
313
|
+
assert_equal ["foo/Bar.md"], units.map(&:path)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def test_units_keep_out_of_scope_file_unsplit
|
|
318
|
+
# スコープ外ファイル(front matter 注入なし)は関係があっても分割しない。
|
|
319
|
+
# サルベージは別スコープの再実行で扱う(分割すると library なしの
|
|
320
|
+
# エンティティファイルが散乱する)
|
|
321
|
+
with_orchestrator do |orch|
|
|
322
|
+
rrd = "= class A < Object\ninclude Enumerable\n\nA。\n\n= class B < Object\nB。\n"
|
|
323
|
+
units = orch.units("unreachable/File", rrd)
|
|
324
|
+
assert_equal ["unreachable/File.md"], units.map(&:path)
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def test_units_resolve_renamed_h1_into_single_entity
|
|
329
|
+
# thread/Mutex パターン: 常真ゲートの改名 H1 ペア → 分割ではなく単一エンティティ化。
|
|
330
|
+
# alias が front matter に上がる
|
|
331
|
+
with_orchestrator do |orch|
|
|
332
|
+
rrd = "\#@since 2.3.0\n= class T::Mutex < Object\nalias Mutex\n\#@else\n" \
|
|
333
|
+
"= class Mutex < Object\n\#@end\n\n本文。\n"
|
|
334
|
+
units = orch.units("foo/Bar", rrd)
|
|
335
|
+
assert_equal ["foo/Bar.md"], units.map(&:path)
|
|
336
|
+
assert_equal <<~MD, orch.convert_unit(units[0])
|
|
337
|
+
---
|
|
338
|
+
library: foo
|
|
339
|
+
alias:
|
|
340
|
+
- Mutex
|
|
341
|
+
---
|
|
342
|
+
# class T::Mutex < Object
|
|
343
|
+
|
|
344
|
+
本文。
|
|
345
|
+
MD
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def test_units_move_segment_gate_to_front_matter
|
|
350
|
+
# スコープ内ゲート付きエンティティを含む分割: セグメントの全体ゲートが since に
|
|
351
|
+
with_orchestrator do |orch|
|
|
352
|
+
rrd = "= class Conf < Object\ninclude Enumerable\n\n説明。\n\n" \
|
|
353
|
+
"\#@since 3.2\n= class Conf::New < Object\n新しい。\n\#@end\n"
|
|
354
|
+
units = orch.units("foo/Bar", rrd)
|
|
355
|
+
assert_equal ["foo/Conf.md", "foo/Conf__New.md"], units.map(&:path)
|
|
356
|
+
assert_equal <<~MD, orch.convert_unit(units[1])
|
|
357
|
+
---
|
|
358
|
+
library: foo
|
|
359
|
+
since: "3.2"
|
|
360
|
+
---
|
|
361
|
+
# class Conf::New < Object
|
|
362
|
+
新しい。
|
|
363
|
+
MD
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def test_units_single_entity_file_passes_through
|
|
368
|
+
with_orchestrator do |orch|
|
|
369
|
+
units = orch.units("foo/Bar", FILES["foo/Bar"])
|
|
370
|
+
assert_equal ["foo/Bar.md"], units.map(&:path)
|
|
371
|
+
assert_equal orch.convert("foo/Bar", FILES["foo/Bar"]), orch.convert_unit(units[0])
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def test_units_library_file_keeps_own_path
|
|
376
|
+
with_orchestrator do |orch|
|
|
377
|
+
units = orch.units("foo.rd", FILES["foo.rd"])
|
|
378
|
+
assert_equal ["foo.md"], units.map(&:path)
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
# ---- ライブラリファイルのインライン・エンティティ分割 ----
|
|
383
|
+
|
|
384
|
+
def test_units_split_inline_entities_out_of_library_file
|
|
385
|
+
# sdbm.rd 型: ライブラリ概要 + インライン・エンティティ複数(関係あり)。
|
|
386
|
+
# エンティティは <libname>/ 配下へ、library を注入。概要部は元パスに残る
|
|
387
|
+
with_orchestrator do |orch|
|
|
388
|
+
rrd = "category Cat\n\n概要。\n\n= class A < Object\ninclude Enumerable\n\nA。\n\n= class A::E < StandardError\nE。\n"
|
|
389
|
+
units = orch.units("foo.rd", rrd)
|
|
390
|
+
assert_equal ["foo.md", "foo/A.md", "foo/A__E.md"], units.map(&:path)
|
|
391
|
+
assert_equal <<~MD, orch.convert_unit(units[0])
|
|
392
|
+
---
|
|
393
|
+
type: library
|
|
394
|
+
category: Cat
|
|
395
|
+
---
|
|
396
|
+
概要。
|
|
397
|
+
|
|
398
|
+
MD
|
|
399
|
+
assert_equal <<~MD, orch.convert_unit(units[1])
|
|
400
|
+
---
|
|
401
|
+
library: foo
|
|
402
|
+
include:
|
|
403
|
+
- Enumerable
|
|
404
|
+
---
|
|
405
|
+
# class A < Object
|
|
406
|
+
|
|
407
|
+
A。
|
|
408
|
+
|
|
409
|
+
MD
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
def test_units_keep_dual_library_entity_file_unsplit
|
|
414
|
+
# pathname 型(lib + 単一エンティティ兼用)は仕様が認める形なので分割しない
|
|
415
|
+
with_orchestrator do |orch|
|
|
416
|
+
rrd = "category Cat\n\n概要。\n\n= class A < Object\ninclude Enumerable\n\nA。\n"
|
|
417
|
+
units = orch.units("foo.rd", rrd)
|
|
418
|
+
assert_equal ["foo.md"], units.map(&:path)
|
|
419
|
+
md = orch.convert_unit(units[0])
|
|
420
|
+
assert_match(/\Ainclude:\n - Enumerable\n/, md[/include:.*?(?=---)/m])
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
def test_units_rewrite_relative_includes_in_relocated_segments
|
|
425
|
+
# cgi/core.rd の #@include(util.rd) 型: lib 分割でセグメントが <libname>/ 配下へ
|
|
426
|
+
# 移るため、相対 include は新ディレクトリから解決できるよう書き換える
|
|
427
|
+
with_orchestrator do |orch|
|
|
428
|
+
rrd = "概要。\n\n= class A < Object\ninclude Enumerable\n\n\#@include(frag)\n\n" \
|
|
429
|
+
"= class B < Object\nB。\n"
|
|
430
|
+
units = orch.units("foo.rd", rrd)
|
|
431
|
+
a = units.find { |u| u.path == "foo/A.md" }
|
|
432
|
+
assert_match(%r{\#@include\(\.\./frag\)}, a.rrd)
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
def test_units_inline_entities_inherit_library_gate
|
|
437
|
+
# gated ライブラリ(until 3.1)のインライン・エンティティは until を継承する。
|
|
438
|
+
# 概要部が無くてもライブラリ自体が発見から消えないよう front matter だけの
|
|
439
|
+
# 概要ユニットを合成する
|
|
440
|
+
with_orchestrator do |orch|
|
|
441
|
+
rrd = "= class G < Object\ninclude Enumerable\n\nG。\n\n= class G::E < StandardError\nE。\n"
|
|
442
|
+
units = orch.units("gated.rd", rrd)
|
|
443
|
+
assert_equal ["gated.md", "gated/G.md", "gated/G__E.md"], units.map(&:path)
|
|
444
|
+
assert_equal "---\ntype: library\nuntil: \"3.1\"\n---\n", orch.convert_unit(units[0])
|
|
445
|
+
assert_equal({ "library" => "gated", "until" => "3.1" }, units[1].front_matter)
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
def test_sublibrary_case_collision_renamed_with_name_front_matter
|
|
450
|
+
# x/x.rd の出力 x/x.md はメンバー出力 x/X.md と大文字小文字のみで衝突し、
|
|
451
|
+
# macOS 等の case-insensitive FS でチェックアウト不能になる。
|
|
452
|
+
# basename に .lib を挟んで回避し、ライブラリ名は name: で保つ(rdoc/rdoc 型)
|
|
453
|
+
with_orchestrator do |orch|
|
|
454
|
+
units = orch.units("x/x.rd", FILES["x/x.rd"])
|
|
455
|
+
assert_equal ["x/x.lib.md"], units.map(&:path)
|
|
456
|
+
md = orch.convert_unit(units.first)
|
|
457
|
+
assert md.start_with?("---\ntype: library\nname: x/x\n---\n"), md[0, 80].inspect
|
|
458
|
+
end
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
def test_non_colliding_library_is_not_renamed
|
|
462
|
+
with_orchestrator do |orch|
|
|
463
|
+
units = orch.units("x.rd", FILES["x.rd"])
|
|
464
|
+
assert_equal ["x.md"], units.map(&:path)
|
|
465
|
+
assert_nil units.first.front_matter["name"]
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
def test_renamed_library_roundtrip_restores_rd
|
|
470
|
+
# name: は md 側だけの情報(ファイル名衝突回避)。md→rd では消え、
|
|
471
|
+
# reduce の rd 到達点がそのまま復元される
|
|
472
|
+
with_orchestrator do |orch|
|
|
473
|
+
unit = orch.units("x/x.rd", FILES["x/x.rd"]).first
|
|
474
|
+
md = orch.convert_unit(unit)
|
|
475
|
+
assert_equal unit.rrd, BitClust::MarkdownToRRD.convert(md)
|
|
476
|
+
end
|
|
477
|
+
end
|
|
478
|
+
end
|