aozora2html 2.0.0 → 3.0.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.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rubocop.yml +19 -0
  3. data/.github/workflows/ruby.yml +4 -1
  4. data/.rubocop.yml +36 -152
  5. data/.rubocop_todo.yml +7 -0
  6. data/CHANGELOG.md +26 -0
  7. data/Gemfile +2 -0
  8. data/Guardfile +3 -1
  9. data/HACKING.md +45 -0
  10. data/README.md +14 -6
  11. data/Rakefile +12 -5
  12. data/aozora2html.gemspec +24 -22
  13. data/bin/aozora2html +21 -19
  14. data/lib/aozora2html/accent_parser.rb +62 -54
  15. data/lib/aozora2html/error.rb +5 -4
  16. data/lib/aozora2html/header.rb +20 -18
  17. data/lib/aozora2html/i18n.rb +40 -20
  18. data/lib/aozora2html/ruby_buffer.rb +63 -28
  19. data/lib/aozora2html/string_refinements.rb +36 -0
  20. data/lib/aozora2html/style_stack.rb +6 -0
  21. data/lib/aozora2html/tag/accent.rb +10 -12
  22. data/lib/aozora2html/tag/block.rb +11 -9
  23. data/lib/aozora2html/tag/chitsuki.rb +6 -2
  24. data/lib/aozora2html/tag/dakuten_katakana.rb +10 -8
  25. data/lib/aozora2html/tag/decorate.rb +4 -3
  26. data/lib/aozora2html/tag/dir.rb +4 -2
  27. data/lib/aozora2html/tag/editor_note.rb +7 -4
  28. data/lib/aozora2html/tag/embed_gaiji.rb +15 -11
  29. data/lib/aozora2html/tag/font_size.rb +5 -2
  30. data/lib/aozora2html/tag/gaiji.rb +4 -3
  31. data/lib/aozora2html/tag/img.rb +4 -4
  32. data/lib/aozora2html/tag/indent.rb +3 -3
  33. data/lib/aozora2html/tag/inline.rb +10 -7
  34. data/lib/aozora2html/tag/inline_caption.rb +4 -2
  35. data/lib/aozora2html/tag/inline_font_size.rb +4 -3
  36. data/lib/aozora2html/tag/inline_keigakomi.rb +4 -2
  37. data/lib/aozora2html/tag/inline_yokogumi.rb +4 -3
  38. data/lib/aozora2html/tag/jisage.rb +3 -1
  39. data/lib/aozora2html/tag/jizume.rb +3 -0
  40. data/lib/aozora2html/tag/kaeriten.rb +4 -2
  41. data/lib/aozora2html/tag/keigakomi.rb +15 -9
  42. data/lib/aozora2html/tag/kunten.rb +4 -4
  43. data/lib/aozora2html/tag/midashi.rb +3 -1
  44. data/lib/aozora2html/tag/multiline.rb +3 -0
  45. data/lib/aozora2html/tag/multiline_caption.rb +6 -8
  46. data/lib/aozora2html/tag/multiline_chitsuki.rb +3 -1
  47. data/lib/aozora2html/tag/multiline_jisage.rb +3 -1
  48. data/lib/aozora2html/tag/multiline_midashi.rb +6 -3
  49. data/lib/aozora2html/tag/multiline_style.rb +5 -3
  50. data/lib/aozora2html/tag/multiline_yokogumi.rb +6 -9
  51. data/lib/aozora2html/tag/okurigana.rb +4 -2
  52. data/lib/aozora2html/tag/oneline_chitsuki.rb +3 -2
  53. data/lib/aozora2html/tag/oneline_indent.rb +8 -1
  54. data/lib/aozora2html/tag/oneline_jisage.rb +3 -0
  55. data/lib/aozora2html/tag/reference_mentioned.rb +22 -21
  56. data/lib/aozora2html/tag/ruby.rb +174 -70
  57. data/lib/aozora2html/tag/un_embed_gaiji.rb +8 -2
  58. data/lib/aozora2html/tag.rb +40 -38
  59. data/lib/aozora2html/tag_parser.rb +23 -16
  60. data/lib/aozora2html/text_buffer.rb +50 -0
  61. data/lib/aozora2html/utils.rb +113 -50
  62. data/lib/aozora2html/version.rb +3 -1
  63. data/lib/aozora2html/yaml_loader.rb +8 -2
  64. data/lib/aozora2html/zip.rb +4 -0
  65. data/lib/aozora2html.rb +1358 -3
  66. data/lib/extensions.rb +2 -34
  67. data/lib/jstream.rb +96 -25
  68. data/sample/chukiichiran_kinyurei.html +15 -2
  69. data/sample/chukiichiran_kinyurei.txt +15 -2
  70. data/test/test_aozora2html.rb +137 -148
  71. data/test/test_aozora_accent_parser.rb +26 -9
  72. data/test/test_command_parse.rb +25 -22
  73. data/test/test_compat.rb +3 -4
  74. data/test/test_dakuten_katakana_tag.rb +10 -12
  75. data/test/test_decorate_tag.rb +9 -6
  76. data/test/test_dir_tag.rb +9 -6
  77. data/test/test_editor_note_tag.rb +8 -5
  78. data/test/test_exception.rb +10 -8
  79. data/test/test_font_size_tag.rb +16 -13
  80. data/test/test_gaiji_tag.rb +15 -14
  81. data/test/test_header.rb +25 -40
  82. data/test/test_helper.rb +3 -1
  83. data/test/test_i18n.rb +22 -6
  84. data/test/test_img_tag.rb +9 -5
  85. data/test/test_inline_caption_tag.rb +9 -6
  86. data/test/test_inline_font_size_tag.rb +13 -10
  87. data/test/test_inline_keigakomi_tag.rb +9 -6
  88. data/test/test_inline_yokogumi_tag.rb +9 -6
  89. data/test/test_jizume_tag.rb +9 -7
  90. data/test/test_jstream.rb +33 -30
  91. data/test/test_kaeriten_tag.rb +9 -6
  92. data/test/test_keigakomi_tag.rb +11 -9
  93. data/test/test_midashi_tag.rb +15 -14
  94. data/test/test_multiline_caption_tag.rb +7 -5
  95. data/test/test_multiline_midashi_tag.rb +24 -25
  96. data/test/test_multiline_style_tag.rb +9 -7
  97. data/test/test_multiline_yokogumi_tag.rb +7 -5
  98. data/test/test_okurigana_tag.rb +9 -6
  99. data/test/test_ruby_parse.rb +14 -14
  100. data/test/test_ruby_tag.rb +9 -6
  101. data/test/test_tag_parser.rb +28 -26
  102. metadata +60 -14
  103. data/.travis.yml +0 -12
  104. data/lib/t2hs.rb +0 -1607
