bitclust-core 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/data/bitclust/template.lillia/class +4 -1
  3. data/data/bitclust/template.lillia/class-index +4 -1
  4. data/data/bitclust/template.lillia/doc +4 -1
  5. data/data/bitclust/template.lillia/layout +2 -0
  6. data/data/bitclust/template.lillia/library +4 -1
  7. data/data/bitclust/template.lillia/library-index +4 -1
  8. data/data/bitclust/template.lillia/method +2 -1
  9. data/data/bitclust/template.offline/class +4 -1
  10. data/data/bitclust/template.offline/class-index +4 -1
  11. data/data/bitclust/template.offline/doc +4 -1
  12. data/data/bitclust/template.offline/function +1 -0
  13. data/data/bitclust/template.offline/function-index +4 -1
  14. data/data/bitclust/template.offline/layout +3 -0
  15. data/data/bitclust/template.offline/library +4 -1
  16. data/data/bitclust/template.offline/library-index +4 -1
  17. data/data/bitclust/template.offline/method +1 -0
  18. data/data/bitclust/template/class +4 -1
  19. data/data/bitclust/template/class-index +4 -1
  20. data/data/bitclust/template/doc +4 -1
  21. data/data/bitclust/template/function +4 -1
  22. data/data/bitclust/template/layout +3 -0
  23. data/data/bitclust/template/library +4 -1
  24. data/data/bitclust/template/library-index +4 -1
  25. data/data/bitclust/template/method +1 -0
  26. data/lib/bitclust/classentry.rb +4 -0
  27. data/lib/bitclust/docentry.rb +4 -1
  28. data/lib/bitclust/functionentry.rb +3 -1
  29. data/lib/bitclust/libraryentry.rb +5 -3
  30. data/lib/bitclust/methodentry.rb +3 -1
  31. data/lib/bitclust/preprocessor.rb +74 -14
  32. data/lib/bitclust/rdcompiler.rb +35 -15
  33. data/lib/bitclust/screen.rb +12 -1
  34. data/lib/bitclust/subcommands/preproc_command.rb +1 -1
  35. data/lib/bitclust/subcommands/statichtml_command.rb +12 -1
  36. data/lib/bitclust/syntax_highlighter.rb +318 -0
  37. data/lib/bitclust/version.rb +1 -1
  38. data/test/test_preprocessor.rb +209 -1
  39. data/test/test_rdcompiler.rb +79 -0
  40. data/theme/default/style.css +12 -0
  41. data/theme/default/syntax-highlight.css +209 -0
  42. metadata +5 -3
@@ -11,6 +11,8 @@ require 'bitclust/methodsignature'
11
11
  require 'bitclust/lineinput'
12
12
  require 'bitclust/htmlutils'
13
13
  require 'bitclust/textutils'
14
+ require 'bitclust/messagecatalog'
15
+ require 'bitclust/syntax_highlighter'
14
16
  require 'stringio'
15
17
 
16
18
  module BitClust
@@ -20,6 +22,7 @@ module BitClust
20
22
 
21
23
  include HTMLUtils
22
24
  include TextUtils
25
+ include Translatable
23
26
 
24
27
  def initialize(urlmapper, hlevel = 1, opt = {})
25
28
  @urlmapper = urlmapper
@@ -30,6 +33,7 @@ module BitClust
30
33
  @class = nil
31
34
  @method = nil
32
35
  @option = opt.dup
36
+ init_message_catalog(@catalog)
33
37
  end
34
38
 
35
39
  def compile(src)
@@ -80,7 +84,7 @@ module BitClust
80
84
  @item_stack = []
81
85
  item_list($1.size)
82
86
  raise "@item_stack should be empty. #{@item_stack.inspect}" unless @item_stack.empty?
83
- when %r<\A//emlist\{>
87
+ when %r<\A//emlist(?:\[(?:[^\[\]]+?)?\]\[\w+?\])?\{>
84
88
  emlist
85
89
  when /\A:\s/
86
90
  dlist
