query-stream 1.4.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.
data/lib/query_stream.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # ================================================================
4
- # File: lib/query_stream.rb
5
3
  # ================================================================
6
4
  # 責務:
7
5
  # QueryStream gem のエントリポイント。
@@ -120,8 +118,6 @@ module QueryStream
120
118
  parsed = QueryStreamParser.parse(query)
121
119
 
122
120
  # --- Phase: Load Data ---
123
- # gem 内でログ出力せず、構造化された属性を持つ例外を raise する。
124
- # メッセージの構成・ログ出力・i18n は呼び出し元の責務とする。
125
121
  data_file = DataResolver.resolve(parsed[:source], data_dir)
126
122
  unless data_file
127
123
  expected = File.join(data_dir, "#{parsed[:source]}.yml")
@@ -135,6 +131,7 @@ module QueryStream
135
131
  records = DataResolver.load_records(data_file)
136
132
 
137
133
  # --- Phase: Filter ---
134
+ FilterEngine.validate_fields!(records, parsed)
138
135
  records = FilterEngine.apply_filters(records, parsed[:filters])
139
136
 
140
137
  # --- Phase: Sort ---
@@ -147,13 +144,11 @@ module QueryStream
147
144
  if parsed[:single_lookup]
148
145
  case records.size
149
146
  when 0
150
- # gem 内でログ出力せず、構造化された属性を持つ警告を呼び出し元に委ねる。
151
147
  on_warning&.call(NoResultWarning.new(query: query, location: location))
152
148
  return ''
153
149
  when 1
154
150
  # 正常
155
151
  else
156
- # gem 内でログ出力せず、構造化された属性を持つ警告を呼び出し元に委ねる。
157
152
  on_warning&.call(
158
153
  AmbiguousQueryWarning.new(query: query, location: location, count: records.size)
159
154
  )
@@ -168,8 +163,6 @@ module QueryStream
168
163
 
169
164
  unless File.exist?(template_path)
170
165
  hint = build_template_hint(singular, style, format, templates_dir)