@@ -1,16 +1,18 @@
1
- # encoding: utf-8
2
- require 'aozora2html/ruby_buffer'
3
- class Aozora2Html
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ruby_buffer'
4
4
 
5
+ class Aozora2Html
5
6
  # accent特殊文字を生かすための再帰呼び出し
6
7
  class AccentParser < Aozora2Html
7
-
8
- def initialize(input, endchar, chuuki, image)
9
- if not(input.is_a?(Jstream))
10
- raise ArgumentError, "tag_parser must supply Jstream as input"
8
+ def initialize(input, endchar, chuuki, image, gaiji_dir:) # rubocop:disable Lint/MissingSuper
9
+ unless input.is_a?(Jstream)
10
+ raise ArgumentError, 'tag_parser must supply Jstream as input'
11
11
  end
12
+
12
13
  @stream = input
13
- @buffer = []
14
+ @gaiji_dir = gaiji_dir
15
+ @buffer = Aozora2Html::TextBuffer.new
14
16
  @ruby_buf = Aozora2Html::RubyBuffer.new
15
17
  @chuuki_table = chuuki
16
18
  @images = image # globalな環境を記録するアイテムは共有する必要あり
@@ -19,71 +21,77 @@ class Aozora2Html
19
21
  @encount_accent = nil
20
22
  end
21
23
 
22
- def general_output # 出力は配列で返す
24
+ # 出力は配列で返す
25
+ def general_output
23
26
  @ruby_buf.dump_into(@buffer)
