changelog-parser 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/CHANGELOG.md +19 -0
- data/README.md +59 -18
- data/exe/changelog-parser +176 -74
- data/lib/changelog/parser/version.rb +1 -1
- data/lib/changelog/parser.rb +80 -0
- 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: 91646e7a7752f0f7c0766b6f488c9cf551f9ffd6b23f850ddf0b0598ff059c23
|
|
4
|
+
data.tar.gz: cd34eeb7f5033457acb042bf34e1130169de8384a2445a77672f99fa22780c66
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ea798c67a91d6393a2c56a82373e7ac268952989e68185dcf51690b4a65212992b69266b326a2dd8bf9e669a9496fb2ed5528ec4a05e15e516ea6c9e89b9ea7d
|
|
7
|
+
data.tar.gz: 86e2a23610383116b309d8face4db4d8a6d99c201bfdaf162025b0297286c82a434f4f545b06a8844815d35a8b77311c54ba522c337bd29f6a6f96fe9bc8d37a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.2.0] - 2025-12-23
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `between(old_version, new_version)` method to extract content between versions
|
|
8
|
+
- `line_for_version(version)` method with Dependabot-style pattern matching
|
|
9
|
+
- `find_changelog(directory)` class method to locate changelog files
|
|
10
|
+
- `find_and_parse(directory)` class method for one-step discovery and parsing
|
|
11
|
+
- `to_html` method for markdown to HTML conversion (requires optional markdown gem)
|
|
12
|
+
- Vandamme compatibility layer (`require "changelog/parser/vandamme"`)
|
|
13
|
+
- CLI now accepts directories and auto-finds changelog files
|
|
14
|
+
- CLI `between` command for extracting content between versions
|
|
15
|
+
- CLI `validate` command for checking Keep a Changelog format compliance
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- CLI now uses subcommands (`parse`, `list`, `show`, `between`) instead of flags
|
|
20
|
+
- Version matching now uses negative lookahead to avoid substring matches (e.g., won't match 1.0.1 when looking for 1.0.10)
|
|
21
|
+
|
|
3
22
|
## [0.1.0] - 2025-12-23
|
|
4
23
|
|
|
5
24
|
### Added
|
data/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Changelog::Parser
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://rubygems.org/gems/changelog-parser)
|
|
4
|
+
|
|
5
|
+
A Ruby gem for parsing changelog files into structured data. Supports the Keep a Changelog format, markdown headers, and custom patterns.
|
|
4
6
|
|
|
5
7
|
Inspired by [vandamme](https://github.com/tech-angels/vandamme).
|
|
6
8
|
|
|
@@ -94,6 +96,35 @@ Changelog::Parser.new(content, format: :markdown)
|
|
|
94
96
|
Changelog::Parser.new(content, format: :underline)
|
|
95
97
|
```
|
|
96
98
|
|
|
99
|
+
### Extracting content between versions
|
|
100
|
+
|
|
101
|
+
Extract changelog content between two versions (like Dependabot does for PR descriptions):
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
parser = Changelog::Parser.new(changelog)
|
|
105
|
+
|
|
106
|
+
# Get content between old and new version
|
|
107
|
+
parser.between("1.0.0", "2.0.0")
|
|
108
|
+
|
|
109
|
+
# Get content from a version to the end
|
|
110
|
+
parser.between(nil, "1.5.0")
|
|
111
|
+
|
|
112
|
+
# Get content from start to a version
|
|
113
|
+
parser.between("1.5.0", nil)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Finding changelog files
|
|
117
|
+
|
|
118
|
+
Automatically find and parse changelog files in a directory:
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
# Find changelog file (searches for CHANGELOG.md, NEWS, HISTORY, etc.)
|
|
122
|
+
path = Changelog::Parser.find_changelog("/path/to/project")
|
|
123
|
+
|
|
124
|
+
# Find and parse in one step
|
|
125
|
+
result = Changelog::Parser.find_and_parse("/path/to/project")
|
|
126
|
+
```
|
|
127
|
+
|
|
97
128
|
### Custom patterns
|
|
98
129
|
|
|
99
130
|
For changelogs with non-standard formats, provide a custom regex:
|
|
@@ -112,42 +143,52 @@ The gem includes a command-line interface:
|
|
|
112
143
|
|
|
113
144
|
```bash
|
|
114
145
|
# Parse a changelog and output JSON
|
|
115
|
-
changelog-parser CHANGELOG.md
|
|
146
|
+
changelog-parser parse CHANGELOG.md
|
|
116
147
|
|
|
117
|
-
#
|
|
118
|
-
changelog-parser
|
|
148
|
+
# Parse from a directory (auto-finds CHANGELOG.md, NEWS, HISTORY, etc.)
|
|
149
|
+
changelog-parser parse /path/to/project
|
|
119
150
|
|
|
120
151
|
# List versions only
|
|
121
|
-
changelog-parser
|
|
152
|
+
changelog-parser list CHANGELOG.md
|
|
122
153
|
|
|
123
|
-
#
|
|
124
|
-
changelog-parser
|
|
154
|
+
# Show content for a specific version
|
|
155
|
+
changelog-parser show 1.0.0 CHANGELOG.md
|
|
125
156
|
|
|
126
|
-
#
|
|
127
|
-
changelog-parser
|
|
157
|
+
# Show content between two versions (for PR descriptions)
|
|
158
|
+
changelog-parser between 1.0.0 2.0.0 CHANGELOG.md
|
|
128
159
|
|
|
129
|
-
#
|
|
130
|
-
changelog-parser
|
|
160
|
+
# Validate against Keep a Changelog format
|
|
161
|
+
changelog-parser validate CHANGELOG.md
|
|
162
|
+
|
|
163
|
+
# Pretty print JSON
|
|
164
|
+
changelog-parser parse --pretty CHANGELOG.md
|
|
131
165
|
|
|
132
166
|
# Read from stdin
|
|
133
|
-
cat CHANGELOG.md | changelog-parser -
|
|
167
|
+
cat CHANGELOG.md | changelog-parser parse -
|
|
134
168
|
|
|
135
169
|
# Custom regex pattern
|
|
136
|
-
changelog-parser --pattern "^## v([\d.]+)" CHANGELOG.md
|
|
170
|
+
changelog-parser parse --pattern "^## v([\d.]+)" CHANGELOG.md
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Commands
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
parse Parse changelog and output JSON (default)
|
|
177
|
+
list List version numbers only
|
|
178
|
+
show Show content for a specific version
|
|
179
|
+
between Show content between two versions
|
|
180
|
+
validate Validate changelog against Keep a Changelog format
|
|
137
181
|
```
|
|
138
182
|
|
|
139
|
-
###
|
|
183
|
+
### Options
|
|
140
184
|
|
|
141
185
|
```
|
|
142
186
|
-f, --format FORMAT Changelog format (keep_a_changelog, markdown, underline)
|
|
143
|
-
-v, --version VERSION Show only a specific version
|
|
144
|
-
-l, --list List versions only
|
|
145
|
-
-c, --content Output content only (requires --version)
|
|
146
187
|
-p, --pattern REGEX Custom version header regex pattern
|
|
147
188
|
-m, --match-group N Regex capture group for version (default: 1)
|
|
148
189
|
--pretty Pretty print JSON output
|
|
149
190
|
-h, --help Show help message
|
|
150
|
-
--
|
|
191
|
+
--version Show gem version
|
|
151
192
|
```
|
|
152
193
|
|
|
153
194
|
## Supported formats
|
data/exe/changelog-parser
CHANGED
|
@@ -5,16 +5,55 @@ require "optparse"
|
|
|
5
5
|
require "json"
|
|
6
6
|
require_relative "../lib/changelog/parser"
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
def load_changelog(path, options)
|
|
9
|
+
if path.nil? || path == "-"
|
|
10
|
+
$stdin.read
|
|
11
|
+
elsif File.directory?(path)
|
|
12
|
+
changelog_path = Changelog::Parser.find_changelog(path)
|
|
13
|
+
unless changelog_path
|
|
14
|
+
warn "Error: No changelog found in directory: #{path}"
|
|
15
|
+
exit 1
|
|
16
|
+
end
|
|
17
|
+
File.read(changelog_path)
|
|
18
|
+
elsif File.exist?(path)
|
|
19
|
+
File.read(path)
|
|
20
|
+
else
|
|
21
|
+
warn "Error: File or directory not found: #{path}"
|
|
22
|
+
exit 1
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def build_parser(content, options)
|
|
27
|
+
Changelog::Parser.new(
|
|
28
|
+
content,
|
|
29
|
+
format: options[:format],
|
|
30
|
+
version_pattern: options[:pattern],
|
|
31
|
+
match_group: options[:match_group] || 1
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def output_json(data, pretty: false)
|
|
36
|
+
json_data = data.transform_values do |entry|
|
|
37
|
+
entry.transform_values { |v| v.is_a?(Date) ? v.to_s : v }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if pretty
|
|
41
|
+
puts JSON.pretty_generate(json_data)
|
|
42
|
+
else
|
|
43
|
+
puts JSON.generate(json_data)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
options = {}
|
|
48
|
+
global_opts = OptionParser.new do |opts|
|
|
49
|
+
opts.banner = "Usage: changelog-parser <command> [options] [file_or_directory]"
|
|
16
50
|
opts.separator ""
|
|
17
|
-
opts.separator "
|
|
51
|
+
opts.separator "Commands:"
|
|
52
|
+
opts.separator " parse Parse changelog and output JSON (default)"
|
|
53
|
+
opts.separator " list List version numbers only"
|
|
54
|
+
opts.separator " show Show content for a specific version"
|
|
55
|
+
opts.separator " between Show content between two versions"
|
|
56
|
+
opts.separator " validate Validate changelog against Keep a Changelog format"
|
|
18
57
|
opts.separator ""
|
|
19
58
|
opts.separator "Options:"
|
|
20
59
|
|
|
@@ -23,18 +62,6 @@ parser = OptionParser.new do |opts|
|
|
|
23
62
|
options[:format] = f
|
|
24
63
|
end
|
|
25
64
|
|
|
26
|
-
opts.on("-v", "--version VERSION", "Show only a specific version") do |v|
|
|
27
|
-
options[:version] = v
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
opts.on("-l", "--list", "List versions only") do
|
|
31
|
-
options[:output] = :list
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
opts.on("-c", "--content", "Output content only (requires --version)") do
|
|
35
|
-
options[:output] = :content
|
|
36
|
-
end
|
|
37
|
-
|
|
38
65
|
opts.on("-p", "--pattern REGEX", "Custom version header regex pattern") do |p|
|
|
39
66
|
options[:pattern] = Regexp.new(p)
|
|
40
67
|
end
|
|
@@ -47,86 +74,161 @@ parser = OptionParser.new do |opts|
|
|
|
47
74
|
options[:pretty] = true
|
|
48
75
|
end
|
|
49
76
|
|
|
50
|
-
opts.
|
|
77
|
+
opts.on("-h", "--help", "Show this help message") do
|
|
51
78
|
puts opts
|
|
79
|
+
puts ""
|
|
80
|
+
puts "Examples:"
|
|
81
|
+
puts " changelog-parser parse CHANGELOG.md"
|
|
82
|
+
puts " changelog-parser list ."
|
|
83
|
+
puts " changelog-parser show 1.0.0 CHANGELOG.md"
|
|
84
|
+
puts " changelog-parser between 1.0.0 2.0.0 CHANGELOG.md"
|
|
85
|
+
puts " cat CHANGELOG.md | changelog-parser parse -"
|
|
52
86
|
exit
|
|
53
87
|
end
|
|
54
88
|
|
|
55
|
-
opts.
|
|
89
|
+
opts.on("--version", "Show gem version") do
|
|
56
90
|
puts Changelog::Parser::VERSION
|
|
57
91
|
exit
|
|
58
92
|
end
|
|
59
93
|
end
|
|
60
94
|
|
|
61
95
|
begin
|
|
62
|
-
|
|
63
|
-
rescue OptionParser::
|
|
96
|
+
global_opts.parse!
|
|
97
|
+
rescue OptionParser::InvalidOption => e
|
|
64
98
|
warn "Error: #{e.message}"
|
|
65
|
-
warn
|
|
99
|
+
warn global_opts
|
|
66
100
|
exit 1
|
|
67
101
|
end
|
|
68
102
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
103
|
+
command = ARGV.shift || "parse"
|
|
104
|
+
|
|
105
|
+
case command
|
|
106
|
+
when "parse"
|
|
107
|
+
path = ARGV.shift
|
|
108
|
+
content = load_changelog(path, options)
|
|
109
|
+
parser = build_parser(content, options)
|
|
110
|
+
output_json(parser.parse, pretty: options[:pretty])
|
|
111
|
+
|
|
112
|
+
when "list"
|
|
113
|
+
path = ARGV.shift
|
|
114
|
+
content = load_changelog(path, options)
|
|
115
|
+
parser = build_parser(content, options)
|
|
116
|
+
puts parser.versions.join("\n")
|
|
117
|
+
|
|
118
|
+
when "show"
|
|
119
|
+
version = ARGV.shift
|
|
120
|
+
path = ARGV.shift
|
|
121
|
+
|
|
122
|
+
# Check if version looks like a file path (missing version argument)
|
|
123
|
+
if version && File.exist?(version) && !path
|
|
124
|
+
warn "Error: show requires a version argument"
|
|
125
|
+
warn "Usage: changelog-parser show <version> [file_or_directory]"
|
|
75
126
|
exit 1
|
|
76
127
|
end
|
|
77
|
-
File.read(file)
|
|
78
|
-
end
|
|
79
128
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
end
|
|
129
|
+
unless version
|
|
130
|
+
warn "Error: show requires a version argument"
|
|
131
|
+
warn "Usage: changelog-parser show <version> [file_or_directory]"
|
|
132
|
+
exit 1
|
|
133
|
+
end
|
|
85
134
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
135
|
+
content = load_changelog(path, options)
|
|
136
|
+
parser = build_parser(content, options)
|
|
137
|
+
entry = parser[version]
|
|
138
|
+
|
|
139
|
+
unless entry
|
|
140
|
+
warn "Error: Version not found: #{version}"
|
|
141
|
+
exit 1
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
puts entry[:content]
|
|
145
|
+
|
|
146
|
+
when "between"
|
|
147
|
+
old_version = ARGV.shift
|
|
148
|
+
new_version = ARGV.shift
|
|
149
|
+
path = ARGV.shift
|
|
150
|
+
|
|
151
|
+
# Check if new_version looks like a file path (missing second version)
|
|
152
|
+
if new_version && File.exist?(new_version) && !path
|
|
153
|
+
warn "Error: between requires two version arguments"
|
|
154
|
+
warn "Usage: changelog-parser between <old_version> <new_version> [file_or_directory]"
|
|
155
|
+
exit 1
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
unless old_version && new_version
|
|
159
|
+
warn "Error: between requires two version arguments"
|
|
160
|
+
warn "Usage: changelog-parser between <old_version> <new_version> [file_or_directory]"
|
|
101
161
|
exit 1
|
|
102
162
|
end
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
163
|
+
|
|
164
|
+
content = load_changelog(path, options)
|
|
165
|
+
parser = build_parser(content, options)
|
|
166
|
+
result = parser.between(old_version, new_version)
|
|
167
|
+
|
|
168
|
+
if result
|
|
169
|
+
puts result
|
|
106
170
|
else
|
|
107
|
-
warn "
|
|
171
|
+
warn "Error: Could not find versions in changelog"
|
|
108
172
|
exit 1
|
|
109
173
|
end
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
174
|
+
|
|
175
|
+
when "validate"
|
|
176
|
+
path = ARGV.shift
|
|
177
|
+
content = load_changelog(path, options)
|
|
178
|
+
parser = build_parser(content, options)
|
|
179
|
+
result = parser.parse
|
|
180
|
+
errors = []
|
|
181
|
+
warnings = []
|
|
182
|
+
|
|
183
|
+
# Check if any versions were found
|
|
184
|
+
if result.empty?
|
|
185
|
+
errors << "No versions found in changelog"
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Check for Unreleased section
|
|
189
|
+
unless result.key?("Unreleased")
|
|
190
|
+
warnings << "No [Unreleased] section found"
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Check for empty versions (Unreleased can be empty)
|
|
194
|
+
result.each do |version, entry|
|
|
195
|
+
next if version == "Unreleased"
|
|
196
|
+
if entry[:content].nil? || entry[:content].strip.empty?
|
|
197
|
+
warnings << "Version #{version} has no content"
|
|
116
198
|
end
|
|
117
|
-
{ options[:version] => entry }
|
|
118
|
-
else
|
|
119
|
-
result
|
|
120
199
|
end
|
|
121
200
|
|
|
122
|
-
#
|
|
123
|
-
|
|
124
|
-
|
|
201
|
+
# Check date ordering (should be descending)
|
|
202
|
+
dated_versions = result.reject { |_, e| e[:date].nil? }
|
|
203
|
+
dates = dated_versions.values.map { |e| e[:date] }
|
|
204
|
+
unless dates == dates.sort.reverse
|
|
205
|
+
warnings << "Dates are not in descending order"
|
|
125
206
|
end
|
|
126
207
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
208
|
+
# Check for missing dates
|
|
209
|
+
result.each do |version, entry|
|
|
210
|
+
next if version == "Unreleased"
|
|
211
|
+
if entry[:date].nil?
|
|
212
|
+
warnings << "Version #{version} has no date"
|
|
213
|
+
end
|
|
131
214
|
end
|
|
215
|
+
|
|
216
|
+
# Output results
|
|
217
|
+
if errors.empty? && warnings.empty?
|
|
218
|
+
puts "Valid changelog with #{result.size} version(s)"
|
|
219
|
+
exit 0
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
errors.each { |e| warn "Error: #{e}" }
|
|
223
|
+
warnings.each { |w| warn "Warning: #{w}" }
|
|
224
|
+
|
|
225
|
+
exit 1 if errors.any?
|
|
226
|
+
exit 0
|
|
227
|
+
|
|
228
|
+
else
|
|
229
|
+
# Treat unknown command as a path (backwards compatibility)
|
|
230
|
+
path = command
|
|
231
|
+
content = load_changelog(path, options)
|
|
232
|
+
parser = build_parser(content, options)
|
|
233
|
+
output_json(parser.parse, pretty: options[:pretty])
|
|
132
234
|
end
|
data/lib/changelog/parser.rb
CHANGED
|
@@ -22,6 +22,17 @@ module Changelog
|
|
|
22
22
|
underline: UNDERLINE_HEADER
|
|
23
23
|
}.freeze
|
|
24
24
|
|
|
25
|
+
# Common changelog filenames in priority order (from Dependabot)
|
|
26
|
+
CHANGELOG_FILENAMES = %w[
|
|
27
|
+
changelog
|
|
28
|
+
news
|
|
29
|
+
changes
|
|
30
|
+
history
|
|
31
|
+
release
|
|
32
|
+
whatsnew
|
|
33
|
+
releases
|
|
34
|
+
].freeze
|
|
35
|
+
|
|
25
36
|
attr_reader :changelog, :version_pattern, :match_group
|
|
26
37
|
|
|
27
38
|
def initialize(changelog, format: nil, version_pattern: nil, match_group: 1)
|
|
@@ -91,6 +102,46 @@ module Changelog
|
|
|
91
102
|
end
|
|
92
103
|
end
|
|
93
104
|
|
|
105
|
+
def between(old_version, new_version)
|
|
106
|
+
old_line = line_for_version(old_version)
|
|
107
|
+
new_line = line_for_version(new_version)
|
|
108
|
+
lines = changelog.split("\n")
|
|
109
|
+
|
|
110
|
+
range = if old_line && new_line
|
|
111
|
+
old_line < new_line ? (old_line..-1) : (new_line..old_line - 1)
|
|
112
|
+
elsif old_line
|
|
113
|
+
old_line.zero? ? nil : (0..old_line - 1)
|
|
114
|
+
elsif new_line
|
|
115
|
+
(new_line..-1)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
return nil unless range
|
|
119
|
+
|
|
120
|
+
lines[range]&.join("\n")&.rstrip
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def line_for_version(version)
|
|
124
|
+
return nil unless version
|
|
125
|
+
|
|
126
|
+
version = version.to_s.gsub(/^v/i, "")
|
|
127
|
+
escaped = Regexp.escape(version)
|
|
128
|
+
lines = changelog.split("\n")
|
|
129
|
+
|
|
130
|
+
lines.find_index.with_index do |line, index|
|
|
131
|
+
next false unless line.match?(/(?<!\.)#{escaped}(?![.\-\w])/)
|
|
132
|
+
next false if line.match?(/#{escaped}\.\./)
|
|
133
|
+
|
|
134
|
+
next true if line.start_with?("#", "!", "==")
|
|
135
|
+
next true if line.match?(/^v?#{escaped}:?\s/)
|
|
136
|
+
next true if line.match?(/^\[#{escaped}\]/)
|
|
137
|
+
next true if line.match?(/^[\+\*\-]\s+(version\s+)?#{escaped}/i)
|
|
138
|
+
next true if line.match?(/^\d{4}-\d{2}-\d{2}/)
|
|
139
|
+
next true if lines[index + 1]&.match?(/^[=\-\+]{3,}\s*$/)
|
|
140
|
+
|
|
141
|
+
false
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
94
145
|
def self.parse(changelog, **options)
|
|
95
146
|
new(changelog, **options).parse
|
|
96
147
|
end
|
|
@@ -100,6 +151,35 @@ module Changelog
|
|
|
100
151
|
new(content, **options).parse
|
|
101
152
|
end
|
|
102
153
|
|
|
154
|
+
def self.find_changelog(directory = ".")
|
|
155
|
+
files = Dir.entries(directory).select { |f| File.file?(File.join(directory, f)) }
|
|
156
|
+
|
|
157
|
+
CHANGELOG_FILENAMES.each do |name|
|
|
158
|
+
pattern = /\A#{name}(\.(md|txt|rst|rdoc|markdown))?\z/i
|
|
159
|
+
candidates = files.select { |f| f.match?(pattern) }
|
|
160
|
+
candidates = candidates.reject { |f| f.end_with?(".sh") }
|
|
161
|
+
|
|
162
|
+
return File.join(directory, candidates.first) if candidates.one?
|
|
163
|
+
|
|
164
|
+
candidates.each do |candidate|
|
|
165
|
+
path = File.join(directory, candidate)
|
|
166
|
+
size = File.size(path)
|
|
167
|
+
next if size > 1_000_000 || size < 100
|
|
168
|
+
|
|
169
|
+
return path
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
nil
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def self.find_and_parse(directory = ".", **options)
|
|
177
|
+
path = find_changelog(directory)
|
|
178
|
+
return nil unless path
|
|
179
|
+
|
|
180
|
+
parse_file(path, **options)
|
|
181
|
+
end
|
|
182
|
+
|
|
103
183
|
def resolve_pattern(format, custom_pattern)
|
|
104
184
|
return custom_pattern if custom_pattern
|
|
105
185
|
return FORMATS.fetch(format) if format
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: changelog-parser
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Nesbitt
|
|
@@ -10,7 +10,7 @@ cert_chain: []
|
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies: []
|
|
12
12
|
description: A Ruby gem for parsing changelog files. Supports Keep a Changelog format,
|
|
13
|
-
markdown headers, and custom patterns.
|
|
13
|
+
markdown headers, and custom patterns.
|
|
14
14
|
email:
|
|
15
15
|
- andrewnez@gmail.com
|
|
16
16
|
executables:
|