utopia 0.12.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -2
  3. data/Gemfile +6 -0
  4. data/README.md +48 -14
  5. data/Rakefile +5 -0
  6. data/bin/utopia +132 -15
  7. data/lib/utopia.rb +13 -10
  8. data/lib/utopia/content.rb +140 -0
  9. data/lib/utopia/content/link.rb +124 -0
  10. data/lib/utopia/content/links.rb +228 -0
  11. data/lib/utopia/content/node.rb +387 -0
  12. data/lib/utopia/content/processor.rb +128 -0
  13. data/lib/utopia/content/tag.rb +102 -0
  14. data/lib/utopia/controller.rb +137 -0
  15. data/lib/utopia/controller/action.rb +112 -0
  16. data/lib/utopia/controller/base.rb +174 -0
  17. data/lib/utopia/{middleware/controller → controller}/variables.rb +36 -38
  18. data/lib/utopia/exception_handler.rb +79 -0
  19. data/lib/utopia/extensions/array.rb +2 -2
  20. data/lib/utopia/localization.rb +143 -0
  21. data/lib/utopia/mail_exceptions.rb +136 -0
  22. data/lib/utopia/middleware.rb +7 -22
  23. data/lib/utopia/path.rb +150 -60
  24. data/lib/utopia/redirector.rb +152 -0
  25. data/lib/utopia/{extensions/hash.rb → session.rb} +4 -6
  26. data/lib/utopia/session/encrypted_cookie.rb +46 -48
  27. data/lib/utopia/{middleware/directory_index.rb → session/lazy_hash.rb} +44 -27
  28. data/lib/utopia/static.rb +255 -0
  29. data/lib/utopia/tags/deferred.rb +12 -8
  30. data/lib/utopia/tags/environment.rb +18 -6
  31. data/lib/utopia/tags/node.rb +12 -8
  32. data/lib/utopia/tags/override.rb +12 -12
  33. data/lib/utopia/version.rb +1 -1
  34. data/setup/.bowerrc +3 -0
  35. data/{lib/utopia/setup → setup}/Gemfile +1 -1
  36. data/setup/Rakefile +4 -0
  37. data/{lib/utopia/setup → setup}/cache/head/readme.txt +0 -0
  38. data/{lib/utopia/setup → setup}/cache/meta/readme.txt +0 -0
  39. data/setup/config.ru +64 -0
  40. data/{lib/utopia/setup → setup}/lib/readme.txt +0 -0
  41. data/{lib/utopia/setup → setup}/pages/_heading.xnode +0 -0
  42. data/{lib/utopia/setup → setup}/pages/_page.xnode +1 -1
  43. data/{lib/utopia/setup → setup}/pages/_static/icon.png +0 -0
  44. data/setup/pages/_static/site.css +70 -0
  45. data/{lib/utopia/setup → setup}/pages/errors/exception.xnode +0 -0
  46. data/{lib/utopia/setup → setup}/pages/errors/file-not-found.xnode +0 -0
  47. data/{lib/utopia/setup → setup}/pages/links.yaml +0 -0
  48. data/setup/pages/welcome/index.xnode +17 -0
  49. data/{lib/utopia/setup → setup}/public/readme.txt +0 -0
  50. data/spec/utopia/content/link_spec.rb +108 -0
  51. data/spec/utopia/content/links/foo/index.xnode +0 -0
  52. data/spec/utopia/content/links/foo/links.yaml +2 -0
  53. data/spec/utopia/content/links/foo/test.de.xnode +0 -0
  54. data/spec/utopia/content/links/foo/test.en.xnode +0 -0
  55. data/spec/utopia/content/links/links.yaml +9 -0
  56. data/spec/utopia/content/links/welcome.xnode +0 -0
  57. data/spec/utopia/content/localized/five/index.en.xnode +0 -0
  58. data/spec/utopia/content/localized/four/index.en.xnode +0 -0
  59. data/spec/utopia/content/localized/four/index.zh.xnode +0 -0
  60. data/spec/utopia/content/localized/four/links.yaml +4 -0
  61. data/spec/utopia/content/localized/links.yaml +16 -0
  62. data/spec/utopia/content/localized/one.xnode +0 -0
  63. data/spec/utopia/content/localized/three/index.xnode +0 -0
  64. data/spec/utopia/content/localized/two.en.xnode +0 -0
  65. data/spec/utopia/content/localized/two.zh.xnode +0 -0
  66. data/spec/utopia/content/node/ordered/first.xnode +0 -0
  67. data/spec/utopia/content/node/ordered/index.xnode +0 -0
  68. data/spec/utopia/content/node/ordered/links.yaml +4 -0
  69. data/spec/utopia/content/node/ordered/second.xnode +0 -0
  70. data/spec/utopia/content/node/related/foo.en.xnode +0 -0
  71. data/spec/utopia/content/node/related/foo.ja.xnode +0 -0
  72. data/spec/utopia/content/node/related/links.yaml +4 -0
  73. data/spec/utopia/content/node_spec.rb +63 -0
  74. data/spec/utopia/{middleware/content_spec.rb → content/processor_spec.rb} +34 -23
  75. data/spec/utopia/content_spec.rb +87 -0
  76. data/spec/utopia/content_spec.ru +10 -0
  77. data/spec/utopia/{middleware/controller_spec.rb → controller_spec.rb} +61 -16
  78. data/spec/utopia/controller_spec.ru +4 -0
  79. data/spec/utopia/extensions_spec.rb +6 -17
  80. data/spec/utopia/localization_spec.rb +60 -0
  81. data/spec/utopia/localization_spec.ru +11 -0
  82. data/{lib/utopia/tags.rb → spec/utopia/middleware_spec.rb} +8 -14
  83. data/spec/utopia/{middleware/content_root → pages}/_heading.xnode +0 -0
  84. data/spec/utopia/pages/content/_show-value.xnode +1 -0
  85. data/spec/utopia/pages/content/test-partial.xnode +1 -0
  86. data/spec/utopia/pages/controller/controller.rb +28 -0
  87. data/spec/utopia/pages/controller/index.xnode +1 -0
  88. data/spec/utopia/pages/controller/nested/controller.rb +4 -0
  89. data/spec/utopia/{middleware/content_root → pages}/index.xnode +0 -0
  90. data/spec/utopia/pages/localized.de.txt +1 -0
  91. data/spec/utopia/pages/localized.en.txt +1 -0
  92. data/spec/utopia/pages/localized.jp.txt +1 -0
  93. data/spec/utopia/pages/node/index.xnode +1 -0
  94. data/spec/utopia/pages/test.txt +1 -0
  95. data/spec/utopia/path_spec.rb +109 -0
  96. data/spec/utopia/rack_spec.rb +2 -0
  97. data/spec/utopia/session_spec.rb +82 -0
  98. data/spec/utopia/session_spec.ru +20 -0
  99. data/spec/utopia/spec_helper.rb +16 -0
  100. data/{lib/utopia/extensions/string.rb → spec/utopia/static_spec.rb} +24 -15
  101. data/spec/utopia/static_spec.ru +4 -0
  102. data/utopia.gemspec +3 -3
  103. metadata +138 -54
  104. data/lib/utopia/extensions/regexp.rb +0 -33
  105. data/lib/utopia/link.rb +0 -288
  106. data/lib/utopia/middleware/all.rb +0 -33
  107. data/lib/utopia/middleware/content.rb +0 -157
  108. data/lib/utopia/middleware/content/node.rb +0 -386
  109. data/lib/utopia/middleware/content/processor.rb +0 -123
  110. data/lib/utopia/middleware/controller.rb +0 -130
  111. data/lib/utopia/middleware/controller/action.rb +0 -121
  112. data/lib/utopia/middleware/controller/base.rb +0 -184
  113. data/lib/utopia/middleware/exception_handler.rb +0 -80
  114. data/lib/utopia/middleware/localization.rb +0 -147
  115. data/lib/utopia/middleware/localization/name.rb +0 -69
  116. data/lib/utopia/middleware/mail_exceptions.rb +0 -138
  117. data/lib/utopia/middleware/redirector.rb +0 -146
  118. data/lib/utopia/middleware/requester.rb +0 -126
  119. data/lib/utopia/middleware/static.rb +0 -295
  120. data/lib/utopia/setup.rb +0 -60
  121. data/lib/utopia/setup/config.ru +0 -47
  122. data/lib/utopia/setup/pages/_static/background.png +0 -0
  123. data/lib/utopia/setup/pages/_static/site.css +0 -48
  124. data/lib/utopia/setup/pages/welcome/index.xnode +0 -7
  125. data/lib/utopia/tag.rb +0 -105
  126. data/lib/utopia/tags/all.rb +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 296a41faf645d12aa55672af9445a4f94f939da1