24
- if !@encount_accent
25
- @buffer.unshift("〔".encode("shift_jis"))
27
+ unless @encount_accent
28
+ @buffer.unshift(ACCENT_BEGIN)
26
29
  end
27
- if @closed and !@encount_accent
28
- @buffer.push("〕".encode("shift_jis"))
29
- elsif not(@closed)
30
+ if @closed && !@encount_accent
31
+ @buffer.push(ACCENT_END)
32
+ elsif !@closed
30
33
  @buffer.push("<br />\r\n")
31
34
  end
32
35
  @buffer
33
36
  end
34
37
 
35
38
  def parse
36
- first = read_char
37
- if found = Aozora2Html::ACCENT_TABLE[first]
38
- if found2 = found[@stream.peek_char(0)]
39
- if found2.is_a?(Hash)
40
- if found3 = found2[@stream.peek_char(1)]
41
- first = Aozora2Html::Tag::Accent.new(self, *found3)
39
+ loop do
40
+ first = read_char
41
+
42
+ found = Aozora2Html::ACCENT_TABLE[first]
43
+ if found
44
+ found2 = found[@stream.peek_char(0)]
45
+ if found2
46
+ if found2.is_a?(Hash)
47
+ found3 = found2[@stream.peek_char(1)]
48
+ if found3
49
+ first = Aozora2Html::Tag::Accent.new(self, *found3, gaiji_dir: @gaiji_dir)
50
+ @encount_accent = true
51
+ @chuuki_table[:accent] = true
52
+ read_char
53
+ read_char
54
+ end
55
+ elsif found2
56
+ first = Aozora2Html::Tag::Accent.new(self, *found2, gaiji_dir: @gaiji_dir)
42
57
  @encount_accent = true
43
- @chuuki_table[:accent] = true
44
- read_char
45
58
  read_char
59
+ @chuuki_table[:accent] = true
46
60
  end
47
- elsif found2
48
- first = Aozora2Html::Tag::Accent.new(self, *found2)
49
- @encount_accent = true
50
- read_char
51
- @chuuki_table[:accent] = true
52
61
  end
53
62
  end
54
- end
55
- case first
56
- when Aozora2Html::GAIJI_MARK
57
- first = dispatch_gaiji
58
- when "[".encode("shift_jis")
59
- first = dispatch_aozora_command
60
- when Aozora2Html::KU
61
- assign_kunoji
62
- when "《".encode("shift_jis")
63
- first = apply_ruby
64
- end
65
- if first == "\r\n"
66
- if @encount_accent
67
- puts "警告(#{line_number}行目):アクセント分解の亀甲括弧の始めと終わりが、行中で揃っていません".encode("shift_jis")
63
+
64
+ case first
65
+ when Aozora2Html::GAIJI_MARK
66
+ first = dispatch_gaiji
67
+ when COMMAND_BEGIN
68
+ first = dispatch_aozora_command
69
+ when Aozora2Html::KU
70
+ assign_kunoji
71
+ when RUBY_BEGIN_MARK
72
+ first = apply_ruby
73
+ end
74
+ if first == "\r\n"
75
+ if @encount_accent
76
+ puts I18n.t(:warn_invalid_accent_brancket, line_number)
77
+ end
78
+ throw :terminate
79
+ elsif first == ACCENT_END
80
+ @closed = true
81
+ throw :terminate
82
+ elsif first == RUBY_PREFIX
83
+ @ruby_buf.dump_into(@buffer)
84
+ @ruby_buf.protected = true
85
+ elsif (first != '') && !first.nil?
86
+ Utils.illegal_char_check(first, line_number)
87
+ push_chars(escape_special_chars(first))
68
88
  end
69
- throw :terminate
70
- elsif first == "〕".encode("shift_jis")
71
- @closed = true
72
- throw :terminate
73
- elsif first == RUBY_PREFIX
74
- @ruby_buf.dump_into(@buffer)
75
- @ruby_buf.protected = true
76
- elsif first != "" and first != nil
77
- illegal_char_check(first, line_number)
78
- push_chars(first)
79
89
  end