171
- # gem 内でログ出力せず、構造化された属性を持つ例外を raise する。
172
- # メッセージの構成・ログ出力・i18n は呼び出し元の責務とする。
173
166
  raise TemplateNotFoundError.new(
174
167
  template_path: template_path,
175
168
  query: query,
@@ -185,7 +178,7 @@ module QueryStream
185
178
 
186
179
  # --- Phase: Post-render filter ---
187
180
  # 展開結果を呼び出し元の後段フィルタへ通す(画像パス解決など gem 外の後処理)。
188
- # コールバックが String 以外を返した場合は安全側に倒して元の展開結果を採用する。
181
+ # コールバックが String 以外を返した場合は、元の展開結果を採用する。
189
182
  return rendered unless post_render
190
183
 
191
184
  context = {
@@ -198,6 +191,9 @@ module QueryStream
198
191
  }
199
192
  result = post_render.call(rendered, context)
200
193
  result.is_a?(String) ? result : rendered
194
+ rescue InvalidQueryError => e
195
+ # パーサーとフィルタは記法の位置を知らないので、ここで付け足して投げ直す
196
+ raise e.with_context(query:, location:)
201
197
  end
202
198
 
203
199
  # テキスト内の QueryStream 記法を検出してリストを返す
@@ -226,16 +222,12 @@ module QueryStream
226
222
 
227
223
  # その行を QueryStream 記法として扱うか。
228
224
  #
229
- # **不正な UTF-8 を含む行は記法として解釈しない。** `match?` はそういう行に
230
- # `ArgumentError: invalid byte sequence in UTF-8` を投げるので、素通しにすると
231
- # 原稿に 1 バイトの壊れが混ざっただけで展開が丸ごと止まる。
232
- # ここでバイト列を書き換えて(scrub して)通す手もあるが採らない——gem が黙って
233
- # 原稿のバイト列を変えると、著者が気付けない形で本文が変わる。
234
- # 記法として読めない行は本文として、そのまま返すのが正しい。
225
+ # 不正な UTF-8 を含む行は記法として解釈せず、本文としてそのまま返す。`match?` はそういう行に
226
+ # `ArgumentError` を投げるので、捕まえないと展開全体が止まる。scrub しないのは、原稿のバイト列を
227
+ # 変えないため。
235
228
  #
236
- # EncodingError と ArgumentError の両方を捕まえるのは意図的である。壊れたバイト列に
237
- # Ruby がどちらを投げるかはメソッド次第で(match? / 先頭破損の lstrip は ArgumentError、
238
- # strip は Encoding::CompatibilityError)、その差で展開が止まってはならない。
229
+ # EncodingError と ArgumentError の両方を捕まえる。壊れたバイト列に Ruby が投げる例外はメソッドで
230
+ # 異なる(match? / 先頭破損の lstrip は ArgumentError、strip は Encoding::CompatibilityError)。
239
231
  def query_line?(line)
240
232
  line.match?(QUERY_STREAM_PATTERN)
241
233
  rescue EncodingError, ArgumentError
@@ -243,9 +235,7 @@ module QueryStream
243
235
  end
244
236
 
245
237
  # コードフェンスの開始/終了行か。
246
- # `lstrip` も不正な UTF-8 で ArgumentError を投げるので、query_line? と同じく
247
- # 「読めない行は本文」へ倒す。ここを素通しにすると、記法判定だけ守っても
248
- # 手前のフェンス判定で落ちる。
238
+ # `lstrip` も不正な UTF-8 で ArgumentError を投げるので、query_line? と同じく本文として扱う。
249
239
  def code_fence?(line)
250
240
  line.lstrip.start_with?('```')
251
241
  rescue EncodingError, ArgumentError
@@ -254,10 +244,9 @@ module QueryStream
254
244
 
255
245
  # 引数をファイルパスとして読むべきか。
256
246
  #
257
- # `scan` はパスと本文のどちらも受け取る API なので、本文をそのまま
258
- # `File.exist?` へ渡すと壊れる——NUL バイトを含めば `ArgumentError`、
259
- # ディレクトリなら「存在する」と判定されて `File.read` が `Errno::EISDIR` を出す。
260
- # パスとして成立しうる形だけを先に選別し、判定自体の失敗も本文扱いに倒す。
247
+ # `scan` はパスと本文のどちらも受け取る。本文を `File.exist?` へ渡すと、NUL バイトを含む場合は
248
+ # `ArgumentError` になり、ディレクトリは `File.read` が `Errno::EISDIR` を出す。
249
+ # パスとして成立する形だけを先に選び、判定の失敗も本文として扱う。
261
250
  def readable_file?(str)
262
251
  s = str.to_s
263
252
  return false if s.empty? || s.include?("\0") || s.include?("\n")
data/query-stream.gemspec CHANGED
@@ -8,9 +8,10 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ['Atelier Mirai']
9
9
  spec.email = ['contact@atelier-mirai.net']
10
10
 
11
- spec.summary = 'QueryStream - YAML/JSON data renderer with template expansion'
12
- spec.description = 'A generic Ruby library that expands QueryStream notation in text content ' \
13
- 'by combining YAML/JSON data files with template files.'
11
+ spec.summary = 'YAML / JSON のデータとテンプレートから、文章中の 1 行の記法を展開する Ruby ライブラリ'
12
+ spec.description = 'QueryStream は、文章中に書いた `= books | tags=ruby | -year | 5` のような 1 行の記法を、' \
13
+ 'YAML / JSON のデータファイルとテンプレートを組み合わせて展開する汎用の Ruby ライブラリです。' \
14
+ '抽出条件、並べ替え、件数、スタイルを指定できます。'
14
15
  spec.homepage = 'https://github.com/Atelier-Mirai/query-stream'
15
16
  spec.license = 'MIT'
16
17
 
@@ -20,18 +21,16 @@ Gem::Specification.new do |spec|
20
21
  spec.required_ruby_version = '>= 3.4'
21
22
 
22
23
  spec.files = Dir.glob('{lib,bin}/**/*') +
23
- %w[README.md CHANGELOG.md RELEASE_NOTE.md LICENSE Gemfile query-stream.gemspec]
24
+ %w[README.md CHANGELOG.md RELEASE_NOTE.md LICENSE query-stream.gemspec]
24
25
  spec.bindir = 'bin'
25
26
  spec.executables = ['query-stream']
26
27
  spec.require_paths = ['lib']
27
28
 
28
- # Runtime dependencies
29
- # logger への依存は 1.4.0 で外した。gem 自身はログを出さず、失敗は構造化例外で伝える。
30
29
  spec.add_dependency 'samovar', '~> 2.1'
31
30
 
32
- # Development dependencies
33
31
  spec.add_development_dependency 'bundler'
34
32
  spec.add_development_dependency 'rake', '~> 13.2'
35
- spec.add_development_dependency 'minitest', '~> 5.22'
33
+ spec.add_development_dependency 'minitest', '>= 5.22'
34
+ spec.add_development_dependency 'rubocop', '~> 1.81'
36
35
  spec.metadata['rubygems_mfa_required'] = 'false'
37
36
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: query-stream
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Atelier Mirai
@@ -55,18 +55,32 @@ dependencies:
55
55
  name: minitest
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - "~>"
58
+ - - ">="
59
59
  - !ruby/object:Gem::Version
60
60
  version: '5.22'
61
61
  type: :development
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - "~>"
65
+ - - ">="
66
66
  - !ruby/object:Gem::Version
67
67
  version: '5.22'
68
- description: A generic Ruby library that expands QueryStream notation in text content
69
- by combining YAML/JSON data files with template files.
68
+ - !ruby/object:Gem::Dependency
69
+ name: rubocop
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.81'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '1.81'
82
+ description: QueryStream は、文章中に書いた `= books | tags=ruby | -year | 5` のような 1 行の記法を、YAML
83
+ / JSON のデータファイルとテンプレートを組み合わせて展開する汎用の Ruby ライブラリです。抽出条件、並べ替え、件数、スタイルを指定できます。
70
84
  email:
71
85
  - contact@atelier-mirai.net
72
86
  executables:
@@ -75,7 +89,6 @@ extensions: []
75
89
  extra_rdoc_files: []
76
90
  files:
77
91
  - CHANGELOG.md
78
- - Gemfile
79
92
  - LICENSE
80
93
  - README.md
81
94
  - RELEASE_NOTE.md
@@ -112,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
125
  - !ruby/object:Gem::Version
113
126
  version: '0'
114
127
  requirements: []
115
- rubygems_version: 4.0.16
128
+ rubygems_version: 4.0.20
116
129
  specification_version: 4
117
- summary: QueryStream - YAML/JSON data renderer with template expansion
130
+ summary: YAML / JSON のデータとテンプレートから、文章中の 1 行の記法を展開する Ruby ライブラリ
118
131
  test_files: []
data/Gemfile DELETED
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source 'https://rubygems.org'
4
-
5
- gemspec