4
- data.tar.gz: 53019aaae569b4191d3361d3d2a1094a9e52bcfe
3
+ metadata.gz: 2de92361694a0d93055b13141f7373bdca9ba4c8
4
+ data.tar.gz: abf743ebf57a07d8850fb22719ee62085e4c1166
5
5
  SHA512:
6
- metadata.gz: 34aaf114f9917265dbe27b65379bb77cb66fda5310b27384d2edcae8dc21fc01d7d814d6ea79f98fca46be81cbf2c1b9dc0c1da9f40b6af20dffa7cfb5dd2557
7
- data.tar.gz: 09e47aa4fd61d9d015c7aa836c734dda5f20570efd02bacdd745756b2e02c6fc4e32e413bd47dfd1d140d740adf340dd4f0682b08ad63b579352af2798b0fae7
6
+ metadata.gz: bdeeca349e075376b9a5a65c97195e92e4e67c3b6c21077ab93fbf86395dd4745b41c63cc0362371a9af1b8162ece2a7c65011c081b617ef6e1cd05c0920280d
7
+ data.tar.gz: 0a135fa1fd8069f1a8b90ea8f040bd1dad4f71891e37735099184a3579d2191f21a8e8bf0b87955ffe6d4835561ce28f9b21d97423ba7b423b9a8b0d4afaeec7
@@ -1,5 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
- - "1.9.3"
4
3
  - "2.0"
