milestoner 17.11.0 → 18.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.adoc +183 -79
  4. data/lib/milestoner/builders/ascii_doc.rb +30 -10
  5. data/lib/milestoner/builders/container.rb +1 -0
  6. data/lib/milestoner/builders/feed.rb +46 -0
  7. data/lib/milestoner/builders/markdown.rb +30 -10
  8. data/lib/milestoner/builders/stream.rb +19 -8
  9. data/lib/milestoner/builders/web.rb +46 -16
  10. data/lib/milestoner/cli/actions/build/basename.rb +27 -0
  11. data/lib/milestoner/cli/actions/build/format.rb +4 -4
  12. data/lib/milestoner/cli/actions/build/label.rb +3 -3
  13. data/lib/milestoner/cli/actions/build/layout.rb +3 -3
  14. data/lib/milestoner/cli/actions/build/max.rb +24 -0
  15. data/lib/milestoner/cli/actions/build/root.rb +3 -3
  16. data/lib/milestoner/cli/actions/build/stylesheet.rb +36 -0
  17. data/lib/milestoner/cli/actions/build/tail.rb +26 -0
  18. data/lib/milestoner/cli/actions/build/version.rb +7 -3
  19. data/lib/milestoner/cli/actions/cache/delete.rb +1 -1
  20. data/lib/milestoner/cli/actions/cache/find.rb +2 -2
  21. data/lib/milestoner/cli/actions/cache/info.rb +1 -1
  22. data/lib/milestoner/cli/actions/cache/list.rb +2 -2
  23. data/lib/milestoner/cli/actions/next.rb +2 -2
  24. data/lib/milestoner/cli/actions/publish.rb +19 -4
  25. data/lib/milestoner/cli/commands/build.rb +15 -25
  26. data/lib/milestoner/cli/commands/cache.rb +1 -1
  27. data/lib/milestoner/commits/categorizer.rb +2 -2
  28. data/lib/milestoner/commits/enricher.rb +1 -1
  29. data/lib/milestoner/commits/enrichers/body.rb +2 -2
  30. data/lib/milestoner/commits/enrichers/format.rb +2 -2
  31. data/lib/milestoner/commits/enrichers/issue.rb +2 -2
  32. data/lib/milestoner/commits/enrichers/milestone.rb +1 -1
  33. data/lib/milestoner/commits/enrichers/note.rb +2 -2
  34. data/lib/milestoner/commits/enrichers/review.rb +2 -2
  35. data/lib/milestoner/commits/enrichers/uri.rb +2 -2
  36. data/lib/milestoner/commits/tagger.rb +78 -0
  37. data/lib/milestoner/configuration/contract.rb +30 -8
  38. data/lib/milestoner/configuration/defaults.yml +49 -24
  39. data/lib/milestoner/configuration/model.rb +17 -8
  40. data/lib/milestoner/configuration/transformers/build/template_paths.rb +4 -4
  41. data/lib/milestoner/configuration/transformers/citations/description.rb +5 -3
  42. data/lib/milestoner/configuration/transformers/citations/label.rb +2 -3
  43. data/lib/milestoner/configuration/transformers/citations/uri.rb +48 -0
  44. data/lib/milestoner/configuration/transformers/gems/description.rb +8 -2
  45. data/lib/milestoner/configuration/transformers/gems/label.rb +6 -3
  46. data/lib/milestoner/configuration/transformers/gems/name.rb +8 -2
  47. data/lib/milestoner/configuration/transformers/gems/uri.rb +12 -3
  48. data/lib/milestoner/configuration/transformers/generator/label.rb +2 -2
  49. data/lib/milestoner/configuration/transformers/generator/uri.rb +2 -2
  50. data/lib/milestoner/configuration/transformers/generator/version.rb +2 -2
  51. data/lib/milestoner/configuration/transformers/project/author.rb +5 -2
  52. data/lib/milestoner/configuration/transformers/project/label.rb +2 -2
  53. data/lib/milestoner/configuration/transformers/project/version.rb +2 -2
  54. data/lib/milestoner/configuration/transformers/syndication/link.rb +33 -0
  55. data/lib/milestoner/container.rb +20 -16
  56. data/lib/milestoner/models/commit.rb +2 -0
  57. data/lib/milestoner/models/tag.rb +8 -0
  58. data/lib/milestoner/renderers/universal.rb +2 -2
  59. data/lib/milestoner/syndication/builder.rb +120 -0
  60. data/lib/milestoner/syndication/refine.rb +25 -0
  61. data/lib/milestoner/syndication/shared.rb +25 -0
  62. data/lib/milestoner/tags/creator.rb +11 -33
  63. data/lib/milestoner/tags/publisher.rb +13 -5
  64. data/lib/milestoner/tags/pusher.rb +22 -13
  65. data/lib/milestoner/templates/layouts/page.html.erb +7 -1
  66. data/lib/milestoner/templates/layouts/page.xml.erb +11 -0
  67. data/lib/milestoner/templates/milestones/_avatar.adoc.erb +1 -0
  68. data/lib/milestoner/templates/milestones/_avatar.html.erb +1 -1
  69. data/lib/milestoner/templates/milestones/_avatar.md.erb +2 -0
  70. data/lib/milestoner/templates/milestones/_avatar.xml.erb +5 -0
  71. data/lib/milestoner/templates/milestones/_commit.adoc.erb +1 -1
  72. data/lib/milestoner/templates/milestones/_commit.html.erb +18 -8
  73. data/lib/milestoner/templates/milestones/_commit.md.erb +1 -1
  74. data/lib/milestoner/templates/milestones/_commit.xml.erb +84 -0
  75. data/lib/milestoner/templates/milestones/_icon.adoc.erb +1 -0
  76. data/lib/milestoner/templates/milestones/_icon.html.erb +2 -2
  77. data/lib/milestoner/templates/milestones/_icon.md.erb +5 -0
  78. data/lib/milestoner/templates/milestones/_icon.xml.erb +5 -0
  79. data/lib/milestoner/templates/milestones/_profile.adoc.erb +1 -0
  80. data/lib/milestoner/templates/milestones/_profile.md.erb +1 -0
  81. data/lib/milestoner/templates/milestones/_profile.xml.erb +5 -0
  82. data/lib/milestoner/templates/milestones/_tag.adoc.erb +13 -0
  83. data/lib/milestoner/templates/milestones/_tag.html.erb +82 -0
  84. data/lib/milestoner/templates/milestones/_tag.md.erb +18 -0
  85. data/lib/milestoner/templates/milestones/_tag.stream.erb +14 -0
  86. data/lib/milestoner/templates/milestones/_tag.xml.erb +27 -0
  87. data/lib/milestoner/templates/milestones/show.adoc.erb +1 -11
  88. data/lib/milestoner/templates/milestones/show.html.erb +1 -46
  89. data/lib/milestoner/templates/milestones/show.md.erb +1 -11
  90. data/lib/milestoner/templates/milestones/show.stream.erb +1 -11
  91. data/lib/milestoner/templates/milestones/show.xml.erb +1 -0
  92. data/lib/milestoner/templates/public/page.css.erb +111 -60
  93. data/lib/milestoner/views/context.rb +7 -4
  94. data/lib/milestoner/views/milestones/show.rb +4 -29
  95. data/lib/milestoner/views/parts/commit.rb +8 -8
  96. data/lib/milestoner/views/parts/tag.rb +51 -0
  97. data/milestoner.gemspec +8 -7
  98. data.tar.gz.sig +0 -0
  99. metadata +58 -22
  100. metadata.gz.sig +3 -3
  101. data/lib/milestoner/configuration/transformers/project/generator.rb +0 -35
  102. data/lib/milestoner/configuration/transformers/project/name.rb +0 -21
  103. data/lib/milestoner/configuration/transformers/uri/avatar.rb +0 -20
  104. data/lib/milestoner/configuration/transformers/uri/commit.rb +0 -23
  105. data/lib/milestoner/configuration/transformers/uri/profile.rb +0 -20
  106. data/lib/milestoner/configuration/transformers/uri/review.rb +0 -23
  107. data/lib/milestoner/configuration/transformers/uri/tracker.rb +0 -23
  108. data/lib/milestoner/error.rb +0 -7
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/monads"
4
+ require "refinements/pathname"
5
+ require "versionaire"
6
+
7
+ module Milestoner
8
+ module Commits
9
+ # Assembles all commits for a tag.
10
+ class Tagger
11
+ include Milestoner::Import[:git, :settings, :logger]
12
+ include Enrichers::Import[author_enricher: :author]
13
+ include Dry::Monads[:result]
14
+
15
+ using Refinements::Pathname
16
+ using Versionaire::Cast
17
+
18
+ def initialize(enricher: Commits::Enricher.new, model: Models::Tag, **)
19
+ @enricher = enricher
20
+ @model = model
21
+ super(**)
22
+ end
23
+
24
+ def call
25
+ git.tags("--sort=taggerdate")
26
+ .fmap { |tags| tail tags.last(settings.build_max).map(&:version) }
27
+ .fmap { |references| slice(references).reverse }
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :enricher, :model
33
+
34
+ def tail references
35
+ references.append "HEAD" if settings.build_tail == "head"
36
+ references
37
+ end
38
+
39
+ def slice references
40
+ references.each_cons(2).with_object [] do |(min, max), entries|
41
+ add_enrichment entries, min, max
42
+ end
43
+ end
44
+
45
+ def add_enrichment(all, *) = enrich(*).bind { |entry| all.append entry }
46
+
47
+ def enrich min, max
48
+ enricher.call(min:, max:).bind { |commits| build_record git.tag_show(max), commits }
49
+ end
50
+
51
+ def build_record result, commits
52
+ result.fmap { |tag| record_for tag, commits }
53
+ rescue Versionaire::Error => error
54
+ logger.error error.message
55
+ Failure error
56
+ end
57
+
58
+ def record_for tag, commits
59
+ model[
60
+ author: author(tag),
61
+ commits:,
62
+ committed_at: committed_at(tag.committed_at),
63
+ sha: tag.sha,
64
+ signature: tag.signature,
65
+ version: Version(tag.version || settings.project_version),
66
+ ]
67
+ end
68
+
69
+ def author tag
70
+ tag = tag.dup
71
+ tag.author_name ||= settings.project_author
72
+ author_enricher.call tag
73
+ end
74
+
75
+ def committed_at(at) = at ? Time.at(at.to_i).utc : settings.loaded_at
76
+ end
77
+ end
78
+ end
@@ -8,11 +8,14 @@ Dry::Schema.load_extensions :monads
8
8
  module Milestoner
