sheep-a-changelog 0.1.4 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 041f2db4fdd1e1b435a9702d4746d603a67205e69d5b715abc2864182eefd4d4
4
- data.tar.gz: 263e3379126dbbbed82eeb94bef04c0ca5256cc46d347b3e498ab723db1e2088
3
+ metadata.gz: 97b4d535fc2e01b02db09270df9394f32fba28ae90dbb8afdee687484e2a5bc8
4
+ data.tar.gz: 790a3e1a6569d44473852c6e3f23eb53229c5d75e377474938e9745253599202
5
5
  SHA512:
6
- metadata.gz: a077f385b659c543cbf3349a2a9cc54cece15582ea2b3e93cf5106ae71b14c7600dd4f83358644b4e95e9b2f011d481c5fe2c8c8110153ce4a4264429eda6338
7
- data.tar.gz: 869112435098cde9c8b3d130feb2b47257f7cf8e7d7184b91d416b10e2a0236143360edbdd926241a78936bc55ead88e06751940429f7eb017346de2f8f11cb9
6
+ metadata.gz: 54c466cde177deb6d832c62bf9be2481faa23b9e802bfb48415d41fa21bcd4bc769cbe1cdd00123bedc7468d79f52730de914e2ef8514beebc334eedd403a4b6
7
+ data.tar.gz: 362c51c13e2010ced70fd7524a17fd867b6cf4312b8a85c32c536bad070519661b8c828e58c3d7376dc7aeee1be767d731d7c1d222e95a24700648caf6e0142a
data/README.md CHANGED
@@ -12,5 +12,128 @@
12
12
 
13
13
  :sheep: Simple, particular, example driven parser of keep-a-changelog format.
14
14
 
15
+ ## About
15
16
 