5
- - "2.1"
4
+ - "2.1"
5
+ - "2.2"
6
+ - "rbx-2"
7
+ matrix:
8
+ allow_failures:
9
+ - rvm: "rbx-2"
data/Gemfile CHANGED
@@ -2,3 +2,9 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in utopia.gemspec
4
4
  gemspec
5
+
6
+ group :test do
7
+ gem 'rack-test'
8
+ gem 'simplecov'
9
+ gem 'coveralls', require: false
10
+ end
data/README.md CHANGED
@@ -2,38 +2,72 @@
2
2
 
3
3
  Utopia is a website generation framework which provides a robust set of tools
4
4
  to build highly complex dynamic websites. It uses the filesystem heavily for
5
- content and provides frameworks for interacting with files and directories as
5
+ content and provides functions for interacting with files and directories as
6
6
  structure representing the website.
7
7
 
8
8
  Utopia builds on top of Rack with the following middleware:
9
9
 
10
- * `Utopia::Middleware::Static`: Serve static files with recursive lookup
11
- * `Utopia::Middleware::Requester`: Allow nesting of virtual requests
12
- * `Utopia::Middleware::Redirector`: Redirect URL patterns and status codes
13
- * `Utopia::Middleware::Logger`: Advanced rotating access log
14
- * `Utopia::Middleware::Localization`: Non-intrusive localization of resources
15
- * `Utopia::Middleware::DirectoryIndex`: Redirect directory requests to specific files
16
- * `Utopia::Middleware::Controller`: Dynamic behaviour with recursive execution
17
- * `Utopia::Middleware::Content`: XML-style template engine with powerful tag behaviours
18
- * `Utopia::Session::EncryptedCookie`: Session storage using an encrypted cookie
10
+ - `Utopia::Static`: Serve static files with recursive lookup.
11
+ - `Utopia::Redirector`: Redirect URL patterns and status codes.
12
+ - `Utopia::Localization`: Non-intrusive localization of resources.
13
+ - `Utopia::Controller`: Dynamic behaviour with recursive execution.
14
+ - `Utopia::Content`: XML-style template engine with powerful tag behaviours.
15
+ - `Utopia::Session::EncryptedCookie`: Session storage using an encrypted cookie.
19
16
 
