Class: Ronn::Document

Inherits:
Object
  • Object
show all
Includes:
Utils
Defined in:
lib/ronn/document.rb

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

Instance Method Summary collapse

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.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/ronn/document.rb', line 64

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)
      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

#dataObject (readonly)

The raw input data, read from path or stream and unmodified.



26
27
28
# File 'lib/ronn/document.rb', line 26

def data
  @data
end

#dateObject

The date the man page was published. If not set explicitly, this is the file’s modified time or, if no file is given, the current time.



55
56
57
# File 'lib/ronn/document.rb', line 55

def date
  @date
end

#indexObject

The index used to resolve man and file references.



29
30
31
# File 'lib/ronn/document.rb', line 29

def index
  @index
end

#manualObject

The manual this document belongs to; center displayed in the header.



47
48
49
# File 'lib/ronn/document.rb', line 47

def manual
  @manual
end

#nameObject

Returns the manual page name based first on the document’s contents and then on the path name.



35
36
37
# File 'lib/ronn/document.rb', line 35

def name
  @name
end

#organizationObject

The name of the group, organization, or individual responsible for this document; displayed in the left portion of the footer.



51
52
53
# File 'lib/ronn/document.rb', line 51

def organization
  @organization
end

#pathObject (readonly)

Path to the Ronn document. This may be ‘-’ or nil when the Ronn::Document object is created with a stream.



23
24
25
# File 'lib/ronn/document.rb', line 23

def path
  @path
end

#sectionObject

Returns the manual page section based first on the document’s contents and then on the path name.



39
40
41
# File 'lib/ronn/document.rb', line 39

def section
  @section
end

#stylesObject

Array of style modules to apply to the document.



58
59
60
# File 'lib/ronn/document.rb', line 58

def styles
  @styles
end

#taglineObject

Single sentence description of the thing being described by this man page; displayed in the NAME section.



43
44
45
# File 'lib/ronn/document.rb', line 43

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.



91
92
93
94
95
# File 'lib/ronn/document.rb', line 91

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.



220
221
222
# File 'lib/ronn/document.rb', line 220

def convert(format)
  send "to_#{format}"
end

#htmlObject

A Hpricot::Document for the manual content fragment.



214
215
216
# File 'lib/ronn/document.rb', line 214

def html
  @html ||= process_html!
end

#markdownObject

Preprocessed markdown input text.



209
210
211
# File 'lib/ronn/document.rb', line 209

def markdown
  @markdown ||= process_markdown!
end

#name?Boolean

Truthful when the name was extracted from the name section of the document.

Returns:

  • (Boolean)


129
130
131
# File 'lib/ronn/document.rb', line 129

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.



100
101
102
103
104
105
106
# File 'lib/ronn/document.rb', line 100

def path_for(type=nil)
  if @basename
    File.join(File.dirname(path), basename(type))
  else
    basename(type)
  end
end

#path_nameObject

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.



111
112
113
# File 'lib/ronn/document.rb', line 111

def path_name
  @basename[/^[^.]+/] if @basename
end

#path_sectionObject

Returns the <section> part of the path, or nil when no path is available.



117
118
119
# File 'lib/ronn/document.rb', line 117

def path_section
  $1 if @basename.to_s =~ /\.(\d\w*)\./
end

#reference_nameObject

The name used to reference this manual.



146
147
148
# File 'lib/ronn/document.rb', line 146

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.

Returns:

  • (Boolean)


141
142
143
# File 'lib/ronn/document.rb', line 141

def section?
  !@section.nil?
end

#sniffObject

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.



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/ronn/document.rb', line 190

def sniff
  html = Markdown.new(data[0, 512]).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

#titleObject

The document’s title when no name section was defined. When a name section exists, this value is nil.



159
160
161
# File 'lib/ronn/document.rb', line 159

def title
  @tagline if !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.

Returns:

  • (Boolean)


153
154
155
# File 'lib/ronn/document.rb', line 153

def title?
  !name? && tagline
end

#to_hObject



263
264
265
266
# File 'lib/ronn/document.rb', line 263

def to_h
  %w[name section tagline manual organization date styles toc].
  inject({}) { |hash, name| hash[name] = send(name); hash }
end

#to_htmlObject

Convert the document to HTML and return the result as a string.



234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/ronn/document.rb', line 234

def to_html
  if layout = ENV['RONN_LAYOUT']
    if !File.exist?(layout_path = File.expand_path(layout))
      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(wrap_class=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.



250
251
252
253
254
255
256
257
# File 'lib/ronn/document.rb', line 250

def to_html_fragment(wrap_class='mp')
  return html.to_s if wrap_class.nil?
  [
    "<div class='#{wrap_class}'>",
    html.to_s,
    "</div>"
  ].join("\n")
end

#to_jsonObject



273
274
275
276
# File 'lib/ronn/document.rb', line 273

def to_json
  require 'json'
  to_h.merge('date' => date.iso8601).to_json
end

#to_markdownObject



259
260
261
# File 'lib/ronn/document.rb', line 259

def to_markdown
  markdown
end

#to_roffObject

Convert the document to roff and return the result as a string.



225
226
227
228
229
230
231
# File 'lib/ronn/document.rb', line 225

def to_roff
  RoffFilter.new(
    to_html_fragment(wrap_class=nil),
    name, section, tagline,
    manual, organization, date
  ).to_s
end

#to_yamlObject



268
269
270
271
# File 'lib/ronn/document.rb', line 268

def to_yaml
  require 'yaml'
  to_h.to_yaml
end

#tocObject 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.



175
176
177
178
# File 'lib/ronn/document.rb', line 175

def toc
  @toc ||=
    html.search('h2[@id]').map { |h2| [h2.attributes['id'], h2.inner_text] }
end