16
17
  Parse a markdown changelog in [keep-a-changelog](https://keepachangelog.com) format to the optimal resolution depth to perform semantic tasks.
18
+
19
+ ## Install
20
+
21
+ See [RubyGems](https://rubygems.org/gems/sheep-a-changelog) for installation instructions (simply add to your Gemfile).
22
+
23
+ Sheep-a-changelog requires at least ruby 2.2, and is [tested](https://travis-ci.com/grissius/sheep-a-changelog) on several minor versions up to 2.5.
24
+
25
+ ## Getting started
26
+
27
+ ```ruby
28
+ require 'sheep-a-changelog'
29
+
30
+ # Load keep-a-changelog markdown file as a string
31
+ contents = File.read('./path/to/CHANGELOG.md')
32
+
33
+ # Create an abstraction for it using the parser
34
+ # SheepAChangelog.parse: string -> SheepAChangelog.Node
35
+ doc = SheepAChangelog.parse(contents)
36
+
37
+ # TODO temper with the structure
38
+ # See features section
39
+
40
+ # Serialize back to string
41
+ updated = doc.to_s
42
+
43
+ # Save back
44
+ File.write('./path/to/CHANGELOG.md', updated)
45
+ ```
46
+
47
+ ## Features
48
+
49
+ ### Release
50
+ This method performs the following actions:
51
+ - Rename current _unreleased_ version log to _new version_
52
+ - Add anchor for _new version_
53
+ - Add empty _unreleased_
54
+ - Update _unreleased_ anchor
55
+
56
+ It accepts arguments
57
+ 1. `new_version` - semver format
58
+ 2. `tag_prefix` - prefix for `new_version` for git tags (used for anchors). Defaults to `v`
59
+ 3. `date` - date of the release, defaults to now
60
+
61
+ ```ruby
62
+ doc.release('2.0.0', 'v', Time.utc(2017, 6, 20))
63
+ ```
64
+
65
+
66
+ ### Inspect element
67
+ ```ruby
68
+ node.build_tree
69
+ # :title - heading (string) or :empty for top-level node
70
+ # :lines - string[] of contents belonging to this node, without anchors and child nodes
71
+ # :anchors - { :v, :url } of anchor nodes
72
+ # :nodes - child nodes
73
+ ```
74
+ ```yaml
75
+ :title: :empty
76
+ :lines: []
77
+ :anchors:
78
+ - :v: Unreleased
79
+ :url: https://github.com/olivierlacan/keep-a-changelog/compare/v1.0.0...HEAD
80
+ - :v: 1.0.0
81
+ :url: https://github.com/olivierlacan/keep-a-changelog/compare/v0.3.0...v1.0.0
82
+ :nodes:
83
+ - :title: Changelog
84
+ :lines:
85
+ - All notable changes to this project will be documented in this file.
86
+ - ''
87
+ - The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
88
+ - and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
89
+ - ''
90
+ :anchors: []
91
+ :nodes:
92
+ - :title: "[1.0.0] - 2017-06-20"
93
+ :lines: []
94
+ :anchors: []
95
+ :nodes:
96
+ - :title: Added
97
+ :lines:
98
+ - '- "Frequently Asked Questions" section.'
99
+ - ''
100
+ :anchors: []
101
+ :nodes: []
102
+ ```
103
+
104
+ ### Latest version title
105
+ Returns the contents of the heading for the latest version.
106
+ ```ruby
107
+ doc.latest_version_title
108
+ # --> "[1.0.0] - 2017-06-20"
109
+ ```
110
+
111
+ ### Diff prefix
112
+ Returns URL prefix for the anchors. If multiple used, return the most frequent.
113
+ ```ruby
114
+ doc.diff_prefix
115
+ # --> "https://github.com/olivierlacan/keep-a-changelog/compare/"
116
+ ```
117
+
118
+ ### Rename version
119
+ Rename version. Looking for exact match. This only changes the title and keeps the contents (inlcuding all children intact.)
120
+ ```ruby
121
+ doc.rename_version('[Unreleased]', new_version)
122
+ ```
123
+
124
+ ### Add anchor
125
+ ```ruby
126
+ doc.add_anchor('LABEL', 'vFROM', 'vTO')
127
+ # adds "[LABEL]: {diff_prefix}/vFROM...vTO" as the topmost anchor
128
+ ```
129
+
130
+ ## Todo
131
+
132
+ - :heavy_check_mark: Ensure unreleased
133
+ - :heavy_check_mark: Release
134
+ - :construction: Initialize
135
+ - :construction: Sort type sections
136
+ - :construction: Fix typos in type sections
137
+
138
+ ## License
139
+ Licensed under [MIT](./LICENSE)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 0.2.0
@@ -1,2 +1,7 @@
1
+ require_relative 'sheep-a-changelog/parser'
2
+
1
3
  module SheepAChangelog
4
+ def self.parse(changelog)
5
+ Parser.parse(changelog)
6
+ end
2
7
  end
@@ -0,0 +1,63 @@
1
+ require_relative 'node'
2
+
3
+ module SheepAChangelog
4
+ class Document < Node
5
+ def initialize(lines)
6
+ super(lines, :empty, 0)
7
+ end
8
+
9
+ # Return parent node to version nodes
10
+ def version_root
11
+ nodes.first
12
+ end
13
+
14
+ # Return title of the latest version node
15
+ def latest_version_title(n = 0)
16
+ version_root.nodes[n].title
17
+ end
18
+
19
+ # Return the latest version
20
+ def latest_version(n = 0)
21
+ latest_version_title(n).match(/^\[(\S+)\].*/).to_a[1]
22
+ end
23
+
24
+ def add_empty_version(name)
25
+ version_root.nodes.unshift(Node.new([''], name, 2))
26
+ end
27
+
28
+ def diff_prefix
29
+ anchors.map { |a| a[:url].match(%r{^(.*\/)(.*\.\.\..*)$}).to_a[1] }
30
+ .each_with_object(Hash.new(0)) { |word, counts| counts[word] += 1 }
31
+ .to_a
32
+ .min { |a, b| b[1] <=> a[1] }
33
+ .first
34
+ end
35
+
36
+ def rename_version(from, to)
37
+ parent = version_root
38
+ parent.nodes.map! do |node|
39
+ if node.title == from
40
+ Node.new(node.all_lines_wo_heading.first, to, 2)
41
+ else
42
+ node
43
+ end
44
+ end
45
+ end
46
+
47
+ def add_anchor(name, from, to)
48
+ anchors.unshift(v: name, url: "#{diff_prefix}#{from}...#{to}")
49
+ end
50
+
51
+ def remove_anchor_unreleased
52
+ anchors.reject! { |a| a[:v] == 'Unreleased' }
53
+ end
54
+
55
+ def release(version, tag_prefix, t = Time.now)
56
+ remove_anchor_unreleased
57
+ rename_version('[Unreleased]', "[#{version}] - #{t.strftime('%Y-%m-%d')}")
58
+ add_anchor(version, tag_prefix + latest_version(1), version)
59
+ add_empty_version('[Unreleased]')
60
+ add_anchor('Unreleased', tag_prefix + version, 'HEAD')
61
+ end
62
+ end
63
+ end
@@ -1,6 +1,7 @@
1
1
  module SheepAChangelog
2
2
  class Node
3
- attr_accessor :lines, :nodes
3
+ attr_reader :lines, :title, :anchors
4
+ attr_accessor :nodes
4
5
  def self.parse(string)
5
6
  new(string.split("\n"))
6
7
  end
@@ -34,23 +35,26 @@ module SheepAChangelog
34
35
  end
35
36
 
36
37
  def self.pick_lines(lines)
37
- content_lines = []
38
- anchor_lines = []
39
- lines.each do |line|
40
- if line =~ /^\[.*\].*\s*:\s*\S+$/
41
- anchor_lines << line
42
- else
43
- content_lines << line
44
- end
38
+ # add matches for links
39
+ groups_lines = lines.inject([]) do |acc, line|
40
+ groups = line.match(/^\[(.*)\]\s*:\s*(\S+)\s*$/).to_a
41
+ acc + [[groups, line]]
45
42
  end
46
- [content_lines, anchor_lines]
43
+ # if no matches, it is content lines
44
+ content_lines = groups_lines
45
+ .select { |x| x.first.empty? }.map { |_, l| l }
46
+ # if matches, it is link
47
+ anchors = groups_lines
48
+ .reject { |x| x.first.empty? }
49
+ .map { |groups, _| { v: groups[1], url: groups[2] } }
50
+ [content_lines, anchors]
47
51
  end
48
52
 
49
53
  # Create node hierarchy from keep-a-changeloh markdown lines
50
- def initialize(lines, title = :empty, level = 0)
51
- content_lines, anchor_lines = Node.pick_lines(lines)
54
+ def initialize(lines, title, level)
55
+ content_lines, anchors = Node.pick_lines(lines)
52
56
  @title = title
53
- @anchor_lines = anchor_lines
57
+ @anchors = anchors
54
58
  @nodes = build_nodes(content_lines, level + 1)
55
59
  @level = level
56
60
  end
@@ -67,9 +71,15 @@ module SheepAChangelog
67
71
  def all_lines
68
72
  res = []
69
73
  res << format_heading if @title != :empty
70
- res += @lines unless @lines.empty?
71
- res += @nodes.map(&:all_lines) unless @nodes.empty?
72
- res += @anchor_lines unless @anchor_lines.empty?
74
+ res += all_lines_wo_heading
75
+ res
76
+ end
77
+
78
+ def all_lines_wo_heading
79
+ res = []
80
+ res += @lines
81
+ res += @nodes.map(&:all_lines)
82
+ res += @anchors.map { |a| "[#{a[:v]}]: #{a[:url]}" }
73
83
  res
74
84
  end
75
85
 
@@ -82,7 +92,7 @@ module SheepAChangelog
82
92
  def build_tree
83
93
  { title: @title,
84
94
  lines: @lines,
85
- anchor_nodes: @anchor_lines,
95
+ anchors: @anchors,
86
96
  nodes: @nodes.map(&:build_tree) }
87
97
  end
88
98
  end
@@ -1,9 +1,9 @@
1
- require_relative 'node'
1
+ require_relative 'document'
2
2
 
3
3
  module SheepAChangelog
4
4
  module Parser
5
5
  def self.parse(contents)
6
- doc = Node.parse(contents)
6
+ doc = Document.parse(contents)
7
7
  doc
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sheep-a-changelog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaroslav Šmolík
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-14 00:00:00.000000000 Z
11
+ date: 2019-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: coveralls
@@ -118,6 +118,7 @@ files:
118
118
  - README.md
119
119
  - VERSION
120
120
  - lib/sheep-a-changelog.rb
121
+ - lib/sheep-a-changelog/document.rb
121
122
  - lib/sheep-a-changelog/meta.rb
122
123
  - lib/sheep-a-changelog/node.rb
123
124
  - lib/sheep-a-changelog/parser.rb
@@ -141,8 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
142
  - !ruby/object:Gem::Version
142
143
  version: '0'
143
144
  requirements: []
144
- rubyforge_project:
145
- rubygems_version: 2.7.7
145
+ rubygems_version: 3.0.2
146
146
  signing_key:
147
147
  specification_version: 4
148
148
  summary: Simple, particular, example driven parser of keep-a-changelog format.