9
9
  module Configuration
10
10
  Contract = Dry::Schema.Params do
11
- required(:avatar_domain).filled :string
12
11
  required(:avatar_uri).filled :string
12
+ required(:build_basename).filled :string
13
13
  required(:build_format).filled :string
14
14
  required(:build_layout) { str? | bool? }
15
+ required(:build_max).filled :integer
15
16
  required(:build_root).filled Etcher::Types::Pathname
17
+ required(:build_stylesheet) { bool? | str? }
18
+ required(:build_tail).filled :string
16
19
  required(:build_template_paths).array Etcher::Types::Pathname
17
20
 
18
21
  required(:commit_categories).array(:hash) do
@@ -20,25 +23,44 @@ module Milestoner
20
23
  required(:label).filled :string
21
24
  end
22
25
 
23
- required(:commit_domain).filled :string
24
26
  required(:commit_format).filled :string
25
27
  required(:commit_uri).filled :string
26
28
  required(:generator_label).filled :string
27
29
  required(:generator_uri).filled :string
28
30
  required(:generator_version).filled Etcher::Types::Version
29
31
  required(:loaded_at).filled :time
30
- required(:profile_domain).filled :string
32
+ required(:organization_label).filled :string
33
+ required(:organization_uri).filled :string
31
34
  required(:profile_uri).filled :string
