readme_yard 0.2.0 → 0.4.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.
data/lib/readme_yard.rb CHANGED
@@ -1,45 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "yard"
3
4
  require "yard-readme"
5
+ require "tty-markdown"
4
6
  require_relative "readme_yard/version"
5
7
  require_relative "readme_yard/error"
6
8
  require_relative "readme_yard/logger"
7
9
  require_relative "readme_yard/readme_tag"
8
10
  require_relative "readme_yard/example_tag"
9
11
  require_relative "readme_yard/comment_tag"
12
+ require_relative "readme_yard/code_tag"
10
13
  require_relative "readme_yard/source_tag"
11
- require_relative "readme_yard/object_tag"
14
+ require_relative "readme_yard/value_tag"
15
+ require_relative "readme_yard/string_tag"
16
+ require_relative "readme_yard/tag_registry"
17
+ require_relative "readme_yard/yard_opts_manager"
18
+ require "diffy"
12
19
 
13
- YARDReadme::DocstringParser.readme_tag_names = %w[comment source object]
20
+ YARD::Readme::DocstringParser.readme_tag_names = ReadmeYard::TagRegistry.tag_names
14
21
 
15
22
  #
16
23
  # @readme
17
- # Build a better README with [YARD](https://yardoc.org),
18
- # one that summarizes and contextualizes the code and documentation,
19
- # without duplicating them.
24
+ # Build a better README with [YARD](https://yardoc.org)
25
+ # by generating it straight from the source.
20
26
  #
21
- # This gem aims to minimize the effort needed to keep
22
- # your code, docs, and README useful, syncd, and correct.
27
+ # This gem aims to minimize the effort needed to keep your
28
+ # README, documentation, and source code synced, useful,
29
+ # and correct. Among its features, it introduces the @readme tag
30
+ # that enables you to embed code comments directly into README sections,
31
+ # eliminating redundancy and keeping documentation consistent
32
+ # across your codebase and project README.
23
33
  #
24
- # For a glimpse of how it works, check out the [README_YARD.md](https://github.com/mattruzicka/readme_yard/blob/main/README_YARD.md)
25
- # template from which this gem's README was generated.
34
+ # Look at the [README_YARD.md](https://github.com/mattruzicka/readme_yard/blob/main/README_YARD.md)
35
+ # template for this project to see how it works.
26
36
  # If you're reading the README, that means this text is here
27
- # because `{@readme ReadmeYard}` is in the README_YARD file
28
- # and someone ran `readme build` at the command line.
37
+ # because the custom `{@readme ReadmeYard}` markdown tag is in
38
+ # README_YARD.md and `readme build` was run at the command line.
29
39
  #
30
40
  # Here's the [full documentation](https://rubydoc.info/github/mattruzicka/readme_yard).
31
41
  #
32
42
  class ReadmeYard
33
- #
34
- # @readme comment
35
- #
36
- # @example
37
- # ReadmeYard.hello_world #=> "Hello 🌎 🌍 🌏"
38
- #
39
- def self.hello_world
40
- "Hello 🌎 🌍 🌏"
41
- end
42
-
43
43
  #
44
44
  # @see #command_line_usage
45
45
  #
@@ -49,23 +49,15 @@ class ReadmeYard
49
49
  case arg
50
50
  when "build"
51
51
  readme_yard.build(options: options)
52
- when "doc"
53
- readme_yard.doc(options: options)
52
+ when "yard"
53
+ readme_yard.yard(options: options)
54
+ when "version"
55
+ Logger.puts_md(VERSION)
54
56
  else
55
- puts TTY::Markdown.parse(readme_yard.command_line_usage)
57
+ Logger.puts_md(readme_yard.command_line_usage)
56
58
  end
57
59
  rescue Error => e
58
- puts TTY::Markdown.parse(e.message)
59
- end
60
-
61
- TAG_CLASS_LOOKUP = { "readme" => ReadmeTag,
62
- "example" => ExampleTag,
63
- "source" => SourceTag,
64
- "comment" => CommentTag,
65
- "object" => ObjectTag }.freeze
66
-
67
- def self.lookup_tag_class(tag_name)
68
- TAG_CLASS_LOOKUP[tag_name]
60
+ Logger.puts_md(e.message)
69
61
  end