80
90
  end
81
91
 
82
92
  def process
83
93
  catch(:terminate) do
84
- loop do
85
- parse
86
- end
94
+ parse
87
95
  end
88
96
  general_output
89
97
  end
@@ -1,10 +1,12 @@
1
- require "aozora2html/i18n"
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'i18n'
2
4
 
3
- # 例外class
4
5
  class Aozora2Html
6
+ # 例外class
5
7
  class Error < StandardError
6
-
7
8
  def initialize(msg)
9
+ super
8
10
  @message = msg
9
11
  end
10
12
 
@@ -13,4 +15,3 @@ class Aozora2Html
13
15
  end
14
16
  end
15
17
  end
16
-
@@ -1,8 +1,11 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  class Aozora2Html
4
+ # ヘッダ生成用
3
5
  class Header
4
- def initialize()
6
+ def initialize(css_files:)
5
7
  @header = []
8
+ @css_files = css_files
6
9
  end
7
10
 
8
11
  def push(line)
@@ -14,17 +17,17 @@ class Aozora2Html
14
17
  if found
15
18
  "<h2 class=\"#{true_name or attr}\">#{found}</h2>\r\n"
16
19
  else
17
- ""
20
+ ''
18
21
  end
19
22
  end
20
23
 
21
24
  def header_element_type(string)
22
25
  original = true
23
26
  string.each_char do |ch|
24
- code = ch.unpack("H*")[0]
25
- if ("00" <= code and code <= "7f") or # 1byte
26
- ("8140" <= code and code <= "8258") or # 1-1, 3-25
27
- ("839f" <= code and code <= "8491") # 6-1, 7-81
27
+ code = ch.unpack1('H*')
28
+ if ((code >= '00') && (code <= '7f')) || # 1byte
29
+ ((code >= '8140') && (code <= '8258')) || # 1-1, 3-25
30
+ ((code >= '839f') && (code <= '8491')) # 6-1, 7-81
28
31
  # continue
29
32
  else
30
33
  original = false
@@ -61,13 +64,13 @@ class Aozora2Html
61
64
  def build_title(header_info)
62
65
  buf = [:author, :translator, :editor, :henyaku,
63
66
  :title, :original_title,
64
- :subtitle, :original_subtitle].map{|item| header_info[item]}.compact
65
- buf_str = buf.join(" ")
67
+ :subtitle, :original_subtitle].filter_map { |item| header_info[item] }
68
+ buf_str = buf.join(' ')
66
69
  "<title>#{buf_str}</title>"
67
70
  end
68
71
 
69
72
  def build_header_info
70
- header_info = {:title => @header[0]}
73
+ header_info = { title: @header[0] }
71
74
  case @header.length
72
75
  when 2
73
76
  process_person(@header[1], header_info)
@@ -96,7 +99,7 @@ class Aozora2Html
96
99
  header_info[:subtitle] = @header[2]
97
100
  header_info[:author] = @header[3]
98
101
  if process_person(@header[4], header_info) == :author
99
- raise Aozora2Html::Error, "parser encounted author twice"
102
+ raise Aozora2Html::Error, 'parser encounted author twice'
100
103
  end
101
104
  when 6
102
105
  header_info[:original_title] = @header[1]
@@ -104,14 +107,14 @@ class Aozora2Html
104
107
  header_info[:original_subtitle] = @header[3]
105
108
  header_info[:author] = @header[4]
106
109
  if process_person(@header[5], header_info) == :author
107
- raise Aozora2Html::Error, "parser encounted author twice"
110
+ raise Aozora2Html::Error, 'parser encounted author twice'
108
111
  end
109
112
  end
110
113
  header_info
111
114
  end
112
115
 
113
116
  def to_html
114
- header_info = build_header_info()
117
+ header_info = build_header_info
115
118
 
116
119
  # <title> 行を構築
117
120
  html_title = build_title(header_info)
@@ -119,8 +122,8 @@ class Aozora2Html
119
122
  # 出力
120
123
  out_buf = []