@@ -133,7 +137,7 @@ module BitClust
133
137
  raise "@item_stack should be empty. #{@item_stack.inspect}" unless @item_stack.empty?
134
138
  when /\A:\s/
135
139
  dlist
136
- when %r<\A//emlist\{>
140
+ when %r<\A//emlist(?:\[(?:[^\[\]]+?)?\]\[\w+?\])?\{>
137
141
  emlist
138
142
  when /\A\s+\S/
139
143
  list
@@ -221,7 +225,7 @@ module BitClust
221
225
  # empty lines separate paragraphs.
222
226
  def dd_with_p
223
227
  line '<dd>'
224
- while /\A(?:\s|\z)/ =~ @f.peek or %r!\A//emlist\{! =~ @f.peek
228
+ while /\A(?:\s|\z)/ =~ @f.peek or %r!\A//emlist(?:\[(?:[^\[\]]+?)?\]\[\w+?\])?\{! =~ @f.peek
225
229
  case @f.peek
226
230
  when /\A$/
227
231
  @f.gets
@@ -231,8 +235,8 @@ module BitClust
231
235
  line compile_text(line.strip)
232
236
  end
233
237
  line '</p>'
234
- when %r!\A//emlist\{!
235
- emlist
238
+ when %r!\A//emlist(?:\[(?:[^\[\]]+?)?\]\[\w+?\])?\{!
239
+ emlist
236
240
  else
237
241
  raise 'must not happen'
238
242
  end
@@ -243,14 +247,14 @@ module BitClust
243
247
  # empty lines do not separate paragraphs.
244
248
  def dd_without_p
245
249
  line '<dd>'
246
- while /\A[ \t]/ =~ @f.peek or %r!\A//emlist\{! =~ @f.peek
250
+ while /\A[ \t]/ =~ @f.peek or %r!\A//emlist(?:\[(?:[^\[\]]+?)?\]\[\w+?\])?\{! =~ @f.peek
247
251
  case @f.peek
248
252
  when /\A[ \t\z]/
249
253
  @f.while_match(/\A[ \t\z]/) do |line|
250
254
  line compile_text(line.strip)
251
255
  end
252
- when %r!\A//emlist\{!
253
- emlist
256
+ when %r!\A//emlist(?:\[(?:[^\[\]]+?)?\]\[\w+?\])?\{!
257
+ emlist
254
258
  end
255
259
  end
256
260
  line '</dd>'
@@ -261,12 +265,28 @@ module BitClust
261
265
  end
262
266
 
263
267
  def emlist
