mq-ruby 0.1.28 → 0.1.30
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/Cargo.lock +1977 -0
- data/Cargo.toml +7 -3
- data/README.md +44 -3
- data/lib/mq/query.rb +97 -0
- metadata +2 -1
data/Cargo.toml
CHANGED
|
@@ -10,7 +10,7 @@ name = "mq-ruby"
|
|
|
10
10
|
publish = false
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
repository = "https://github.com/harehare/mq"
|
|
13
|
-
version = "0.1.
|
|
13
|
+
version = "0.1.30"
|
|
14
14
|
|
|
15
15
|
[lib]
|
|
16
16
|
crate-type = ["cdylib"]
|
|
@@ -18,6 +18,10 @@ name = "mq_ruby"
|
|
|
18
18
|
|
|
19
19
|
[dependencies]
|
|
20
20
|
magnus = {version = "0.8"}
|
|
21
|
-
mq-lang = "0.
|
|
22
|
-
mq-markdown = "0.
|
|
21
|
+
mq-lang = {version = "0.7.0", features = ["css-selector"]}
|
|
22
|
+
mq-markdown = "0.7.0"
|
|
23
|
+
# Pinned below the rb-sys releases (0.9.120+) that added Ruby 4.x-specific
|
|
24
|
+
# ABI handling, which is buggy on Ruby 4.0 under magnus 0.8.2 and breaks
|
|
25
|
+
# TypedData class conversion (see MQ::Result CI failures on Ruby 4.0).
|
|
26
|
+
rb-sys = "=0.9.117"
|
|
23
27
|
|
data/README.md
CHANGED
|
@@ -254,6 +254,7 @@ MQ::Query.list.map { contains("important") }
|
|
|
254
254
|
.to_html # to_html() — HTML string
|
|
255
255
|
.to_string # to_string() — string coercion
|
|
256
256
|
.to_number # to_number() — numeric coercion
|
|
257
|
+
.to_boolean # to_boolean() — boolean coercion
|
|
257
258
|
.to_array # to_array()
|
|
258
259
|
.to_bytes # to_bytes()
|
|
259
260
|
.to_markdown_string # to_markdown_string()
|
|
@@ -267,22 +268,34 @@ MQ::Query.list.map { contains("important") }
|
|
|
267
268
|
.rtrim # rtrim()
|
|
268
269
|
.downcase # downcase()
|
|
269
270
|
.upcase # upcase()
|
|
271
|
+
.ascii_downcase # ascii_downcase()
|
|
272
|
+
.ascii_upcase # ascii_upcase()
|
|
270
273
|
.len # len()
|
|
271
274
|
.utf8bytelen # utf8bytelen()
|
|
272
275
|
.explode # explode() — string to codepoints
|
|
273
276
|
.implode # implode() — codepoints to string
|
|
274
277
|
.url_encode # url_encode()
|
|
278
|
+
.url_decode # url_decode()
|
|
275
279
|
.intern # intern()
|
|
280
|
+
.html_escape # html_escape()
|
|
281
|
+
.html_unescape # html_unescape()
|
|
282
|
+
.sanitize_html # sanitize_html() — strip dangerous tags/attrs
|
|
283
|
+
.strip_tags # strip_tags() — remove all HTML tags
|
|
276
284
|
|
|
277
285
|
.split(",") # split(",")
|
|
278
286
|
.gsub("pat", "r") # gsub("pat", "r") — regex replace all
|
|
279
287
|
.replace("a", "b") # replace("a", "b") — literal replace
|
|
280
288
|
.test("\\d+") # test("\\d+") — regex test → bool
|
|
281
289
|
.capture("(\\w+)") # capture("(\\w+)") — regex capture
|
|
290
|
+
.scan("(\\w+)") # scan("(\\w+)") — all regex matches
|
|
282
291
|
.slice(0, 5) # slice(0, 5)
|
|
283
292
|
.index("sub") # index("sub") — position of substring
|
|
284
293
|
.rindex("sub") # rindex("sub") — last position
|
|
285
294
|
.repeat(3) # repeat(3)
|
|
295
|
+
.word_wrap(20) # word_wrap(20) — wrap text to column width
|
|
296
|
+
.truncate(10, "…") # truncate(10, "…") — shorten with an ellipsis
|
|
297
|
+
.token_count # token_count() — estimate LLM token count
|
|
298
|
+
.token_count("gpt-4") # token_count("gpt-4")
|
|
286
299
|
```
|
|
287
300
|
|
|
288
301
|
#### Collection Operations
|
|
@@ -309,6 +322,8 @@ MQ::Query.list.map { contains("important") }
|
|
|
309
322
|
.range(3) # range(3)
|
|
310
323
|
.del("key") # del("key")
|
|
311
324
|
.insert(0, "val") # insert(0, "val")
|
|
325
|
+
.shuffle # shuffle() — random order
|
|
326
|
+
.sample(3) # sample(3) — n random elements, no replacement
|
|
312
327
|
```
|
|
313
328
|
|
|
314
329
|
#### Math Operations
|
|
@@ -350,8 +365,18 @@ MQ::Query.list.map { contains("important") }
|
|
|
350
365
|
.sha512 # sha512()
|
|
351
366
|
.from_hex # from_hex()
|
|
352
367
|
.to_hex # to_hex()
|
|
368
|
+
.uuid # uuid() — random (v4) UUID
|
|
369
|
+
.uuid_v4 # uuid_v4() — alias of uuid
|
|
370
|
+
.uuid_v7 # uuid_v7() — time-ordered (v7) UUID
|
|
371
|
+
.rand # rand() — pseudo-random number in [0, 1)
|
|
372
|
+
.rand_int(1, 10) # rand_int(1, 10) — pseudo-random integer in [min, max]
|
|
353
373
|
```
|
|
354
374
|
|
|
375
|
+
`MQ::Query.uuid`, `.uuid_v4`, `.uuid_v7`, `.rand`, `.rand_int(min, max)`, and
|
|
376
|
+
`.random_string(len, charset)` are also available as class-level generators to
|
|
377
|
+
start a query without a preceding selector, e.g. `MQ::Query.uuid.to_query # =>
|
|
378
|
+
"uuid()"`.
|
|
379
|
+
|
|
355
380
|
#### Path Operations
|
|
356
381
|
|
|
357
382
|
```ruby
|
|
@@ -360,14 +385,30 @@ MQ::Query.list.map { contains("important") }
|
|
|
360
385
|
.extname # extname()
|
|
361
386
|
.stem # stem()
|
|
362
387
|
.path_join("sub") # path_join("sub")
|
|
388
|
+
.glob_match("docs/readme.md") # glob_match("docs/readme.md") — self is the glob pattern
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
#### HTML / CSS Selector Operations
|
|
392
|
+
|
|
393
|
+
Query a raw HTML string directly with a CSS selector, bypassing Markdown
|
|
394
|
+
conversion — useful for tags/classes/ids/`data-*` attributes that would
|
|
395
|
+
otherwise be lost.
|
|
396
|
+
|
|
397
|
+
```ruby
|
|
398
|
+
.css("p.intro") # css("p.intro") — outer HTML of matches
|
|
399
|
+
.css_text("p.intro") # css_text("p.intro") — text content of matches
|
|
400
|
+
.css_attr("a", "href") # css_attr("a", "href") — attribute value of matches
|
|
363
401
|
```
|
|
364
402
|
|
|
365
403
|
#### Dict Operations
|
|
366
404
|
|
|
367
405
|
```ruby
|
|
368
|
-
.get("key")
|
|
369
|
-
.set("key", "val")
|
|
370
|
-
.property("key")
|
|
406
|
+
.get("key") # get("key")
|
|
407
|
+
.set("key", "val") # set("key", "val")
|
|
408
|
+
.property("key") # ."key"
|
|
409
|
+
.get_path(["a", "b"]) # get_path(["a", "b"])
|
|
410
|
+
.set_path(["a", "b"], "val") # set_path(["a", "b"], "val")
|
|
411
|
+
.paths # paths() — array of leaf-path arrays
|
|
371
412
|
```
|
|
372
413
|
|
|
373
414
|
#### Markdown Attribute Operations
|
data/lib/mq/query.rb
CHANGED
|
@@ -66,6 +66,7 @@ module MQ
|
|
|
66
66
|
def to_html = pipe_with("to_html()")
|
|
67
67
|
def to_string = pipe_with("to_string()")
|
|
68
68
|
def to_number = pipe_with("to_number()")
|
|
69
|
+
def to_boolean = pipe_with("to_boolean()")
|
|
69
70
|
def to_array = pipe_with("to_array()")
|
|
70
71
|
def to_bytes = pipe_with("to_bytes()")
|
|
71
72
|
def to_markdown_string = pipe_with("to_markdown_string()")
|
|
@@ -135,15 +136,42 @@ module MQ
|
|
|
135
136
|
pipe_with("repeat(#{n})")
|
|
136
137
|
end
|
|
137
138
|
|
|
139
|
+
def shuffle = pipe_with("shuffle()")
|
|
140
|
+
|
|
141
|
+
def sample(n)
|
|
142
|
+
pipe_with("sample(#{n})")
|
|
143
|
+
end
|
|
144
|
+
|
|
138
145
|
def trim = pipe_with("trim()")
|
|
139
146
|
def ltrim = pipe_with("ltrim()")
|
|
140
147
|
def rtrim = pipe_with("rtrim()")
|
|
141
148
|
def downcase = pipe_with("downcase()")
|
|
142
149
|
def upcase = pipe_with("upcase()")
|
|
150
|
+
def ascii_downcase = pipe_with("ascii_downcase()")
|
|
151
|
+
def ascii_upcase = pipe_with("ascii_upcase()")
|
|
143
152
|
def explode = pipe_with("explode()")
|
|
144
153
|
def implode = pipe_with("implode()")
|
|
145
154
|
def url_encode = pipe_with("url_encode()")
|
|
155
|
+
def url_decode = pipe_with("url_decode()")
|
|
146
156
|
def intern = pipe_with("intern()")
|
|
157
|
+
def html_escape = pipe_with("html_escape()")
|
|
158
|
+
def html_unescape = pipe_with("html_unescape()")
|
|
159
|
+
def sanitize_html = pipe_with("sanitize_html()")
|
|
160
|
+
def strip_tags = pipe_with("strip_tags()")
|
|
161
|
+
|
|
162
|
+
def word_wrap(width)
|
|
163
|
+
pipe_with("word_wrap(#{width})")
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def truncate(len, ellipsis)
|
|
167
|
+
pipe_with("truncate(#{len}, #{ellipsis.inspect})")
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Estimates (or, when mq was built with tiktoken support, exactly counts) the
|
|
171
|
+
# LLM tokens the current string would consume. +model+ is optional.
|
|
172
|
+
def token_count(model = nil)
|
|
173
|
+
model ? pipe_with("token_count(#{model.inspect})") : pipe_with("token_count()")
|
|
174
|
+
end
|
|
147
175
|
|
|
148
176
|
def gsub(pattern, replacement)
|
|
149
177
|
pipe_with("gsub(#{pattern.inspect}, #{replacement.inspect})")
|
|
@@ -161,6 +189,10 @@ module MQ
|
|
|
161
189
|
pipe_with("capture(#{pattern.inspect})")
|
|
162
190
|
end
|
|
163
191
|
|
|
192
|
+
def scan(pattern)
|
|
193
|
+
pipe_with("scan(#{pattern.inspect})")
|
|
194
|
+
end
|
|
195
|
+
|
|
164
196
|
def abs = pipe_with("abs()")
|
|
165
197
|
def ceil = pipe_with("ceil()")
|
|
166
198
|
def floor = pipe_with("floor()")
|
|
@@ -205,6 +237,15 @@ module MQ
|
|
|
205
237
|
def to_hex = pipe_with("to_hex()")
|
|
206
238
|
def to_hex_str = pipe_with("to_hex()")
|
|
207
239
|
|
|
240
|
+
def uuid = pipe_with("uuid()")
|
|
241
|
+
def uuid_v4 = pipe_with("uuid_v4()")
|
|
242
|
+
def uuid_v7 = pipe_with("uuid_v7()")
|
|
243
|
+
def rand = pipe_with("rand()")
|
|
244
|
+
|
|
245
|
+
def rand_int(min, max)
|
|
246
|
+
pipe_with("rand_int(#{min}, #{max})")
|
|
247
|
+
end
|
|
248
|
+
|
|
208
249
|
def basename = pipe_with("basename()")
|
|
209
250
|
def dirname = pipe_with("dirname()")
|
|
210
251
|
def extname = pipe_with("extname()")
|
|
@@ -214,6 +255,30 @@ module MQ
|
|
|
214
255
|
pipe_with("path_join(#{other.inspect})")
|
|
215
256
|
end
|
|
216
257
|
|
|
258
|
+
# Treats the current string as a glob pattern (e.g. "*.md", "docs/**/*.rs")
|
|
259
|
+
# and returns whether it matches +path+.
|
|
260
|
+
def glob_match(path)
|
|
261
|
+
pipe_with("glob_match(#{path.inspect})")
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Returns the outer HTML of every element in the current (raw) HTML string
|
|
265
|
+
# matching the CSS +selector+, as an array of strings.
|
|
266
|
+
def css(selector)
|
|
267
|
+
pipe_with("css(#{selector.inspect})")
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Returns the text content of every element in the current (raw) HTML
|
|
271
|
+
# string matching the CSS +selector+, as an array of strings.
|
|
272
|
+
def css_text(selector)
|
|
273
|
+
pipe_with("css_text(#{selector.inspect})")
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# Returns the value of attribute +name+ for every element in the current
|
|
277
|
+
# (raw) HTML string matching the CSS +selector+, as an array.
|
|
278
|
+
def css_attr(selector, name)
|
|
279
|
+
pipe_with("css_attr(#{selector.inspect}, #{name.inspect})")
|
|
280
|
+
end
|
|
281
|
+
|
|
217
282
|
def get(key)
|
|
218
283
|
pipe_with("get(#{key.inspect})")
|
|
219
284
|
end
|
|
@@ -222,6 +287,22 @@ module MQ
|
|
|
222
287
|
pipe_with("set(#{key.inspect}, #{val.inspect})")
|
|
223
288
|
end
|
|
224
289
|
|
|
290
|
+
# Retrieves a nested value by following an array of keys/indices.
|
|
291
|
+
def get_path(path)
|
|
292
|
+
pipe_with("get_path(#{path.inspect})")
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# Sets a nested value by following an array of keys/indices, creating
|
|
296
|
+
# missing intermediate dicts/arrays automatically.
|
|
297
|
+
def set_path(path, new_value)
|
|
298
|
+
pipe_with("set_path(#{path.inspect}, #{new_value.inspect})")
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# Returns an array of leaf-path arrays for the current value.
|
|
302
|
+
def paths
|
|
303
|
+
pipe_with("paths()")
|
|
304
|
+
end
|
|
305
|
+
|
|
225
306
|
# Access a dict property by key (generates ."key" selector)
|
|
226
307
|
def property(key)
|
|
227
308
|
pipe_with(".\"#{key}\"")
|
|
@@ -453,6 +534,22 @@ module MQ
|
|
|
453
534
|
|
|
454
535
|
def to_text = new("to_text()")
|
|
455
536
|
def to_markdown = new("to_markdown()")
|
|
537
|
+
|
|
538
|
+
# --- Value generators (usable as query starting points) ---
|
|
539
|
+
def uuid = new("uuid()")
|
|
540
|
+
def uuid_v4 = new("uuid_v4()")
|
|
541
|
+
def uuid_v7 = new("uuid_v7()")
|
|
542
|
+
def rand = new("rand()")
|
|
543
|
+
|
|
544
|
+
def rand_int(min, max)
|
|
545
|
+
new("rand_int(#{min}, #{max})")
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
# Returns a random string of +len+ characters drawn (with replacement)
|
|
549
|
+
# from +charset+.
|
|
550
|
+
def random_string(len, charset)
|
|
551
|
+
new("random_string(#{len}, #{charset.inspect})")
|
|
552
|
+
end
|
|
456
553
|
end
|
|
457
554
|
|
|
458
555
|
private
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mq-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.30
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Takahiro Sato
|
|
@@ -72,6 +72,7 @@ extensions:
|
|
|
72
72
|
- extconf.rb
|
|
73
73
|
extra_rdoc_files: []
|
|
74
74
|
files:
|
|
75
|
+
- Cargo.lock
|
|
75
76
|
- Cargo.toml
|
|
76
77
|
- LICENSE
|
|
77
78
|
- README.md
|