121
124
  out_buf.push("<?xml version=\"1.0\" encoding=\"Shift_JIS\"?>\r\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"\r\n \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"ja\" >\r\n<head>\r\n <meta http-equiv=\"Content-Type\" content=\"text/html;charset=Shift_JIS\" />\r\n <meta http-equiv=\"content-style-type\" content=\"text/css\" />\r\n")
122
- $css_files.each do |css|
123
- out_buf.push("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"" + css + "\" />\r\n")
125
+ @css_files.each do |css|
126
+ out_buf.push("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"#{css}\" />\r\n")
124
127
  end
125
128
  out_buf.push("\t#{html_title}\r\n <script type=\"text/javascript\" src=\"../../jquery-1.4.2.min.js\"></script>\r\n <link rel=\"Schema.DC\" href=\"http://purl.org/dc/elements/1.1/\" />\r\n <meta name=\"DC.Title\" content=\"#{header_info[:title]}\" />\r\n <meta name=\"DC.Creator\" content=\"#{header_info[:author]}\" />\r\n <meta name=\"DC.Publisher\" content=\"#{AOZORABUNKO}\" />\r\n</head>\r\n<body>\r\n<div class=\"metadata\">\r\n")
126
129
  out_buf.push("<h1 class=\"title\">#{header_info[:title]}</h1>\r\n" +
@@ -130,10 +133,9 @@ class Aozora2Html
130
133
  out_header_info(header_info, :author) +
131
134
  out_header_info(header_info, :editor) +
132
135
  out_header_info(header_info, :translator) +
133
- out_header_info(header_info, :henyaku, "editor-translator"))
136
+ out_header_info(header_info, :henyaku, 'editor-translator'))
134
137
  out_buf.push("<br />\r\n<br />\r\n</div>\r\n<div id=\"contents\" style=\"display:none\"></div><div class=\"main_text\">")
135
- out_buf.join("")
138
+ out_buf.join
136
139
  end
137
-
138
140
  end
139
141
  end
@@ -1,28 +1,48 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'string_refinements'
4
+
2
5
  class Aozora2Html
6
+ # Internationalization(I18n) class
7
+ #
8
+ # コード内に日本語メッセージが氾濫しないようにするためのクラス
3
9
  class I18n
10
+ @use_utf8 = nil
11
+
12
+ class << self
13
+ attr_accessor :use_utf8
14
+ end
15
+
4
16
  MSG = {
5
- :tag_syntax_error => "注記を重ねる際の原則、「狭い範囲を先に、広い範囲を後に」が守られていません。リンク先の指針を参考に、書き方をあらためてください",
6
- :undefined_header => "未定義な見出しです",
7
- :use_crlf => "改行コードを、「CR+LF」にあらためてください",
8
- :error_stop => "エラー(%d行目):%s. \r\n処理を停止します",
9
- :invalid_font_size => "文字サイズの指定が不正です",
10
- :unsupported_ruby => "サポートされていない複雑なルビ付けです",
11
- :warn_onebyte => "警告(%d行目):1バイトの「%s」が使われています",
12
- :warn_chuki => "警告(%d行目):注記記号の誤用の可能性がある、「%s」が使われています",
13
- :warn_jis_gaiji => "警告(%d行目):JIS外字「%s」が使われています",
14
- :dont_crlf_in_style => "%s中に改行されました。改行をまたぐ要素にはブロック表記を用いてください",
15
- :terminate_in_style => "%s中に本文が終了しました",
16
- :invalid_closing => "%sを閉じようとしましたが、%s中ではありません",
17
- :invalid_nesting => "%sを終了しようとしましたが、%s中です",
18
- :dont_use_double_ruby => "同じ箇所に2つのルビはつけられません",
19
- :dont_allow_triple_ruby => "1つの単語に3つのルビはつけられません",
20
- :warn_unexpected_terminator => "警告(%d行目):予期せぬファイル終端",
21
- :warn_undefined_command => "警告(%d行目):「%s」は未対応のコマンドのため無視します",
22
- }
17
+ tag_syntax_error: '注記を重ねる際の原則、「狭い範囲を先に、広い範囲を後に」が守られていません。リンク先の指針を参考に、書き方をあらためてください',
18
+ undefined_header: '未定義な見出しです',
19
+ use_crlf: '改行コードを、「CR+LF」にあらためてください',
20
+ error_stop: "エラー(%d行目):%s. \r\n処理を停止します",
21
+ invalid_font_size: '文字サイズの指定が不正です',
22
+ unsupported_ruby: 'サポートされていない複雑なルビ付けです',
23
+ warn_onebyte: '警告(%d行目):1バイトの「%s」が使われています',
24
+ warn_chuki: '警告(%d行目):注記記号の誤用の可能性がある、「%s」が使われています',
25
+ warn_jis_gaiji: '警告(%d行目):JIS外字「%s」が使われています',
26
+ dont_crlf_in_style: '%s中に改行されました。改行をまたぐ要素にはブロック表記を用いてください',
27
+ terminate_in_style: '%s中に本文が終了しました',
28
+ invalid_closing: '%sを閉じようとしましたが、%s中ではありません',
29
+ invalid_nesting: '%sを終了しようとしましたが、%s中です',
30
+ dont_use_double_ruby: '同じ箇所に2つのルビはつけられません',
31
+ dont_allow_triple_ruby: '1つの単語に3つのルビはつけられません',
32
+ warn_invalid_accent_brancket: '警告(%d行目):アクセント分解の亀甲括弧の始めと終わりが、行中で揃っていません',
33
+ warn_unexpected_terminator: '警告(%d行目):予期せぬファイル終端',
34
+ warn_undefined_command: '警告(%d行目):「%s」は未対応のコマンドのため無視します'
35
+ }.freeze
36
+
37
+ using StringRefinements
23
38
 
