kinbote 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/CHANGES +0 -0
  2. data/LICENSE +22 -0
  3. data/README.rdoc +19 -0
  4. data/Rakefile +64 -0
  5. data/bin/kinbote +13 -0
  6. data/kinbote.gemspec +75 -0
  7. data/lib/kinbote.rb +5 -0
  8. data/lib/kinbote/attribute.rb +71 -0
  9. data/lib/kinbote/base.rb +19 -0
  10. data/lib/kinbote/page.rb +189 -0
  11. data/lib/kinbote/page_match.rb +12 -0
  12. data/lib/kinbote/site.rb +175 -0
  13. data/lib/kinbote/util.rb +48 -0
  14. data/lib/kinbote/value.rb +45 -0
  15. data/lib/sinatra/kinbote.rb +115 -0
  16. data/lib/sinatra/kinbote_helpers.rb +63 -0
  17. data/site/.kinbote/views/attributes.haml +19 -0
  18. data/site/.kinbote/views/examples/header.haml +12 -0
  19. data/site/.kinbote/views/examples/home.haml +40 -0
  20. data/site/.kinbote/views/examples/page_attributes.haml +1 -0
  21. data/site/.kinbote/views/examples/page_attributes_title.haml +2 -0
  22. data/site/.kinbote/views/examples/related.haml +16 -0
  23. data/site/.kinbote/views/examples/related2.haml +8 -0
  24. data/site/.kinbote/views/examples/related_any.haml +8 -0
  25. data/site/.kinbote/views/examples/specific.haml +3 -0
  26. data/site/.kinbote/views/layout.haml +14 -0
  27. data/site/.kinbote/views/page.haml +18 -0
  28. data/site/.kinbote/views/pages.haml +26 -0
  29. data/site/.kinbote/views/site.haml +4 -0
  30. data/site/config/site.yml +1 -0
  31. data/site/kinbote-server +15 -0
  32. data/site/public/favicon.ico +0 -0
  33. data/site/public/js/core.js +2 -0
  34. data/site/public/js/jquery.js +19 -0
  35. data/site/public/robots.txt +1 -0
  36. data/site/views/404.haml +1 -0
  37. data/site/views/500.haml +1 -0
  38. data/site/views/index.haml +1 -0
  39. data/site/views/layout.haml +21 -0
  40. data/site/views/sass/core.sass +14 -0
  41. data/site/views/snippets/sample.haml +4 -0
  42. metadata +130 -0
@@ -0,0 +1,12 @@
1
+ module Kinbote
2
+ class PageMatch
3
+ attr_accessor :page, :attribute, :value
4
+
5
+ def initialize(page, attribute, value = nil)
6
+ @page = page
7
+ @attribute = attribute
8
+ @value = value
9
+ end
10
+
11
+ end
12
+ end
@@ -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
@@ -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