hummel 0.1.0 → 0.2.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/.ruby-version +1 -1
- data/CHANGELOG.md +34 -0
- data/README.md +28 -9
- data/lib/hummel/decode.rb +32 -38
- data/lib/hummel/encode.rb +3 -3
- data/lib/hummel/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4b63f273b7a493c53d0d0bdfad24ee9a273005cb0bc63cd81605d8bfd6f660dc
|
|
4
|
+
data.tar.gz: 446cb68dbfdf83a1182c88dcdeb40250548fc41a61bbe3f7fe440383591d0032
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6c5d709a0459493125a4caea694b7b89f93f8511207d9ff2e3a41d2389608f416860781a2b1d10633ccde5ea44aa87fee18f1dc041d49e243d50dc11b1861bac
|
|
7
|
+
data.tar.gz: 5a04eb2f91d13e99c060980e123f17447be47813579165c3ab6653accb6219c4dead58e5d71e5f399dfffcdef99cf54eadc190a1640329ec69475fec9fb77229
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
4.0.1
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
1
8
|
## [Unreleased]
|
|
2
9
|
|
|
10
|
+
## [0.2.0] - 2026-02-16
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Update parser and encoder to HUML v0.2.0 spec
|
|
14
|
+
- Remove triple-backtick multiline string syntax
|
|
15
|
+
- Triple-quote `"""` multiline strings now preserve relative indentation (strip uniform indent)
|
|
16
|
+
- Enforce strict indentation for multiline vectors inside list items
|
|
17
|
+
|
|
18
|
+
### Internal
|
|
19
|
+
- Abort test suite early if `tests/` submodule is missing
|
|
20
|
+
|
|
21
|
+
## [0.1.1] - 2025-10-12
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- Improve code coverage and remove dead code
|
|
25
|
+
- Update README.md with naming scheme and fixes
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- Fix README example
|
|
29
|
+
|
|
30
|
+
### Internal
|
|
31
|
+
- Achieve 100% code coverage
|
|
32
|
+
- Add code coverage tracking with SimpleCov
|
|
33
|
+
- Update CI workflow with permissions and coverage upload
|
|
34
|
+
- Add matrix.ruby to artifact naming
|
|
35
|
+
- Add workflow_dispatch trigger to CI
|
|
36
|
+
|
|
3
37
|
## [0.1.0] - 2025-10-12
|
|
4
38
|
|
|
5
39
|
- Initial release
|
data/README.md
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Hummel
|
|
2
2
|
|
|
3
|
-
An HUML parser implementation in ruby.
|
|
4
|
-
|
|
5
|
-
> **Note:** The gem is named `hummel` because `huml` was already taken on rubygems.org.
|
|
3
|
+
An [HUML](https://huml.io) parser implementation in ruby.
|
|
6
4
|
|
|
7
5
|
## Installation
|
|
8
6
|
|
|
9
7
|
Add this line to your application's Gemfile:
|
|
10
8
|
|
|
11
9
|
```ruby
|
|
12
|
-
gem 'hummel'
|
|
10
|
+
gem 'hummel'
|
|
13
11
|
```
|
|
14
12
|
|
|
15
13
|
And then execute:
|
|
@@ -21,7 +19,7 @@ bundle install
|
|
|
21
19
|
Or install it yourself as:
|
|
22
20
|
|
|
23
21
|
```bash
|
|
24
|
-
gem install hummel
|
|
22
|
+
gem install hummel
|
|
25
23
|
```
|
|
26
24
|
|
|
27
25
|
## Usage
|
|
@@ -32,9 +30,9 @@ gem install hummel --source https://gem.coop
|
|
|
32
30
|
require 'hummel'
|
|
33
31
|
|
|
34
32
|
huml_string = <<~HUML
|
|
35
|
-
name: John Doe
|
|
33
|
+
name: "John Doe"
|
|
36
34
|
age: 30
|
|
37
|
-
email: john@example.com
|
|
35
|
+
email: "john@example.com"
|
|
38
36
|
HUML
|
|
39
37
|
|
|
40
38
|
data = Hummel::Decode.parse(huml_string)
|
|
@@ -80,7 +78,24 @@ Hummel::Encode.stringify(data, include_version: true)
|
|
|
80
78
|
|
|
81
79
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
82
80
|
|
|
83
|
-
To install this gem onto your local machine, run `
|
|
81
|
+
To install this gem onto your local machine, run `bin/rake install`.
|
|
82
|
+
|
|
83
|
+
To release a new version:
|
|
84
|
+
|
|
85
|
+
1. Run tests and linters: `bin/rake` and address any issues in separate commits.
|
|
86
|
+
2. Update the version number in `lib/hummel/version.rb`.
|
|
87
|
+
3. Update the `CHANGELOG.md` to include this version and brief summaries of changes.
|
|
88
|
+
4. Commit changes:
|
|
89
|
+
|
|
90
|
+
git add lib/hummel/version.rb CHANGELOG.md
|
|
91
|
+
git commit -m "Bump version to 0.2.0"
|
|
92
|
+
|
|
93
|
+
5. Run `bin/rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
94
|
+
6. Create a GitHub Release from the tag with the CHANGELOG.md notes.
|
|
95
|
+
|
|
96
|
+
> **Note**: In follow up commits to this release please re-add the [Unreleased] section to CHANGELOG.md for future work.
|
|
97
|
+
|
|
98
|
+
> **Note**: Make sure you're authed with rubygems.org via `gem signin` before running the release command.
|
|
84
99
|
|
|
85
100
|
## Contributing
|
|
86
101
|
|
|
@@ -93,3 +108,7 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
|
93
108
|
## Code of Conduct
|
|
94
109
|
|
|
95
110
|
Everyone interacting in the Hummel project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/djbender/hummel/blob/main/CODE_OF_CONDUCT.md).
|
|
111
|
+
|
|
112
|
+
## Name
|
|
113
|
+
|
|
114
|
+
This gem is named `hummel` because `huml` was already taken on [rubygems.org](https://rubygems.org).
|
data/lib/hummel/decode.rb
CHANGED
|
@@ -78,8 +78,8 @@ module Hummel
|
|
|
78
78
|
|
|
79
79
|
if pos > starting_pos
|
|
80
80
|
version = data[starting_pos...pos]
|
|
81
|
-
if version != "v0.
|
|
82
|
-
raise error("unsupported version '#{version}'. expected 'v0.
|
|
81
|
+
if version != "v0.2.0"
|
|
82
|
+
raise error("unsupported version '#{version}'. expected 'v0.2.0'")
|
|
83
83
|
end
|
|
84
84
|
end
|
|
85
85
|
end
|
|
@@ -178,7 +178,7 @@ module Hummel
|
|
|
178
178
|
result[key] = if indicator == ":"
|
|
179
179
|
assert_space("after ':'")
|
|
180
180
|
|
|
181
|
-
multiline = peek_string(
|
|
181
|
+
multiline = peek_string('"""')
|
|
182
182
|
|
|
183
183
|
value = parse_value(current_indent)
|
|
184
184
|
|
|
@@ -249,6 +249,10 @@ module Hummel
|
|
|
249
249
|
vector_type = multiline_vector_type(indent)
|
|
250
250
|
next_indent = current_indent
|
|
251
251
|
|
|
252
|
+
if next_indent != indent
|
|
253
|
+
raise error("bad indent #{next_indent}, expected #{indent}")
|
|
254
|
+
end
|
|
255
|
+
|
|
252
256
|
parse_multiline_method = method(:"parse_multiline_#{vector_type}")
|
|
253
257
|
return parse_multiline_method.call(next_indent)
|
|
254
258
|
end
|
|
@@ -364,11 +368,11 @@ module Hummel
|
|
|
364
368
|
character = data[self.pos]
|
|
365
369
|
|
|
366
370
|
if character == '"'
|
|
367
|
-
return peek_string('"""') ? parse_multiline_string(key_indent
|
|
371
|
+
return peek_string('"""') ? parse_multiline_string(key_indent) : parse_string
|
|
368
372
|
end
|
|
369
373
|
|
|
370
374
|
if character == "`" && peek_string("```")
|
|
371
|
-
|
|
375
|
+
raise error("backtick multiline strings are not supported in HUML v0.2.0")
|
|
372
376
|
end
|
|
373
377
|
|
|
374
378
|
SPECIAL_VALUES.each do |string, value|
|
|
@@ -450,24 +454,19 @@ module Hummel
|
|
|
450
454
|
raise error("unclosed string")
|
|
451
455
|
end
|
|
452
456
|
|
|
453
|
-
def parse_multiline_string(key_indent
|
|
457
|
+
def parse_multiline_string(key_indent)
|
|
454
458
|
delimiter = data[pos, 3]
|
|
455
459
|
advance(3)
|
|
456
460
|
consume_line
|
|
457
461
|
|
|
458
|
-
#
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
required_indent
|
|
463
|
-
if content.length >= required_indent && space_string?(content[0, required_indent])
|
|
464
|
-
return content[required_indent..]
|
|
465
|
-
end
|
|
466
|
-
|
|
467
|
-
content
|
|
462
|
+
# strip required 2-space indent relative to key
|
|
463
|
+
required_indent = key_indent + 2
|
|
464
|
+
process_line = ->(content, _line_indent) do
|
|
465
|
+
if content.length >= required_indent && space_string?(content[0, required_indent])
|
|
466
|
+
return content[required_indent..]
|
|
468
467
|
end
|
|
469
|
-
|
|
470
|
-
|
|
468
|
+
|
|
469
|
+
content
|
|
471
470
|
end
|
|
472
471
|
|
|
473
472
|
lines = []
|
|
@@ -515,7 +514,7 @@ module Hummel
|
|
|
515
514
|
|
|
516
515
|
NUMBER_BASE_PREFIXES.each do |prefix, base|
|
|
517
516
|
if peek_string(prefix)
|
|
518
|
-
parse_base(start: starting_pos, base: base, prefix:)
|
|
517
|
+
return parse_base(start: starting_pos, base: base, prefix:)
|
|
519
518
|
end
|
|
520
519
|
end
|
|
521
520
|
|
|
@@ -579,10 +578,7 @@ module Hummel
|
|
|
579
578
|
line_start = self.pos
|
|
580
579
|
skip_spaces
|
|
581
580
|
|
|
582
|
-
if done?
|
|
583
|
-
raise error("trailing spaces are not allowed") if self.pos > line_start
|
|
584
|
-
return
|
|
585
|
-
end
|
|
581
|
+
raise error("trailing spaces are not allowed") if done?
|
|
586
582
|
|
|
587
583
|
if !["\n", "#"].include?(data[self.pos])
|
|
588
584
|
return # Found content
|
|
@@ -714,9 +710,7 @@ module Hummel
|
|
|
714
710
|
current_pos = pos
|
|
715
711
|
while current_pos < data.length && !["\n", "#"].include?(data[current_pos])
|
|
716
712
|
if data[current_pos] == ":"
|
|
717
|
-
|
|
718
|
-
return true
|
|
719
|
-
end
|
|
713
|
+
return true
|
|
720
714
|
end
|
|
721
715
|
current_pos += 1
|
|
722
716
|
end
|
|
@@ -733,12 +727,12 @@ module Hummel
|
|
|
733
727
|
end
|
|
734
728
|
|
|
735
729
|
def inline_dict_at_root?
|
|
736
|
-
line_end = data.index("\n", pos)
|
|
737
|
-
comment_index = data.index("#", pos)
|
|
730
|
+
line_end = data.index("\n", pos)
|
|
731
|
+
comment_index = data.index("#", pos)
|
|
738
732
|
|
|
739
733
|
marker = [
|
|
740
|
-
line_end,
|
|
741
|
-
comment_index
|
|
734
|
+
line_end || data.length,
|
|
735
|
+
comment_index || data.length
|
|
742
736
|
].min
|
|
743
737
|
|
|
744
738
|
line = data[pos...marker]
|
|
@@ -747,13 +741,15 @@ module Hummel
|
|
|
747
741
|
|
|
748
742
|
return false unless has_colon && has_comma
|
|
749
743
|
|
|
750
|
-
remaining_content = if line_end
|
|
751
|
-
|
|
744
|
+
remaining_content = if line_end.nil?
|
|
745
|
+
# Single-line input, no subsequent lines
|
|
746
|
+
false
|
|
752
747
|
else
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
748
|
+
# Multi-line input, check if subsequent lines have non-comment content
|
|
749
|
+
data.split("\n")[1..].any? do |line|
|
|
750
|
+
trimmed = line.strip
|
|
751
|
+
trimmed && !trimmed.start_with?("#")
|
|
752
|
+
end
|
|
757
753
|
end
|
|
758
754
|
|
|
759
755
|
!remaining_content
|
|
@@ -813,8 +809,6 @@ module Hummel
|
|
|
813
809
|
end
|
|
814
810
|
|
|
815
811
|
def skip_first
|
|
816
|
-
return unless block_given?
|
|
817
|
-
|
|
818
812
|
@first = true if @first.nil?
|
|
819
813
|
yield unless @first
|
|
820
814
|
@first = false
|
data/lib/hummel/encode.rb
CHANGED
|
@@ -9,7 +9,7 @@ module Hummel
|
|
|
9
9
|
# Convert a Ruby object to HUML format
|
|
10
10
|
def stringify(obj, cfg = {})
|
|
11
11
|
lines = []
|
|
12
|
-
lines.concat(["%HUML v0.
|
|
12
|
+
lines.concat(["%HUML v0.2.0", ""]) if cfg[:include_version]
|
|
13
13
|
|
|
14
14
|
lines.concat(encode_value(obj, 0, true))
|
|
15
15
|
lines << "" # Ensure document ends with newline
|
|
@@ -25,6 +25,7 @@ module Hummel
|
|
|
25
25
|
def encode_value(value, indent, is_root_level = false)
|
|
26
26
|
return ["null"] if value.nil?
|
|
27
27
|
|
|
28
|
+
# TODO: dynamic dispatch refactor?
|
|
28
29
|
case value
|
|
29
30
|
when TrueClass, FalseClass
|
|
30
31
|
[value.to_s]
|
|
@@ -58,9 +59,8 @@ module Hummel
|
|
|
58
59
|
|
|
59
60
|
# Multi-line string
|
|
60
61
|
str_lines = str.split("\n")
|
|
61
|
-
str_lines.pop if str_lines.last && str_lines.last.empty?
|
|
62
62
|
|
|
63
|
-
["
|
|
63
|
+
['"""'] + str_lines.map { |line| "#{" " * indent}#{line}" } + ["#{" " * (indent - 2)}\"\"\""]
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
# Encode an array value - returns array of lines
|
data/lib/hummel/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hummel
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Derek Bender
|
|
@@ -54,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
54
54
|
- !ruby/object:Gem::Version
|
|
55
55
|
version: '0'
|
|
56
56
|
requirements: []
|
|
57
|
-
rubygems_version:
|
|
57
|
+
rubygems_version: 4.0.4
|
|
58
58
|
specification_version: 4
|
|
59
59
|
summary: A Ruby parser and encoder for HUML (Human Markup Language)
|
|
60
60
|
test_files: []
|