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.



93
94
95
96
# File 'lib/docter/collection.rb', line 93

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.



298
299
300
301
# File 'lib/docter/collection.rb', line 298

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.



160
161
162
163
# File 'lib/docter/collection.rb', line 160

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'


207
208
209
210
211
212
213
214
215
216
217
# File 'lib/docter/collection.rb', line 207

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.



269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/docter/collection.rb', line 269

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.



149
150
151
152
# File 'lib/docter/collection.rb', line 149

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

#next(page) ⇒ Object



194
195
196
197
198
# File 'lib/docter/collection.rb', line 194

def next(page)
  pages = toc.map { |entry| page(entry.url) }.compact
  index = pages.index(page)
  pages[index + 1] if index
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’.



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

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

#pagesObject

:call-seq:

pages => Pages

Returns all the pages in this collection/



182
183
184
185
186
# File 'lib/docter/collection.rb', line 182

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



188
189
190
191
192
# File 'lib/docter/collection.rb', line 188

def prev(page)
  pages = toc.map { |entry| page(entry.url) }.compact
  index = pages.index(page)
  pages[index - 1] if index && 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.



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/docter/collection.rb', line 231

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



120
121
122
123
124
125
# File 'lib/docter/server.rb', line 120

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



99
100
101
102
103
104
# File 'lib/docter/collection.rb', line 99

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.



110
111
112
113
114
115
116
117
# File 'lib/docter/collection.rb', line 110

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.



134
135
136
137
138
139
140
141
142
143
# File 'lib/docter/collection.rb', line 134

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.



124
125
126
127
# File 'lib/docter/collection.rb', line 124

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