32
35
  required(:project_author).filled :string
33
- optional(:project_description).maybe :string
36
+ optional(:project_description).filled :string
34
37
  optional(:project_label).filled :string
35
38
  required(:project_name).filled :string
36
- optional(:project_owner).filled :string
37
- optional(:project_uri).maybe :string
39
+ required(:project_owner).filled :string
40
+ required(:project_uri_home).filled :string
41
+ optional(:project_uri_icon).filled :string
42
+ optional(:project_uri_logo).filled :string
43
+ required(:project_uri_version).filled :string
38
44
  required(:project_version).filled Etcher::Types::Version
39
- required(:review_domain).filled :string
40
45
  required(:review_uri).filled :string
41
- required(:tracker_domain).filled :string
46
+
47
+ required(:syndication_categories).array(:hash) do
48
+ required(:label).filled :string
49
+ required(:name).filled :string
50
+ end
51
+
52
+ required(:syndication_entry_label).filled :string
53
+ required(:syndication_entry_uri).filled :string
54
+ required(:syndication_id).filled :string
55
+ required(:syndication_label).filled :string
56
+
57
+ required(:syndication_links).array(:hash) do
58
+ required(:label).filled :string
59
+ required(:mime).filled :string
60
+ required(:relation).filled :string
61
+ required(:uri).filled :string
62
+ end
63
+
42
64
  required(:tracker_uri).filled :string
