utopia 1.8.3 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/documentation/.bowerrc +4 -0
- data/documentation/.rspec +4 -0
- data/documentation/Gemfile +27 -0
- data/documentation/Rakefile +5 -0
- data/documentation/config.ru +50 -0
- data/documentation/config/README.md +7 -0
- data/documentation/config/environment.rb +10 -0
- data/documentation/lib/readme.txt +1 -0
- data/documentation/pages/_heading.xnode +2 -0
- data/documentation/pages/_page.xnode +28 -0
- data/documentation/pages/errors/exception.xnode +5 -0
- data/documentation/pages/errors/file-not-found.xnode +5 -0
- data/documentation/pages/links.yaml +2 -0
- data/documentation/pages/welcome/index.xnode +41 -0
- data/documentation/pages/wiki/content.md +7 -0
- data/{setup/examples → documentation/pages}/wiki/controller.rb +8 -6
- data/documentation/pages/wiki/development-environment-setup/content.md +14 -0
- data/{setup/examples → documentation/pages}/wiki/edit.xnode +1 -1
- data/documentation/pages/wiki/server-setup/content.md +40 -0
- data/documentation/pages/wiki/show.xnode +12 -0
- data/documentation/pages/wiki/your-first-page/content.md +31 -0
- data/documentation/public +1 -0
- data/documentation/spec/website_context.rb +11 -0
- data/documentation/spec/website_spec.rb +15 -0
- data/documentation/tasks/test.rake +10 -0
- data/documentation/tasks/utopia.rake +38 -0
- data/lib/utopia/content.rb +2 -2
- data/lib/utopia/content/link.rb +5 -1
- data/lib/utopia/content/markup.rb +86 -66
- data/lib/utopia/content/tag.rb +28 -45
- data/lib/utopia/content/transaction.rb +31 -25
- data/lib/utopia/controller/actions.rb +1 -0
- data/lib/utopia/redirection.rb +4 -4
- data/lib/utopia/version.rb +1 -1
- data/setup/site/public/_static/site.css +20 -8
- data/spec/utopia/content/markup_spec.rb +10 -10
- data/spec/utopia/content/tag_spec.rb +36 -0
- data/spec/utopia/controller/middleware_spec.ru +4 -1
- data/spec/utopia/controller/middleware_spec/controller/controller.rb +2 -0
- data/spec/utopia/controller/middleware_spec/controller/nested/controller.rb +2 -0
- data/spec/utopia/controller/middleware_spec/redirect/controller.rb +2 -0
- data/spec/utopia/controller/middleware_spec/redirect/test/controller.rb +2 -0
- data/spec/utopia/controller/respond_spec.ru +5 -2
- data/spec/utopia/exceptions/handler_spec.ru +3 -1
- data/spec/utopia/exceptions/handler_spec/controller.rb +2 -0
- data/spec/utopia/exceptions/mailer_spec.ru +6 -2
- data/spec/utopia/localization_spec.rb +2 -2
- data/spec/utopia/localization_spec.ru +2 -1
- data/spec/utopia/localization_spec/controller.rb +2 -0
- data/spec/utopia/performance_spec/config.ru +1 -0
- data/spec/utopia/performance_spec/pages/api/controller.rb +1 -1
- data/utopia.gemspec +3 -3
- metadata +36 -14
- data/ext/utopia/xnode/fast_scanner/extconf.rb +0 -6
- data/ext/utopia/xnode/fast_scanner/parser.c +0 -289
- data/setup/examples/wiki/index.xnode +0 -10
- data/setup/examples/wiki/welcome/content.md +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92b8e6466b0a5eea4cb1e6009734e9cea5c76160
|
4
|
+
data.tar.gz: 9854cb98bf4f4ac5794fe19370c3af2e28aec456
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fdc050063c8b3b7ece0d94ee388fec013f52adc0cc2f63f92a7e4bb94eb849a8ecbfb41664a183047475adc88f5959b019077edc5cdbb9061eb8b8a8057a2a60
|
7
|
+
data.tar.gz: 781fe07c015abd3d777f2b4cd0340d43deee4846ca05ec2171c882569bd56add14604cc54ae5276b414dc778be77d2be7c86e90835a4793abb1df52b462b4117
|
data/Gemfile
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
source "https://rubygems.org"
|
3
|
+
|
4
|
+
gem "utopia", path: File.expand_path("../", __dir__)
|
5
|
+
|
6
|
+
gem "rake"
|
7
|
+
gem "bundler"
|
8
|
+
|
9
|
+
gem "kramdown"
|
10
|
+
|
11
|
+
group :development do
|
12
|
+
# For `rake server`:
|
13
|
+
gem "puma"
|
14
|
+
|
15
|
+
# For `rake console`:
|
16
|
+
gem "pry"
|
17
|
+
gem "rack-test"
|
18
|
+
|
19
|
+
# For `rspec` testing:
|
20
|
+
gem "rspec"
|
21
|
+
gem "simplecov"
|
22
|
+
end
|
23
|
+
|
24
|
+
group :production do
|
25
|
+
# Used for passenger-config to restart server after deployment:
|
26
|
+
gem "passenger"
|
27
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env rackup
|
2
|
+
|
3
|
+
require_relative 'config/environment'
|
4
|
+
|
5
|
+
if RACK_ENV == :production
|
6
|
+
# Handle exceptions in production with a error page and send an email notification:
|
7
|
+
use Utopia::Exceptions::Handler
|
8
|
+
use Utopia::Exceptions::Mailer
|
9
|
+
else
|
10
|
+
# We want to propate exceptions up when running tests:
|
11
|
+
use Rack::ShowExceptions unless RACK_ENV == :test
|
12
|
+
|
13
|
+
# Serve the public directory in a similar way to the web server:
|
14
|
+
use Utopia::Static, root: 'public'
|
15
|
+
end
|
16
|
+
|
17
|
+
use Rack::Sendfile
|
18
|
+
|
19
|
+
use Utopia::ContentLength
|
20
|
+
|
21
|
+
use Utopia::Redirection::Rewrite,
|
22
|
+
'/' => '/welcome/index'
|
23
|
+
|
24
|
+
use Utopia::Redirection::DirectoryIndex
|
25
|
+
|
26
|
+
use Utopia::Redirection::Errors,
|
27
|
+
404 => '/errors/file-not-found'
|
28
|
+
|
29
|
+
use Utopia::Localization,
|
30
|
+
:default_locale => 'en',
|
31
|
+
:locales => ['en', 'de', 'ja', 'zh'],
|
32
|
+
:nonlocalized => ['/_static/', '/_cache/']
|
33
|
+
|
34
|
+
use Utopia::Controller,
|
35
|
+
cache_controllers: (RACK_ENV == :production),
|
36
|
+
base: Utopia::Controller::Base
|
37
|
+
|
38
|
+
use Utopia::Static
|
39
|
+
|
40
|
+
# Serve dynamic content
|
41
|
+
use Utopia::Content,
|
42
|
+
cache_templates: (RACK_ENV == :production),
|
43
|
+
tags: {
|
44
|
+
'deferred' => Utopia::Tags::Deferred,
|
45
|
+
'override' => Utopia::Tags::Override,
|
46
|
+
'node' => Utopia::Tags::Node,
|
47
|
+
'environment' => Utopia::Tags::Environment.for(RACK_ENV)
|
48
|
+
}
|
49
|
+
|
50
|
+
run lambda { |env| [404, {}, []] }
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Utopia Config
|
2
|
+
|
3
|
+
This directory contains `environment.rb` which is used to initialize the running environment for tasks and servers.
|
4
|
+
|
5
|
+
## Setting Environment Variables
|
6
|
+
|
7
|
+
If you wish to set environment variables on a per-deployment basis, you can do so by creating an `config/environment.yaml` and populating it with key-value pairs.
|
@@ -0,0 +1 @@
|
|
1
|
+
You can add additional code for your application in this directory, and require it directly from the config.ru.
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<?r response.content_type = "text/html; charset=utf-8" ?>
|
5
|
+
<?r response.cache! ?>
|
6
|
+
|
7
|
+
<?r if title = self[:title] ?>
|
8
|
+
<title>#{title.gsub(/<.*?>/, "")} - Utopia</title>
|
9
|
+
<?r else ?>
|
10
|
+
<title>Utopia</title>
|
11
|
+
<?r end ?>
|
12
|
+
|
13
|
+
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous" />
|
14
|
+
|
15
|
+
<link rel="icon" type="image/png" href="/_static/icon.png" />
|
16
|
+
<link rel="stylesheet" href="/_static/site.css" type="text/css" media="screen" />
|
17
|
+
</head>
|
18
|
+
|
19
|
+
<body class="#{attributes[:class]}">
|
20
|
+
<header>
|
21
|
+
<img src="/_static/utopia.svg" />
|
22
|
+
</header>
|
23
|
+
|
24
|
+
<div id="page">
|
25
|
+
<content />
|
26
|
+
</div>
|
27
|
+
</body>
|
28
|
+
</html>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<page class="front">
|
2
|
+
<heading>Welcome to Utopia...</heading>
|
3
|
+
|
4
|
+
<section class="features">
|
5
|
+
<div>
|
6
|
+
<i class="fa fa-bolt"></i>
|
7
|
+
<h2>Low latency and high throughput</h2>
|
8
|
+
<p>Utopia has been carefully tuned for low-latency and algorithmic efficiency. During development, requests reload the entire stack, while in production everything is cached using <a href="http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Map.html">thread-safe data-structures</a>. Serve thousands of requests per second with ease.</p>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
<div>
|
12
|
+
<i class="fa fa-cubes"></i>
|
13
|
+
<h2>Modular code and structure</h2>
|
14
|
+
<p>Utopia provides independently useful <a href="https://github.com/rack/rack">Rack</a> middleware and has been designed with simplicify in mind. Several fully-featured webapps and a ton of commercial websites have guided the development of the Utopia stack. It is capable of handling a diverse range of requirements.</p>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<div>
|
18
|
+
<i class="fa fa-code"></i>
|
19
|
+
<h2>Well tested and maintained</h2>
|
20
|
+
<p>Utopia comprises a <a href="https://github.com/ioquatix/utopia">core gem</a> and several supporting libraries, the main ones being <a href="https://github.com/ioquatix/trenni">trenni</a> for templates and parsing, and <a href="https://github.com/ioquatix/http-accept">http-accept</a> for HTTP header processing. Together, these gems have over 90% test coverage.</p>
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<div>
|
24
|
+
<i class="fa fa-server"></i>
|
25
|
+
<h2>Batteries included</h2>
|
26
|
+
<p>Utopia includes both a recommended development model and a server deployment model out of the box. This is exposed via the <code>utopia</code> command. We recommend use of <a href="https://www.nginx.com">Nginx</a> and <a href="https://www.phusionpassenger.com">Passenger</a> for server side deployment.</p>
|
27
|
+
</div>
|
28
|
+
|
29
|
+
<div>
|
30
|
+
<i class="fa fa-globe"></i>
|
31
|
+
<h2>Standards compliant localization</h2>
|
32
|
+
<p>Utopia supports the <code>Accept-Language</code> header and transparently selects the correct view to render. Build multi-lingual websites and webapps easily: translate content incrementally as required, or not at all.</p>
|
33
|
+
</div>
|
34
|
+
</section>
|
35
|
+
|
36
|
+
<section>
|
37
|
+
<h2>Documentation</h2>
|
38
|
+
|
39
|
+
<p>For up-to-date documentation, please browse the included <a href="/wiki/">wiki</a>. Feel free to improve it and submit a PR :)</p>
|
40
|
+
</section>
|
41
|
+
</page>
|
@@ -4,18 +4,20 @@ prepend Actions
|
|
4
4
|
on '**' do |request, path|
|
5
5
|
@page_path = path.components[0..-2]
|
6
6
|
|
7
|
-
if @page_path.empty?
|
8
|
-
goto! "welcome/index"
|
9
|
-
end
|
10
|
-
|
11
7
|
@page_file = File.join(BASE_PATH, @page_path, "content.md")
|
12
|
-
|
8
|
+
|
9
|
+
if last_path_component = @page_path.last
|
10
|
+
@page_title = Trenni::Strings::to_title(last_path_component)
|
11
|
+
else
|
12
|
+
@page_title = "Wiki"
|
13
|
+
end
|
13
14
|
end
|
14
15
|
|
15
16
|
def read_contents
|
16
17
|
if File.exist? @page_file
|
17
18
|
File.read(@page_file)
|
18
19
|
else
|
20
|
+
"\# #{@page_title}\n\n" +
|
19
21
|
"This page is empty."
|
20
22
|
end
|
21
23
|
end
|
@@ -37,5 +39,5 @@ end
|
|
37
39
|
on '**/index' do |request, path|
|
38
40
|
@content = read_contents
|
39
41
|
|
40
|
-
path.components = ["
|
42
|
+
path.components = ["show"]
|
41
43
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Development Environment Setup
|
2
|
+
|
3
|
+
Utopia is built on Ruby and Rack. Therefore, Ruby (suggested 2.0+) should be installed and working. Then, simply run:
|
4
|
+
|
5
|
+
$ gem install utopia
|
6
|
+
|
7
|
+
To install all required dependencies.
|
8
|
+
|
9
|
+
Utopia and it's dependencies are built on Linux and Mac by default, and therefore compatibility with Windows is not guaranteed.
|
10
|
+
|
11
|
+
## Atom Integration
|
12
|
+
|
13
|
+
Utopia uses [Trenni](https://github.com/ioquatix/trenni) for templates and it has a syntax slightly different from ERB. However, there is a [package for Atom](https://atom.io/packages/language-trenni) which provides accurate syntax highlighting.
|
14
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Server Setup
|
2
|
+
|
3
|
+
The best deployment platform for Utopia is Linux. Specifically, [Arch Linux](https://www.archlinux.org/) with the following packages:
|
4
|
+
|
5
|
+
- [nginx-mainline-passenger](https://aur.archlinux.org/packages/nginx-mainline-passenger/)
|
6
|
+
- [passenger-nginx-module](https://aur.archlinux.org/packages/passenger-nginx-module/)
|
7
|
+
|
8
|
+
There have been issues with the official packages and thus these packages were developed and tested with Utopia deployment in mind.
|
9
|
+
|
10
|
+
## Sample Nginx Configuration
|
11
|
+
|
12
|
+
Create a configuration file for your site, e.g. `/etc/nginx/sites/www.example.com`:
|
13
|
+
|
14
|
+
server {
|
15
|
+
listen 80;
|
16
|
+
server_name www.example.com;
|
17
|
+
root /srv/http/www.example.com/public;
|
18
|
+
passenger_enabled on;
|
19
|
+
}
|
20
|
+
|
21
|
+
server {
|
22
|
+
listen 80;
|
23
|
+
server_name example.com;
|
24
|
+
rewrite ^ http://www.example.com$uri permanent;
|
25
|
+
}
|
26
|
+
|
27
|
+
## Deployment via Git
|
28
|
+
|
29
|
+
The preferred method of deployment to a production server is via git. The `utopia` command assists with setup of a remote git repository on the server. It will setup a `git` `post-update` hook which will deploy the site correctly and restart passenger for that site.
|
30
|
+
|
31
|
+
To setup a server for deployment:
|
32
|
+
|
33
|
+
$ mkdir /srv/http/www.example.com
|
34
|
+
$ cd /srv/http/www.example.com
|
35
|
+
$ sudo -u http utopia server create
|
36
|
+
|
37
|
+
On your development machine, you should setup the git remote:
|
38
|
+
|
39
|
+
$ git remote add production ssh://remote/srv/http/www.example.com
|
40
|
+
$ git push --set-upstream production master
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<page>
|
2
|
+
<?r
|
3
|
+
transaction.attributes[:title] ||= @page_title
|
4
|
+
?>
|
5
|
+
|
6
|
+
#{MarkupString.raw Kramdown::Document.new(self[:content]).to_html}
|
7
|
+
|
8
|
+
<footer>
|
9
|
+
Last Modified: #{File.mtime(self[:page_file]) rescue "N/A"} —
|
10
|
+
<a href="edit">Edit</a>
|
11
|
+
</footer>
|
12
|
+
</page>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Your First Page
|
2
|
+
|
3
|
+
To setup the default site, simply create a directory and use the `utopia` command:
|
4
|
+
|
5
|
+
$ mkdir www.example.com
|
6
|
+
$ cd www.example.com
|
7
|
+
$ utopia site create
|
8
|
+
$ rake server
|
9
|
+
|
10
|
+
You will now have a basic template site running on http://localhost:9292.
|
11
|
+
|
12
|
+
## Welcome Page
|
13
|
+
|
14
|
+
Utopia includes a redirection middleware to redirect all root-level requests to a given URI. The default being `/welcome/index`:
|
15
|
+
|
16
|
+
use Utopia::Redirection::Rewrite,
|
17
|
+
'/' => '/welcome/index'
|
18
|
+
|
19
|
+
This page includes a basic overview of Utopia. Most of it's standard HTML, except for the outer `<page>` tag. Utopia uses the name `page` to lookup the file-system hierarchy. First, it looks for `/welcome/_page.xnode`, and then it looks for `/_page.xnode` which it finds. This page template includes a tag `<content/>` which is replaced with the inner body of the `<page>` tag. This recursive lookup is the heart of Utopia.
|
20
|
+
|
21
|
+
## Links
|
22
|
+
|
23
|
+
Utopia is a content-centric web application platform. It leverages the file-system to provide a mapping between logical resources and files on disk. The primary mode of mapping incoming requests to specific nodes (content) is done using the `links.yaml` file.
|
24
|
+
|
25
|
+
The links file associates metadata with node names for a given directory. This can include things like redirects, titles, descriptions, etc. You can add any metadata you like, to support your specific use-case. The primary use of the links files is to provide site structure, e.g. menus. In addition, they can function as a rudimentary data-store for static information, e.g. a list of applications (each with it's own page), a list of features, etc.
|
26
|
+
|
27
|
+
You'll notice that there is a file `/links.yaml`. This file contains important metadata relating to the `errors` subdirectory. As we don't want these nodes showing up in a top level menu, we mark them as `display: false`
|
28
|
+
|
29
|
+
errors:
|
30
|
+
display: false
|
31
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
../setup/site/public
|
@@ -0,0 +1,11 @@
|
|
1
|
+
|
2
|
+
require 'rack/test'
|
3
|
+
|
4
|
+
RSpec.shared_context "website" do
|
5
|
+
include Rack::Test::Methods
|
6
|
+
|
7
|
+
let(:rackup_path) {File.expand_path('../config.ru', __dir__)}
|
8
|
+
let(:rackup_directory) {File.dirname(rackup_path)}
|
9
|
+
|
10
|
+
let(:app) {Rack::Builder.parse_file(rackup_path).first}
|
11
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
require_relative 'website_context'
|
3
|
+
|
4
|
+
# Learn about best practice specs from http://betterspecs.org
|
5
|
+
RSpec.describe "my website" do
|
6
|
+
include_context "website"
|
7
|
+
|
8
|
+
it "should have an accessible front page" do
|
9
|
+
get "/"
|
10
|
+
|
11
|
+
follow_redirect!
|
12
|
+
|
13
|
+
expect(last_response.status).to be == 200
|
14
|
+
end
|
15
|
+
end
|