Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow blocks to parse/to_html for custom behaviour #16

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions lib/vandamme/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,21 @@ class Parser
# Defaults to /^#{0,3} ?([\w\d\.-]+\.[\w\d\.-]+[a-zA-Z0-9])(?: \/ (\w+ \d{1,2}(?:st|nd|rd|th)?,\s\d{4}|\d{4}-\d{2}-\d{2}|\w+))?\n?[=-]*/
# See http://tech-angels.github.com/vandamme/#changelogs-convention
# * +format+ (optional):: One of "raw", "markdown", "rdoc"
#
# * +match_group+ (optional):: A number to say which match group to use as key
# * +custom_hash_filler+ (optional):: A Proc that receives a hash, the regex match and content
# and should fill the hash with custom content (another hash)
#
def initialize(options={})
if options[:match_group] && options[:custom_hash_filler]
raise ArgumentError, "only one of match_group or custom_hash_filler should be given"
end

@changelog = options.fetch :changelog
regexp = options[:version_header_exp] || DEFAULT_REGEXP
@version_header_exp = regexp.is_a?(Regexp) ? regexp : Regexp.new(/#{regexp}/)
@match_group = options[:match_group] || 0
@format = options[:format] || :raw
@custom_hash_filler = options[:custom_hash_filler]
@changelog_hash = {}
end

Expand All @@ -32,12 +39,20 @@ def initialize(options={})
# Parse changelog file, filling +@changelog_hash+ with
# versions as keys, and version changelog as content.
#
# When a block is given, yield the changelog hash, match and content.
# It's up to the caller to fill the hash as they see fit.
#
def parse
@changelog.scan(@version_header_exp) do |match|
version_content = $~.post_match
changelog_scanner = StringScanner.new(version_content)
changelog_scanner.scan_until(@version_header_exp)
@changelog_hash[match[@match_group]] = (changelog_scanner.pre_match || version_content).gsub(/(\A\n+|\n+\z)/, '')
content = (changelog_scanner.pre_match || version_content).gsub(/(\A\n+|\n+\z)/, '')
if @custom_hash_filler
@custom_hash_filler.call(@changelog_hash, match, content)
else
@changelog_hash[match[@match_group]] = content
end
end
@changelog_hash
end
Expand All @@ -47,10 +62,18 @@ def parse
# "rdoc", "md", 'markdown", "raw", etc.)
# See https://github.com/github/markup/blob/master/lib/github/markups.rb
# for more formats. The corresponding gem must be bundled.
#
# If the @changelog_hash is not just key -> String(content), a block must be provided
# that can get the string content from the custom content. For example,
# if the content is a hash like { date: '2017-09-19', content: '* Things' }, calling
# to_html { |hash| hash[:content] } will render "<ul><li>Things</li></ul>"
def to_html
self.parse if @changelog_hash.empty?
# GitHub Markup API is really weird, we MUST pass a file name for format detection as 1st arg:
@changelog_hash.inject({}) { |h,(k,v)| h[k] = GitHub::Markup.render(".#{@format}", v); h }
@changelog_hash.each_with_object({}) do |(k, v), h|
value = block_given? ? yield(v) : v
# GitHub Markup API is really weird, we MUST pass a file name for format detection as 1st arg:
h[k] = GitHub::Markup.render(".#{@format}", value)
end
end
end
end
93 changes: 79 additions & 14 deletions spec/vandamme/parser_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
require 'spec_helper'

describe Vandamme::Parser do
context "both match_group and custom_hash_filler are provided" do
it "raises an ArgumentError" do
expect {
Vandamme::Parser.new(
changelog: '',
match_group: 1,
custom_hash_filler: -> {}
)
}.to raise_error(ArgumentError, /only one of match_group or custom_hash_filler should be given/)
end
end
context "with json gem changelog" do
let(:changelog_file) { File.read("spec/fixtures/json.md") }
let(:changelog_as_hash) {
Expand Down Expand Up @@ -178,22 +189,76 @@
eos
}

let(:changelog_as_hash) {
{
"X.Y.Z" => "* Update API \n* Fix bug #1",
"1.2.3-pre.1" => "* Update API ",
"1.0.0-x.7.z.92" => ""
}
}


before do
@parser = Vandamme::Parser.new(changelog: changelog_file)
@changelog_parsed = @parser.parse
let(:hash_filler) { nil }
let(:parser) do
Vandamme::Parser.new(
changelog: changelog_file,
format: 'markdown',
custom_hash_filler: hash_filler
)
end

it "should parse file and fill changelog hash" do
expect(@changelog_parsed).to eq(changelog_as_hash)
describe "#parse" do
subject(:parsed) { parser.parse }

context "no blocks are given" do
let(:changelog_as_hash) {
{
"X.Y.Z" => "* Update API \n* Fix bug #1",
"1.2.3-pre.1" => "* Update API ",
"1.0.0-x.7.z.92" => ""
}
}
let(:changelog_as_html_hash) {
{
"X.Y.Z" => "<ul>\n<li>Update API</li>\n<li>Fix bug #1</li>\n</ul>\n",
"1.2.3-pre.1" => "<ul>\n<li>Update API</li>\n</ul>\n",
"1.0.0-x.7.z.92" => ""
}
}

it "should parse file and fill changelog hash" do
expect(parsed).to eq(changelog_as_hash)
end

it "renders to_html" do
expect(parser.to_html).to eq(changelog_as_html_hash)
end
end

context "blocks are given" do
let(:hash_filler) do
->(result, header_match, content) do
result[header_match[0]] = { date: header_match[1], content: content }
end
end
let(:content_getter) do
->(hash) { hash[:content] }
end
let(:changelog_as_hash) {
{
"X.Y.Z" => { date: "Unreleased", content: "* Update API \n* Fix bug #1" },
"1.2.3-pre.1" => { date: "2013-02-14", content: "* Update API "},
"1.0.0-x.7.z.92" => { date: nil, content: ""},
}
}
let(:changelog_as_html_hash) {
{
"X.Y.Z" => "<ul>\n<li>Update API</li>\n<li>Fix bug #1</li>\n</ul>\n",
"1.2.3-pre.1" => "<ul>\n<li>Update API</li>\n</ul>\n",
"1.0.0-x.7.z.92" => ""
}
}

it "should parse file and fill custom changelog hash" do
expect(parsed).to eq(changelog_as_hash)
end

it "renders to_html" do
expect(parser.to_html(&content_getter)).to eq(changelog_as_html_hash)
end
end
end

end
end