43
65
  end
44
66
  end
@@ -1,31 +1,56 @@
1
1
  avatar:
2
- domain: https://avatars.githubusercontent.com
3
- uri: "%<domain>s/u/%<id>s"
2
+ uri: "https://avatars.githubusercontent.com/u/%<id>s"
4
3
  build:
5
- format: web
6
- layout: page
7
- root: tmp/milestone
4
+ basename: "index"
5
+ format: "stream"
6
+ layout: "page"
7
+ max: 1
8
+ root: "tmp/milestones"
9
+ stylesheet: "page"
10
+ tail: "head"
8
11
  commit:
9
12
  categories:
10
- - emoji: ✅
11
- label: Fixed
12
- - emoji: 🟢
13
- label: Added
14
- - emoji: 🔼
15
- label: Updated
16
- - emoji: ⛔️
17
- label: Removed
18
- - emoji: 🔁
19
- label: Refactored
20
- domain: https://github.com
21
- format: asciidoc
22
- uri: "%<domain>s/%<owner>s/%<name>s/commit/%<id>s"
13
+ - emoji: ""
14
+ label: "Fixed"
15
+ - emoji: "🟢"
16
+ label: "Added"
17
+ - emoji: "🔼"
18
+ label: "Updated"
19
+ - emoji: "⛔️"
20
+ label: "Removed"
21
+ - emoji: "🔁"
22
+ label: "Refactored"
23
+ format: "asciidoc"
24
+ uri: "https://github.com/%<project_owner>s/%<project_name>s/commit/%<id>s"
25
+ organization:
26
+ label: "Undefined"
27
+ uri: "https://undefined.io"
23
28
  profile:
24
- domain: https://github.com
25
- uri: "%<domain>s/%<id>s"
29
+ uri: "https://github.com/%<id>s"
30
+ project:
31
+ owner: "undefined"
32
+ uri:
33
+ home: "%<organization_uri>s/projects/%<project_name>s"
34
+ version: "%<project_uri_home>s/versions/%<id>s"
26
35
  review:
27
- domain: https://github.com
28
- uri: "%<domain>s/%<owner>s/%<name>s/pulls/%<id>s"
36
+ uri: "https://github.com/%<project_owner>s/%<project_name>s/pulls/%<id>s"
37
+ syndication:
38
+ categories:
39
+ - label: "Milestones"
40
+ name: "milestones"
41
+ entry:
42
+ label: "%<id>s"
43
+ uri: "%<project_uri_version>s"
44
+ id: "%<project_uri_version>s"
45
+ label: "%<organization_label>s: %<project_label>s"
46
+ links:
47
+ - label: "%<organization_label>s: %<project_label>s (web)"
48
+ mime: "text/html"
49
+ relation: "alternate"
50
+ uri: "%<project_uri_home>s/versions"
51
+ - label: "%<organization_label>s: %<project_label>s (feed)"
52
+ mime: "application/atom+xml"
53
+ relation: "self"
54
+ uri: "%<project_uri_home>s/versions.xml"
29
55
  tracker:
30
- domain: https://github.com
31
- uri: "%<domain>s/%<owner>s/%<name>s/issues/%<id>s"
56
+ uri: "https://github.com/%<project_owner>s/%<project_name>s/issues/%<id>s"
@@ -3,33 +3,42 @@
3
3
  module Milestoner
4
4
  module Configuration
5
5
  # Defines configuration content as the primary source of truth for use throughout the gem.
6
- Model = Struct.new :avatar_domain,
7
- :avatar_uri,
6
+ Model = Struct.new :avatar_uri,
7
+ :build_basename,
8
8
  :build_format,
9
9
  :build_layout,
10
+ :build_max,
10
11
  :build_root,
12
+ :build_stylesheet,
13
+ :build_tail,
11
14
  :build_template_paths,
12
15
  :commit_categories,
13
- :commit_domain,
14
16
  :commit_format,
15
17
  :commit_uri,
16
18
  :generator_label,
17
19
  :generator_uri,
18
20
  :generator_version,
19
21
  :loaded_at,
20
- :profile_domain,
22
+ :organization_label,
23
+ :organization_uri,
21
24
  :profile_uri,
22
25
  :project_author,
23
26
  :project_description,
24
- :project_generator,
25
27
  :project_label,
26
28
  :project_name,
27
29
  :project_owner,
28
- :project_uri,
30
+ :project_uri_home,
31
+ :project_uri_icon,
32
+ :project_uri_logo,
33
+ :project_uri_version,
29
34
  :project_version,
30
- :review_domain,
31
35
  :review_uri,
32
- :tracker_domain,
36
+ :syndication_categories,
37
+ :syndication_entry_label,
38
+ :syndication_entry_uri,
39
+ :syndication_id,
40
+ :syndication_label,
41
+ :syndication_links,
33
42
  :tracker_uri
34
43
  end
35
44
  end
@@ -14,17 +14,17 @@ module Milestoner
14
14
 
15
15
  def initialize key = :build_template_paths,
16
16
  default: Pathname(__dir__).join("../../../templates"),
17
- xdg_config: Runcom::Config.new("milestoner/templates")
17
+ xdg: Runcom::Config.new("milestoner/templates")
18
18
  @key = key
19
19
  @default = default
20
- @xdg_config = xdg_config
20
+ @xdg = xdg
21
21
  end
22
22
 
23
- def call(attributes) = Success attributes.merge!(key => xdg_config.all.append(default))
23
+ def call(attributes) = Success attributes.merge!(key => xdg.all.append(default))
24
24
 
25
25
  private
26
26
 
27
- attr_reader :key, :default, :xdg_config
27
+ attr_reader :key, :default, :xdg
28
28
  end
29
29
  end
30
30
  end
@@ -24,9 +24,11 @@ module Milestoner
24
24
  end
25
25
 
26
26
  def call attributes
27
- attributes.fetch_value(key) { citation.open(path).abstract }
28
- .then { |value| value unless String(value).empty? }
29
- .then { |value| Success attributes.merge!(key => value) }
27
+ attributes.fetch key do
28
+ attributes.merge!(key => citation.open(path).abstract).compress!
29
+ end
30
+
31
+ Success attributes
30
32
  end
31
33
 
32
34
  private
@@ -24,9 +24,8 @@ module Milestoner
24
24
  end
25
25
 
26
26
  def call attributes
27
- attributes.fetch_value(key) { citation.open(path).title }
28
- .then { |value| value unless String(value).empty? }
29
- .then { |value| Success attributes.merge!(key => value) }
27
+ attributes.fetch(key) { attributes.merge!(key => citation.open(path).title).compress! }
28
+ Success attributes
30
29
  end
31
30
 