70
62
 
71
63
  def initialize
@@ -76,7 +68,9 @@ class ReadmeYard
76
68
  attr_accessor :readme_path, :readme_yard_path
77
69
 
78
70
  #
79
- # This method returns the following `@readme` text
71
+ # This unnecessarily meta method returns the `@readme` text you see
72
+ # below (if you're reading this in the source code). It was implemented
73
+ # just for fun as a demonstration of @readme tags.
80
74
  #
81
75
  # @readme
82
76
  # ## Command Line Usage
@@ -85,13 +79,15 @@ class ReadmeYard
85
79
  #
86
80
  # `readme build` - Reads from README_YARD.md and writes to README.md.
87
81
  #
88
- # `readme doc` - Same as `readme build` + generates yard docs.
82
+ # `readme yard` - Same as `readme build` + generates yard docs.
83
+ #
84
+ # `readme version` - Prints the current version of ReadmeYard.
89
85
  #
90
86
  def command_line_usage
91
87
  yard_parse_this_file
92
88
  yard_object = YARD::Registry.at("#{self.class.name}##{__method__}")
93
89
  yard_tags = yard_object.tags(:readme)
94
- "\n#{ReadmeTag.format_markdown(yard_object, yard_tags)}\n\n"
90
+ "\n#{ReadmeTag.format_tags(yard_object, yard_tags)}\n\n"
95
91
  end
96
92
 
97
93
  #
@@ -105,20 +101,19 @@ class ReadmeYard
105
101
  # `-q` silence yardoc output statements
106
102
  #
107
103
  def build(options: "-nq")
108
- find_or_upsert_yardopts
109
- run_yardoc(options: options)
110
- File.write(readme_path, gsub_tags!(readme_yard_md))
104
+ YARD::CLI::Yardoc.run(options || "-nq")
105
+ old_readme = File.exist?(readme_path) ? File.read(readme_path) : ""
106
+ new_readme = gsub_tags!(readme_yard_md)
107
+ File.write(readme_path, new_readme)
108
+ show_readme_diff(old_readme, new_readme)
111
109
  end
112
110
 
113
111
  #
114
- # @readme Same as "build" + generates yard docs.
112
+ # @readme Same as "build" + generates yard `docs.
115
113
  #
116
- def doc(options: "-q")
117
- build(options: options || "-q")
118
- end
119
-
120
- def run_yardoc(options: "-nq")
121
- YARD::CLI::Yardoc.run(options || "-nq")
114
+ def yard(options: "")
115
+ YardOptsManager.upsert_yardopts
116
+ build(options: options || "")
122
117
  end
123
118
 
124
119
  private
@@ -144,43 +139,6 @@ class ReadmeYard
144
139
  " for usage.\n\n{@readme ReadmeYard#default_readme_yard_md}"
145
140
  end
146
141
 
147
- YARDOPTS_FILE = ".yardopts"
148
-
149
- def find_or_upsert_yardopts
150
- File.exist?(YARDOPTS_FILE) ? update_yardopts_file : create_yardopts_file
151
- end
152
-
153
- def update_yardopts_file
154
- text = File.read(YARDOPTS_FILE)
155
- text_addition = build_yardopts_text_addition(text)
156
- File.open(YARDOPTS_FILE, "a") { |f| f.write(text_addition) } if text_addition
157
- end
158
-
159
- def build_yardopts_text_addition(yardopts_text)
160
- return if yardopts_text.match?(/\s*--plugin\s+readme\W/)
161
-
162
- readme_plugin_opts = default_readme_plugin_opts(yardopts_text)
163
- case yardopts_text
164
- when /\s*--markup\s+markdown/, /\s*-m\s+markdown/
165
- readme_plugin_opts
166
- when /\s*--markup\s/, /\s*-m\s/
167
- warn_about_supported_markdown
168
- readme_plugin_opts
169
- else
170
- readme_plugin_opts << "--markup markdown\n"
171
- end
172
- end
173
-
174
- def default_readme_plugin_opts(yardopts_text)
175
- readme_opts = +""
176
- readme_opts << "\n" unless yardopts_text.lines.last.include?("\n")
177
- readme_opts << "--plugin readme\n"
178
- end
179
-
180
- def create_yardopts_file
181
- File.write(YARDOPTS_FILE, "--plugin readme\n--markup markdown\n")
182
- end
183
-
184
142
  def gsub_tags!(markdown)
