hx 0.16.0 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -4,7 +4,22 @@ A miniature web site generator; a spiritual successor to Hobix.
4
4
 
5
5
  == History
6
6
 
7
- == The Concept
7
+ == Concepts
8
+
9
+ === Filters
10
+
11
+ === Require and Autoload
12
+
13
+ Hx supports a very limited sort of autoload; when a filter class name
14
+ is provided in a configuration file, and that class doesn't already
15
+ exist, Hx will try to require a corresponding library. The name of that
16
+ library will be derived from the class name; for example, if
17
+ Hx::Backend::RawFiles is missing, Hx will try to require
18
+ <code>hx/backend/rawfiles</code>.
19
+
20
+ Beyond this, you can also manually require additional libraries
21
+ at load time by listing them in the <code>require</code> section in
22
+ the configuration file.
8
23
 
9
24
  == Tutorial
10
25
 
@@ -17,6 +32,92 @@ A miniature web site generator; a spiritual successor to Hobix.
17
32
  options:
18
33
  entry_dir: static
19
34
 
35
+ === A Site With Entries and Indexes
36
+
37
+ options:
38
+ output_dir: site
39
+ sources:
40
+ entries:
41
+ - filter: Hx::Backend::Hobix
42
+ options:
43
+ entry_dir: entries
44
+ - sort_by: updated
45
+ indices:
46
+ input: entries
47
+ filter: Hx::Listing::RecursiveIndex
48
+ output:
49
+ - input: indices
50
+ filter: Hx::Output::LiquidTemplate
51
+ options:
52
+ extension: html
53
+ template: section
54
+ - input: entries
55
+ filter: Hx::Output::LiquidTemplate
56
+ options:
57
+ extension: html
58
+ template: entry
59
+ - filter: Hx::Backend::RawFiles
60
+ options:
61
+ entry_dir: static
62
+
63
+ === A Site with Date-Based Archives and an Atom Feed
64
+
65
+ options:
66
+ output_dir: site
67
+ template_dir: templates
68
+ sources:
69
+ entries:
70
+ - filter: Hx::Backend::Hobix
71
+ options:
72
+ entry_dir: entries
73
+ - sort_by: updated
74
+ indices:
75
+ input: entries
76
+ filter: Hx::Listing::RecursiveIndex
77
+ archives:
78
+ input: entries
79
+ filter: Hx::Listing::DateArchive
80
+ sort_by: id
81
+ output:
82
+ - input: indices
83
+ only: index
84
+ filter: Hx::Output::LiquidTemplate
85
+ options:
86
+ extension: html
87
+ template: front
88
+ - input: indices
89
+ except: index
90
+ filter: Hx::Output::LiquidTemplate
91
+ options:
92
+ extension: html
93
+ template: section
94
+ - input: entries
95
+ filter: Hx::Output::LiquidTemplate
96
+ options:
97
+ extension: html
98
+ template: entry
99
+ - input: archives
100
+ only: */index
101
+ filter: Hx::Output::LiquidTemplate
102
+ options:
103
+ extension: html
104
+ template: year
105
+ - input: archives
106
+ only: */*/index
107
+ filter: Hx::Output::LiquidTemplate
108
+ options:
109
+ extension: html
110
+ template: month
111
+ - input: indices
112
+ only: index
113
+ filter: Hx::Output::LiquidTemplate
114
+ options:
115
+ extension: atom
116
+ template: feed
117
+ - filter: Hx::Backend::RawFiles
118
+ options:
119
+ entry_dir: static
120
+
20
121
  == Copyright
21
122
 
22
123
  Copyright (c) 2009-2011 MenTaLguY. See LICENSE for details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.16.0
1
+ 0.17.0
data/lib/hx.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # hx - A very small website generator.
2
2
  #
3
- # Copyright (c) 2009-2010 MenTaLguY <mental@rydia.net>
3
+ # Copyright (c) 2009-2011 MenTaLguY <mental@rydia.net>
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining
6
6
  # a copy of this software and associated documentation files (the
@@ -332,6 +332,42 @@ class Sort
332
332
  end
333
333
  end
334
334
 
335
+ class IncludeFragments
336
+ include Hx::Filter
337
+
338
+ def initialize(input, options)
339
+ @input = input
340
+ @fragments = options[:fragments] || {}
341
+ @fragment_paths = Set.new(@fragments.values)
342
+ end
343
+
344
+ def edit_entry(path, prototype)
345
+ raise EditingNotSupported, path if @fragment_paths.include? path
346
+ @input.edit_entry(path, prototype) { |text| yield text }
347
+ self
348
+ end
349
+
350
+ def each_entry_path(selector)
351
+ @input.each_entry_path(selector) do |path|
352
+ yield path unless @fragment_paths.include? path
353
+ end
354
+ self
355
+ end
356
+
357
+ def get_entry(path)
358
+ raise NoSuchEntryError, path if @fragment_paths.include? path
359
+ entry = @input.get_entry(path)
360
+ entry = entry.dup
361
+ for field, fragment_path in @fragments
362
+ begin
363
+ entry[field] = @input.get_entry(path)
364
+ rescue NoSuchEntryError
365
+ end
366
+ end
367
+ entry
368
+ end
369
+ end
370
+
335
371
  Chain = Object.new
336
372
  def Chain.new(input, options)
337
373
  filters = options[:chain] || []
@@ -437,6 +473,11 @@ def self.build_source(options, default_input, sources, raw_source)
437
473
  source = Overlay.new(*input_sources)
438
474
  end
439
475
 
476
+ if raw_source.has_key? 'fragments'
477
+ source = IncludeFragments.new(source,
478
+ :fragments => raw_source['fragments'])
479
+ end
480
+
440
481
  if raw_source.has_key? 'filter'
441
482
  if raw_source.has_key? 'options'
442
483
  filter_options = options.dup
data/lib/hx/listing.rb ADDED
@@ -0,0 +1,41 @@
1
+ # hx/listing - Common listing utilities
2
+ #
3
+ # Copyright (c) 2009-2010 MenTaLguY <mental@rydia.net>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ require 'hx/listing/limit'
25
+ require 'hx/listing/paginate'
26
+
27
+ module Hx
28
+ module Listing
29
+
30
+ def self.apply_options(listing, options)
31
+ if options.has_key? :limit
32
+ listing = Limit.new(listing, :limit => options[:limit])
33
+ end
34
+ if options.has_key? :page_size
35
+ listing = Paginate.new(listing, :page_size => options[:page_size])
36
+ end
37
+ listing
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,71 @@
1
+ # hx/listing/datearchive - Date-based archive generator
2
+ #
3
+ # Copyright (c) 2011 MenTaLguY <mental@rydia.net>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ require 'hx'
25
+ require 'hx/listing'
26
+
27
+ module Hx
28
+ module Listing
29
+
30
+ class DateArchive
31
+ include Hx::Filter
32
+
33
+ def self.new(input, options)
34
+ listing = super(input, options)
35
+ Listing.apply_options(listing, options)
36
+ end
37
+
38
+ def initialize(input, options)
39
+ @input = input
40
+ @date_fields = Array(options[:date_fields] || %w(created updated))
41
+ @index_name = options[:index_name] || "index"
42
+ end
43
+
44
+ def each_entry(selector)
45
+ indices = {}
46
+ @input.each_entry_path(Path::ALL) do |path, entry|
47
+ date = @date_fields.map { |field| entry[field] }.compact.first
48
+ next unless date
49
+ month_path = "%04d/%02d/#{@index_name}" % [date.year, date.month]
50
+ year_path = "%04d/#{@index_name}" % [date.year]
51
+ for index_path in [month_path, year_path]
52
+ next unless selector.accept_path? index_path
53
+ index_entry = indices[index_path]
54
+ unless index_entry
55
+ index_entry = {"items" => [], "year" => date.year, "updated" => date}
56
+ index_entry["month"] = date.month if index_path == month_path
57
+ indices[index_path] = index_entry
58
+ end
59
+ index_entry["updated"] = date if date > index_entry["updated"]
60
+ index_entry["items"] << {"path" => path, "entry" => entry}
61
+ end
62
+ end
63
+ indices.each do |index_path, index_entry|
64
+ yield index_path, index_entry
65
+ end
66
+ self
67
+ end
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,62 @@
1
+ # hx/listing/flatindex - Flat index generator
2
+ #
3
+ # Copyright (c) 2009-2011 MenTaLguY <mental@rydia.net>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ require 'hx'
25
+ require 'hx/listing'
26
+ require 'set'
27
+
28
+ module Hx
29
+ module Listing
30
+
31
+ class FlatIndex
32
+ include Hx::Filter
33
+
34
+ def self.new(input, options)
35
+ listing = super(input, options)
36
+ Listing.apply_options(listing, options)
37
+ end
38
+
39
+ def initialize(input, options)
40
+ @input = input
41
+ @index_name = options[:index_name] || "index"
42
+ end
43
+
44
+ def each_entry_path(selector)
45
+ yield @index_name if selector.accept_path? @index_name
46
+ self
47
+ end
48
+
49
+ def get_entry(path)
50
+ raise NoSuchEntryError, path unless path == @index_name
51
+ index = {'items' => []}
52
+ @input.each_entry(Path::ALL) do |path, entry|
53
+ index['items'] << {'path' => path, 'entry' => entry}
54
+ updated = [entry['updated'], index['updated']].compact.max
55
+ index['updated'] = updated if updated
56
+ end
57
+ index
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -1,6 +1,6 @@
1
1
  # hx/listing/recursiveindex - Recursive index generator
2
2
  #
3
- # Copyright (c) 2009-2010 MenTaLguY <mental@rydia.net>
3
+ # Copyright (c) 2009-2011 MenTaLguY <mental@rydia.net>
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining
6
6
  # a copy of this software and associated documentation files (the
@@ -22,8 +22,7 @@
22
22
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
 
24
24
  require 'hx'
25
- require 'hx/listing/limit'
26
- require 'hx/listing/paginate'
25
+ require 'hx/listing'
27
26
  require 'set'
28
27
 
29
28
  module Hx
@@ -34,32 +33,22 @@ class RecursiveIndex
34
33
 
35
34
  def self.new(input, options)
36
35
  listing = super(input, options)
37
- if options.has_key? :limit
38
- listing = Limit.new(listing, :limit => options[:limit])
39
- end
40
- if options.has_key? :page_size
41
- listing = Paginate.new(listing, :page_size => options[:page_size])
42
- end
43
- listing
36
+ Listing.apply_options(listing, options)
44
37
  end
45
38
 
46
39
  def initialize(input, options)
47
40
  @input = input
41
+ @index_name = options[:index_name] || "index"
42
+ @index_re = %r!^((?:.*/)?)#{Regexp.quote(@index_name)}$!
48
43
  end
