keepachangelog 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 43670bf15155e781900c3e2ef0cc4867037d4814
4
- data.tar.gz: f4060bb3c0ab0ba82a24f73e53c283c47bc9e627
3
+ metadata.gz: beb911086da3260f5c4f06ff2f57b219ddb19a06
4
+ data.tar.gz: d08ff76239c9a49db9ee5f46f33d3f4df75498bd
5
5
  SHA512:
6
- metadata.gz: dba49f142c11099ef4eb18e8ee0b68abbc9b6f73b8436df90959e2fc286d0fb5e8bacb00c291651c434015e88b6753bace3e768726393ef3ea10dae18f81c410
7
- data.tar.gz: 14e98f3e890e8b5d8729660561951241c29e73eaf80f60cde9895ec55171368c563f333c74090445116f6055411044f9a4a688e42e67559f62a4d767ab3f9e77
6
+ metadata.gz: 5fb6c397a7f820740f5f86206f6e37211afbfc564afd4cf17c0f7de4907b6ff57faf50333abec10ccde44b4d18f04a72d0c1d096d148d0e9c54b7f033bc33fce
7
+ data.tar.gz: 0237365f64e45fd84ee99b74fd9c0b68f57621f063e0d2c7abf249525c7149f256ade2bb9ceb5b5c979d4ba05ff064f590f8d26377d147a65c8c75c263ea31a3
@@ -4,6 +4,9 @@ Style/Documentation:
4
4
  Style/ClassAndModuleChildren:
5
5
  Enabled: false
6
6
 
7
+ Style/AsciiComments:
8
+ Enabled: false
9
+
7
10
  Metrics/BlockLength:
8
11
  Exclude:
9
12
  - 'spec/**/*'
@@ -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.1.0...HEAD
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- keepachangelog (0.1.0)
4
+ keepachangelog (0.2.0)
5
5
  json (~> 2.0)
6
6
  thor (~> 0.19)
7
7
 
@@ -84,4 +84,4 @@ DEPENDENCIES
84
84
  simplecov (~> 0.14)
85
85
 
86
86
  BUNDLED WITH
87
- 1.14.3
87
+ 1.14.6
@@ -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 parse`
12
- Then the output should contain "Options"
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 parse`
13
+ When I successfully run `keepachangelog markdown`
14
14
  Then the output should contain:
15
15
  """
16
- [{"version":"Unreleased","url":null,"date":null,"changes":{"New":["Feature A"]}}]
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
- [{"version":"Unreleased","url":null,"date":null,"changes":{"New":["Feature A"]}}]
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
- [{"version":"Unreleased","url":null,"date":null,"changes":{"New":["Feature A"]}}]
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
+ """
@@ -18,22 +18,38 @@ module Keepachangelog
18
18
  shell.say Keepachangelog.version
19
19
  end
20
20
 
21
- desc '<options> parse', 'Parse a changelog'
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 changelog file',
28
+ desc: 'Path to the Changelog file',
29
29
  default: 'CHANGELOG.md',
30
30
  aliases: '-p'
31
- def parse
32
- require 'keepachangelog/parser'
33
- p = Parser.load(options[:path])
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
- default_task :parse
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(content = '')
6
- self.parsed_content = parse(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
- private
31
-
32
- def parse(content)
33
- content = "\n" + clean(content).strip + "\n"
34
- anchors = extract_anchors! content
35
- versions = content.split(/\n\s*## /)[1..-1]
36
- versions.map { |v| parse_version v, anchors }
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keepachangelog",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Parser for changelogs based on keepachangelog.com",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -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
@@ -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
@@ -1,3 +1,5 @@
1
1
  require 'simplecov'
2
2
  SimpleCov.start
3
3
  require 'keepachangelog'
4
+ require 'keepachangelog/parser/markdown'
5
+ require 'keepachangelog/parser/yaml'
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.1.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/parse.feature
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