32
31
  private
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cff"
4
+ require "dry/monads"
5
+ require "pathname"
6
+ require "refinements/hash"
7
+
8
+ module Milestoner
9
+ module Configuration
10
+ module Transformers
11
+ module Citations
12
+ # Conditionally updates project URI based on citation URL.
13
+ class URI
14
+ include Dry::Monads[:result]
15
+
16
+ using Refinements::Hash
17
+
18
+ def initialize key = :project_uri,
19
+ path: Pathname.pwd.join("CITATION.cff"),
20
+ citation: CFF::File
21
+ @key = key
22
+ @path = path
23
+ @citation = citation
24
+ end
25
+
26
+ def call attributes
27
+ process attributes
28
+ Success attributes
29
+ rescue KeyError => error
30
+ Failure step: :transform,
31
+ payload: "Unable to transform #{key.inspect}, missing specifier: " \
32
+ "\"#{error.message[/<.+>/]}\"."
33
+ end
34
+
35
+ private
36
+
37
+ attr_reader :key, :path, :citation
38
+
39
+ def process attributes
40
+ attributes.fetch(key) { citation.open(path).url }
41
+ .then { |value| value.match?(/%<.+>s/) ? format(value, attributes) : value }
42
+ .then { |value| attributes.merge!(key => value).compress! }
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "dry/monads"
4
4
  require "pathname"
5
+ require "refinements/hash"
5
6
 
6
7
  module Milestoner
7
8
  module Configuration
@@ -12,6 +13,8 @@ module Milestoner
12
13
  include Import[:spec_loader]
13
14
  include Dry::Monads[:result]
14
15
 
16
+ using Refinements::Hash
17
+
15
18
  def initialize(key = :project_description, path: "#{Pathname.pwd.basename}.gemspec", **)
16
19
  @key = key
17
20
  @path = path
@@ -19,8 +22,11 @@ module Milestoner
19
22
  end
20
23
 
21
24
  def call attributes
22
- attributes.fetch(key) { spec_loader.call(path).summary }
23
- .then { |value| Success attributes.merge!(key => value) }
25
+ attributes.fetch key do
26
+ attributes.merge!(key => spec_loader.call(path).summary).compress!
27
+ end
28
+
29
+ Success attributes
24
30
  end
25
31
 
26
32
  private
@@ -19,9 +19,12 @@ module Milestoner
19
19
  end
20
20
 
21
21
  def call attributes
22
- attributes.fetch(key) { spec_loader.call(path).label }
23
- .then { |value| value unless value == "Undefined" }
24
- .then { |value| Success attributes.merge!(key => value) }
22
+ attributes.fetch key do
23
+ value = spec_loader.call(path).label
24
+ attributes.merge! key => value unless value == "Undefined"
25
+ end
26
+
27
+ Success attributes
25
28
  end
26
29
 
27
30
  private
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "dry/monads"
4
4
  require "pathname"
5
+ require "refinements/hash"
5
6
 
6
7
  module Milestoner
7
8
  module Configuration
@@ -12,6 +13,8 @@ module Milestoner
12
13
  include Import[:spec_loader]
13
14
  include Dry::Monads[:result]
14
15
 
16
+ using Refinements::Hash
17
+
15
18
  def initialize(key = :project_name, path: "#{Pathname.pwd.basename}.gemspec", **)
16
19
  @key = key
17
20
  @path = path
@@ -19,8 +22,11 @@ module Milestoner
19
22
  end
20
23
 
21
24
  def call attributes
22
- attributes.fetch(key) { spec_loader.call(path).name }
23
- .then { |value| Success attributes.merge!(key => value) }
25
+ attributes.fetch key do
26
+ attributes.merge!(key => spec_loader.call(path).name).compress!
27
+ end
28
+
29
+ Success attributes
24
30
  end
25
31
 
26
32
  private
@@ -19,14 +19,23 @@ module Milestoner
19
19
  end
20
20
 
21
21
  def call attributes
22
- attributes.fetch(key) { spec_loader.call(path).homepage_url }
23
- .then { |value| value unless String(value).empty? }
24
- .then { |value| Success attributes.merge!(key => value) }
22
+ process attributes
23
+ Success attributes
24
+ rescue KeyError => error
25
+ Failure step: :transform,
26
+ payload: "Unable to transform #{key.inspect}, missing specifier: " \
27
+ "\"#{error.message[/<.+>/]}\"."
25
28
  end