49
44
 
50
- def merge_updated(index, entry)
51
- updated = [entry, index].map { |e| e['updated'] }.compact.max
52
- index['updated'] = updated if updated
53
- end
54
- private :merge_updated
55
-
56
45
  def each_entry_path(selector)
57
46
  emitted = Set.new
58
- @input.each_entry_path(Path::ALL) do |path, entry|
47
+ @input.each_entry_path(Path::ALL) do |path|
59
48
  components = path.split("/")
60
49
  until components.empty?
61
50
  components.pop
62
- index_path = (components + ["index"]).join("/")
51
+ index_path = (components + [@index_name]).join("/")
63
52
  break if emitted.include? index_path
64
53
  yield index_path if selector.accept_path? index_path
65
54
  emitted.add index_path
@@ -69,9 +58,8 @@ class RecursiveIndex
69
58
  end
70
59
 
71
60
  def get_entry(path)
72
- raise NoSuchEntryError, path unless path =~ %r!^((?:.*/)?)index$!
73
- prefix = $1
74
- selector = Path.parse_pattern("#{prefix}**")
61
+ raise NoSuchEntryError, path unless path =~ @index_re
62
+ selector = Path.parse_pattern("#{$1}**")
75
63
  index = {'items' => []}
76
64
  @input.each_entry(selector) do |child_path, entry|