185
143
  markdown.gsub!(/([^`]|^)(\{@\w+\s.+\})/) { |string| format_tag_markdown(string) }
186
144
  markdown
@@ -201,12 +159,17 @@ class ReadmeYard
201
159
 
202
160
  def format_yard_tags_markdown(yard_object, tag_name, string)
203
161
  yard_tags = yard_object.tags(tag_name)
162
+ tag_class = TagRegistry.find_class(tag_name)
163
+
204
164
  if yard_tags.empty?
205
- warn_about_yard_tags_not_found(yard_object, tag_name)
206
- string
165
+ if tag_class.respond_to?(:format_yard_object)
166
+ tag_class.format_yard_object(yard_object) || string
167
+ else
168
+ Logger.warn("The `@#{tag_name}` tag is missing from `#{yard_object}`.")
169
+ string
170
+ end
207
171
  else
208
- tag_class = self.class.lookup_tag_class(tag_name)
209
- tag_class.format_markdown(yard_object, yard_tags)
172
+ tag_class.format_tags(yard_object, yard_tags)
210
173
  end
211
174
  end
212
175
 
@@ -224,12 +187,14 @@ class ReadmeYard
224
187
  YARD.parse(current_file_path)
225
188
  end
226
189
 
227
- def warn_about_supported_markdown
228
- Logger.warn "\n*Readme Yard* works best with markdown." \
229
- "\nConsider adding `--markup markdown` to your `.yardopts` file.\n\n"
230
- end
190
+ def show_readme_diff(old_content, new_content)
191
+ if old_content == new_content
192
+ Logger.puts_md("\n**No changes** to README.md\n\n")
193
+ return
194
+ end
231
195
 
232
- def warn_about_yard_tags_not_found(yard_object, tag_name)
233
- Logger.warn "The `@#{tag_name}` *Readme Yard* tag is missing from #{yard_object}."
196
+ diff = Diffy::Diff.new(old_content, new_content, context: 0).to_s(:color)
197
+ Logger.puts_md("\n**Changes to README.md:**\n\n")
198
+ Logger.puts_text "#{diff}\n"
234
199
  end
235
200
  end
data/readme_yard.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
 
11
11
  spec.summary = "Build a better README with YARD."
12
12
  spec.homepage = "https://github.com/mattruzicka/readme_yard"
13
- spec.required_ruby_version = ">= 2.5"
13
+ spec.required_ruby_version = ">= 3.0"
14
14
 
15
15
  spec.metadata["homepage_uri"] = spec.homepage
16
16
  spec.metadata["source_code_uri"] = spec.homepage
@@ -22,12 +22,17 @@ Gem::Specification.new do |spec|
22
22
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
23
23
  end
24
24
 
25
- spec.executables << "readme"
25
+ spec.bindir = "bin"
26
+ spec.executables = ["readme"]
26
27
  spec.require_paths = ["lib"]
27
28
 
28
29
  # Uncomment to register a new dependency of your gem
30
+ spec.add_dependency "diffy", "~> 3.4"
29
31
  spec.add_dependency "tty-markdown", "~> 0.7"
30
- spec.add_dependency "yard-readme", "~> 0.3"
32
+ spec.add_dependency "yard", "~> 0.9"
33
+ spec.add_dependency "yard-readme", "~> 0.5"
34
+
35
+ spec.add_development_dependency "irb"
31
36
 
32
37
  # For more information and examples about making a new gem, checkout our
33
38
  # guide at: https://bundler.io/guides/creating_gem.html
metadata CHANGED
@@ -1,15 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: readme_yard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Ruzicka
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2021-08-08 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: diffy
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '3.4'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '3.4'
13
26
  - !ruby/object:Gem::Dependency
14
27
  name: tty-markdown
15
28
  requirement: !ruby/object:Gem::Requirement
@@ -24,22 +37,48 @@ dependencies:
24
37
  - - "~>"
25
38
  - !ruby/object:Gem::Version
26
39
  version: '0.7'
40
+ - !ruby/object:Gem::Dependency
41
+ name: yard
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.9'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.9'
27
54
  - !ruby/object:Gem::Dependency
28
55
  name: yard-readme
29
56
  requirement: !ruby/object:Gem::Requirement
30
57
  requirements:
31
58
  - - "~>"
32
59
  - !ruby/object:Gem::Version
33
- version: '0.3'
60
+ version: '0.5'
34
61
  type: :runtime
35
62
  prerelease: false
36
63
  version_requirements: !ruby/object:Gem::Requirement
37
64
  requirements:
38
65
  - - "~>"
39
66
  - !ruby/object:Gem::Version
40
- version: '0.3'
41
- description:
42
- email:
67
+ version: '0.5'
68
+ - !ruby/object:Gem::Dependency
69
+ name: irb
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
43
82
  executables:
44
83
  - readme
45
84
  extensions: []
@@ -59,14 +98,18 @@ files:
59
98
  - bin/readme
60
99
  - bin/setup
61
100
  - lib/readme_yard.rb
101
+ - lib/readme_yard/code_tag.rb
62
102
  - lib/readme_yard/comment_tag.rb
63
103
  - lib/readme_yard/error.rb
64
104
  - lib/readme_yard/example_tag.rb
65
105
  - lib/readme_yard/logger.rb
66
- - lib/readme_yard/object_tag.rb
67
106
  - lib/readme_yard/readme_tag.rb
68
107
  - lib/readme_yard/source_tag.rb
108
+ - lib/readme_yard/string_tag.rb
109
+ - lib/readme_yard/tag_registry.rb
110
+ - lib/readme_yard/value_tag.rb
69
111
  - lib/readme_yard/version.rb
112
+ - lib/readme_yard/yard_opts_manager.rb
70
113
  - readme_yard.gemspec
71
114
  homepage: https://github.com/mattruzicka/readme_yard
72
115
  licenses:
@@ -75,7 +118,6 @@ metadata:
75
118
  homepage_uri: https://github.com/mattruzicka/readme_yard
76
119
  source_code_uri: https://github.com/mattruzicka/readme_yard
77
120
  changelog_uri: https://github.com/mattruzicka/readme_yard/blob/master/CHANGELOG.md
78
- post_install_message:
79
121
  rdoc_options: []
80
122
  require_paths:
81
123
  - lib
@@ -83,15 +125,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
83
125
  requirements:
84
126
  - - ">="
85
127
  - !ruby/object:Gem::Version
86
- version: '2.5'
128
+ version: '3.0'
87
129
  required_rubygems_version: !ruby/object:Gem::Requirement
88
130
  requirements:
89
131
  - - ">="
90
132
  - !ruby/object:Gem::Version
91
133
  version: '0'
92
134
  requirements: []
93
- rubygems_version: 3.2.3
94
- signing_key:
135
+ rubygems_version: 3.6.8
95
136
  specification_version: 4
96
137
  summary: Build a better README with YARD.
97
138
  test_files: []
@@ -1,21 +0,0 @@
1
- class ReadmeYard
2
- #
3
- # @readme
4
- # ```@readme object``` - Embeds the comment and source.
5
- #
6
- class ObjectTag
7
- class << self
8
- #
9
- # This method's comment and code is in the README because
10
- # because `@readme object` is below, in the actual source code.
11
- #
12
- # @readme object
13
- #
14
- def format_tag_markdown(yard_object, _tag)
15
- text = CommentTag.format_docstring_as_comment(yard_object)
16
- text << "\n#{yard_object.source}"
17
- ExampleTag.format_ruby(text)
18
- end
19
- end
20
- end
21
- end