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.
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