danwrong-evil 0.1 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +1 -0
- data/LICENSE +22 -0
- data/Manifest +33 -7
- data/README.textile +20 -0
- data/Rakefile +21 -2
- data/assets/config.ru +10 -2
- data/assets/evil-lib.js +222 -0
- data/assets/evil.css +204 -10
- data/assets/evil.js +20 -0
- data/assets/logo.png +0 -0
- data/evil.gemspec +32 -19
- data/lib/evil/application.rb +85 -17
- data/lib/evil/extensions.rb +71 -0
- data/lib/evil/helpers.rb +62 -0
- data/lib/evil/models/config_pair.rb +7 -0
- data/lib/evil/models/template.rb +10 -9
- data/lib/evil/models.rb +0 -12
- data/lib/evil/open_id.rb +101 -0
- data/lib/evil/plugin/base.rb +56 -0
- data/lib/evil/plugin/configuration.rb +77 -0
- data/lib/evil/plugin/environment.rb +15 -0
- data/lib/evil/plugin/filesystem.rb +18 -0
- data/lib/evil/plugin/tag.rb +81 -0
- data/lib/evil/plugin.rb +21 -0
- data/lib/evil/setup/generator.rb +13 -1
- data/lib/evil/setup/migration.rb +4 -11
- data/lib/evil.rb +34 -1
- data/test/app/evil_test.rb +64 -0
- data/test/dev_env.rb +10 -0
- data/test/test_helper.rb +12 -0
- data/test/units/plugin/base_test.rb +47 -0
- data/test/units/plugin/tag_test.rb +108 -0
- data/views/_banner.haml +8 -0
- data/views/_errors.haml +9 -0
- data/views/index.haml +41 -0
- data/views/layout.haml +13 -0
- data/views/login.haml +5 -0
- data/views/plugins/_fields.haml +7 -0
- data/views/plugins/edit.haml +2 -0
- data/views/plugins/fields/_password.haml +3 -0
- data/views/plugins/fields/_text.haml +3 -0
- data/views/plugins/new.haml +6 -0
- data/views/templates/_fields.haml +23 -0
- data/views/templates/edit.haml +3 -0
- data/views/templates/new.haml +3 -0
- metadata +115 -13
- data/lib/evil/models/plugin.rb +0 -13
- data/test/harness/config.ru +0 -9
- data/test/harness/evil.db +0 -0
- data/test/harness/public/javascripts/evil.js +0 -0
- data/test/harness/public/stylesheets/evil.css +0 -24
- data/test/harness/tmp/restart.txt +0 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
module Evil
|
2
|
+
module Plugin
|
3
|
+
|
4
|
+
class TagExecution
|
5
|
+
|
6
|
+
def initialize(tag, options, context, &block)
|
7
|
+
@options = evaluate(options, context)
|
8
|
+
@context = context
|
9
|
+
@tag = tag
|
10
|
+
@proc = block
|
11
|
+
end
|
12
|
+
|
13
|
+
def body(locals={})
|
14
|
+
@context.stack do
|
15
|
+
locals.each { |k, v| @context[k.to_s] = v }
|
16
|
+
return @tag.render_body(@context).to_s
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute
|
21
|
+
self.instance_exec(@options, &@proc)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
execute.to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def evaluate(options, context)
|
31
|
+
options.inject({}) do |evaluated, pair|
|
32
|
+
opt, value = pair
|
33
|
+
evaluated[opt] = context[value]; evaluated
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Tag < Liquid::Block
|
39
|
+
Syntax = /((#{Liquid::TagAttributes}\s?,?\s?)*)/
|
40
|
+
|
41
|
+
class << self
|
42
|
+
attr_accessor :tag_proc
|
43
|
+
attr_accessor :plugin
|
44
|
+
|
45
|
+
def from(&block)
|
46
|
+
tag = Class.new(self)
|
47
|
+
tag.tag_proc = block; tag
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize(tag_name, markup, tokens)
|
52
|
+
super
|
53
|
+
|
54
|
+
if markup =~ Syntax
|
55
|
+
@options = parse_options($1)
|
56
|
+
else
|
57
|
+
raise Liquid::SyntaxError.new("Syntax Error in tag '#{tagname}' - Valid syntax: #{tagname} [ opt : 'val', opt : 'val' ]")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def render(context)
|
62
|
+
TagExecution.new(self, @options, context, &self.class.tag_proc).to_s
|
63
|
+
end
|
64
|
+
|
65
|
+
def render_body(context)
|
66
|
+
render_all(@nodelist, context)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def parse_options(opt_string)
|
72
|
+
pairs = opt_string.split(',')
|
73
|
+
pairs.inject({}) do |opts, pair|
|
74
|
+
opt, value = pair.split(':')
|
75
|
+
opts[opt.strip.to_sym] = value.strip; opts
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
data/lib/evil/plugin.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Evil
|
2
|
+
module Plugin
|
3
|
+
autoload :Base, 'evil/plugin/base'
|
4
|
+
autoload :Tag, 'evil/plugin/tag'
|
5
|
+
autoload :Environment, 'evil/plugin/environment'
|
6
|
+
autoload :Filesystem, 'evil/plugin/filesystem'
|
7
|
+
autoload :Configuration, 'evil/plugin/configuration'
|
8
|
+
|
9
|
+
def self.evaluate(plugin_source)
|
10
|
+
Environment.module_eval plugin_source
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.from_file(file)
|
14
|
+
evaluate(File.read(file))
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.find_plugin(name)
|
18
|
+
Environment.plugins.find { |p| p.name == name }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/evil/setup/generator.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'evil/models'
|
3
3
|
require 'evil/setup/migration'
|
4
|
+
require 'digest/sha1'
|
4
5
|
|
5
6
|
module Evil
|
6
7
|
module Setup
|
@@ -14,11 +15,14 @@ module Evil
|
|
14
15
|
public/images
|
15
16
|
public/stylesheets
|
16
17
|
public/javascripts
|
18
|
+
plugins
|
17
19
|
}
|
18
20
|
|
19
21
|
ASSETS = [
|
20
22
|
['evil.css', 'public/stylesheets/evil.css'],
|
21
23
|
['evil.js', 'public/javascripts/evil.js'],
|
24
|
+
['evil-lib.js', 'public/javascripts/evil-lib.js'],
|
25
|
+
['logo.png', 'public/images/logo.png'],
|
22
26
|
['config.ru', 'config.ru']
|
23
27
|
]
|
24
28
|
|
@@ -30,12 +34,14 @@ module Evil
|
|
30
34
|
puts "Generating Evil application..."
|
31
35
|
create_dir_tree!
|
32
36
|
copy_assets!
|
37
|
+
set_cookie_secret!
|
33
38
|
puts "Initializing database..."
|
34
39
|
create_database!
|
35
40
|
end
|
36
41
|
|
37
42
|
def create_dir_tree!
|
38
43
|
DIR_LAYOUT.each do |dir|
|
44
|
+
puts "Directory #{@path}/#{dir}"
|
39
45
|
mkdir_p "#{@path}/#{dir}"
|
40
46
|
end
|
41
47
|
end
|
@@ -51,10 +57,16 @@ module Evil
|
|
51
57
|
|
52
58
|
def copy_assets!
|
53
59
|
ASSETS.each do |file, dest|
|
60
|
+
puts "File #{File.join(@path, dest)}"
|
54
61
|
cp File.join(ASSET_PATH, file), File.join(@path, dest)
|
55
62
|
end
|
56
63
|
end
|
57
|
-
|
64
|
+
|
65
|
+
def set_cookie_secret!
|
66
|
+
rackup = File.read(File.join(@path, 'config.ru'))
|
67
|
+
rackup.gsub!(/__SECRET__/, Digest::SHA1.hexdigest("__EVIL__#{Time.now.to_s}__#{rand(999999)}"))
|
68
|
+
File.open(File.join(@path, 'config.ru'), 'w') { |f| f.write(rackup) }
|
69
|
+
end
|
58
70
|
end
|
59
71
|
end
|
60
72
|
end
|
data/lib/evil/setup/migration.rb
CHANGED
@@ -8,27 +8,20 @@ module Evil
|
|
8
8
|
def create_evil_tables
|
9
9
|
create_table :evil_templates do |t|
|
10
10
|
t.integer :ttl, :position
|
11
|
-
t.string :title, :route
|
11
|
+
t.string :title, :route, :content_type, :encoding
|
12
12
|
t.text :source
|
13
13
|
t.timestamps
|
14
|
-
end unless Evil::Models::Template.table_exists?
|
15
|
-
|
16
|
-
create_table :evil_plugins do |t|
|
17
|
-
t.string :name, :description, :author
|
18
|
-
t.text :source, :url
|
19
|
-
t.boolean :enabled
|
20
|
-
t.timestamps
|
21
|
-
end unless Evil::Models::Plugin.table_exists?
|
14
|
+
end unless Evil::Models::Template.table_exists?
|
22
15
|
|
23
16
|
unless Evil::Models::ConfigPair.table_exists?
|
24
17
|
create_table :evil_config_pairs do |t|
|
25
|
-
t.
|
18
|
+
t.string :plugin
|
26
19
|
t.string :key
|
27
20
|
t.text :value
|
28
21
|
t.timestamps
|
29
22
|
end
|
30
23
|
|
31
|
-
add_index :evil_config_pairs, :
|
24
|
+
add_index :evil_config_pairs, :plugin
|
32
25
|
end
|
33
26
|
|
34
27
|
create_table :evil_whitelists do |t|
|
data/lib/evil.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'liquid'
|
2
|
+
require 'liquid_inheritance'
|
3
|
+
require 'httparty'
|
4
|
+
|
1
5
|
module Evil
|
2
6
|
module Setup
|
3
7
|
autoload :DbTool, 'evil/setup/db_tool'
|
@@ -5,11 +9,40 @@ module Evil
|
|
5
9
|
autoload :Migration, 'evil/setup/migration'
|
6
10
|
end
|
7
11
|
|
12
|
+
autoload :OpenID, 'evil/open_id'
|
13
|
+
autoload :Helpers, 'evil/helpers'
|
14
|
+
autoload :Extensions, 'evil/extensions'
|
15
|
+
|
16
|
+
autoload :Plugin, 'evil/plugin'
|
17
|
+
|
8
18
|
autoload :Application, 'evil/application'
|
9
19
|
|
10
20
|
class << self
|
11
21
|
attr_accessor :gem_root, :app_root
|
22
|
+
|
23
|
+
def heroku?
|
24
|
+
Object.const_defined?(:Heroku)
|
25
|
+
end
|
12
26
|
end
|
13
27
|
end
|
14
28
|
|
15
|
-
Evil.gem_root = File.join(File.dirname(__FILE__), '..')
|
29
|
+
Evil.gem_root = File.join(File.dirname(__FILE__), '..')
|
30
|
+
|
31
|
+
class Proc
|
32
|
+
def bind(object)
|
33
|
+
block, time = self, Time.now
|
34
|
+
(class << object; self end).class_eval do
|
35
|
+
method_name = "__bind_#{time.to_i}_#{time.usec}"
|
36
|
+
define_method(method_name, &block)
|
37
|
+
method = instance_method(method_name)
|
38
|
+
remove_method(method_name)
|
39
|
+
method
|
40
|
+
end.bind(object)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Object
|
45
|
+
def instance_exec(*arguments, &block)
|
46
|
+
block.bind(self)[*arguments]
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../test_helper')
|
2
|
+
require 'evil/application'
|
3
|
+
|
4
|
+
class EvilTest < Test::Unit::TestCase
|
5
|
+
include Sinatra::Test
|
6
|
+
|
7
|
+
context 'running the evil application' do
|
8
|
+
setup do
|
9
|
+
@app = Evil::Application
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'while not logged in' do
|
13
|
+
|
14
|
+
context 'GET /admin' do
|
15
|
+
setup do
|
16
|
+
get '/admin'
|
17
|
+
end
|
18
|
+
|
19
|
+
should 'not be authorized' do
|
20
|
+
assert_equal 401, response.status
|
21
|
+
assert_match /openid_url/, response.body
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'while logged in' do
|
28
|
+
setup do
|
29
|
+
@env = { 'rack.session' => { :identity_url => 'www.danwebb.net' } }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'GET /admin' do
|
33
|
+
setup do
|
34
|
+
get '/admin', {}, @env
|
35
|
+
end
|
36
|
+
|
37
|
+
should 'be successful' do
|
38
|
+
assert response.ok?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'GET /admin/templates/1 with existing template' do
|
43
|
+
setup do
|
44
|
+
get '/admin/templates/1', {}, @env
|
45
|
+
end
|
46
|
+
|
47
|
+
should 'be successful' do
|
48
|
+
assert response.ok?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'GET /admin/templates/nothinghere with non-existing template' do
|
53
|
+
setup do
|
54
|
+
get '/admin/templates/nothinghere', {}, @env
|
55
|
+
end
|
56
|
+
|
57
|
+
should 'be not found' do
|
58
|
+
assert_equal 404, response.status
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
data/test/dev_env.rb
ADDED
data/test/test_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), '../lib'))
|
2
|
+
require 'rubygems'
|
3
|
+
require 'evil'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'shoulda'
|
6
|
+
require 'sinatra/test'
|
7
|
+
require 'mocha'
|
8
|
+
|
9
|
+
require 'redgreen' rescue nil
|
10
|
+
|
11
|
+
Sinatra::Default.set :environment, 'test'
|
12
|
+
Evil.app_root = File.join(File.dirname(__FILE__), 'example')
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class BaseTest < Test::Unit::TestCase
|
2
|
+
should 'initialize with a name and a block that recieves the new instance' do
|
3
|
+
plugin = Evil::Plugin::Base.new 'Test Plugin' do |p|
|
4
|
+
assert_instance_of Evil::Plugin::Base, p
|
5
|
+
end
|
6
|
+
|
7
|
+
assert_equal 'Test Plugin', plugin.name
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'given a plugin instance with a description and setup set' do
|
11
|
+
setup do
|
12
|
+
@setup_proc = Proc.new {}
|
13
|
+
|
14
|
+
@plugin = Evil::Plugin::Base.new 'Test Plugin' do |p|
|
15
|
+
p.description 'A plugin for testing plugins'
|
16
|
+
|
17
|
+
p.setup &@setup_proc
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
should 'have a description set' do
|
23
|
+
assert_equal 'A plugin for testing plugins', @plugin.description
|
24
|
+
end
|
25
|
+
|
26
|
+
should 'call the setup proc when init called' do
|
27
|
+
@setup_proc.expects(:call)
|
28
|
+
|
29
|
+
@plugin.init
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
should 'create and register a tag instance when plugin initialize with a tag call' do
|
35
|
+
Evil::Plugin::Tag.expects(:from).returns(t = Class.new(Liquid::Tag))
|
36
|
+
Liquid::Template.expects(:register_tag).with(:thing, t)
|
37
|
+
|
38
|
+
Evil::Plugin::Base.new 'Test Plugin' do |p|
|
39
|
+
p.tag :thing do
|
40
|
+
'a tag'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../../test_helper')
|
2
|
+
require 'liquid'
|
3
|
+
|
4
|
+
class TagTest < Test::Unit::TestCase
|
5
|
+
context 'with a custom tag defined that returns a string' do
|
6
|
+
setup do
|
7
|
+
Liquid::Template.register_tag('test', Evil::Plugin::Tag.from { |params|
|
8
|
+
'hello'
|
9
|
+
})
|
10
|
+
end
|
11
|
+
|
12
|
+
should 'output the string' do
|
13
|
+
template = Liquid::Template.parse('{% test %}{% endtest %}')
|
14
|
+
|
15
|
+
assert_equal 'hello', template.render
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'with a custom tag defined that returns a parameter' do
|
20
|
+
setup do
|
21
|
+
Liquid::Template.register_tag('test', Evil::Plugin::Tag.from { |params|
|
22
|
+
params[:a]
|
23
|
+
})
|
24
|
+
end
|
25
|
+
|
26
|
+
should 'output that parameter if passed as a constant' do
|
27
|
+
template = Liquid::Template.parse('{% test a: "thing" %}{% endtest %}')
|
28
|
+
|
29
|
+
assert_equal 'thing', template.render
|
30
|
+
end
|
31
|
+
|
32
|
+
should 'output that parameter if passed as a variable' do
|
33
|
+
template = Liquid::Template.parse('{% test a: var %}{% endtest %}')
|
34
|
+
|
35
|
+
assert_equal 'thing', template.render('var' => 'thing')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with a custom tag defined that uses the body method' do
|
40
|
+
setup do
|
41
|
+
Liquid::Template.register_tag('test', Evil::Plugin::Tag.from { |params|
|
42
|
+
times = params[:times] || 1
|
43
|
+
out = ''
|
44
|
+
times.times { |i| out << body(:i => i) }
|
45
|
+
out
|
46
|
+
})
|
47
|
+
end
|
48
|
+
|
49
|
+
should 'output the contents of the tag' do
|
50
|
+
template = Liquid::Template.parse('{% test %}a{% endtest %}')
|
51
|
+
|
52
|
+
assert_equal 'a', template.render
|
53
|
+
end
|
54
|
+
|
55
|
+
should 'remember the i variable passed to body' do
|
56
|
+
template = Liquid::Template.parse('{% test %}{{ i }}{% endtest %}')
|
57
|
+
|
58
|
+
assert_equal '0', template.render
|
59
|
+
end
|
60
|
+
|
61
|
+
should 'be different value of i for each repetition of body' do
|
62
|
+
template = Liquid::Template.parse('{% test times: 10 %}{{ i }}{% endtest %}')
|
63
|
+
|
64
|
+
assert_equal '0123456789', template.render
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'with 2 custom tags defined' do
|
69
|
+
setup do
|
70
|
+
Liquid::Template.register_tag('test', Evil::Plugin::Tag.from { |params|
|
71
|
+
times = params[:times] || 1
|
72
|
+
out = ''
|
73
|
+
times.times { |i| out << body(:i => i) }
|
74
|
+
out
|
75
|
+
})
|
76
|
+
|
77
|
+
Liquid::Template.register_tag('test2', Evil::Plugin::Tag.from { |params|
|
78
|
+
params[:a]
|
79
|
+
})
|
80
|
+
end
|
81
|
+
|
82
|
+
should 'be able to nest tags' do
|
83
|
+
template = Liquid::Template.parse("{% test times: 2 %}{% test2 a: 4 %}{% endtest2 %}{% endtest %}")
|
84
|
+
|
85
|
+
assert_equal '44', template.render
|
86
|
+
end
|
87
|
+
|
88
|
+
should 'be able to use vars from outer tag in inner tag' do
|
89
|
+
template = Liquid::Template.parse("{% test times: 2 %}{% test2 a: i %}{% endtest2 %}{% endtest %}")
|
90
|
+
|
91
|
+
assert_equal '01', template.render
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'with a custom tag with more than one parameter defined' do
|
96
|
+
setup do
|
97
|
+
Liquid::Template.register_tag('test', Evil::Plugin::Tag.from { |params|
|
98
|
+
[params[:a], params[:b]].join('|')
|
99
|
+
})
|
100
|
+
end
|
101
|
+
|
102
|
+
should 'output both parameters' do
|
103
|
+
template = Liquid::Template.parse("{% test a: 'g', b: 'a' %}{% endtest %}")
|
104
|
+
|
105
|
+
assert_equal 'g|a', template.render
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/views/_banner.haml
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
- if session[:identity_url]
|
2
|
+
#banner
|
3
|
+
%a{ :href => '/admin' }
|
4
|
+
%img#logo{ :src => '/images/logo.png', :alt => 'Evil' }
|
5
|
+
%form{ :method => 'post', :action => '/admin/openid/logout', :id => 'logout' }
|
6
|
+
Logged in as
|
7
|
+
%em= session[:identity_url]
|
8
|
+
%input.submit{ :type => 'submit', :value => 'Log out' }
|
data/views/_errors.haml
ADDED
data/views/index.haml
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#overview
|
2
|
+
%table#template-overview
|
3
|
+
%thead
|
4
|
+
%tr.title
|
5
|
+
%th{ :colspan => 3 } Templates
|
6
|
+
%tr
|
7
|
+
%th Name
|
8
|
+
%th URL Pattern
|
9
|
+
%th TTL
|
10
|
+
%th
|
11
|
+
%tbody
|
12
|
+
- @templates.each_with_index do |template, i|
|
13
|
+
%tr{ :class => ('alt' if i % 2 == 1) }
|
14
|
+
%td= template.title
|
15
|
+
%td= template.route
|
16
|
+
%td= template.route.empty? ? 'N/A' : template.ttl
|
17
|
+
%td.tools
|
18
|
+
%a{ :href => "/admin/templates/#{template.id}"} Edit
|
19
|
+
%tfoot
|
20
|
+
%tr
|
21
|
+
%td{ :colspan => 4 }
|
22
|
+
%a{ :href => '/admin/templates/new' } Add Template...
|
23
|
+
|
24
|
+
%table#plugin-overview
|
25
|
+
%thead
|
26
|
+
%tr.title
|
27
|
+
%th{ :colspan => 3 } Plugin Configuration
|
28
|
+
%tr
|
29
|
+
%th Name
|
30
|
+
%th
|
31
|
+
%tbody
|
32
|
+
- @plugins.each_with_index do |plugin, i|
|
33
|
+
%tr{ :class => ('alt' if i % 2 == 1) }
|
34
|
+
%td= plugin
|
35
|
+
%td.tools
|
36
|
+
%a{ :href => "/admin/plugins/#{urlencode(plugin)}"} Edit
|
37
|
+
%tfoot
|
38
|
+
%tr
|
39
|
+
%td{ :colspan => 3 }
|
40
|
+
%a{ :href => '/admin/plugins/new' } Add Configuration...
|
41
|
+
|
data/views/layout.haml
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
!!!
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%title Evil Admin
|
5
|
+
%link{ :rel => 'stylesheet', :href => '/stylesheets/evil.css', :type => 'text/css' }
|
6
|
+
%body
|
7
|
+
= partial(:banner)
|
8
|
+
#content
|
9
|
+
= yield
|
10
|
+
%script{ :type => 'text/javascript', :src => 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js' }
|
11
|
+
%script{ :type => 'text/javascript', :src => '/javascripts/evil-lib.js' }
|
12
|
+
%script{ :type => 'text/javascript', :src => '/javascripts/evil.js' }
|
13
|
+
|
data/views/login.haml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
%p
|
2
|
+
%label{ :for => 'template_title' }
|
3
|
+
Title *
|
4
|
+
%input#template_title.text{ :name => 'template[title]', :value => @template.title }
|
5
|
+
%p
|
6
|
+
%label{ :for => 'template_route' }
|
7
|
+
Route
|
8
|
+
%input#template_route.text{ :name => 'template[route]', :value => @template.route }
|
9
|
+
%p
|
10
|
+
%label{ :for => 'template_source' }
|
11
|
+
Source *
|
12
|
+
%textarea#template_source{ :name => 'template[source]' }= @template.source
|
13
|
+
%p
|
14
|
+
%label{ :for => 'template_ttl' }
|
15
|
+
Expires every (seconds)
|
16
|
+
%input#template_ttl.text{ :name => 'template[ttl]', :value => @template.ttl || 600 }
|
17
|
+
%p
|
18
|
+
%label{ :for => 'template_content_type' }
|
19
|
+
Content Type
|
20
|
+
%input#template_content_type.short{ :name => 'template[content_type]', :value => @template.content_type || 'text/html' }
|
21
|
+
%input#template_encoding.short{ :name => 'template[encoding]', :value => @template.encoding || 'utf-8' }
|
22
|
+
%p
|
23
|
+
%input.submit{ :value => 'Save', :type => 'submit' }
|