Class: Docter::Collection

Inherits:
Object
  • Object
show all
Includes:
HTML
Defined in:
lib/docter/server.rb,
lib/docter/collection.rb

Defined Under Namespace

Classes: ToCResource

Instance Method Summary collapse

Methods included from HTML

inner_text_from, regexp_attribute, regexp_element

Constructor Details

#initialize(title = nil) ⇒ Collection

Returns a new instance of Collection.



77
78
79
80
# File 'lib/docter/collection.rb', line 77

def initialize(title = nil)
  @title = title
  @sources = FileList[]
end

Instance Method Details

#dependenciesObject

:call-seq:

Returns a list of dependencies (resource files, the template file, etc). Useful when creating a Rake task based on this template.



281
282
283
284
# File 'lib/docter/collection.rb', line 281

def dependencies() #:nodoc:
  files = @sources.map { |path| File.directory?(path) ? FileList[path, File.join(path, "**/*")] : path }.flatten +
    (@toc_resource ? [@toc_resource.filename] : [])
end

#exclude(*paths) ⇒ Object

:call-seq:

exclude(*paths) => self

Excludes files or directories from the collection.



144
145
146
147
# File 'lib/docter/collection.rb', line 144

def exclude(*paths)
  @sources.exclude *paths.flatten
  self
end

#file(path) ⇒ Object

:call-seq:

file(path) => filename

Returns the full path based on the relative path. For example:

collection.include("pages", "LICENSE")
collection.find("index.textile") => "pages/index.textile"
collection.find("LICENSE") => "LICENSE"


190
191
192
193
194
195
196
197
198
199
200
# File 'lib/docter/collection.rb', line 190

def file(path)      
  @sources.inject(nil) do |found, file|
    break found if found
    if File.directory?(file)
      base = file + "/"
      FileList[File.join(file, "**/*")].find { |file| file.sub(base, "") == path }
    else
      file if File.basename(file) == path
    end
  end
end

#generate(template, to_dir, *args) ⇒ Object

:call-seq:

generate(template, to_dir, :all?)
generate(template, to_dir, pages)
generate(template, to_dir, page)
generate(template, to_dir, :one_page)

The first form generates all pages from the ToC into the destination directory. The :all argument is optional. In addition, it copies all other resource files to the destination directory.

The second form works the same way but only for the specified pages, and the third form for a single page. Neither copies any resource files.

The fourth form generates a single HTML document in the destination directory (index.html) with all pages from the ToC, and copies all resource files to the destination directory. It will typically use a different template than the first three forms.



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/docter/collection.rb', line 252

def generate(template, to_dir, *args)
  options = Hash === args.last ? args.pop : {}
  if args.empty? || args.first == :all
    generate template, to_dir, pages, options
    template.copy_resources to_dir
  elsif args.first == :one_page
    mkpath to_dir
    File.join(to_dir, "index.html").tap do |filename|
      puts "Generating #{filename}" if verbose
      html = render(template, options)
      File.open(filename, "w") { |file| file.write html }
    end
    template.copy_resources to_dir
  else
    mkpath to_dir
    args.flatten.each do |page|
      File.join(to_dir, page.path).tap do |filename|
        puts "Generating #{filename}" if verbose
        html = render(template, page, options)
        File.open(filename, "w") { |file| file.write html }
      end
    end
  end
end

#include(*paths) ⇒ Object Also known as: add

:call-seq:

include(*paths) => self

Adds files and directories to the collection.



133
134
135
136
# File 'lib/docter/collection.rb', line 133

def include(*paths)
  @sources.include *paths.flatten
  self
end

#next(page) ⇒ Object



178
179
180
181
# File 'lib/docter/collection.rb', line 178

def next(page)
  pages = toc.map { |entry| page(entry.url) }.compact
  pages[pages.index(page) + 1]
end

#page(path) ⇒ Object

:call-seq:

page(path) => Page

Returns a page based on its path.

For example:

collection.include("doc/pages")
collection.page("index.html")

Will return a page generated from “doc/pages/index.textile”.



