keepachangelog 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/.rubocop.yml +3 -0
- data/CHANGELOG.md +6 -1
- data/Gemfile.lock +2 -2
- data/features/help.feature +2 -3
- data/features/{parse.feature → markdown.feature} +4 -4
- data/features/yaml.feature +17 -0
- data/lib/keepachangelog/cli.rb +22 -6
- data/lib/keepachangelog/markdown_printer.rb +90 -0
- data/lib/keepachangelog/parser.rb +33 -61
- data/lib/keepachangelog/parser/markdown.rb +68 -0
- data/lib/keepachangelog/parser/yaml.rb +110 -0
- data/package.json +1 -1
- data/spec/markdown_printer_spec.rb +19 -0
- data/spec/parser/markdown_spec.rb +109 -0
- data/spec/parser/yaml_spec.rb +50 -0
- data/spec/parser_spec.rb +0 -118
- data/spec/spec_helper.rb +2 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: beb911086da3260f5c4f06ff2f57b219ddb19a06
|
4
|
+
data.tar.gz: d08ff76239c9a49db9ee5f46f33d3f4df75498bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5fb6c397a7f820740f5f86206f6e37211afbfc564afd4cf17c0f7de4907b6ff57faf50333abec10ccde44b4d18f04a72d0c1d096d148d0e9c54b7f033bc33fce
|
7
|
+
data.tar.gz: 0237365f64e45fd84ee99b74fd9c0b68f57621f063e0d2c7abf249525c7149f256ade2bb9ceb5b5c979d4ba05ff064f590f8d26377d147a65c8c75c263ea31a3
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -4,11 +4,16 @@ Alla ändringar till detta projekt dokumenteras i denna fil.
|
|
4
4
|
Formatet är baserat på [Keep a Changelog](http://keepachangelog.com/)
|
5
5
|
och detta projekt följer [Semantic Versioning](http://semver.org/).
|
6
6
|
|
7
|
+
## [0.2.0] - 2017-03-27
|
8
|
+
- Förmåga att läsa in Changelog i YAML-format.
|
9
|
+
- Förmåga att skriva till Markdown-format.
|
10
|
+
|
7
11
|
## [0.1.0] - 2017-03-27
|
8
12
|
### Nytt
|
9
13
|
- Ruby gem som exponerar verktyget via Ruby och CLI.
|
10
14
|
- Förmåga att konvertera Changelog till JSON.
|
11
15
|
- Förmåga att konvertera Changelog till YAML.
|
12
16
|
|
13
|
-
[Unreleased]: https://git.basalt.se/chbr/keepachangelog/compare/0.
|
17
|
+
[Unreleased]: https://git.basalt.se/chbr/keepachangelog/compare/0.2.0...HEAD
|
18
|
+
[0.2.0]: https://git.basalt.se/chbr/keepachangelog/compare/0.1.0...0.2.0
|
14
19
|
[0.1.0]: https://git.basalt.se/chbr/keepachangelog/compare/77986bc...0.1.0
|
data/Gemfile.lock
CHANGED
data/features/help.feature
CHANGED
@@ -8,6 +8,5 @@ Feature: Show help
|
|
8
8
|
Then the output should contain "Keepachangelog commands"
|
9
9
|
|
10
10
|
Scenario: Getting help about a command
|
11
|
-
When I successfully run `keepachangelog help
|
12
|
-
Then the output should contain "
|
13
|
-
And the output should contain "Usage"
|
11
|
+
When I successfully run `keepachangelog help markdown`
|
12
|
+
Then the output should contain "Usage"
|
@@ -10,10 +10,10 @@ Feature: List transformators
|
|
10
10
|
### New
|
11
11
|
- Feature A
|
12
12
|
"""
|
13
|
-
When I successfully run `keepachangelog
|
13
|
+
When I successfully run `keepachangelog markdown`
|
14
14
|
Then the output should contain:
|
15
15
|
"""
|
16
|
-
|
16
|
+
{"versions":{"Unreleased":{"url":null,"date":null,"changes":{"New":["Feature A"]}}}}
|
17
17
|
"""
|
18
18
|
|
19
19
|
Scenario: Running without command
|
@@ -26,7 +26,7 @@ Feature: List transformators
|
|
26
26
|
When I successfully run `keepachangelog`
|
27
27
|
Then the output should contain:
|
28
28
|
"""
|
29
|
-
|
29
|
+
{"versions":{"Unreleased":{"url":null,"date":null,"changes":{"New":["Feature A"]}}}}
|
30
30
|
"""
|
31
31
|
|
32
32
|
Scenario: Changelog has a non-default filename
|
@@ -39,5 +39,5 @@ Feature: List transformators
|
|
39
39
|
When I successfully run `keepachangelog --path=HISTORY.md`
|
40
40
|
Then the output should contain:
|
41
41
|
"""
|
42
|
-
|
42
|
+
{"versions":{"Unreleased":{"url":null,"date":null,"changes":{"New":["Feature A"]}}}}
|
43
43
|
"""
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Feature: List transformators
|
2
|
+
|
3
|
+
Parse a changelog by running `keepachangelog parse` or just simply
|
4
|
+
`keepachangelog`.
|
5
|
+
|
6
|
+
Scenario: Running with command
|
7
|
+
Given a file "changelog/1.0.0/1.yml" with:
|
8
|
+
"""
|
9
|
+
---
|
10
|
+
title: Feature A
|
11
|
+
type: New
|
12
|
+
"""
|
13
|
+
When I successfully run `keepachangelog yaml`
|
14
|
+
Then the output should contain:
|
15
|
+
"""
|
16
|
+
{"versions":{"1.0.0":{"changes":{"New":["Feature A"]}}}}
|
17
|
+
"""
|
data/lib/keepachangelog/cli.rb
CHANGED
@@ -18,22 +18,38 @@ module Keepachangelog
|
|
18
18
|
shell.say Keepachangelog.version
|
19
19
|
end
|
20
20
|
|
21
|
-
desc '
|
21
|
+
desc 'markdown', 'Parse a changelog in markdown'
|
22
22
|
option :format, type: :string,
|
23
23
|
desc: 'The output format',
|
24
24
|
default: 'json',
|
25
25
|
banner: 'json|yaml',
|
26
26
|
aliases: '-f'
|
27
27
|
option :path, type: :string,
|
28
|
-
desc: 'Path to the
|
28
|
+
desc: 'Path to the Changelog file',
|
29
29
|
default: 'CHANGELOG.md',
|
30
30
|
aliases: '-p'
|
31
|
-
def
|
32
|
-
require 'keepachangelog/parser'
|
33
|
-
p =
|
31
|
+
def markdown
|
32
|
+
require 'keepachangelog/parser/markdown'
|
33
|
+
p = MarkdownParser.load(options[:path])
|
34
34
|
shell.say p.send("to_#{options[:format]}")
|
35
35
|
end
|
36
36
|
|
37
|
-
|
37
|
+
desc 'yaml', 'Parse a folder of YAML files'
|
38
|
+
option :format, type: :string,
|
39
|
+
desc: 'The output format',
|
40
|
+
default: 'json',
|
41
|
+
banner: 'json|yaml',
|
42
|
+
aliases: '-f'
|
43
|
+
option :path, type: :string,
|
44
|
+
desc: 'Path to the yaml folder',
|
45
|
+
default: 'changelog',
|
46
|
+
aliases: '-p'
|
47
|
+
def yaml
|
48
|
+
require 'keepachangelog/parser/yaml'
|
49
|
+
p = YamlParser.load(options[:path])
|
50
|
+
shell.say p.send("to_#{options[:format]}")
|
51
|
+
end
|
52
|
+
|
53
|
+
default_task :markdown
|
38
54
|
end
|
39
55
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Keepachangelog
|
2
|
+
class MarkdownPrinter
|
3
|
+
attr_accessor :options
|
4
|
+
attr_accessor :versions
|
5
|
+
|
6
|
+
def initialize(versions, options = {})
|
7
|
+
self.options = options
|
8
|
+
self.versions = versions
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
[
|
13
|
+
"# #{options[:title] || default_title}",
|
14
|
+
clean_intro(options[:intro]) || default_intro,
|
15
|
+
'',
|
16
|
+
versions.reverse_each.map do |k, v|
|
17
|
+
version(k, v)
|
18
|
+
end,
|
19
|
+
anchors
|
20
|
+
].flatten.join("\n")
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def clean_intro(text)
|
26
|
+
text.to_s.strip.gsub("\n", "\n\n")
|
27
|
+
end
|
28
|
+
|
29
|
+
def version(header, content)
|
30
|
+
[
|
31
|
+
version_header(header),
|
32
|
+
content['changes'].map { |k, v| section(k, v) }
|
33
|
+
]
|
34
|
+
end
|
35
|
+
|
36
|
+
def section(header, content)
|
37
|
+
[
|
38
|
+
"### #{header}",
|
39
|
+
content.map { |c| change(c) },
|
40
|
+
''
|
41
|
+
]
|
42
|
+
end
|
43
|
+
|
44
|
+
def anchors
|
45
|
+
v = versions.keys.sort.reverse
|
46
|
+
(0..v.length - 1).map { |i| anchor(v, i) }
|
47
|
+
end
|
48
|
+
|
49
|
+
def anchor(v, i)
|
50
|
+
from_v = i == v.length - 1 ? first_commit : v[i + 1]
|
51
|
+
to_v = v[i] == 'Unreleased' ? 'HEAD' : v[i]
|
52
|
+
"[#{v[i]}]: #{options[:url]}/compare/#{from_v}..#{to_v}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def change(content)
|
56
|
+
"- #{content}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def default_title
|
60
|
+
'Change log'
|
61
|
+
end
|
62
|
+
|
63
|
+
def default_intro
|
64
|
+
"All notable changes to this project will be documented in this file.
|
65
|
+
|
66
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
67
|
+
and this project adheres to [Semantic Versioning](http://semver.org/)."
|
68
|
+
end
|
69
|
+
|
70
|
+
def first_commit
|
71
|
+
`git rev-parse --short $(git rev-list --max-parents=0 HEAD) 2>/dev/null`
|
72
|
+
.strip
|
73
|
+
end
|
74
|
+
|
75
|
+
def version_date(version)
|
76
|
+
date = `git log -1 --format=%aI #{version} 2>/dev/null`.strip
|
77
|
+
DateTime.parse(date).strftime('%Y-%m-%d')
|
78
|
+
rescue
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
|
82
|
+
def version_header(version)
|
83
|
+
header = version
|
84
|
+
header = "[#{header}]" if options[:url]
|
85
|
+
date = version_date(version)
|
86
|
+
header += " - #{date}" if date
|
87
|
+
"## #{header}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -1,82 +1,54 @@
|
|
1
|
+
require 'keepachangelog/markdown_printer'
|
2
|
+
|
1
3
|
module Keepachangelog
|
2
4
|
class Parser
|
3
5
|
attr_accessor :parsed_content
|
4
6
|
|
5
|
-
def initialize
|
6
|
-
self.parsed_content =
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.load(filename = 'CHANGELOG.md')
|
10
|
-
content = File.open(filename, &:read)
|
11
|
-
new(content)
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.parse(content)
|
15
|
-
new(content)
|
7
|
+
def initialize
|
8
|
+
self.parsed_content = { 'versions' => {} }
|
16
9
|
end
|
17
10
|
|
11
|
+
# Changelog in JSON format
|
12
|
+
#
|
13
|
+
# Example:
|
14
|
+
# ```json
|
15
|
+
# {"1.0.0": { "changes": { "New": ["Feature A"] } } }
|
16
|
+
# ```
|
18
17
|
def to_json
|
19
18
|
parsed_content.to_json
|
20
19
|
end
|
21
20
|
|
21
|
+
# Changelog in YAML format
|
22
|
+
#
|
23
|
+
# Example:
|
24
|
+
# ```yaml
|
25
|
+
# ---
|
26
|
+
# 0.1.0:
|
27
|
+
# changes:
|
28
|
+
# New:
|
29
|
+
# - Feature A
|
30
|
+
# ```
|
22
31
|
def to_yaml
|
23
32
|
parsed_content.to_yaml
|
24
33
|
end
|
25
34
|
|
35
|
+
# Changelog as a Ruby string
|
36
|
+
#
|
37
|
+
# Example:
|
38
|
+
# ```ruby
|
39
|
+
# {"0.1.0"=>{"changes"=>{"New"=>["Feature A"]}}
|
40
|
+
# ```
|
26
41
|
def to_s
|
27
42
|
parsed_content.to_s
|
28
43
|
end
|
29
44
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
def clean(content)
|
40
|
-
content.sub(/^.*?\n\s*## /, '## ')
|
41
|
-
end
|
42
|
-
|
43
|
-
def parse_version(content, anchors)
|
44
|
-
header_pattern = /\[(?<name>.*)\]( - (?<date>\d\d\d\d-\d\d-\d\d))?/
|
45
|
-
sections = content.split(/\n\s*### /)
|
46
|
-
header = sections[0].match header_pattern
|
47
|
-
{
|
48
|
-
'version' => header[:name],
|
49
|
-
'url' => get_url(header[:name], anchors),
|
50
|
-
'date' => header[:date],
|
51
|
-
'changes' => sections[1..-1].map { |s| parse_section s }.to_h
|
52
|
-
}
|
53
|
-
end
|
54
|
-
|
55
|
-
def get_url(version, anchors)
|
56
|
-
anchors.keys.include?(version) ? anchors[version] : nil
|
57
|
-
end
|
58
|
-
|
59
|
-
def parse_section(content)
|
60
|
-
lines = content.split("\n")
|
61
|
-
bullets = lines[1..-1]
|
62
|
-
.select { |s| s.strip.start_with?('- ') }
|
63
|
-
.map { |s| clean_bullet(s) }
|
64
|
-
[lines[0], bullets]
|
65
|
-
end
|
66
|
-
|
67
|
-
def clean_bullet(string)
|
68
|
-
string.strip.gsub(/^\s*- /, '').gsub(/\(.*#\d+\)\.?$/, '').strip
|
69
|
-
end
|
70
|
-
|
71
|
-
def extract_anchors!(content)
|
72
|
-
anchor_pattern = /\n\s*\[(.*)\]: (.*)\s*\n/
|
73
|
-
anchors = content.scan anchor_pattern
|
74
|
-
cleaned_content = ''
|
75
|
-
while cleaned_content.to_s != content.to_s
|
76
|
-
cleaned_content = content.gsub anchor_pattern, "\n"
|
77
|
-
content.replace(cleaned_content)
|
78
|
-
end
|
79
|
-
anchors.map { |x| [x[0], x[1]] }.to_h
|
45
|
+
# Changelog as Markdown
|
46
|
+
def to_md
|
47
|
+
md = MarkdownPrinter.new(parsed_content['versions'],
|
48
|
+
title: parsed_content['title'],
|
49
|
+
intro: parsed_content['intro'],
|
50
|
+
url: parsed_content['url'])
|
51
|
+
md.to_s
|
80
52
|
end
|
81
53
|
end
|
82
54
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Keepachangelog
|
2
|
+
# Parser for Markdown content
|
3
|
+
class MarkdownParser < Parser
|
4
|
+
# Parse raw markdown content
|
5
|
+
def self.parse(content = '')
|
6
|
+
new.parse(content)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Parse a file with markdown content
|
10
|
+
def self.load(filename = 'CHANGELOG.md')
|
11
|
+
parse File.open(filename, &:read)
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse(content)
|
15
|
+
content = "\n" + clean(content).strip + "\n"
|
16
|
+
anchors = extract_anchors! content
|
17
|
+
versions = content.split(/\n\s*## /)[1..-1]
|
18
|
+
{
|
19
|
+
'versions' => versions.map { |v| parse_version v, anchors }.to_h
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def clean(content)
|
26
|
+
content.sub(/^.*?\n\s*## /, '## ')
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse_version(content, anchors)
|
30
|
+
header_pattern = /\[(?<name>.*)\]( - (?<date>\d\d\d\d-\d\d-\d\d))?/
|
31
|
+
sections = content.split(/\n\s*### /)
|
32
|
+
header = sections[0].match header_pattern
|
33
|
+
[header[:name],
|
34
|
+
{
|
35
|
+
'url' => get_url(header[:name], anchors),
|
36
|
+
'date' => header[:date],
|
37
|
+
'changes' => sections[1..-1].map { |s| parse_section s }.to_h
|
38
|
+
}]
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_url(version, anchors)
|
42
|
+
anchors.keys.include?(version) ? anchors[version] : nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def parse_section(content)
|
46
|
+
lines = content.split("\n")
|
47
|
+
bullets = lines[1..-1]
|
48
|
+
.select { |s| s.strip.start_with?('- ') }
|
49
|
+
.map { |s| clean_bullet(s) }
|
50
|
+
[lines[0], bullets]
|
51
|
+
end
|
52
|
+
|
53
|
+
def clean_bullet(string)
|
54
|
+
string.strip.gsub(/^\s*- /, '').gsub(/\(.*#\d+\)\.?$/, '').strip
|
55
|
+
end
|
56
|
+
|
57
|
+
def extract_anchors!(content)
|
58
|
+
anchor_pattern = /\n\s*\[(.*)\]: (.*)\s*\n/
|
59
|
+
anchors = content.scan anchor_pattern
|
60
|
+
cleaned_content = ''
|
61
|
+
while cleaned_content.to_s != content.to_s
|
62
|
+
cleaned_content = content.gsub anchor_pattern, "\n"
|
63
|
+
content.replace(cleaned_content)
|
64
|
+
end
|
65
|
+
anchors.map { |x| [x[0], x[1]] }.to_h
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module Keepachangelog
|
2
|
+
# Parser for YAML content
|
3
|
+
#
|
4
|
+
# The YAML files describing the Changelog are expected to be in a folder
|
5
|
+
# structure where each version is its own folder and each Merge Request
|
6
|
+
# or Pull Request is in its own YAML-file.
|
7
|
+
#
|
8
|
+
# ```
|
9
|
+
# changelog
|
10
|
+
# ├── 0.1.0
|
11
|
+
# │ └── 1-first-merge-request.yaml
|
12
|
+
# ├── 0.2.0
|
13
|
+
# │ └── 3-another-cool-mr.yaml
|
14
|
+
# ├── 0.3.0
|
15
|
+
# │ ├── 8-fixing-some-stuff.yaml
|
16
|
+
# │ └── 9-add-new-feature.yaml
|
17
|
+
# └── unreleased
|
18
|
+
# └── 11-minor-patch.yaml
|
19
|
+
# ```
|
20
|
+
#
|
21
|
+
# Each YAML file is expected to be in the following format:
|
22
|
+
#
|
23
|
+
# ```yaml
|
24
|
+
# ---
|
25
|
+
# title: The ability to perform Foo while Bar is active
|
26
|
+
# merge_request: 11
|
27
|
+
# issue: 42
|
28
|
+
# author: @chbr
|
29
|
+
# type: New
|
30
|
+
# ```
|
31
|
+
#
|
32
|
+
# - `title` is a single sentence without punctiation that describes the
|
33
|
+
# change
|
34
|
+
# - `merge_request` is the ID of the MR or PR (optional)
|
35
|
+
# - `issue` is the ID of the issue (optional)
|
36
|
+
# - `author` is the username of the author (optional)
|
37
|
+
# - `type` is the type of change, for example *New*, *Changed*, *Fixed*,
|
38
|
+
# *Removed* or *Security*.
|
39
|
+
class YamlParser < Parser
|
40
|
+
# Parse raw yaml content of a single file
|
41
|
+
def self.parse(content, version = 'unreleased')
|
42
|
+
new.parse(content, version)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Parse a folder with YAML files
|
46
|
+
def self.load(path = 'changelog')
|
47
|
+
p = new
|
48
|
+
p.load(path)
|
49
|
+
p
|
50
|
+
end
|
51
|
+
|
52
|
+
# Parse raw yaml content of a single file
|
53
|
+
def parse(content, version)
|
54
|
+
initialize_version version
|
55
|
+
yaml = YAML.safe_load content
|
56
|
+
return {} unless yaml
|
57
|
+
add_change yaml, version
|
58
|
+
end
|
59
|
+
|
60
|
+
# Parse a folder with YAML files
|
61
|
+
def load(path = 'changelog')
|
62
|
+
read_meta("#{path}/meta.yaml")
|
63
|
+
Dir.glob("#{path}/*").each { |f| parse_version(f) }
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def read_meta(path)
|
69
|
+
return unless File.exist?(path)
|
70
|
+
content = File.open(path, &:read)
|
71
|
+
yaml = YAML.safe_load content
|
72
|
+
return unless yaml
|
73
|
+
parsed_content['title'] = yaml['title']
|
74
|
+
parsed_content['url'] = yaml['url']
|
75
|
+
parsed_content['intro'] = yaml['intro']
|
76
|
+
end
|
77
|
+
|
78
|
+
def add_change(yaml, version)
|
79
|
+
changes = parsed_content['versions'][version]['changes']
|
80
|
+
changes[yaml['type']] = (changes[yaml['type']] || []) +
|
81
|
+
[generate_line(yaml)]
|
82
|
+
parsed_content
|
83
|
+
end
|
84
|
+
|
85
|
+
def parse_version(folder)
|
86
|
+
version = File.basename(folder)
|
87
|
+
return if version == 'meta.yaml'
|
88
|
+
initialize_version version
|
89
|
+
files = Dir.glob("#{folder}/**/*.yaml") +
|
90
|
+
Dir.glob("#{folder}/**/*.yml")
|
91
|
+
files.sort.each { |f| parse_file(f, version) }
|
92
|
+
end
|
93
|
+
|
94
|
+
def parse_file(filename, version)
|
95
|
+
parse File.open(filename, &:read), version
|
96
|
+
end
|
97
|
+
|
98
|
+
def generate_line(yaml)
|
99
|
+
line = yaml['title']
|
100
|
+
line += " (!#{yaml['merge_request']})" if yaml['merge_request']
|
101
|
+
line += " (##{yaml['issue']})" if yaml['issue']
|
102
|
+
line += " (#{yaml['author']})" if yaml['author']
|
103
|
+
line
|
104
|
+
end
|
105
|
+
|
106
|
+
def initialize_version(version)
|
107
|
+
parsed_content['versions'][version] = { 'changes' => {} }
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
data/package.json
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Keepachangelog
|
4
|
+
describe MarkdownPrinter do
|
5
|
+
describe '.to_s' do
|
6
|
+
it 'should print markdown document' do
|
7
|
+
versions = {
|
8
|
+
'1.0.0' => {
|
9
|
+
'changes' => { 'New' => ['Feature A'] }
|
10
|
+
}
|
11
|
+
}
|
12
|
+
p = MarkdownPrinter.new(versions, title: 'My Title')
|
13
|
+
md = p.to_s
|
14
|
+
expect(md).to match('# My Title')
|
15
|
+
expect(md).to match('## 1.0.0')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Keepachangelog
|
4
|
+
describe MarkdownParser do
|
5
|
+
describe '.parse' do
|
6
|
+
it 'should parse empty content' do
|
7
|
+
cl = MarkdownParser.parse('')
|
8
|
+
expect(cl).to eq('versions' => {})
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should parse single version' do
|
12
|
+
content = "
|
13
|
+
## [1.2.3] - 2017-01-01
|
14
|
+
### New
|
15
|
+
- Feature A
|
16
|
+
### Fixed
|
17
|
+
- Feature B
|
18
|
+
[1.2.3]: http://test.io
|
19
|
+
"
|
20
|
+
cl = MarkdownParser.parse(content)
|
21
|
+
expect(cl).to eq(
|
22
|
+
'versions' => {
|
23
|
+
'1.2.3' => {
|
24
|
+
'url' => 'http://test.io',
|
25
|
+
'date' => '2017-01-01',
|
26
|
+
'changes' => {
|
27
|
+
'New' => ['Feature A'],
|
28
|
+
'Fixed' => ['Feature B']
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should parse multiple versions' do
|
36
|
+
content = "
|
37
|
+
## [2.0.0] - 2017-01-01
|
38
|
+
### New
|
39
|
+
- Feature A
|
40
|
+
## [1.0.0]
|
41
|
+
### Fixed
|
42
|
+
- Feature B
|
43
|
+
[1.0.0]: http://test.io
|
44
|
+
"
|
45
|
+
cl = MarkdownParser.parse(content)
|
46
|
+
expect(cl).to eq(
|
47
|
+
'versions' => {
|
48
|
+
'2.0.0' => {
|
49
|
+
'url' => nil,
|
50
|
+
'date' => '2017-01-01',
|
51
|
+
'changes' => { 'New' => ['Feature A'] }
|
52
|
+
},
|
53
|
+
'1.0.0' => {
|
54
|
+
'url' => 'http://test.io',
|
55
|
+
'date' => nil,
|
56
|
+
'changes' => { 'Fixed' => ['Feature B'] }
|
57
|
+
}
|
58
|
+
}
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should parse version without sections' do
|
63
|
+
content = "
|
64
|
+
## [3.0.0]
|
65
|
+
## [2.0.0] - 2017-01-01
|
66
|
+
### New
|
67
|
+
- Feature A
|
68
|
+
## [1.0.0]
|
69
|
+
"
|
70
|
+
cl = MarkdownParser.parse(content)
|
71
|
+
expect(cl).to eq(
|
72
|
+
'versions' => {
|
73
|
+
'3.0.0' => {
|
74
|
+
'url' => nil, 'date' => nil, 'changes' => {}
|
75
|
+
},
|
76
|
+
'2.0.0' => {
|
77
|
+
'url' => nil,
|
78
|
+
'date' => '2017-01-01',
|
79
|
+
'changes' => { 'New' => ['Feature A'] }
|
80
|
+
},
|
81
|
+
'1.0.0' => {
|
82
|
+
'url' => nil, 'date' => nil, 'changes' => {}
|
83
|
+
}
|
84
|
+
}
|
85
|
+
)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '.load' do
|
90
|
+
it 'should parse content of file' do
|
91
|
+
content = 'test changelog'
|
92
|
+
allow(File).to receive(:open).and_call_original
|
93
|
+
expect(File).to receive(:open).with('test.md')
|
94
|
+
.and_yield(StringIO.new(content))
|
95
|
+
expect(MarkdownParser).to receive(:parse).with(content)
|
96
|
+
MarkdownParser.load('test.md')
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should throw on non-existent file' do
|
100
|
+
expect do
|
101
|
+
MarkdownParser.load('invalid-file')
|
102
|
+
end.to raise_exception(
|
103
|
+
Errno::ENOENT,
|
104
|
+
'No such file or directory @ rb_sysopen - invalid-file'
|
105
|
+
)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Keepachangelog
|
4
|
+
describe YamlParser do
|
5
|
+
describe '.parse' do
|
6
|
+
it 'should parse empty content' do
|
7
|
+
cl = YamlParser.parse('')
|
8
|
+
expect(cl).to eq({})
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should parse single version' do
|
12
|
+
content = "
|
13
|
+
---
|
14
|
+
title: Feature A
|
15
|
+
type: New
|
16
|
+
"
|
17
|
+
cl = YamlParser.parse(content, '1.2.3')
|
18
|
+
expect(cl).to eq(
|
19
|
+
'versions' => {
|
20
|
+
'1.2.3' => {
|
21
|
+
'changes' => {
|
22
|
+
'New' => ['Feature A']
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '.load' do
|
31
|
+
it 'should parse content of folder' do
|
32
|
+
content = 'test changelog'
|
33
|
+
allow(File).to receive(:open).and_call_original
|
34
|
+
allow(File).to receive(:open).with('changelog/1.0.0/1.yml')
|
35
|
+
.and_yield(StringIO.new(content))
|
36
|
+
expect(Dir).to receive(:glob).with('changelog/*')
|
37
|
+
.and_return(['changelog/1.0.0'])
|
38
|
+
expect(Dir).to receive(:glob).with('changelog/1.0.0/**/*.yml')
|
39
|
+
.and_return(['changelog/1.0.0/1.yml'])
|
40
|
+
expect(Dir).to receive(:glob).with('changelog/1.0.0/**/*.yaml')
|
41
|
+
.and_return([])
|
42
|
+
|
43
|
+
expect_any_instance_of(YamlParser).to \
|
44
|
+
receive(:parse).with('test changelog', '1.0.0')
|
45
|
+
|
46
|
+
YamlParser.load
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/spec/parser_spec.rb
CHANGED
@@ -2,124 +2,6 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Keepachangelog
|
4
4
|
describe Parser do
|
5
|
-
describe '#parse' do
|
6
|
-
it 'should parse empty content' do
|
7
|
-
content = ''
|
8
|
-
p = Parser.new(content)
|
9
|
-
expect(p.parsed_content).to eq([])
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'should parse single version' do
|
13
|
-
content = "
|
14
|
-
## [1.2.3] - 2017-01-01
|
15
|
-
### New
|
16
|
-
- Feature A
|
17
|
-
### Fixed
|
18
|
-
- Feature B
|
19
|
-
[1.2.3]: http://test.io
|
20
|
-
"
|
21
|
-
p = Parser.new(content)
|
22
|
-
expect(p.parsed_content).to eq(
|
23
|
-
[
|
24
|
-
{
|
25
|
-
'version' => '1.2.3',
|
26
|
-
'url' => 'http://test.io',
|
27
|
-
'date' => '2017-01-01',
|
28
|
-
'changes' => {
|
29
|
-
'New' => ['Feature A'],
|
30
|
-
'Fixed' => ['Feature B']
|
31
|
-
}
|
32
|
-
}
|
33
|
-
]
|
34
|
-
)
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'should parse multiple versions' do
|
38
|
-
content = "
|
39
|
-
## [2.0.0] - 2017-01-01
|
40
|
-
### New
|
41
|
-
- Feature A
|
42
|
-
## [1.0.0]
|
43
|
-
### Fixed
|
44
|
-
- Feature B
|
45
|
-
[1.0.0]: http://test.io
|
46
|
-
"
|
47
|
-
p = Parser.new(content)
|
48
|
-
expect(p.parsed_content).to eq(
|
49
|
-
[
|
50
|
-
{
|
51
|
-
'version' => '2.0.0',
|
52
|
-
'url' => nil,
|
53
|
-
'date' => '2017-01-01',
|
54
|
-
'changes' => { 'New' => ['Feature A'] }
|
55
|
-
},
|
56
|
-
{
|
57
|
-
'version' => '1.0.0',
|
58
|
-
'url' => 'http://test.io',
|
59
|
-
'date' => nil,
|
60
|
-
'changes' => { 'Fixed' => ['Feature B'] }
|
61
|
-
}
|
62
|
-
]
|
63
|
-
)
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'should parse version without sections' do
|
67
|
-
content = "
|
68
|
-
## [3.0.0]
|
69
|
-
## [2.0.0] - 2017-01-01
|
70
|
-
### New
|
71
|
-
- Feature A
|
72
|
-
## [1.0.0]
|
73
|
-
"
|
74
|
-
p = Parser.new(content)
|
75
|
-
expect(p.parsed_content).to eq(
|
76
|
-
[
|
77
|
-
{
|
78
|
-
'version' => '3.0.0', 'url' => nil, 'date' => nil,
|
79
|
-
'changes' => {}
|
80
|
-
},
|
81
|
-
{
|
82
|
-
'version' => '2.0.0',
|
83
|
-
'url' => nil,
|
84
|
-
'date' => '2017-01-01',
|
85
|
-
'changes' => { 'New' => ['Feature A'] }
|
86
|
-
},
|
87
|
-
{
|
88
|
-
'version' => '1.0.0', 'url' => nil, 'date' => nil,
|
89
|
-
'changes' => {}
|
90
|
-
}
|
91
|
-
]
|
92
|
-
)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
describe '.load' do
|
97
|
-
it 'should parse content of file' do
|
98
|
-
content = 'test changelog'
|
99
|
-
allow(File).to receive(:open).and_call_original
|
100
|
-
expect(File).to receive(:open).with('test.md')
|
101
|
-
.and_yield(StringIO.new(content))
|
102
|
-
expect(Parser).to receive(:new).with(content)
|
103
|
-
Parser.load('test.md')
|
104
|
-
end
|
105
|
-
|
106
|
-
it 'should throw on non-existent file' do
|
107
|
-
expect do
|
108
|
-
Parser.load('invalid-file')
|
109
|
-
end.to raise_exception(
|
110
|
-
Errno::ENOENT,
|
111
|
-
'No such file or directory @ rb_sysopen - invalid-file'
|
112
|
-
)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
describe '.parse' do
|
117
|
-
it 'should call on .new' do
|
118
|
-
expect(Parser).to receive(:new).with('test')
|
119
|
-
Parser.parse('test')
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
5
|
describe '.to_json' do
|
124
6
|
it 'should cast parsed content into json' do
|
125
7
|
p = Parser.new
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: keepachangelog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Basalt AB
|
@@ -144,15 +144,22 @@ files:
|
|
144
144
|
- bin/setup
|
145
145
|
- exe/keepachangelog
|
146
146
|
- features/help.feature
|
147
|
-
- features/
|
147
|
+
- features/markdown.feature
|
148
148
|
- features/support/aruba.rb
|
149
149
|
- features/version.feature
|
150
|
+
- features/yaml.feature
|
150
151
|
- keepachangelog.gemspec
|
151
152
|
- lib/keepachangelog.rb
|
152
153
|
- lib/keepachangelog/cli.rb
|
154
|
+
- lib/keepachangelog/markdown_printer.rb
|
153
155
|
- lib/keepachangelog/parser.rb
|
156
|
+
- lib/keepachangelog/parser/markdown.rb
|
157
|
+
- lib/keepachangelog/parser/yaml.rb
|
154
158
|
- lib/keepachangelog/version.rb
|
155
159
|
- package.json
|
160
|
+
- spec/markdown_printer_spec.rb
|
161
|
+
- spec/parser/markdown_spec.rb
|
162
|
+
- spec/parser/yaml_spec.rb
|
156
163
|
- spec/parser_spec.rb
|
157
164
|
- spec/spec_helper.rb
|
158
165
|
- spec/version_spec.rb
|