77
65
  if child_path == path
@@ -79,7 +67,8 @@ class RecursiveIndex
79
67
  else
80
68
  index['items'] << {'path' => child_path, 'entry' => entry}
81
69
  end
82
- merge_updated(index, entry)
70
+ updated = [entry['updated'], index['updated']].compact.max
71
+ index['updated'] = updated if updated
83
72
  end
84
73
  raise NoSuchEntryError, path if index['items'].empty?
85
74
  index
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hx
3
3
  version: !ruby/object:Gem::Version
4
- hash: 95
4
+ hash: 91
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 16
8
+ - 17
9
9
  - 0
10
- version: 0.16.0
10
+ version: 0.17.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - MenTaLguY
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-06 00:00:00 -08:00
18
+ date: 2011-03-07 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -59,6 +59,9 @@ files:
59
59
  - lib/hx/backend/hobix.rb
60
60
  - lib/hx/backend/rawfiles.rb
61
61
  - lib/hx/cli.rb
62
+ - lib/hx/listing.rb
63
+ - lib/hx/listing/datearchive.rb
64
+ - lib/hx/listing/flatindex.rb
62
65
  - lib/hx/listing/limit.rb
63
66
  - lib/hx/listing/paginate.rb
64
67
  - lib/hx/listing/recursiveindex.rb