24
39
  def self.t(msg, *args)
25
- (MSG[msg].encode("shift_jis") % args)
40
+ if Aozora2Html::I18n.use_utf8
41
+ args_sjis = args.map { |arg| arg.is_a?(String) ? arg.to_sjis : arg }
42
+ (MSG[msg].to_sjis % args_sjis).force_encoding('cp932').to_utf8
43
+ else
44
+ MSG[msg].to_sjis % args
45
+ end
26
46
  end
27
47
  end
28
48
  end
@@ -1,24 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'string_refinements'
4
+
1
5
  class Aozora2Html
6
+ # ルビ文字列解析用バッファ
2
7
  class RubyBuffer
3
-
4
8
  # `|`が来た時に真にする。ルビの親文字のガード用。
5
9
  attr_accessor :protected
6
10
 
7
- # @ruby_buf内の文字のchar_type
8
- attr_accessor :char_type
9
-
10
- def initialize(item=nil)
11
- clear(item)
11
+ def initialize
12
+ clear
12
13
  end
13
14
 
14
- # バッファの初期化。引数itemがあるときはその1要素のバッファに、
15
- # 引数がなければ`""`の1要素のバッファにする。
16
- def clear(item=nil)
17
- if item
18
- @ruby_buf = [item]
19
- else
20
- @ruby_buf = [""]
21
- end
15
+ # バッファの初期化。`""`の1要素のバッファにする。
16
+ def clear
17
+ @ruby_buf = [+'']
22
18
  @protected = nil
23
19
  @char_type = nil
24
20
  end
@@ -35,30 +31,46 @@ class Aozora2Html
35
31
  @ruby_buf
36
32
  end
37
33
 
38
- def each(&block)
39
- @ruby_buf.each(&block)
34
+ def create_ruby(parser, ruby)
35
+ ans = +''
36
+ notes = []
37
+
38
+ @ruby_buf.each do |token|
39
+ if token.is_a?(Aozora2Html::Tag::UnEmbedGaiji)
40
+ ans.concat(GAIJI_MARK)
41
+ token.escape!
42
+ notes.push(token)
43
+ else
44
+ ans.concat(token.to_s)
45
+ end
46
+ end
47
+
48
+ notes.unshift(Aozora2Html::Tag::Ruby.new(parser, ans, ruby))
49
+ clear
50
+
51
+ notes
40
52
  end
41
53
 
42
54
  def last
43
55
  @ruby_buf.last
44
56
  end
45
57
 
