kinbote 0.0.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/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
|