kinbote 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +0 -0
- data/LICENSE +22 -0
- data/README.rdoc +19 -0
- data/Rakefile +64 -0
- data/bin/kinbote +13 -0
- data/kinbote.gemspec +75 -0
- data/lib/kinbote.rb +5 -0
- data/lib/kinbote/attribute.rb +71 -0
- data/lib/kinbote/base.rb +19 -0
- data/lib/kinbote/page.rb +189 -0
- data/lib/kinbote/page_match.rb +12 -0
- data/lib/kinbote/site.rb +175 -0
- data/lib/kinbote/util.rb +48 -0
- data/lib/kinbote/value.rb +45 -0
- data/lib/sinatra/kinbote.rb +115 -0
- data/lib/sinatra/kinbote_helpers.rb +63 -0
- data/site/.kinbote/views/attributes.haml +19 -0
- data/site/.kinbote/views/examples/header.haml +12 -0
- data/site/.kinbote/views/examples/home.haml +40 -0
- data/site/.kinbote/views/examples/page_attributes.haml +1 -0
- data/site/.kinbote/views/examples/page_attributes_title.haml +2 -0
- data/site/.kinbote/views/examples/related.haml +16 -0
- data/site/.kinbote/views/examples/related2.haml +8 -0
- data/site/.kinbote/views/examples/related_any.haml +8 -0
- data/site/.kinbote/views/examples/specific.haml +3 -0
- data/site/.kinbote/views/layout.haml +14 -0
- data/site/.kinbote/views/page.haml +18 -0
- data/site/.kinbote/views/pages.haml +26 -0
- data/site/.kinbote/views/site.haml +4 -0
- data/site/config/site.yml +1 -0
- data/site/kinbote-server +15 -0
- data/site/public/favicon.ico +0 -0
- data/site/public/js/core.js +2 -0
- data/site/public/js/jquery.js +19 -0
- data/site/public/robots.txt +1 -0
- data/site/views/404.haml +1 -0
- data/site/views/500.haml +1 -0
- data/site/views/index.haml +1 -0
- data/site/views/layout.haml +21 -0
- data/site/views/sass/core.sass +14 -0
- data/site/views/snippets/sample.haml +4 -0
- metadata +130 -0
data/lib/kinbote/site.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
module Kinbote
|
2
|
+
class Site
|
3
|
+
include Util
|
4
|
+
|
5
|
+
attr_reader :pages, :attributes, :kinbote_path, :config
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@pages = []
|
9
|
+
@attributes = []
|
10
|
+
@values = []
|
11
|
+
@kinbote_path = nil
|
12
|
+
@config = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_kinbote_path(path)
|
16
|
+
return if @kinbote_path
|
17
|
+
@kinbote_path = path
|
18
|
+
end
|
19
|
+
|
20
|
+
def read_config
|
21
|
+
if File.exist?("#{@kinbote_path}/config/site.yml")
|
22
|
+
@config = YAML::load_file("#{@kinbote_path}/config/site.yml")
|
23
|
+
else
|
24
|
+
@config = {"title" => "Kinbote Site"}
|
25
|
+
end
|
26
|
+
@config.each do |key, value|
|
27
|
+
Site.send(:define_method, slugify(key).gsub("-", "_").to_sym, Proc.new{ @config[key] }) if !Site.respond_to?(slugify(key).gsub("-", "_").to_sym)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def load_pages
|
32
|
+
Dir.glob("#{@kinbote_path}/views/pages/**/*.{haml}").each do |file|
|
33
|
+
title, attributes = file_attributes(file)
|
34
|
+
@pages << Page.new(title, file, attributes)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def reload_pages
|
39
|
+
files = Dir.glob("#{@kinbote_path}/views/pages/**/*.{haml}")
|
40
|
+
files.each do |file|
|
41
|
+
slug = slug_from_file(file)
|
42
|
+
title, attributes = file_attributes(file)
|
43
|
+
page = find_page(slug)
|
44
|
+
if page
|
45
|
+
next if File.size(file) == page.get_filesize
|
46
|
+
page.set_attributes(attributes.merge({"title" => [title]}))
|
47
|
+
page.set_filesize
|
48
|
+
else
|
49
|
+
@pages << Page.new(title, file, attributes)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
slugs = files.map{|file| slug_from_file(file)}
|
53
|
+
@pages.map{|page| delete_page(page.slug) if !slugs.include?(page.slug)}
|
54
|
+
end
|
55
|
+
|
56
|
+
def file_attributes(file)
|
57
|
+
title = slug_from_file(file)
|
58
|
+
attributes = {}
|
59
|
+
in_atts = false
|
60
|
+
File.read(file).to_a.each do |line|
|
61
|
+
in_atts = true if line.include?("-# Kinbote Page Attributes")
|
62
|
+
in_atts = false if line.include?("-# Kinbote Sample Code")
|
63
|
+
if in_atts && line.include?(":") && line.split(":").size == 2
|
64
|
+
key = line.split(":").first.chomp.strip
|
65
|
+
value = line.split(":").last.chomp.strip
|
66
|
+
if key.downcase == "title"
|
67
|
+
title = value if key.downcase == "title"
|
68
|
+
next
|
69
|
+
else
|
70
|
+
attributes.has_key?(key) ? (attributes[key] << value) : (attributes[key] = [value])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
[title, attributes]
|
75
|
+
end
|
76
|
+
|
77
|
+
def find_page(slug)
|
78
|
+
@pages.each do |page|
|
79
|
+
return page if page.slug == slug
|
80
|
+
end
|
81
|
+
nil
|
82
|
+
end
|
83
|
+
|
84
|
+
def find_attribute(name, page = nil)
|
85
|
+
(page ? page.attributes : @attributes).each do |attribute|
|
86
|
+
return attribute if (attribute.name == name || attribute._varname == name)
|
87
|
+
end
|
88
|
+
nil
|
89
|
+
end
|
90
|
+
|
91
|
+
def find_value(val, attribute, global = false)
|
92
|
+
(global ? @values : attribute.values).each do |value|
|
93
|
+
return value if (value.value == val && attribute.name == value.attribute.name)
|
94
|
+
end
|
95
|
+
nil
|
96
|
+
end
|
97
|
+
|
98
|
+
def create_page(title)
|
99
|
+
@pages << Page.new(title)
|
100
|
+
end
|
101
|
+
|
102
|
+
def add_attribute(attribute)
|
103
|
+
@attributes << attribute
|
104
|
+
end
|
105
|
+
|
106
|
+
def add_value(value)
|
107
|
+
@values << value
|
108
|
+
end
|
109
|
+
|
110
|
+
def remove_page_attributes(page)
|
111
|
+
@attributes.map{|att| att.remove_page(page)}
|
112
|
+
@attributes.delete_if{|att| att.pages.size == 0}
|
113
|
+
end
|
114
|
+
|
115
|
+
def delete_page(slug)
|
116
|
+
page = find_page(slug)
|
117
|
+
@attributes.map{|att| att.remove_page(page)}
|
118
|
+
@attributes.delete_if{|att| att.pages.size == 0}
|
119
|
+
page.delete_files
|
120
|
+
@pages.delete_if{|p| p.slug == page.slug}
|
121
|
+
add_kinbote_haml
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_kinbote_haml(page = nil)
|
125
|
+
fname = "#{@kinbote_path}/views/#{page ? page.path : "index"}"
|
126
|
+
f_new = File.open("#{fname}.haml.new", "w")
|
127
|
+
File.read("#{fname}.haml").to_a.each do |line|
|
128
|
+
break if line.include?("-# Kinbote")
|
129
|
+
f_new.puts line
|
130
|
+
end
|
131
|
+
if page
|
132
|
+
kinbote_haml(f_new, "page_attributes_title")
|
133
|
+
kinbote_haml(f_new, "page_attributes", ["Title: #{page.title}"] + page.values.map{|v| "#{v.attribute.name}: #{v.value}"})
|
134
|
+
kinbote_haml(f_new, "header")
|
135
|
+
kinbote_haml(f_new, "specific", page.attributes.map{|a| a._varname})
|
136
|
+
kinbote_haml(f_new, "related", page.attributes.map{|a| a.name.downcase == "date" ? nil : a.name}.compact)
|
137
|
+
kinbote_haml(f_new, "related2", page.attributes.map{|a| "#{a.name}\", \"#{a.values.first.value}"})
|
138
|
+
kinbote_haml(f_new, "related_any")
|
139
|
+
else
|
140
|
+
kinbote_haml(f_new, "home", @attributes.map{|a| a._varname})
|
141
|
+
end
|
142
|
+
f_new.close
|
143
|
+
FileUtils.mv("#{fname}.haml.new", "#{fname}.haml")
|
144
|
+
page.set_filesize if page
|
145
|
+
add_kinbote_haml if page
|
146
|
+
end
|
147
|
+
|
148
|
+
def kinbote_haml(f, example_name, replacements=nil)
|
149
|
+
return if replacements && replacements.size == 0 && example_name != "page_attributes"
|
150
|
+
File.read("#{@kinbote_path}/.kinbote/views/examples/#{example_name}.haml").to_a.each do |line|
|
151
|
+
if replacements && line.include?("$ALL_VALS$")
|
152
|
+
replacements.each do |r|
|
153
|
+
f.puts(line.gsub("$ALL_VALS$", r))
|
154
|
+
end
|
155
|
+
elsif replacements && line.include?("$ALL_VALS_COMMENTED$")
|
156
|
+
replacements.each_with_index do |r, i|
|
157
|
+
if i == replacements.size - 1
|
158
|
+
f.puts(line.gsub("$ALL_VALS_COMMENTED$", r))
|
159
|
+
else
|
160
|
+
f.puts(line.gsub("- ", "-# ").gsub("$ALL_VALS_COMMENTED$", r))
|
161
|
+
end
|
162
|
+
end
|
163
|
+
elsif replacements && line.include?("$FIRST_VAL$")
|
164
|
+
f.puts(line.gsub("$FIRST_VAL$", replacements.first))
|
165
|
+
elsif replacements && line.include?("$LAST_VAL$")
|
166
|
+
f.puts(line.gsub("$LAST_VAL$", replacements.last))
|
167
|
+
else
|
168
|
+
f.puts(line)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
f.puts ""
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
end
|
data/lib/kinbote/util.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Kinbote
|
2
|
+
module Util
|
3
|
+
|
4
|
+
def slugify(str)
|
5
|
+
slug = str.downcase.gsub(/'/, '').gsub(/[^a-z0-9]+/, '-')
|
6
|
+
slug = slug[0, slug.size - 1] if slug[-1, 1] == '-'
|
7
|
+
slug
|
8
|
+
end
|
9
|
+
|
10
|
+
def dir_from_file(file)
|
11
|
+
file.split("/")[0...-1].join("/") + "/"
|
12
|
+
end
|
13
|
+
|
14
|
+
def file_without_extension(file)
|
15
|
+
file.split(".")[0...-1].join(".")
|
16
|
+
end
|
17
|
+
|
18
|
+
def slug_from_file(file)
|
19
|
+
file.split("/").last.split(".").first
|
20
|
+
end
|
21
|
+
|
22
|
+
def type_from_file(file)
|
23
|
+
file.split(".").last
|
24
|
+
end
|
25
|
+
|
26
|
+
def output_path(file)
|
27
|
+
if type_from_file(file) == "haml"
|
28
|
+
"#{$site.kinbote_path}/www/#{view_path(file)}".gsub(".haml", ".html")
|
29
|
+
elsif type_from_file(file) == "sass"
|
30
|
+
"#{$site.kinbote_path}/www/#{view_path(file)}".gsub("/sass/", "/css/").gsub(".sass", ".css")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def view_path(file)
|
35
|
+
file[$site.kinbote_path.size + 7, file.size]
|
36
|
+
end
|
37
|
+
|
38
|
+
def print_state
|
39
|
+
@attributes.each do |a|
|
40
|
+
puts "#{a.name} : #{a.pages.map{|p| p.slug}.join(',')}"
|
41
|
+
a.values.each do |v|
|
42
|
+
puts " #{v.value} : #{v.pages.map{|p| p.slug}.join(',')}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Kinbote
|
2
|
+
class Value
|
3
|
+
attr_accessor :value, :attribute
|
4
|
+
|
5
|
+
def initialize(value, page, attribute, global_value = nil)
|
6
|
+
@value = value.to_s
|
7
|
+
@attribute = attribute
|
8
|
+
@global_value = global_value || self
|
9
|
+
@pages = [page]
|
10
|
+
@css = File.exist?(file_name(:css))
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_page(page)
|
14
|
+
remove_page(page)
|
15
|
+
@pages << page
|
16
|
+
end
|
17
|
+
|
18
|
+
def remove_page(page)
|
19
|
+
@global_value.pages.delete_if{|p| p.slug == page.slug}
|
20
|
+
@pages.delete_if{|p| p.slug == page.slug}
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_css
|
24
|
+
FileUtils.mkdir_p(file_name(:css, true)) if !File.exist?(file_name(:css, true))
|
25
|
+
File.open(file_name(:css), "w") if !File.exist?(file_name(:css))
|
26
|
+
@global_value.css!
|
27
|
+
end
|
28
|
+
|
29
|
+
def file_name(type, dir = nil)
|
30
|
+
if type == :css
|
31
|
+
return "#{$site.kinbote_path}/views/sass/attributes/#{@attribute}/#{!dir ? "#{@value}.sass" : ""}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def css_files
|
36
|
+
@global_value.css? ? ["/css/attributes/#{@attribute}/#{@value}"] : []
|
37
|
+
end
|
38
|
+
|
39
|
+
def pages; @global_value == self ? @pages : @global_value.pages; end
|
40
|
+
def to_s; @value; end
|
41
|
+
def css!; @global_value == self ? @css = true : @global_value.css!; end
|
42
|
+
def css?; @global_value == self ? @css : @global_value.css?; end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'sinatra/kinbote_helpers'
|
3
|
+
|
4
|
+
module Kinbote
|
5
|
+
class Server < Sinatra::Base
|
6
|
+
register Sinatra::KinboteHelpers
|
7
|
+
include Util
|
8
|
+
|
9
|
+
set :haml, {:format => :html5}
|
10
|
+
set :sass, {:syntax => :scss}
|
11
|
+
|
12
|
+
configure do
|
13
|
+
$site = Site.new
|
14
|
+
$site.load_pages
|
15
|
+
end
|
16
|
+
|
17
|
+
before do
|
18
|
+
$site.set_kinbote_path(options.kinbote_path)
|
19
|
+
$site.read_config
|
20
|
+
$site.reload_pages
|
21
|
+
end
|
22
|
+
|
23
|
+
not_found do
|
24
|
+
status 404
|
25
|
+
haml :'404'
|
26
|
+
end
|
27
|
+
|
28
|
+
error do
|
29
|
+
status 500
|
30
|
+
haml :'500'
|
31
|
+
end
|
32
|
+
|
33
|
+
# -----------------------------------------------------------------------------------------
|
34
|
+
|
35
|
+
get '/kinbote' do
|
36
|
+
haml :'../.kinbote/views/site', :layout => :'../.kinbote/views/layout'
|
37
|
+
end
|
38
|
+
|
39
|
+
get '/kinbote/pages' do
|
40
|
+
haml :'../.kinbote/views/pages', :layout => :'../.kinbote/views/layout'
|
41
|
+
end
|
42
|
+
|
43
|
+
post '/kinbote/pages/new' do
|
44
|
+
$site.create_page(params["page"]["title"])
|
45
|
+
redirect '/kinbote/pages'
|
46
|
+
end
|
47
|
+
|
48
|
+
post '/kinbote/pages/*/delete' do
|
49
|
+
$site.delete_page(params[:splat].first)
|
50
|
+
redirect '/kinbote/pages'
|
51
|
+
end
|
52
|
+
|
53
|
+
post '/kinbote/pages/*/css' do
|
54
|
+
$site.find_page(params[:splat].first).create_css
|
55
|
+
redirect '/kinbote/pages'
|
56
|
+
end
|
57
|
+
|
58
|
+
post '/kinbote/attributes/css' do
|
59
|
+
$site.find_attribute(params["attribute"]).create_css
|
60
|
+
redirect '/kinbote/attributes'
|
61
|
+
end
|
62
|
+
|
63
|
+
post '/kinbote/values/css' do
|
64
|
+
$site.find_value(params["value"], $site.find_attribute(params["attribute"]), true).create_css
|
65
|
+
redirect '/kinbote/attributes'
|
66
|
+
end
|
67
|
+
|
68
|
+
get '/kinbote/pages/*' do
|
69
|
+
@p = $site.find_page(params[:splat].first)
|
70
|
+
haml :'../.kinbote/views/page', :layout => :'../.kinbote/views/layout'
|
71
|
+
end
|
72
|
+
|
73
|
+
post '/kinbote/pages/*' do
|
74
|
+
p params
|
75
|
+
@p = $site.find_page(params[:splat].first)
|
76
|
+
@p.set_attributes(kv_to_attributes(params["page"]["keys"], params["page"]["values"]))
|
77
|
+
redirect "/kinbote/pages/#{@p.slug}"
|
78
|
+
end
|
79
|
+
|
80
|
+
get '/kinbote/attributes' do
|
81
|
+
haml :'../.kinbote/views/attributes', :layout => :'../.kinbote/views/layout'
|
82
|
+
end
|
83
|
+
|
84
|
+
post '/kinbote/publish' do
|
85
|
+
set_user_globals
|
86
|
+
publish
|
87
|
+
redirect '/kinbote'
|
88
|
+
end
|
89
|
+
|
90
|
+
# -----------------------------------------------------------------------------------------
|
91
|
+
|
92
|
+
get '/' do
|
93
|
+
set_user_globals
|
94
|
+
haml :index
|
95
|
+
end
|
96
|
+
|
97
|
+
get '/css/pages/*.css' do
|
98
|
+
@page = $site.find_page(params[:splat].first)
|
99
|
+
content_type 'text/css', :charset => 'utf-8'
|
100
|
+
sass :"#{@page.path}"
|
101
|
+
end
|
102
|
+
|
103
|
+
get '/css/*.css' do
|
104
|
+
content_type 'text/css', :charset => 'utf-8'
|
105
|
+
sass :"sass/#{params[:splat].first}"
|
106
|
+
end
|
107
|
+
|
108
|
+
get '/*.html' do
|
109
|
+
set_user_globals
|
110
|
+
@page = $site.find_page(params[:splat].first)
|
111
|
+
haml :"#{@page ? "#{@page.path}" : "404"}"
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Sinatra
|
2
|
+
module KinboteHelpers
|
3
|
+
module Helpers
|
4
|
+
|
5
|
+
def snippet(path)
|
6
|
+
haml("snippets/#{path}".to_sym, :layout => false)
|
7
|
+
end
|
8
|
+
|
9
|
+
def set_user_globals
|
10
|
+
@site = $site
|
11
|
+
@pages = $site.pages
|
12
|
+
@attributes = $site.attributes
|
13
|
+
@attributes.each{|att| eval("@#{att._varname} = att")}
|
14
|
+
end
|
15
|
+
|
16
|
+
def kv_to_attributes(keys, values)
|
17
|
+
attributes = {}
|
18
|
+
keys.each_with_index do |key, i|
|
19
|
+
next if key.size == 0
|
20
|
+
attributes[key] = [] if !attributes.has_key?(key)
|
21
|
+
attributes[key] << values[i] if !attributes[key].include?(values[i])
|
22
|
+
end
|
23
|
+
attributes
|
24
|
+
end
|
25
|
+
|
26
|
+
def publish
|
27
|
+
FileUtils.rm_rf("#{$site.kinbote_path}/www")
|
28
|
+
FileUtils.mkdir_p("#{$site.kinbote_path}/www/css/pages")
|
29
|
+
FileUtils.copy_entry("#{$site.kinbote_path}/public", "#{$site.kinbote_path}/www")
|
30
|
+
files = Dir.glob("#{$site.kinbote_path}/views/**/*.{haml,sass}")
|
31
|
+
files.each do |file|
|
32
|
+
next if file.include?("/.kinbote/") || file.include?("/snippets/") || file.include?("/layout.haml")
|
33
|
+
slug = (file.include?("/views/pages/") ? slug_from_file(file) : nil)
|
34
|
+
@page = (slug ? $site.find_page(slug) : nil)
|
35
|
+
type = type_from_file(file)
|
36
|
+
if @page && type == "haml"
|
37
|
+
File.open("#{$site.kinbote_path}/www/#{@page.slug}.html", 'w') {|f| f.write(haml(:"#{@page.path}")) }
|
38
|
+
elsif @page && type == "sass"
|
39
|
+
File.open("#{$site.kinbote_path}/www/css/pages/#{@page.slug}.css", 'w') {|f| f.write(sass(:"#{@page.path.gsub(".haml", ".sass")}")) }
|
40
|
+
elsif type == "haml"
|
41
|
+
FileUtils.mkdir_p("#{dir_from_file(output_path(file))}")
|
42
|
+
File.open(output_path(file), "w") {|f| f.write(render(type.to_sym, :"#{file_without_extension(view_path(file))}"))}
|
43
|
+
elsif type == "sass"
|
44
|
+
FileUtils.mkdir_p("#{dir_from_file(output_path(file))}")
|
45
|
+
File.open(output_path(file), "w") {|f| f.write(render(type.to_sym, :"#{file_without_extension(view_path(file))}"))}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
return if !$site.config.has_key?("remote_host") || !$site.config.has_key?("remote_user") || !$site.config.has_key?("remote_pw")
|
49
|
+
Net::SCP.start($site.config["remote_host"], $site.config["remote_user"], :password => $site.config["remote_pw"] ) do |scp|
|
50
|
+
scp.upload!("#{$site.kinbote_path}/www", $site.config["remote_path"], :recursive => true)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.registered(app)
|
57
|
+
app.helpers KinboteHelpers::Helpers
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
register KinboteHelpers
|
63
|
+
end
|