264
- @f.gets # discard "//emlist{"
265
- line '<pre>'
266
- @f.until_terminator(%r<\A//\}>) do |line|
267
- line escape_html(line.rstrip)
268
+ command = @f.gets
269
+ if %r!\A//emlist\[(?<caption>[^\[\]]+?)?\]\[(?<lang>\w+?)\]! =~ command
270
+ line "<pre class=\"highlight #{lang}\">"
271
+ line "<span class=\"caption\">#{escape_html(caption)}</span>" if caption
272
+ line "<code>"
273
+ src = ""
274
+ @f.until_terminator(%r<\A//\}>) do |line|
275
+ src << line
276
+ end
277
+ if lang == "ruby"
278
+ string BitClust::SyntaxHighlighter.new(src).highlight
279
+ else
280
+ string src
281
+ end
282
+ line '</code></pre>'
283
+ else
284
+ line '<pre>'
285
+ @f.until_terminator(%r<\A//\}>) do |line|
286
+ line escape_html(line.rstrip)
287
+ end
288
+ line '</pre>'
268
289
  end
269
- line '</pre>'
270
290
  end
271
291
 
272
292
  def list
@@ -294,7 +314,7 @@ module BitClust
294
314
  end
295
315
 
296
316
  def read_paragraph(f)
297
- f.span(%r<\A(?!---|=|//emlist\{)\S>)
317
+ f.span(%r<\A(?!---|=|//emlist(?:\[(?:[^\[\]]+?)?\]\[\w+?\])?\{)\S>)
298
318
  end
299
319
 
300
320
  def see
@@ -349,7 +369,7 @@ module BitClust
349
369
  end
350
370
 
351
371
  def read_entry_paragraph(f)
352
- f.span(%r<\A(?!---|=|//emlist\{|@[a-z])\S>)
372
+ f.span(%r<\A(?!---|=|//emlist(?:\[(?:[^\[\]]+?)?\]\[\w+?\])?\{|@[a-z])\S>)
353
373
  end
354
374
 
355
375
  def method_signature(sig_line, first)
@@ -285,7 +285,7 @@ module BitClust
285
285
 
286
286
  def google_tag_manager
287
287
  tracking_id = @conf[:gtm_tracking_id]
288
- return "" unless tracking_id
288
+ return "\b" unless tracking_id
289
289
  <<-HTML.chomp
290
290
  <!-- Global Site Tag (gtag.js) - Google Analytics -->
291
291
  <script async src="https://www.googletagmanager.com/gtag/js?id=#{tracking_id}"></script>
@@ -299,6 +299,17 @@ module BitClust
299
299
  HTML
300
300
  end
301
301
 
302
+ def meta_robots
303
+ content = @conf[:meta_robots_content]
304
+ return "\b" unless content
305
+ return "\b" if content.empty?
306
+ %Q(<meta name="robots" content="#{content.join(',')}">)
307
+ end
308
+
309
+ def meta_description
310
+ %Q(<meta name="description" content="">)
311
+ end
312
+
302
313
  private
303
314
 
304
315
  def default_encoding
@@ -13,7 +13,7 @@ module BitClust
13
13
  @parser.banner = "Usage: #{File.basename($0, '.*')} <file>..."
14
14
  @parser.on('--param=KVPAIR', 'Set parameter by key/value pair.') {|pair|
15
15
  key, value = pair.split('=', 2)
16
- params[key] = value
16
+ @params[key] = value
17
17
  }
18
18
  end
19
19
 
@@ -63,6 +63,10 @@ module BitClust
63
63
  @bitclust_html_base + "/" + @css_url
64
64
  end
65
65
 
66
+ def custom_css_url(filename)
67
+ @bitclust_html_base + "/" + filename
68
+ end
69
+
66
70
  def favicon_url
67
71
  @bitclust_html_base + "/" + @favicon_url
68
72
  end
@@ -99,6 +103,7 @@ module BitClust
99
103
  @themedir = srcdir_root + "theme/default"
100
104
  @suffix = ".html"
101
105
  @gtm_tracking_id = nil
106
+ @meta_robots_content = ["noindex"]
102
107
  @parser.banner = "Usage: #{File.basename($0, '.*')} statichtml [options]"
103
108
  @parser.on('-o', '--outputdir=PATH', 'Output directory') do |path|
104
109
  begin
@@ -129,6 +134,9 @@ module BitClust
129
134
  @parser.on('--tracking-id=ID', 'Google Tag Manager Tracking ID') do |id|
130
135
  @gtm_tracking_id = id
131
136
  end
137
+ @parser.on('--meta-robots-content=VALUE1,VALUE2,...', Array, 'HTML <meta> element: <meta name="robots" content="VALUE1,VALUE2..."') do |values|
138
+ @meta_robots_content = values
139
+ end
132
140
  @parser.on('--[no-]quiet', 'Be quiet') do |quiet|
133
141
  @verbose = !quiet
134
142
  end
@@ -174,6 +182,8 @@ module BitClust
174
182
  create_index_html(@outputdir)
175
183
  FileUtils.cp(@manager_config[:themedir] + @manager_config[:css_url],
176
184
  @outputdir.to_s, {:verbose => @verbose, :preserve => true})
185
+ FileUtils.cp(@manager_config[:themedir] + "syntax-highlight.css",
186
+ @outputdir.to_s, {:verbose => @verbose, :preserve => true})
177
187
  FileUtils.cp(@manager_config[:themedir] + @manager_config[:favicon_url],
178
188
  @outputdir.to_s, {:verbose => @verbose, :preserve => true})
179
189
  Dir.mktmpdir do |tmpdir|
@@ -201,7 +211,8 @@ module BitClust
201
211
  :tochm_mode => true,
202
212
  :fs_casesensitive => @fs_casesensitive,
203
213
  :canonical_base_url => @canonical_base_url,
204
- :gtm_tracking_id => @gtm_tracking_id
214
+ :gtm_tracking_id => @gtm_tracking_id,
215
+ :meta_robots_content => @meta_robots_content,
205
216
  }
206
217
  @manager_config[:urlmapper] = URLMapperEx.new(@manager_config)
207
218
  @urlmapper = @manager_config[:urlmapper]
@@ -0,0 +1,318 @@
1
+ require "ripper"
2
+ require "bitclust/htmlutils"
3
+
4
+ module BitClust
5
+ class SyntaxHighlighter < Ripper::Filter
6
+ include BitClust::HTMLUtils
7
+
8
+ COLORS = {
9
+ CHAR: "sc", # ?a
10
+ __end__: "k", # __END__
11
+ backref: "vg", # $` $& $' $1 ...
12
+ backtick: "sb", # `
13
+ comma: nil, # ,
14
+ comment: "c1", # #...
15
+ const: "no", # Const
16
+ cvar: "vc", # @@var
17
+ embdoc: nil, # (=begin) document (=end)
18
+ embdoc_beg: "cm", # =begin
19
+ embdoc_end: nil, # =end
20
+ embexpr_beg: "si", # #{
21
+ embexpr_end: "si", # (#{) }
22
+ embvar: "n", # ("...) # (var")
23
+ float: "mf", # 1.23 (float)
24
+ gvar: "vg", # $var
25
+ heredoc_beg: "no", # <<EOS
26
+ heredoc_end: "no", # EOS
27
+ ident: nil, # identifier
28
+ ignored_nl: nil, # ignored \n
29
+ int: "mi", # 1 (integer)
30
+ ivar: "vi", # @var
31
+ kw: "k", # keyword
32
+ label: "ss", # label:
33
+ lbrace: "p", # {
34
+ lbracket: "p", # [
35
+ lparen: "p", # (
36
+ nl: nil, # \n
37
+ op: "o", # operator
38
+ period: "p", # .
39
+ qwords_beg: "sx", # %w(
40
+ rbrace: "p", # }
41
+ rbracket: "p", # ]
42
+ regexp_beg: "sr", # / (regexp/)
43
+ regexp_end: nil, # (/regexp) /
44
+ rparen: "p", # )
45
+ semicolon: nil, # ;
46
+ sp: nil, # space
47
+ symbeg: "ss", # :
48
+ tlambda: "o", # ->
49
+ tlambeg: "p", # (->) {
50
+ tstring_beg: nil, # " (string")
51
+ tstring_content: nil, # (") string (")
52
+ tstring_end: nil, # ("string) "
53
+ words_beg: "sx", # %W(
54
+ words_sep: nil # (%W() )
55
+ }
56
+ LABELS = {
57
+ }
58
+
59
+ KEYWORDS = %w[
60
+ BEGIN END alias begin break case defined\? do else elsif end
61
+ ensure for if in next redo rescue raise retry return super then
62
+ undef unless until when while yield
63
+ ]
64
+
65
+ KEYWORDS_PSEUDO = %w[
66
+ loop include extend raise
67
+ alias_method attr catch throw private module_function
68
+ public protected true false nil __FILE__ __LINE__
69
+ ]
70
+
71
+ BUILTINS_G = %w[
72
+ attr_reader attr_writer attr_accessor
73
+
74
+ __id__ __send__ abort ancestors at_exit autoload binding callcc
75
+ caller catch chomp chop class_eval class_variables clone
76
+ const_defined\? const_get const_missing const_set constants
77
+ display dup eval exec exit extend fail fork format freeze
78
+ getc gets global_variables gsub hash id included_modules
79
+ inspect instance_eval instance_method instance_methods
80
+ instance_variable_get instance_variable_set instance_variables
81
+ lambda load local_variables loop method method_missing
82
+ methods module_eval name object_id open p print printf
83
+ private_class_method private_instance_methods private_methods proc
84
+ protected_instance_methods protected_methods public_class_method
85
+ public_instance_methods public_methods putc puts raise rand
86
+ readline readlines require require_relative scan select self send set_trace_func
87
+ singleton_methods sleep split sprintf srand sub syscall system
88
+ taint test throw to_a to_s trace_var trap untaint untrace_var warn
89
+ ]
90
+
91
+ BUILTINS_Q = %w[
92
+ autoload block_given const_defined eql equal frozen
93
+ include instance_of is_a iterator kind_of method_defined
94
+ nil private_method_defined protected_method_defined
95
+ public_method_defined respond_to tainted
96
+ ]
97
+
98
+ BUILTINS_B = %w[chomp chop exit gsub sub]
99
+
100
+ def initialize(*args)
101
+ super
102
+ @stack = []
103
+ @name_buffer = []
104
+ end
105
+
106
+ def on_default(event, token, data)
107
+ event_name = event.to_s.sub(/\Aon_/, "") # :on_event --> "event"
108
+ style = COLORS[event_name.to_sym]
109
+ data << (style ? "<span class=\"#{style}\">#{escape_html(token)}</span>" : token)
110
+ data
111
+ end
112
+
113
+ def on_embdoc_beg(token, data)
114
+ style = COLORS[:embdoc_beg]
115
+ data << "<span class=\"#{style}\">#{token}"
116
+ data
117
+ end
118
+
119
+ def on_embdoc_end(token, data)
120
+ data << "#{token}</span>"
121
+ data
122
+ end
123
+
124
+ def on_ident(token, data)
125
+ case
126
+ when @stack.last == :symbol
127
+ data << "#{token}</span>"
128
+ @stack.pop
129
+ when @stack.last == :def
130
+ @stack.pop
131
+ data << "<span class=\"nf\">#{token}</span>"
132
+ when @stack.last == :embexpr
133
+ data << "<span class=\"n\">#{token}</span>"
134
+ when @stack.last == :heredoc
135
+ style = COLORS[:heredoc_beg]
136
+ data << "<span class=\"#{style}\">#{token}"
137
+ when @stack.last == :method_call
138
+ data << "<span class=\"nf\">#{token}</span>"
139
+ @stack.pop
140
+ when BUILTINS_G.include?(token)
141
+ data << "<span class=\"nb\">#{token}</span>"
142
+ else
143
+ data << token
144
+ end
145
+ data
146
+ end
147
+
148
+ def on_const(token, data)
149
+ case
150
+ when @stack.last == :class
151
+ @name_buffer << token
152
+ when @stack.last == :module
153
+ @name_buffer << token
154
+ else
155
+ on_default(:on_const, token, data)
156
+ end
157
+ data
158
+ end
159
+
160
+ def on_kw(token, data)
161
+ case
162
+ when @stack.last == :symbol
163
+ data << "#{token}</span>"
164
+ @stack.pop
165
+ when token == "module"
166
+ @stack.push(:module)
167
+ on_default(:on_kw, token, data)
168
+ when token == "class"
169
+ @stack.push(:class)
170
+ on_default(:on_kw, token, data)
171
+ when token == "def"
172
+ @stack.push(:def)
173
+ on_default(:on_kw, token, data)
174
+ when token == "self"
175
+ data << "<span class=\"nc\">#{token}</span>"
176
+ else
177
+ on_default(:on_kw, token, data)
178
+ end
179
+ data
180
+ end
181
+
182
+ def on_period(token, data)
183
+ @stack.push(:method_call)
184
+ on_default(:on_period, token, data)
185
+ end
186
+
187
+ def on_op(token, data)
188
+ case
189
+ when token == "::" && [:class, :module].include?(@stack.last)
190
+ @name_buffer << token
191
+ else
192
+ on_default(:on_op, token, data)
193
+ end
194
+ data
195
+ end
196
+
197
+ def on_sp(token, data)
198
+ case
199
+ when @name_buffer.empty?
200
+ return on_default(:on_sp, token, data)
201
+ when @stack.last == :module
202
+ name = @name_buffer.join
203
+ data << "<span class=\"nn\">#{name}</span>"
204
+ @stack.pop
205
+ @name_buffer.clear
206
+ when @stack.last == :class
207
+ namespace = @name_buffer.values_at(0..-3).join
208
+ operator = @name_buffer[-2]
209
+ name = @name_buffer.last
210
+ data << "<span class=\"nn\">#{namespace}</span>"
211
+ data << "<span class=\"o\">#{operator}</span>"
212
+ data << "<span class=\"nc\">#{name}</span>"
213
+ @stack.pop
214
+ @name_buffer.clear
215
+ end
216
+ on_default(:on_sp, token, data)
217
+ end
218
+
219
+ def on_nl(token, data)
220
+ case
221
+ when @name_buffer.empty?
222
+ return on_default(:on_nl, token, data)
223
+ when @stack.last == :module
224
+ name = @name_buffer.join
225
+ data << "<span class=\"nn\">#{name}</span>"
226
+ @stack.pop
227
+ @name_buffer.clear
228
+ when @stack.last == :class
229
+ namespace = @name_buffer.values_at(0..-3).join
230
+ operator = @name_buffer[-2]
231
+ name = @name_buffer.last
232
+ data << "<span class=\"nn\">#{namespace}</span>"
233
+ data << "<span class=\"o\">#{operator}</span>"
234
+ data << "<span class=\"nc\">#{name}</span>"
235
+ @stack.pop
236
+ @name_buffer.clear
237
+ end
238
+ on_default(:on_nl, token, data)
239
+ end
240
+
241
+ def on_regexp_beg(token, data)
242
+ style = COLORS[:regexp_beg]
243
+ data << "<span class=\"#{style}\">#{token}"
244
+ data
245
+ end
246
+
247
+ def on_regexp_end(token, data)
248
+ data << "#{token}</span>"
249
+ data
250
+ end
251
+
252
+ def on_symbeg(token, data)
253
+ style = COLORS[:symbeg]
254
+ data << "<span class=\"#{style}\">#{token}"
255
+ @stack << :symbol
256
+ data
257
+ end
258
+
259
+ def on_tstring_beg(token, data)
260
+ if token == "'"
261
+ data << "<span class=\"s1\">#{token}"
262
+ @stack << :string1
263
+ else
264
+ data << "<span class=\"s2\">#{token}</span>"
265
+ @stack << :string2
266
+ end
267
+ data
268
+ end
269
+
270
+ def on_tstring_content(token, data)
271
+ case
272
+ when @stack.last == :heredoc
273
+ data << "<span class=\"sh\">#{escape_html(token)}</span>"
274
+ when @stack.last == :string1
275
+ data << escape_html(token)
276
+ when @stack.last == :string2
277
+ data << "<span class=\"s2\">#{escape_html(token)}</span>"
278
+ else
279
+ on_default(:on_tstring_content, token, data)
280
+ end
281
+ data
282
+ end
283
+
284
+ def on_tstring_end(token, data)
285
+ if token == "'"
286
+ data << "#{token}</span>"
287
+ else
288
+ data << "<span class=\"s2\">#{token}</span>"
289
+ end
290
+ @stack.pop
291
+ data
292
+ end
293
+
294
+ def on_heredoc_beg(token, data)
295
+ @stack.push(:heredoc)
296
+ on_default(:on_heredoc_beg, token, data)
297
+ end
298
+
299
+ def on_heredoc_end(token, data)
300
+ @stack.pop
301
+ on_default(:on_heredoc_end, token, data)
302
+ end
303
+
304
+ def on_embexpr_beg(token, data)
305
+ @stack.push(:embexpr)
306
+ on_default(:on_embexpr_beg, token, data)
307
+ end
308
+
309
+ def on_embexpr_end(token, data)
310
+ @stack.pop
311
+ on_default(:on_embexpr_end, token, data)
312
+ end
313
+
314
+ def highlight
315
+ parse("")
316
+ end
317
+ end
318
+ end