20
17
  For more details please see the main [project page][1].
21
18
 
22
19
  [1]: http://www.oriontransfer.co.nz/gems/utopia
23
20
 
24
21
  [![Build Status](https://secure.travis-ci.org/ioquatix/utopia.png)](http://travis-ci.org/ioquatix/utopia)
22
+ [![Coverage Status](https://coveralls.io/repos/ioquatix/utopia/badge.svg)](https://coveralls.io/r/ioquatix/utopia)
23
+
24
+ ## Middleware
25
+
26
+ ### Static
27
+
28
+ This middleware serves static files using the `mime-types` library. By default, it works with `Rack::Sendfile` and `Rack::Cache` and supports `ETag` based caching.
29
+
30
+ ### Redirector
31
+
32
+ A flexible high level URI rewriting system which includes support for string mappings, regular expressions and status codes (e.g. 404 errors).
33
+
34
+ ### Localization
35
+
36
+ The localization middleware uses the `Accept-Language` header to guess the preferred locale out of the given options. If a request path maps to a resource, that resource is returned. Otherwise, a localized request is made.
37
+
38
+ ### Controller
39
+
40
+ A simple recursive controller layer which works in isolation from the view rendering middleware. A controller consists of a set of actions which match against incoming paths and execute code accordingly.
41
+
42
+ ### Content
43
+
44
+ A tag based content generation system which integrates nicely with HTML5. Supports structures which separate generic page templates from dynamically generated content in an easy and consistent way.
45
+
46
+ ### Session
47
+
48
+ The encrypted cookie session management uses symmetric private key encryption to store data on the client and avoid tampering.
25
49
 
26
50
  ## Installation
27
51
 
28
52
  Install utopia:
29
53
 
30
- $ gem install utopia
54
+ $ gem install utopia
31
55
 
32
56
  Create a new site:
33
57
 
34
- $ utopia setup www.example.com
58
+ $ utopia create www.example.com
35
59
  $ cd www.example.com
36
- $ thin start -p 9000
60
+ $ rake server
61
+
62
+ ### Bower Integration
63
+
64
+ If you create a site using the utopia generator, it includes a `.bowerrc` configuration which installs components into `public/_static/components`. To install jquery, for example:
65
+
66
+ bower install jquery
67
+
68
+ Then add the appropriate `<script>` tags to `pages/_page.xnode`:
69
+
70
+ <script src="/_static/components/jquery/dist/jquery.min.js" type="text/javascript"></script>
37
71
 
38
72
  ## Usage
39
73
 
@@ -51,7 +85,7 @@ The default site includes documentation and examples.
51
85
 
52
86
  Released under the MIT license.
53
87
 
54
- Copyright, 2012, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
88
+ Copyright, 2015, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
55
89
 
56
90
  Permission is hereby granted, free of charge, to any person obtaining a copy
57
91
  of this software and associated documentation files (the "Software"), to deal
data/Rakefile CHANGED
@@ -4,3 +4,8 @@ require "rspec/core/rake_task"
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
6
  task :default => :spec
7
+
8
+ task :coverage do
9
+ ENV['COVERAGE'] = 'true'
10
+ Rake::Task['spec'].execute
11
+ end
data/bin/utopia CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
3
+ # Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -21,27 +21,73 @@
21
21
  # THE SOFTWARE.
22
22
 
23
23
  require 'rubygems'
24
- require 'utopia/setup'
24
+ require 'rake'
25
+
26
+ require_relative '../lib/utopia/version'
27
+
28
+ require 'fileutils'
29
+ require 'find'
25
30
  require 'rake'
26
31
 
27
32
  $app = Rake.application = Rake::Application.new
28
33
  $app.init('Utopia')
29
34
 
30
- task :setup do
31
- path = File.expand_path(ARGV.last, Dir.getwd)
32
- FileUtils.mkdir_p path
35
+ module Setup
36
+ DIRECTORIES = ["cache", "cache/meta", "cache/body", "lib", "pages", "public"]
37
+ SYMLINKS = {"public/_static" => "../pages/_static"}
38
+
39
+ CONFIGURATION_FILES = ['config.ru', 'Gemfile', 'Rakefile']
40
+
41
+ # Removed during upgrade process
42
+ OLD_DIRECTORIES = ["access_log"]
43
+ end
33
44
 
34
- Dir.chdir(path) do
35
- Utopia::Setup.copy(path)
45
+ task :create do
46
+ $stderr.puts("Usage: #{File.basename $0} create $path") & exit if ARGV.size != 2
36
47
 
37
- if `which thin`.strip == ""
38
- $stderr.puts "Next, please install thin: `sudo gem install thin'."
39
- end
48
+ destination_root = File.expand_path(ARGV.last, Dir.getwd)
49
+ setup_root = File.expand_path("../../setup", __FILE__)
50
+
51
+ $stderr.puts "Copying files from #{setup_root} to #{destination_root}..."
52
+
53
+ Setup::DIRECTORIES.each do |directory|
54
+ FileUtils.mkdir_p(File.join(destination_root, directory))
55
+ end
40
56
 
41
- if `which git`.strip == ""
42
- $stderr.puts "Now is a good time to learn about git : http://git-scm.com/"
57
+ Find.find(setup_root) do |source_path|
58
+ # What is this doing?
59
+ destination_path = File.join(destination_root, source_path[setup_root.size..-1])
60
+
61
+ if File.directory?(source_path)
62
+ FileUtils.mkdir_p(destination_path)
63
+ else
64
+ if File.exist? destination_path
65
+ $stderr.puts "\tFile already exists: #{destination_path}!"
66
+ else
67
+ $stderr.puts "\tCopying #{source_path} to #{destination_path}..."
68
+ FileUtils.copy_entry(source_path, destination_path)
69
+ end
43
70
  end
71
+ end
44
72
 
73
+ Setup::SYMLINKS.each do |path, target|
74
+ FileUtils.ln_s(target, File.join(destination_root, path))
75
+ end
76
+
77
+ Setup::CONFIGURATION_FILES.each do |configuration_file|
78
+ destination_path = File.join(destination_root, configuration_file)
79
+
80
+ $stderr.puts "Updating #{destination_path}..."
81
+
82
+ buffer = File.read(destination_path).gsub('$UTOPIA_VERSION', Utopia::VERSION)
83
+ File.open(destination_path, "w") { |file| file.write(buffer) }
84
+ end
85
+
86
+ if `which git`.strip == ""
87
+ $stderr.puts "Now is a good time to learn about git : http://git-scm.com/"
88
+ end
89
+
90
+ Dir.chdir(destination_root) do
45
91
  unless File.exist? '.git'
46
92
  sh("git", "init")
47
93
  sh("git", "add", ".")
@@ -49,12 +95,83 @@ task :setup do
49
95
  end
50
96
  end
51
97
 
52
- $stderr.puts "*** Thanks for trying out Utopia! ***"
98
+ $stderr.puts "*** Thanks for using Utopia! ***"
99
+ $stderr.puts "To start the server:\n\tcd #{ARGV.last}\n\trake server"
100
+ end
101
+
102
+ task :upgrade do
103
+ $stderr.puts("Usage: #{File.basename $0} upgrade $path") & exit if ARGV.size != 2
104
+
105
+ destination_root = File.expand_path(ARGV.last || '.', Dir.getwd)
106
+ setup_root = File.expand_path("../../setup", __FILE__)
107
+ directories = ["cache", "cache/meta", "cache/body", "lib", "pages", "public"]
108
+ symlinks = {"public/_static" => "../pages/_static"}
109
+ branch_name = "utopia-upgrade-#{Utopia::VERSION}"
110
+
111
+ $stderr.puts "Upgrading #{destination_root}..."
112
+
113
+ Dir.chdir(destination_root) do
114
+ sh('git', 'checkout', '-b', branch_name)
115
+ end
116
+
117
+ Setup::DIRECTORIES.each do |directory|
118
+ FileUtils.mkdir_p(File.join(destination_root, directory))
119
+ end
120
+
121
+ Setup::OLD_DIRECTORIES.each do |directory|
122
+ path = File.join(destination_root, directory)
123
+ $stderr.puts "\tRemoving #{path}..."
124
+ FileUtils.rm_rf(path)
125
+ end
126
+
127
+ Setup::SYMLINKS.each do |path, target|
128
+ FileUtils.ln_s(target, File.join(destination_root, path), force: true)
129
+ end
130
+
131
+ Setup::CONFIGURATION_FILES.each do |configuration_file|
132
+ source_path = File.join(setup_root, configuration_file)
133
+ destination_path = File.join(destination_root, configuration_file)
134
+
135
+ $stderr.puts "Updating #{destination_path}..."
136
+
137
+ FileUtils.copy_entry(source_path, destination_path)
138
+ buffer = File.read(destination_path).gsub('$UTOPIA_VERSION', Utopia::VERSION)
139
+ File.open(destination_path, "w") { |file| file.write(buffer) }
140
+ end
141
+
142
+ begin
143
+ Dir.chdir(destination_root) do
144
+ # Stage any files that have been changed or removed:
145
+ sh("git", "add", "-u")
146
+
147
+ # Stage any new files that we have explicitly added:
148
+ sh("git", "add", *Setup::CONFIGURATION_FILES, *Setup::SYMLINKS.keys)
149
+
150
+ # Commit all changes:
151
+ sh("git", "commit", "-m", "Upgrade to utopia #{Utopia::VERSION}.")
152
+
153
+ # Checkout master..
154
+ sh("git", "checkout", "master")
155
+
156
+ # and merge:
157
+ sh("git", "merge", "--no-commit", "--no-ff", branch_name)
158
+ end
159
+ rescue RuntimeError
160
+ $stderr.puts "** Detected error with upgrade, reverting changes. Some new files may still exist in tree. **"
161
+
162
+ sh("git", "checkout", "master")
163
+ sh("git", "branch", "-d", branch_name)
164
+ end
165
+
166
+ $stderr.puts "*** Thanks for using Utopia! ***"
53
167
  end
54
168
 
55
169
  task :help do
56
- $stderr.puts "To create a new site, use the setup task:"
57
- $stderr.puts "$ #{File.basename($0)} setup www.example.com"
170
+ $stderr.puts "To create a new site, use the create task:"
171
+ $stderr.puts "\t#{File.basename($0)} create path/to/www.example.com"
172
+
173
+ $stderr.puts "To upgrade an existing site, use the upgrade task:"
174
+ $stderr.puts "\t#{File.basename($0)} upgrade path/to/www.example.com"
58
175
  end
59
176
 
60
177
  task :default => :help
@@ -18,14 +18,17 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
- require 'utopia/version'
21
+ require_relative 'utopia/version'
22
22
 
23
- require 'utopia/middleware/content'
24
- require 'utopia/middleware/controller'
25
- require 'utopia/middleware/directory_index'
26
- require 'utopia/middleware/exception_handler'
27
- require 'utopia/middleware/localization'
28
- require 'utopia/middleware/mail_exceptions'
29
- require 'utopia/middleware/redirector'
30
- require 'utopia/middleware/requester'
31
- require 'utopia/middleware/static'
23
+ require_relative 'utopia/content'
24
+ require_relative 'utopia/controller'
25
+ require_relative 'utopia/exception_handler'
26
+ require_relative 'utopia/localization'
27
+ require_relative 'utopia/mail_exceptions'
28
+ require_relative 'utopia/redirector'
29
+ require_relative 'utopia/static'
30
+
31
+ require_relative 'utopia/tags/deferred'
32
+ require_relative 'utopia/tags/environment'
33
+ require_relative 'utopia/tags/node'
34
+ require_relative 'utopia/tags/override'
@@ -0,0 +1,140 @@
1
+ # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'middleware'
22
+ require_relative 'localization'
23
+
24
+ require_relative 'content/node'
25
+ require_relative 'content/processor'
26
+
27
+ require 'trenni/template'
28
+
29
+ module Utopia
30
+ class Content
31
+ def initialize(app, options = {})
32
+ @app = app
33
+
34
+ @root = File.expand_path(options[:root] || Utopia::default_root)
35
+
36
+ @templates = options[:cache_templates] ? {} : nil
37
+
38
+ @tags = options.fetch(:tags, {})
39
+ end
40
+
41
+ attr :root
42
+ attr :passthrough
43
+
44
+ def fetch_xml(path)
45
+ if @templates
46
+ @templates.fetch(path) do |key|
47
+ @templates[key] = Trenni::Template.load(path)
48
+ end
49
+ else
50
+ Trenni::Template.load(path)
51
+ end
52
+ end
53
+
54
+ # Look up a named tag such as <entry />
55
+ def lookup_tag(name, parent_path)
56
+ if @tags.key? name
57
+ return @tags[name]
58
+ end
59
+
60
+ if String === name && name.index("/")
61
+ name = Path.create(name)
62
+ end
63
+
64
+ if Path === name
65
+ name = parent_path + name
66
+ name_path = name.components.dup
67
+ name_path[-1] += XNODE_EXTENSION
68
+ else
69
+ name_path = name + XNODE_EXTENSION
70
+ end
71
+
72
+ parent_path.ascend do |dir|
73
+ tag_path = File.join(root, dir.components, name_path)
74
+
75
+ if File.exist? tag_path
76
+ return Node.new(self, dir + name, parent_path + name, tag_path)
77
+ end
78
+
79
+ if String === name_path
80
+ tag_path = File.join(root, dir.components, "_" + name_path)
81
+
82
+ if File.exist? tag_path
83
+ return Node.new(self, dir + name, parent_path + name, tag_path)
84
+ end
85
+ end
86
+ end
87
+
88
+ return nil
89
+ end
90
+
91
+ # The request_path is an absolute uri path, e.g. /foo/bar. If an xnode file exists on disk for this exact path, it is instantiated, otherwise nil.
92
+ def lookup_node(request_path)
93
+ name = request_path.last
94
+ name_xnode = name.to_s + XNODE_EXTENSION
95
+
96
+ node_path = File.join(@root, request_path.dirname.components, name_xnode)
97
+
98
+ if File.exist? node_path
99
+ return Node.new(self, request_path.dirname + name, request_path, node_path)
100
+ end
101
+
102
+ return nil
103
+ end
104
+
105
+ def call(env)
106
+ request = Rack::Request.new(env)
107
+ path = Path.create(request.path_info)
108
+
109
+ # Check if the request is to a non-specific index. This only works for requests with a given name:
110
+ basename = path.basename
111
+ directory_path = File.join(@root, path.dirname.components, basename.name)
112
+
113
+ # If the request for /foo/bar{extensions} is actually a directory, rewrite it to /foo/bar/index{extensions}:
114
+ if File.directory? directory_path
115
+ index_path = [basename.name, basename.rename("index")]
116
+
117
+ return [307, {"Location" => path.dirname.join(index_path).to_s}, []]
118
+ end
119
+
120
+ locale = env[Localization::CURRENT_LOCALE_KEY]
121
+ if link = Links.for(@root, path, locale)
122
+ if node = lookup_node(link.path)
123
+ response = Rack::Response.new
124
+
125
+ attributes = nil
126
+
127
+ if request.respond_to?(:controller)
128
+ attributes = request.controller
129
+ end
130
+
131
+ node.process!(request, response, (attributes || {}).to_hash)
132
+
133
+ return response.finish
134
+ end
135
+ end
136
+
137
+ return @app.call(env)
138
+ end
139
+ end
140
+ end