58
+ # バッファ末尾にitemを追加する
59
+ #
60
+ # itemとバッファの最後尾がどちらもStringであれば連結したStringにし、
61
+ # そうでなければバッファの末尾に新しい要素として追加する
46
62
  def push(item)
47
- @ruby_buf.push(item)
63
+ if last.is_a?(String) && item.is_a?(String)
64
+ @ruby_buf.last.concat(item)
65
+ else
66
+ @ruby_buf.push(item)
67
+ end
48
68
  end
49
69
 
50
70
  def length
51
71
  @ruby_buf.length
52
72
  end
53
73
 
54
- def last_concat(item)
55
- @ruby_buf.last.concat(item)
56
- end
57
-
58
- def last_is_string?
59
- @ruby_buf.last.is_a?(String)
60
- end
61
-
62
74
  # buffer management
63
75
  def dump_into(buffer)
64
76
  if @protected
@@ -66,9 +78,9 @@ class Aozora2Html
66
78
  @protected = nil
67
79
  end
68
80
  top = @ruby_buf[0]
69
- if top.is_a?(String) and buffer.last.is_a?(String)
81
+ if top.is_a?(String) && buffer.last.is_a?(String)
70
82
  buffer.last.concat(top)
71
- buffer.concat(@ruby_buf[1,@ruby_buf.length])
83
+ buffer.concat(@ruby_buf[1, @ruby_buf.length])
72
84
  else
73
85
  buffer.concat(@ruby_buf)
74
86
  end
@@ -76,6 +88,29 @@ class Aozora2Html
76
88
  buffer
77
89
  end
78
90
 
91
+ def push_char(char, buffer)
92
+ ctype = char_type(char)
93
+ if (ctype == :hankaku_terminate) && (@char_type == :hankaku)
94
+ push(char)
95
+ @char_type = :else
96
+ elsif @protected || ((ctype != :else) && (ctype == @char_type))
97
+ push(char)
98
+ else
99
+ dump_into(buffer)
100
+ push(char)
101
+ @char_type = ctype
102
+ end
103
+ end
104
+
105
+ private
106
+
107
+ using StringRefinements
108
+
109
+ def char_type(char)
110
+ ## `String#char_type`も定義されているのに注意
111
+ char.char_type
112
+ rescue StandardError
113
+ :else
114
+ end
79
115
  end
80
116
  end