26
29
 
27
30
  private
28
31
 
29
32
  attr_reader :key, :path
33
+
34
+ def process attributes
35
+ attributes.fetch(key) { spec_loader.call(path).homepage_url }
36
+ .then { |value| value.match?(/%<.+>s/) ? format(value, attributes) : value }
37
+ .then { |value| attributes.merge! key => value unless value.empty? }
38
+ end
30
39
  end
31
40
  end
32
41
  end
@@ -17,8 +17,8 @@ module Milestoner
17
17
  end
18
18
 
19
19
  def call attributes
20
- attributes.fetch(key) { specification.label }
21
- .then { |value| Success attributes.merge!(key => value) }
20
+ attributes.fetch(key) { attributes.merge! key => specification.label }
21
+ Success attributes
22
22
  end
23
23
 
24
24
  private
@@ -17,8 +17,8 @@ module Milestoner
17
17
  end
18
18
 
19
19
  def call attributes
20
- attributes.fetch(key) { specification.homepage_url }
21
- .then { |value| Success attributes.merge!(key => value) }
20
+ attributes.fetch(key) { attributes.merge! key => specification.homepage_url }
21
+ Success attributes
22
22
  end
23
23
 
24
24
  private
@@ -17,8 +17,8 @@ module Milestoner
17
17
  end
18
18
 
19
19
  def call attributes
20
- attributes.fetch(key) { specification.version }
21
- .then { |value| Success attributes.merge!(key => value) }
20
+ attributes.fetch(key) { attributes.merge! key => specification.version }
21
+ Success attributes
22
22
  end
23
23
 
24
24
  private
@@ -20,8 +20,11 @@ module Milestoner
20
20
  end
21
21
 
22
22
  def call attributes
23
- attributes.fetch_value(key) { git.get("user.name", nil).value_or(nil) }
24
- .then { |value| Success attributes.merge!(key => value) }
23
+ attributes.fetch key do
24
+ git.get("user.name", nil).bind { |value| attributes.merge!(key => value).compress! }
25
+ end
26
+
27
+ Success attributes
25
28
  end
26
29
 
27
30
  private
@@ -14,8 +14,8 @@ module Milestoner
14
14
  using Refinements::Hash
15
15
 
16
16
  Label = lambda do |attributes, key = :project_label, default: Pathname.pwd.basename.to_s|
17
- attributes.fetch_value(key) { default.titleize }
18
- .then { |value| Dry::Monads::Success attributes.merge!(key => value) }
17
+ attributes.fetch(key) { attributes.merge!(key => default.titleize).compress! }
18
+ Dry::Monads::Success attributes
19
19
  end
20
20
  end
21
21
  end
@@ -19,8 +19,8 @@ module Milestoner
19
19
  end
20
20
 
21
21
  def call attributes
22
- attributes.fetch_value(key) { versioner.call }
23
- .then { |value| Success attributes.merge!(key => value) }
22
+ attributes.fetch_value(key) { attributes.merge! key => versioner.call }
23
+ Success attributes
24
24
  end
25
25
 
26
26
  private
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "core"
4
+ require "dry/monads"
5
+ require "refinements/hash"
6
+
7
+ module Milestoner
8
+ module Configuration
9
+ module Transformers
10
+ # Conditionally updates links based on project details.
11
+ module Syndication
12
+ using Refinements::Hash
13
+
14
+ Link = lambda do |attributes, key = :syndication_links|
15
+ links = attributes.fetch key, Core::EMPTY_ARRAY
16
+
17
+ links.each do |link|
18
+ link.symbolize_keys!
19
+
20
+ link[:label] = format link[:label], attributes
21
+ link[:uri] = format link[:uri], attributes
22
+ end
23
+
24
+ Dry::Monads::Success attributes.merge!(key => links)
25
+ rescue KeyError => error
26
+ Dry::Monads::Failure step: :transform,
27
+ payload: "Unable to transform #{key.inspect}, missing specifier: " \
28
+ "\"#{error.message[/<.+>/]}\"."
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -28,14 +28,10 @@ module Milestoner
28
28
  end
