bitclust-core 1.8.0 → 1.9.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/lib/bitclust/markdown_tree.rb +10 -0
- data/lib/bitclust/methoddatabase.rb +0 -2
- data/lib/bitclust/subcommands/htmlfile_command.rb +71 -6
- data/lib/bitclust/version.rb +1 -1
- data/test/test_extract_command.rb +0 -11
- data/test/test_htmlfile_command.rb +211 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c926bbf2b56a9b2553e97487db023f2ac8aac329ab1af22d2f8b56fa09afc8d5
|
|
4
|
+
data.tar.gz: 072201ad18fc53aac71ac620388018469fe618299f0af50bc5abf0a553e596ab
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 419ddb1ee1e46be729fc87e957a9aebd56a490810f8134b26617654986b77a5f1aef9b0599ecb7b6c9342dcb57c1417510cf93d9a7169614b36f195f67bd7d43
|
|
7
|
+
data.tar.gz: d683d676ce9daa86aa4544730f38898eb21ffdcd4e604711b01db22416531fe080685e5b6eddb533cafa8c71b135f7453f20fd42b58771f86faf762a8d7b602e
|
|
@@ -32,6 +32,11 @@ module BitClust
|
|
|
32
32
|
new(root).scan
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
# 1 ファイル分の front matter と本文の情報(scan が各ファイルで読むもの)
|
|
36
|
+
def self.file_info(path)
|
|
37
|
+
new(File.dirname(path)).file_info(File.basename(path))
|
|
38
|
+
end
|
|
39
|
+
|
|
35
40
|
attr_reader :libraries, :entities, :fragments, :warnings
|
|
36
41
|
|
|
37
42
|
def initialize(root)
|
|
@@ -87,6 +92,11 @@ module BitClust
|
|
|
87
92
|
self
|
|
88
93
|
end
|
|
89
94
|
|
|
95
|
+
# root 相対の path を 1 ファイルだけ読む
|
|
96
|
+
def file_info(path)
|
|
97
|
+
parse_file(path)
|
|
98
|
+
end
|
|
99
|
+
|
|
90
100
|
private
|
|
91
101
|
|
|
92
102
|
def validate(path, info)
|
|
@@ -216,7 +216,6 @@ module BitClust
|
|
|
216
216
|
gate[:until] = until_version if until_version
|
|
217
217
|
md_gate_covers?(version, gate)
|
|
218
218
|
end
|
|
219
|
-
private :md_version_covers?
|
|
220
219
|
|
|
221
220
|
# membership のゲート(MarkdownTree の since/until/version/except)がこの版を
|
|
222
221
|
# 含むか。version は「その版のみ」、except は「その版以外」(#%version V と
|
|
@@ -229,7 +228,6 @@ module BitClust
|
|
|
229
228
|
return false if (except = gate[:except]) && except.any? { |x| v == Gem::Version.new(x) }
|
|
230
229
|
true
|
|
231
230
|
end
|
|
232
|
-
private :md_gate_covers?
|
|
233
231
|
|
|
234
232
|
def refs
|
|
235
233
|
@refs ||= RefsDatabase.load(realpath('refs'))
|
|
@@ -14,13 +14,17 @@ module BitClust
|
|
|
14
14
|
def initialize
|
|
15
15
|
super
|
|
16
16
|
@target = nil
|
|
17
|
+
@library = nil
|
|
17
18
|
@templatedir = srcdir_root + "data/bitclust/template.offline"
|
|
18
19
|
@baseurl = "file://" + srcdir_root.to_s
|
|
19
20
|
@version = RUBY_VERSION
|
|
20
|
-
@parser.banner = "Usage: #{File.basename($0, '.*')} htmlfile [options] rdfile"
|
|
21
|
+
@parser.banner = "Usage: #{File.basename($0, '.*')} htmlfile [options] rdfile|mdfile"
|
|
21
22
|
@parser.on('--target=NAME', 'Compile NAME to HTML.') {|name|
|
|
22
23
|
@target = name
|
|
23
24
|
}
|
|
25
|
+
@parser.on('--library=NAME', 'Library of the Markdown entity file (overrides front matter library:).') {|name|
|
|
26
|
+
@library = name
|
|
27
|
+
}
|
|
24
28
|
@parser.on('--[no-]force', '-f', 'Force to use rd_file template.') {|bool|
|
|
25
29
|
@rd_file = bool
|
|
26
30
|
}
|
|
@@ -47,7 +51,10 @@ module BitClust
|
|
|
47
51
|
end
|
|
48
52
|
@capi = options[:capi]
|
|
49
53
|
target_file = argv[0]
|
|
50
|
-
|
|
54
|
+
if target_file&.end_with?('.md')
|
|
55
|
+
exec_markdown(target_file, options[:prefix] ? db : nil)
|
|
56
|
+
return
|
|
57
|
+
end
|
|
51
58
|
if /refm\/doc\// =~ target_file
|
|
52
59
|
@rd_file = true if @rd_file.nil?
|
|
53
60
|
end
|
|
@@ -89,10 +96,68 @@ module BitClust
|
|
|
89
96
|
|
|
90
97
|
private
|
|
91
98
|
|
|
92
|
-
#
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
99
|
+
# Markdown ソース(manual/ の .md)を変換する。パースは source_format が
|
|
100
|
+
# markdown の dummy DB で行い、描画には real_db があればそれを使う
|
|
101
|
+
def exec_markdown(path, real_db)
|
|
102
|
+
require 'bitclust/mdparser'
|
|
103
|
+
require 'bitclust/markdown_tree'
|
|
104
|
+
props = { 'version' => @version } #: Database::database_properties
|
|
105
|
+
db = MethodDatabase.dummy(props)
|
|
106
|
+
db.properties['source_format'] = 'markdown'
|
|
107
|
+
screen_db = real_db || db
|
|
108
|
+
manager = ScreenManager.new(:templatedir => @templatedir,
|
|
109
|
+
:base_url => @baseurl,
|
|
110
|
+
:cgi_url => @baseurl,
|
|
111
|
+
:default_encoding => 'utf-8')
|
|
112
|
+
@rd_file = true if @rd_file.nil? && %r<(?:\A|/)manual/doc/> =~ path
|
|
113
|
+
if @rd_file
|
|
114
|
+
puts manager.doc_screen(markdown_doc_entry(db, path, props), { :database => screen_db }).body
|
|
115
|
+
elsif @capi
|
|
116
|
+
fdb = FunctionDatabase.dummy(props)
|
|
117
|
+
fdb.properties['source_format'] = 'markdown'
|
|
118
|
+
funcs = MDFunctionParser.new(fdb).parse_file(path, File.basename(path, '.md'), props)
|
|
119
|
+
unless @target
|
|
120
|
+
raise NotImplementedError, "generating a C API html without --target=NAME is not implemented yet."
|
|
121
|
+
end
|
|
122
|
+
puts manager.entry_screen(lookup(funcs, @target), { :database => screen_db, :target_version => @version }).body
|
|
123
|
+
else
|
|
124
|
+
lib = MDParser.new(db).parse_file(path, markdown_libname(db, path), props)
|
|
125
|
+
entry = @target ? lookup(lib, @target) : lib
|
|
126
|
+
puts manager.entry_screen(entry, { :database => screen_db, :target_version => @version }).body
|
|
127
|
+
end
|
|
128
|
+
rescue ParseError, WriterError => ex
|
|
129
|
+
error "#{path}: #{ex.message}"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# manual/doc/ の md を doc ページにする(MethodDatabase#copy_doc_md と同じ手順)
|
|
133
|
+
def markdown_doc_entry(db, path, props)
|
|
134
|
+
rel = path[%r<(?:\A|/)manual/doc/(.+)\.md\z>, 1] || File.basename(path, '.md')
|
|
135
|
+
entry = DocEntry.new(db, NameUtils.libname2id(rel))
|
|
136
|
+
title, source = MDParser.split_doc(Preprocessor.read(path, props))
|
|
137
|
+
entry.title = title
|
|
138
|
+
entry.source = source
|
|
139
|
+
entry.source_location = Location.new(path, 1)
|
|
140
|
+
entry
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# 所属ライブラリ名。--library > ライブラリルート(type: library)の
|
|
144
|
+
# name: またはパス(manual/api/ からの相対、無ければファイル名)>
|
|
145
|
+
# エンティティの library:(この版で生きている先頭の所属)
|
|
146
|
+
def markdown_libname(db, path)
|
|
147
|
+
info = MarkdownTree.file_info(path)
|
|
148
|
+
unless db.md_version_covers?(@version, info[:since], info[:until])
|
|
149
|
+
$stderr.puts "warning: #{path}: front matter の since/until により Ruby #{@version} には含まれないファイルです"
|
|
150
|
+
end
|
|
151
|
+
if (name = @library)
|
|
152
|
+
return name
|
|
153
|
+
end
|
|
154
|
+
if info[:library_file]
|
|
155
|
+
return info[:name] || path[%r<(?:\A|/)api/(.+)\.md\z>, 1] || File.basename(path, '.md')
|
|
156
|
+
end
|
|
157
|
+
memberships = info[:memberships]
|
|
158
|
+
m = memberships.find {|x| db.md_gate_covers?(@version, x) } || memberships.first
|
|
159
|
+
return m[:library] if m
|
|
160
|
+
error "#{path}: front matter に library: がありません。--library=NAME で所属ライブラリを指定してください"
|
|
96
161
|
end
|
|
97
162
|
|
|
98
163
|
def lookup(lib, key)
|
data/lib/bitclust/version.rb
CHANGED
|
@@ -3,7 +3,6 @@ require 'stringio'
|
|
|
3
3
|
require 'tmpdir'
|
|
4
4
|
require 'bitclust'
|
|
5
5
|
require 'bitclust/subcommands/extract_command'
|
|
6
|
-
require 'bitclust/subcommands/htmlfile_command'
|
|
7
6
|
|
|
8
7
|
class TestRdOnlyCommandsRejectMarkdown < Test::Unit::TestCase
|
|
9
8
|
def with_md_file
|
|
@@ -32,14 +31,4 @@ class TestRdOnlyCommandsRejectMarkdown < Test::Unit::TestCase
|
|
|
32
31
|
assert_match(/refm/, msg)
|
|
33
32
|
end
|
|
34
33
|
end
|
|
35
|
-
|
|
36
|
-
def test_htmlfile_explains_markdown_is_unsupported
|
|
37
|
-
with_md_file do |path|
|
|
38
|
-
cmd = BitClust::Subcommands::HtmlfileCommand.new
|
|
39
|
-
cmd.parse([path])
|
|
40
|
-
msg = capture_stderr { assert_raise(SystemExit) { cmd.exec([path], {:prefix => nil, :capi => false}) } }
|
|
41
|
-
assert_match(/Markdown/, msg)
|
|
42
|
-
assert_match(/rake generate|bitclust server/, msg)
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
34
|
end
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'test/unit'
|
|
3
|
+
require 'stringio'
|
|
4
|
+
require 'tmpdir'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
require 'bitclust'
|
|
7
|
+
require 'bitclust/subcommands/htmlfile_command'
|
|
8
|
+
|
|
9
|
+
# htmlfile サブコマンドの Markdown ソース(manual/)の変換。
|
|
10
|
+
#
|
|
11
|
+
# テストリスト:
|
|
12
|
+
# [x] エンティティ md は front matter の library: を所属として変換する
|
|
13
|
+
# [x] library: が多重所属なら、その版で生きている先頭の所属を使う
|
|
14
|
+
# [x] library: が無く --library も無ければエラー
|
|
15
|
+
# [x] --library で所属を指定できる
|
|
16
|
+
# [x] ライブラリルート md(type: library)はファイル名をライブラリ名にする
|
|
17
|
+
# [x] --ruby の版で #%since が解決される
|
|
18
|
+
# [x] manual/doc/ の md は doc ページとして変換する
|
|
19
|
+
# [x] --capi の md は C API として変換する
|
|
20
|
+
# [x] RD ソースは RD として変換する
|
|
21
|
+
class TestHtmlfileCommand < Test::Unit::TestCase
|
|
22
|
+
FOO_MD = <<~'MD'
|
|
23
|
+
---
|
|
24
|
+
library: foo
|
|
25
|
+
---
|
|
26
|
+
# class Foo < Object
|
|
27
|
+
|
|
28
|
+
クラスの説明。
|
|
29
|
+
|
|
30
|
+
## Instance Methods
|
|
31
|
+
|
|
32
|
+
### def bar -> nil
|
|
33
|
+
|
|
34
|
+
bar の **説明**。
|
|
35
|
+
|
|
36
|
+
#%since 3.4
|
|
37
|
+
### def baz -> nil
|
|
38
|
+
|
|
39
|
+
baz の説明。
|
|
40
|
+
#%end
|
|
41
|
+
MD
|
|
42
|
+
|
|
43
|
+
def setup
|
|
44
|
+
@tmpdir = Dir.mktmpdir
|
|
45
|
+
@api = File.join(@tmpdir, 'manual', 'api')
|
|
46
|
+
FileUtils.mkdir_p(File.join(@api, 'foo'))
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def teardown
|
|
50
|
+
FileUtils.rm_rf(@tmpdir)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def write(rel, content)
|
|
54
|
+
path = File.join(@tmpdir, rel)
|
|
55
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
56
|
+
File.write(path, content)
|
|
57
|
+
path
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def run_htmlfile(args, capi: false)
|
|
61
|
+
cmd = BitClust::Subcommands::HtmlfileCommand.new
|
|
62
|
+
argv = args.dup
|
|
63
|
+
cmd.parse(argv)
|
|
64
|
+
out = StringIO.new
|
|
65
|
+
err = StringIO.new
|
|
66
|
+
orig_out, orig_err = $stdout, $stderr
|
|
67
|
+
$stdout, $stderr = out, err
|
|
68
|
+
status = nil
|
|
69
|
+
begin
|
|
70
|
+
cmd.exec(argv, {:prefix => nil, :capi => capi})
|
|
71
|
+
rescue SystemExit => e
|
|
72
|
+
status = e.status
|
|
73
|
+
ensure
|
|
74
|
+
$stdout, $stderr = orig_out, orig_err
|
|
75
|
+
end
|
|
76
|
+
[out.string, err.string, status]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def test_entity_uses_library_in_front_matter
|
|
80
|
+
path = write('manual/api/foo/Foo.md', FOO_MD)
|
|
81
|
+
out, _err, status = run_htmlfile(['--ruby=3.4', '--target=Foo', path])
|
|
82
|
+
assert_nil(status)
|
|
83
|
+
assert_match(/class Foo/, out)
|
|
84
|
+
assert_match(%r{library/foo">library foo<}, out)
|
|
85
|
+
assert_match(%r{<strong>説明</strong>}, out)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_entity_uses_first_live_membership
|
|
89
|
+
path = write('manual/api/foo/Foo.md', <<~'MD')
|
|
90
|
+
---
|
|
91
|
+
library:
|
|
92
|
+
#%until 3.4
|
|
93
|
+
- old_foo
|
|
94
|
+
#%end
|
|
95
|
+
- foo
|
|
96
|
+
- foo_ext
|
|
97
|
+
---
|
|
98
|
+
# class Foo < Object
|
|
99
|
+
|
|
100
|
+
クラスの説明。
|
|
101
|
+
MD
|
|
102
|
+
out, _err, status = run_htmlfile(['--ruby=3.4', '--target=Foo', path])
|
|
103
|
+
assert_nil(status)
|
|
104
|
+
assert_match(%r{library/foo">library foo<}, out)
|
|
105
|
+
out, _err, _status = run_htmlfile(['--ruby=3.3', '--target=Foo', path])
|
|
106
|
+
assert_match(%r{library/old_foo">library old_foo<}, out)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_entity_without_library_is_error
|
|
110
|
+
path = write('manual/api/foo/Foo.md', FOO_MD.sub(/\A---\nlibrary: foo\n---\n/, ''))
|
|
111
|
+
out, err, status = run_htmlfile(['--target=Foo', path])
|
|
112
|
+
assert_equal(1, status)
|
|
113
|
+
assert_equal('', out)
|
|
114
|
+
assert_match(/library:/, err)
|
|
115
|
+
assert_match(/--library/, err)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def test_library_option_gives_library
|
|
119
|
+
path = write('manual/api/foo/Foo.md', FOO_MD.sub(/\A---\nlibrary: foo\n---\n/, ''))
|
|
120
|
+
out, _err, status = run_htmlfile(['--library=bar', '--target=Foo', path])
|
|
121
|
+
assert_nil(status)
|
|
122
|
+
assert_match(%r{library/bar">library bar<}, out)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def test_library_root_uses_file_name
|
|
126
|
+
write('manual/api/foo/Foo.md', FOO_MD)
|
|
127
|
+
path = write('manual/api/net/foo.md', <<~'MD')
|
|
128
|
+
---
|
|
129
|
+
type: library
|
|
130
|
+
category: Network
|
|
131
|
+
---
|
|
132
|
+
foo ライブラリの **説明**。
|
|
133
|
+
MD
|
|
134
|
+
out, _err, status = run_htmlfile([path])
|
|
135
|
+
assert_nil(status)
|
|
136
|
+
assert_match(%r{<h1>library net/foo</h1>}, out)
|
|
137
|
+
assert_match(%r{<strong>説明</strong>}, out)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def test_builtin_library_root
|
|
141
|
+
path = write('manual/api/_builtin.md', "---\ntype: library\n---\n組み込みライブラリ。\n")
|
|
142
|
+
out, _err, status = run_htmlfile([path])
|
|
143
|
+
assert_nil(status)
|
|
144
|
+
assert_match(%r{<title>library _builtin }, out)
|
|
145
|
+
assert_match(/組み込みライブラリ。/, out)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def test_ruby_version_resolves_gates
|
|
149
|
+
path = write('manual/api/foo/Foo.md', FOO_MD)
|
|
150
|
+
out, _err, _status = run_htmlfile(['--ruby=3.4', '--target=Foo', path])
|
|
151
|
+
assert_match(/baz/, out)
|
|
152
|
+
out, _err, _status = run_htmlfile(['--ruby=3.3', '--target=Foo', path])
|
|
153
|
+
assert_match(/bar/, out)
|
|
154
|
+
assert_not_match(/baz/, out)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def test_target_method
|
|
158
|
+
path = write('manual/api/foo/Foo.md', FOO_MD)
|
|
159
|
+
out, _err, status = run_htmlfile(['--ruby=3.4', '--target=Foo#bar', path])
|
|
160
|
+
assert_nil(status)
|
|
161
|
+
assert_match(/bar の <strong>説明<\/strong>/, out)
|
|
162
|
+
assert_not_match(/baz の説明/, out)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def test_doc_page
|
|
166
|
+
path = write('manual/doc/spec/foo.md', <<~'MD')
|
|
167
|
+
# Foo の仕様
|
|
168
|
+
|
|
169
|
+
本文の **強調**。
|
|
170
|
+
MD
|
|
171
|
+
out, _err, status = run_htmlfile([path])
|
|
172
|
+
assert_nil(status)
|
|
173
|
+
assert_match(/Foo の仕様/, out)
|
|
174
|
+
assert_match(%r{本文の <strong>強調</strong>}, out)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def test_capi
|
|
178
|
+
path = write('manual/capi/array.c.md', <<~'MD')
|
|
179
|
+
### VALUE rb_foo_new()
|
|
180
|
+
|
|
181
|
+
空の **Foo** を作ります。
|
|
182
|
+
|
|
183
|
+
### VALUE rb_foo_bar(VALUE foo)
|
|
184
|
+
|
|
185
|
+
bar を返します。
|
|
186
|
+
MD
|
|
187
|
+
out, _err, status = run_htmlfile(['--target=rb_foo_new', path], capi: true)
|
|
188
|
+
assert_nil(status)
|
|
189
|
+
assert_match(/rb_foo_new/, out)
|
|
190
|
+
assert_match(%r{空の <strong>Foo</strong> を作ります。}, out)
|
|
191
|
+
assert_not_match(/bar を返します/, out)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def test_rd_source
|
|
195
|
+
path = write('refm/api/src/foo.rd', <<~'RD')
|
|
196
|
+
= class Foo < Object
|
|
197
|
+
|
|
198
|
+
クラスの説明。
|
|
199
|
+
|
|
200
|
+
== Instance Methods
|
|
201
|
+
|
|
202
|
+
--- bar -> nil
|
|
203
|
+
|
|
204
|
+
bar の説明。
|
|
205
|
+
RD
|
|
206
|
+
out, _err, status = run_htmlfile(['--target=Foo', path])
|
|
207
|
+
assert_nil(status)
|
|
208
|
+
assert_match(/class Foo/, out)
|
|
209
|
+
assert_match(/bar の説明。/, out)
|
|
210
|
+
end
|
|
211
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bitclust-core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- https://github.com/rurema
|
|
@@ -347,6 +347,7 @@ files:
|
|
|
347
347
|
- test/test_extract_command.rb
|
|
348
348
|
- test/test_functiondatabase.rb
|
|
349
349
|
- test/test_functionreferenceparser.rb
|
|
350
|
+
- test/test_htmlfile_command.rb
|
|
350
351
|
- test/test_include_graph.rb
|
|
351
352
|
- test/test_include_pruner.rb
|
|
352
353
|
- test/test_irb_plugin.rb
|
|
@@ -455,6 +456,7 @@ test_files:
|
|
|
455
456
|
- test/test_extract_command.rb
|
|
456
457
|
- test/test_functiondatabase.rb
|
|
457
458
|
- test/test_functionreferenceparser.rb
|
|
459
|
+
- test/test_htmlfile_command.rb
|
|
458
460
|
- test/test_include_graph.rb
|
|
459
461
|
- test/test_include_pruner.rb
|
|
460
462
|
- test/test_irb_plugin.rb
|