81
-
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Aozora2Html
4
+ # String extension
5
+ module StringRefinements
6
+ refine String do
7
+ # used in RubyBuffer#char_type
8
+ def char_type
9
+ case self
10
+ when Aozora2Html::REGEX_HIRAGANA
11
+ :hiragana
12
+ when Aozora2Html::REGEX_KATAKANA
13
+ :katakana
14
+ when Aozora2Html::REGEX_ZENKAKU
15
+ :zenkaku
16
+ when Aozora2Html::REGEX_HANKAKU
17
+ :hankaku
18
+ when Aozora2Html::REGEX_KANJI
19
+ :kanji
20
+ when /[.;"?!)]/
21
+ :hankaku_terminate
22
+ else
23
+ :else
24
+ end
25
+ end
26
+
27
+ def to_sjis
28
+ encode(Encoding::Shift_JIS)
29
+ end
30
+
31
+ def to_utf8
32
+ encode(Encoding::UTF_8)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,4 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Aozora2Html
4
+ # スタイルの状態管理用スタック
5
+ #
6
+ # スタイルの入れ子を扱えるようにスタック構造になっている。
7
+ # 各要素は`[コマンド文字列, 閉じる際に使うHTML文字列]`という2要素の配列になっている。
2
8
  class StyleStack
3
9
  def initialize
4
10
  @stack = []
@@ -1,21 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Aozora2Html
2
4
  class Tag
3
- class Accent < Aozora2Html::Tag
4
-
5
+ # 欧文アクセント文字用
6
+ class Accent < Aozora2Html::Tag::Inline
5
7
  @use_jisx0213 = nil
6
8
 
7
- def self.use_jisx0213=(val)
8
- @use_jisx0213 = val
9
- end
10
-
11
- def self.use_jisx0213
12
- @use_jisx0213
9
+ class << self
10
+ attr_accessor :use_jisx0213
13
11
  end
14
12
 
15
- include Aozora2Html::Tag::Inline
16
- def initialize(parser, code, name)
13
+ def initialize(parser, code, name, gaiji_dir:)
17
14
  @code = code
18
15
  @name = name
16
+ @gaiji_dir = gaiji_dir
19
17
  super
20
18
  end
21
19
 
@@ -29,9 +27,9 @@ class Aozora2Html
29
27
 
30
28
  def to_s
31
29
  if Aozora2Html::Tag::Accent.use_jisx0213
32
- jisx0213_to_unicode(@code.sub(%r|.*/|,"").to_sym)
30
+ jisx0213_to_unicode(@code.sub(%r{.*/}, '').to_sym)
33
31
  else
34
- "<img src=\"#{$gaiji_dir}#{@code}.png\" alt=\"" + GAIJI_MARK + "(#{@name})\" class=\"gaiji\" />"
32
+ "<img src=\"#{@gaiji_dir}#{@code}.png\" alt=\"" + GAIJI_MARK + "(#{@name})\" class=\"gaiji\" />"
35
33
  end
36
34
  end
37
35
  end
@@ -1,19 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Aozora2Html
2
4
  class Tag
3
- module Block
4
- def initialize(parser, *args)
5
- if parser.block_allowed_context?
6
- nil
7
- else
8
- syntax_error
9
- end
5
+ # ブロックタグ用class
6
+ #
7
+ # 各Tagクラスはこれを継承する
8
+ class Block < Aozora2Html::Tag
9
+ def initialize(parser, *_args)
10
+ super()
11
+
12
+ syntax_error unless parser.block_allowed_context?
10
13
  end
11
14
 
12
15
  # 必要に基づきmethod overrideする
13
16
  def close_tag
14
- "</div>"
17
+ '</div>'
15
18
  end
16
19
  end
17
20
  end
18
21
  end
19
-
@@ -1,14 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Aozora2Html
2
4
  class Tag
5
+ # 地付き記法
6
+ #
7
+ # 直接使わない。実際に使うのはサブクラス
3
8
  class Chitsuki < Aozora2Html::Tag::Indent
4
-
5
9
  def initialize(parser, length)
6
10
  @length = length
7
11
  super
8
12
  end
9
13
 
10
14
  def to_s
11
- '<div class="chitsuki_' + @length + '" style="text-align:right; margin-right: ' + @length + 'em">'
15
+ "<div class=\"chitsuki_#{@length}\" style=\"text-align:right; margin-right: #{@length}em\">"
12
16
  end
13
17
  end
14
18
  end
@@ -1,12 +1,13 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  class Aozora2Html
3
4
  class Tag
4
- class DakutenKatakana < Aozora2Html::Tag
5
- include Aozora2Html::Tag::Inline
6
-
7
- def initialize(parser, n, katakana)
8
- @n = n
5
+ # 濁点つきカタカナ用
6
+ class DakutenKatakana < Aozora2Html::Tag::Inline
7
+ def initialize(parser, num, katakana, gaiji_dir:)
8
+ @n = num
9
9
  @katakana = katakana
10
+ @gaiji_dir = gaiji_dir
10
11
  super
11
12
  end
12
13
 
@@ -14,10 +15,11 @@ class Aozora2Html
14
15
  :katakana
15
16
  end
16
17
 
18
+ using StringRefinements
19
+
17
20
  def to_s
18
- "<img src=\"#{$gaiji_dir}/1-07/1-07-8#{@n}.png\" alt=\"" + "※(濁点付き片仮名「".encode("shift_jis") + @katakana + "」、1-07-8".encode("shift_jis") + "#{@n})\" class=\"gaiji\" />"
21
+ "<img src=\"#{@gaiji_dir}/1-07/1-07-8#{@n}.png\" alt=\"" + '※(濁点付き片仮名「'.to_sjis + @katakana + '」、1-07-8'.to_sjis + "#{@n})\" class=\"gaiji\" />"
19
22
  end
20
23
  end
21
24
  end
22
25
  end
23
-