158
159
160
# File 'lib/docter/collection.rb', line 158

def page(path)
  pages.find { |page| page.path == path }
end

#pagesObject

:call-seq:

pages() => Pages

Returns all the pages in this collection/



166
167
168
169
170
# File 'lib/docter/collection.rb', line 166

def pages()
  @pages = @sources.map { |path| File.directory?(path) ? FileList[File.join(path, "**/*")] : path }.flatten.
    inject(@pages || {}) { |pages, file| pages[file] ||= Page.new(file, :collection=>self) ; pages }
  @pages.values
end

#prev(page) ⇒ Object



172
173
174
175
176
# File 'lib/docter/collection.rb', line 172

def prev(page)
  pages = toc.map { |entry| page(entry.url) }.compact
  index = pages.index(page)
  pages[index - 1] if index > 0
end

#render(template, *args) ⇒ Object

:call-seq:

render(template, page, options?) => html
render(template, options?) => html

Render page or collection using the template.

The first form attempts to reload the page if modified and passes the page to the template context, returning a single HTML document generated from that page.

The second form attempts to reload all modified pages from the ToC, and passes all these pages to the template context, returning a single HTML document generates from pages as ordered by the ToC.



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/docter/collection.rb', line 214

def render(template, *args)
  options = Hash === args.last ? args.pop : {}
  template = Template.new(template) unless Template === template
  template.reload if template.modified?
  if page = args.shift
    page.reload if page.modified?
    template.render options.merge(:collection=>self, :page=>page, :one_page=>false)
  else
    pages = toc.map { |entry| page(entry.url) }.compact
    pages.each { |page| page.reload if page.modified? }
    html = template.render(options.merge(:collection=>self, :pages=>pages, :one_page=>true))

    url_map = pages.inject({}) { |map, page| map[page.path] = "##{page.id}" ; map }
    html.gsub(regexp_element("a")) do |link|
      link.gsub(regexp_attribute("href")) do |href|
        url = $3
        url = url_map[url] || url.gsub(/^(.*?)#(.*?)$/) { |path| url_map[$1] ? "##{$2}" : path }
        %{href="#{url}"}
      end
    end
  end
end

#serve(template, *args) ⇒ Object



100
101
102
103
104
105
# File 'lib/docter/server.rb', line 100

def serve(template, *args)
  options = Hash === args.last ? args.pop.clone : {}
  options[:port] = args.shift if Integer === args.first
  args.each { |arg| options[arg.to_sym] = true }
  Server.new(self, template, options).start
end

#titleObject

The collection title (HTML encoded).



83
84
85
86
87
88
# File 'lib/docter/collection.rb', line 83

def title()
  @title || if @toc_resource
    @toc_resource.reload if @toc_resource.modified?
    @toc_resource.title
  end || ""
end

#tocObject

:call-seq:

toc() => ToC

Returns the collection’s ToC.



94
95
96
97
98
99
100
101
# File 'lib/docter/collection.rb', line 94

def toc()
  if @toc_resource
    @toc_resource.reload if @toc_resource.modified?
    @toc_resource.toc
  else
    @toc ||= pages.inject(ToC.new) { |toc, page| toc.add page.toc_entry ; toc }
  end
end

#toc=(toc) ⇒ Object

:call-seq:

toc = toc|filename|nil

Sets the ToC. You can provide an existing ToC, provide a ToC file name, or nil to create the default ToC from all pages in this collection.



118
119
120
121
122
123
124
125
126
127
# File 'lib/docter/collection.rb', line 118

def toc=(toc)
  case toc
  when String
    @toc_resource = ToCResource.new(self, toc)
  when ToCResource
    @toc_resource = toc
  when ToC, nil
    @toc = toc
  end
end

#using(toc) ⇒ Object

:call-seq:

using(toc) => self

Specifies the ToC to use. You can load an exiting ToC object, or specify a filename containing the ToC.



108
109
110
111
# File 'lib/docter/collection.rb', line 108

def using(toc)
  self.toc = toc
  self
end