Class: Ronn::Document
Overview
The Document class can be used to load and inspect a ronn document and to convert a ronn document into other formats, like roff or HTML.
Ronn files may optionally follow the naming convention: “<name>.<section>.ronn”. The <name> and <section> are used in generated documentation unless overridden by the information extracted from the document’s name section.
Constant Summary
Constants included from Utils
Utils::HTML, Utils::HTML_BLOCK, Utils::HTML_EMPTY, Utils::HTML_INLINE
Instance Attribute Summary collapse
-
#data ⇒ Object
readonly
The raw input data, read from path or stream and unmodified.
-
#date ⇒ Object
The date the man page was published.
-
#encoding ⇒ Object
Encoding that the Ronn document is in.
-
#index ⇒ Object
The index used to resolve man and file references.
-
#manual ⇒ Object
The manual this document belongs to; center displayed in the header.
-
#name ⇒ Object
Returns the manual page name based first on the document’s contents and then on the path name.
-
#organization ⇒ Object
The name of the group, organization, or individual responsible for this document; displayed in the left portion of the footer.
-
#outdir ⇒ Object
Output directory to write files to.
-
#path ⇒ Object
readonly
Path to the Ronn document.
-
#section ⇒ Object
Returns the manual page section based first on the document’s contents and then on the path name.
-
#styles ⇒ Object
Array of style modules to apply to the document.
-
#tagline ⇒ Object
Single sentence description of the thing being described by this man page; displayed in the NAME section.
Instance Method Summary collapse
-
#basename(type = nil) ⇒ Object
Generate a file basename of the form “<name>.<section>.<type>” for the given file extension.
-
#convert(format) ⇒ Object
Convert the document to :roff, :html, or :html_fragment and return the result as a string.
-
#html ⇒ Object
A Nokogiri DocumentFragment for the manual content fragment.
-
#initialize(path = nil, attributes = {}, &block) ⇒ Document
constructor
Create a Ronn::Document given a path or with the data returned by calling the block.
-
#markdown ⇒ Object
Preprocessed markdown input text.
-
#name? ⇒ Boolean
Truthful when the name was extracted from the name section of the document.
-
#path_for(type = nil) ⇒ Object
Construct a path for a file near the source file.
-
#path_name ⇒ Object
Returns the <name> part of the path, or nil when no path is available.
-
#path_section ⇒ Object
Returns the <section> part of the path, or nil when no path is available.
-
#reference_name ⇒ Object
The name used to reference this manual.
-
#section? ⇒ Boolean
True when the section number was extracted from the name section of the document.
-
#sniff ⇒ Object
Sniff the document header and extract basic document metadata.
-
#title ⇒ Object
The document’s title when no name section was defined.
-
#title? ⇒ Boolean
Truthful when the document started with an h1 but did not follow the “<name>(<sect>) – <tagline>” convention.
- #to_h ⇒ Object
-
#to_html ⇒ Object
Convert the document to HTML and return the result as a string.
-
#to_html_fragment(wrap_class = 'mp') ⇒ Object
Convert the document to HTML and return the result as a string.
- #to_json(*_args) ⇒ Object
- #to_markdown ⇒ Object
-
#to_roff ⇒ Object
Convert the document to roff and return the result as a string.
- #to_yaml ⇒ Object
-
#toc ⇒ Object
(also: #section_heads)
Retrieve a list of top-level section headings in the document and return as an array of [id, text] tuples, where
id
is the element’s generated id andtext
is the inner text of the heading element.
Methods included from Utils
#block_element?, #child_of?, #empty_element?, #html_element?, #inline_element?
Constructor Details
#initialize(path = nil, attributes = {}, &block) ⇒ Document
Create a Ronn::Document given a path or with the data returned by calling the block. The document is loaded and preprocessed before the intialize method returns. The attributes hash may contain values for any writeable attributes defined on this class.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/ronn/document.rb', line 71 def initialize(path = nil, attributes = {}, &block) @path = path @basename = path.to_s =~ /^-?$/ ? nil : File.basename(path) @reader = block || lambda do |f| if ['-', nil].include?(f) $stdin.read else File.read(f, encoding: @encoding) end end @data = @reader.call(path) @name, @section, @tagline = sniff @styles = %w[man] @manual, @organization, @date = nil @markdown, @input_html, @html = nil @index = Ronn::Index[path || '.'] @index.add_manual(self) if path && name attributes.each { |attr_name, value| send("#{attr_name}=", value) } end |
Instance Attribute Details
#data ⇒ Object (readonly)
The raw input data, read from path or stream and unmodified.
30 31 32 |
# File 'lib/ronn/document.rb', line 30 def data @data end |
#date ⇒ Object
The date the man page was published. If not set explicitly, it first checks for “SOURCE_DATE_EPOCH” to support reproducible builds, then the file’s modified time or, if no file is given, the current time. Center displayed in the document footer.
185 186 187 188 189 190 191 192 193 |
# File 'lib/ronn/document.rb', line 185 def date return @date if @date return Time.at(ENV['SOURCE_DATE_EPOCH'].to_i).gmtime if ENV['SOURCE_DATE_EPOCH'] return File.mtime(path) if File.exist?(path) Time.now end |
#encoding ⇒ Object
Encoding that the Ronn document is in
27 28 29 |
# File 'lib/ronn/document.rb', line 27 def encoding @encoding end |
#index ⇒ Object
The index used to resolve man and file references.
33 34 35 |
# File 'lib/ronn/document.rb', line 33 def index @index end |
#manual ⇒ Object
The manual this document belongs to; center displayed in the header.
51 52 53 |
# File 'lib/ronn/document.rb', line 51 def manual @manual end |
#name ⇒ Object
Returns the manual page name based first on the document’s contents and then on the path name. Usually a single word name of a program or filename; displayed along with the section in the left and right portions of the header as well as the bottom right section of the footer.
140 141 142 |
# File 'lib/ronn/document.rb', line 140 def name @name || path_name end |
#organization ⇒ Object
The name of the group, organization, or individual responsible for this document; displayed in the left portion of the footer.
55 56 57 |
# File 'lib/ronn/document.rb', line 55 def organization @organization end |
#outdir ⇒ Object
Output directory to write files to.
65 66 67 |
# File 'lib/ronn/document.rb', line 65 def outdir @outdir end |
#path ⇒ Object (readonly)
Path to the Ronn document. This may be ‘-’ or nil when the Ronn::Document object is created with a stream, in which case stdin will be read.
24 25 26 |
# File 'lib/ronn/document.rb', line 24 def path @path end |
#section ⇒ Object
Returns the manual page section based first on the document’s contents and then on the path name. A string whose first character is numeric; displayed in parenthesis along with the name.
153 154 155 |
# File 'lib/ronn/document.rb', line 153 def section @section || path_section end |
#styles ⇒ Object
Array of style modules to apply to the document.
62 63 64 |
# File 'lib/ronn/document.rb', line 62 def styles @styles end |
#tagline ⇒ Object
Single sentence description of the thing being described by this man page; displayed in the NAME section.
47 48 49 |
# File 'lib/ronn/document.rb', line 47 def tagline @tagline end |
Instance Method Details
#basename(type = nil) ⇒ Object
Generate a file basename of the form “<name>.<section>.<type>” for the given file extension. Uses the name and section from the source file path but falls back on the name and section defined in the document.
98 99 100 101 102 |
# File 'lib/ronn/document.rb', line 98 def basename(type = nil) type = nil if ['', 'roff'].include?(type.to_s) [path_name || @name, path_section || @section, type] .compact.join('.') end |
#convert(format) ⇒ Object
Convert the document to :roff, :html, or :html_fragment and return the result as a string.
245 246 247 |
# File 'lib/ronn/document.rb', line 245 def convert(format) send "to_#{format}" end |
#html ⇒ Object
A Nokogiri DocumentFragment for the manual content fragment.
239 240 241 |
# File 'lib/ronn/document.rb', line 239 def html @html ||= process_html! end |
#markdown ⇒ Object
Preprocessed markdown input text.
234 235 236 |
# File 'lib/ronn/document.rb', line 234 def markdown @markdown ||= process_markdown! end |
#name? ⇒ Boolean
Truthful when the name was extracted from the name section of the document.
146 147 148 |
# File 'lib/ronn/document.rb', line 146 def name? !@name.nil? end |
#path_for(type = nil) ⇒ Object
Construct a path for a file near the source file. Uses the Document#basename method to generate the basename part and appends it to the dirname of the source document.
107 108 109 110 111 112 113 114 115 |
# File 'lib/ronn/document.rb', line 107 def path_for(type = nil) if @outdir File.join(@outdir, basename(type)) elsif @basename File.join(File.dirname(path), basename(type)) else basename(type) end end |
#path_name ⇒ Object
Returns the <name> part of the path, or nil when no path is available. This is used as the manual page name when the file contents do not include a name section.
120 121 122 123 124 125 126 127 |
# File 'lib/ronn/document.rb', line 120 def path_name return unless @basename parts = @basename.split('.') parts.pop if parts.length > 1 && parts.last =~ /^\w+$/ parts.pop if parts.last =~ /^\d+$/ parts.join('.') end |
#path_section ⇒ Object
Returns the <section> part of the path, or nil when no path is available.
131 132 133 |
# File 'lib/ronn/document.rb', line 131 def path_section $1 if @basename.to_s =~ /\.(\d\w*)\./ end |
#reference_name ⇒ Object
The name used to reference this manual.
164 165 166 |
# File 'lib/ronn/document.rb', line 164 def reference_name name + (section && "(#{section})").to_s end |
#section? ⇒ Boolean
True when the section number was extracted from the name section of the document.
159 160 161 |
# File 'lib/ronn/document.rb', line 159 def section? !@section.nil? end |
#sniff ⇒ Object
Sniff the document header and extract basic document metadata. Return a tuple of the form: [name, section, description], where missing information is represented by nil and any element may be missing.
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/ronn/document.rb', line 213 def sniff html = Kramdown::Document.new(data[0, 512], auto_ids: false, smart_quotes: ['apos', 'apos', 'quot', 'quot'], typographic_symbols: { hellip: '...', ndash: '--', mdash: '--' }).to_html heading, html = html.split("</h1>\n", 2) return [nil, nil, nil] if html.nil? case heading when /([\w_.\[\]~+=@:-]+)\s*\((\d\w*)\)\s*-+\s*(.*)/ # name(section) -- description [$1, $2, $3] when /([\w_.\[\]~+=@:-]+)\s+-+\s+(.*)/ # name -- description [$1, nil, $2] else # description [nil, nil, heading.sub('<h1>', '')] end end |
#title ⇒ Object
The document’s title when no name section was defined. When a name section exists, this value is nil.
177 178 179 |
# File 'lib/ronn/document.rb', line 177 def title @tagline unless name? end |
#title? ⇒ Boolean
Truthful when the document started with an h1 but did not follow the “<name>(<sect>) – <tagline>” convention. We assume this is some kind of custom title.
171 172 173 |
# File 'lib/ronn/document.rb', line 171 def title? !name? && tagline end |
#to_h ⇒ Object
290 291 292 293 |
# File 'lib/ronn/document.rb', line 290 def to_h %w[name section tagline manual organization date styles toc] .each_with_object({}) { |name, hash| hash[name] = send(name) } end |
#to_html ⇒ Object
Convert the document to HTML and return the result as a string. The returned string is a complete HTML document.
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
# File 'lib/ronn/document.rb', line 260 def to_html layout = ENV.fetch('RONN_LAYOUT', nil) layout_path = nil if layout layout_path = File.(layout) unless File.exist?(layout_path) warn "warn: can't find #{layout}, using default layout." layout_path = nil end end template = Ronn::Template.new(self) template.context.push html: to_html_fragment(nil) template.render(layout_path || 'default') end |
#to_html_fragment(wrap_class = 'mp') ⇒ Object
Convert the document to HTML and return the result as a string. The HTML does not include <html>, <head>, or <style> tags.
279 280 281 282 283 284 |
# File 'lib/ronn/document.rb', line 279 def to_html_fragment(wrap_class = 'mp') frag_nodes = html.at('body').children out = frag_nodes.to_s.rstrip out = "<div class='#{wrap_class}'>#{out}\n</div>" unless wrap_class.nil? out end |
#to_json(*_args) ⇒ Object
300 301 302 303 |
# File 'lib/ronn/document.rb', line 300 def to_json(*_args) require 'json' to_h.merge('date' => date.iso8601).to_json end |
#to_markdown ⇒ Object
286 287 288 |
# File 'lib/ronn/document.rb', line 286 def to_markdown markdown end |
#to_roff ⇒ Object
Convert the document to roff and return the result as a string.
250 251 252 253 254 255 256 |
# File 'lib/ronn/document.rb', line 250 def to_roff RoffFilter.new( to_html_fragment(nil), name, section, tagline, manual, organization, date ).to_s end |
#to_yaml ⇒ Object
295 296 297 298 |
# File 'lib/ronn/document.rb', line 295 def to_yaml require 'yaml' to_h.to_yaml end |
#toc ⇒ Object Also known as: section_heads
Retrieve a list of top-level section headings in the document and return as an array of [id, text] tuples, where id
is the element’s generated id and text
is the inner text of the heading element.
198 199 200 201 |
# File 'lib/ronn/document.rb', line 198 def toc @toc ||= html.search('h2[@id]').map { |h2| [h2.attributes['id'].content.upcase, h2.inner_text] } end |