29
29
  end
30
30
 
31
- register :configuration do
32
- self[:defaults].add_loader(:yaml, self["xdg.config"].active)
33
- .then { |registry| Etcher.call registry }
34
- end
35
-
36
- register :defaults do
31
+ register :registry do
37
32
  Etcher::Registry.new(contract: Configuration::Contract, model: Configuration::Model)
38
33
  .add_loader(:yaml, self[:defaults_path])
34
+ .add_loader(:yaml, self["xdg.config"].active)
39
35
  .add_transformer(Configuration::Transformers::Build::Root)
40
36
  .add_transformer(Configuration::Transformers::Build::TemplatePaths.new)
41
37
  .add_transformer(Configuration::Transformers::Gems::Label.new)
@@ -44,28 +40,36 @@ module Milestoner
44
40
  .add_transformer(Configuration::Transformers::Gems::URI.new)
45
41
  .add_transformer(Configuration::Transformers::Citations::Label.new)
46
42
  .add_transformer(Configuration::Transformers::Citations::Description.new)
43
+ .add_transformer(Configuration::Transformers::Citations::URI.new)
47
44
  .add_transformer(Configuration::Transformers::Project::Author.new)
48
45
  .add_transformer(Configuration::Transformers::Project::Label)
49
- .add_transformer(Configuration::Transformers::Project::Name)
46
+ .add_transformer(:basename, :project_name)
50
47
  .add_transformer(Configuration::Transformers::Project::Version.new)
48
+ .add_transformer(:format, :project_uri_home)
49
+ .add_transformer(:format, :project_uri_icon)
50
+ .add_transformer(:format, :project_uri_logo)
51
+ .add_transformer(:format, :project_uri_version, id: "%<id>s")
51
52
  .add_transformer(Configuration::Transformers::Generator::Label.new)
52
53
  .add_transformer(Configuration::Transformers::Generator::URI.new)
53
54
  .add_transformer(Configuration::Transformers::Generator::Version.new)
54
- .add_transformer(Configuration::Transformers::URI::Avatar)
55
- .add_transformer(Configuration::Transformers::URI::Commit)
56
- .add_transformer(Configuration::Transformers::URI::Profile)
57
- .add_transformer(Configuration::Transformers::URI::Review)
58
- .add_transformer(Configuration::Transformers::URI::Tracker)
59
- .add_transformer(:time)
55
+ .add_transformer(:format, :syndication_entry_label, id: "%<id>s")
56
+ .add_transformer(:format, :syndication_entry_uri, id: "%<id>s")
57
+ .add_transformer(:format, :syndication_id, id: "%<id>s")
58
+ .add_transformer(:format, :syndication_label)
59
+ .add_transformer(Configuration::Transformers::Syndication::Link)
60
+ .add_transformer(:format, :commit_uri, id: "%<id>s")
61
+ .add_transformer(:format, :review_uri, id: "%<id>s")
62
+ .add_transformer(:format, :tracker_uri, id: "%<id>s")
63
+ .add_transformer(:time, :loaded_at)
60
64
  end
61
65
 
66
+ register(:settings) { Etcher.call(self[:registry]).dup }
62
67
  register(:specification) { self[:spec_loader].call "#{__dir__}/../../milestoner.gemspec" }
63
- register(:sanitizer) { -> content { Sanitize.fragment content, Sanitize::Config::BASIC } }
68
+ register :sanitizer, -> content { Sanitize.fragment content, Sanitize::Config::BASIC }
64
69
  register(:spec_loader) { Spek::Loader.new }
65
70
  register(:git) { Gitt::Repository.new }
66
- register(:input) { self[:configuration].dup }
67
71
  register(:defaults_path) { Pathname(__dir__).join("configuration/defaults.yml") }
68
72
  register(:logger) { Cogger.new id: :milestoner }
69
- register :kernel, Kernel
73
+ register :io, STDOUT
70
74
  end
71
75
  end