public
Fork of sr/git-wiki
Description: A wiki engine that uses a Git repository as its data store.
Homepage: http://atonie.org/2008/02/git-wiki
Clone URL: git://github.com/al3x/git-wiki.git
Search Repo:
commit  7bfdd2d3239f64f95426a8f44a9eb2df5c7725b1
tree    7ea50f7c446227dbd7bb2d35328a70bb3b227500
parent  6ab04c228788e12251323d3535cacb02d47b94eb
git-wiki / git-wiki.rb
100755 188 lines (155 sloc) 3.842 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#!/usr/bin/env ruby
 
%w(rubygems sinatra git bluecloth rubypants haml).each do |dependency|
  begin
    require dependency
  rescue LoadError => e
    puts "You need to install #{dependency} before we can proceed"
  end
end
 
GIT_REPO = ENV['HOME'] + '/wiki'
HOMEPAGE = 'Home'
 
unless File.exists?(GIT_REPO) && File.directory?(GIT_REPO)
  puts "Initializing repository in #{GIT_REPO}..."
  Git.init(GIT_REPO)
end
 
$repo = Git.open(GIT_REPO)
 
class Page
  attr_reader :name
 
  def initialize(name)
    @name = name
    @filename = File.join(GIT_REPO, @name)
  end
 
  def body
    @body ||= BlueCloth.new(RubyPants.new(raw_body).to_html).to_html.
      gsub(/\b((?:[A-Z]\w+){2,})/) { |m| "<a href=\"/#{m}\">#{m}</a>" }
  end
 
  def raw_body
    @raw_body ||= File.exists?(@filename) ? File.read(@filename) : ''
  end
 
  def body=(content)
    File.open(@filename, 'w') { |f| f << content }
    message = tracked? ? "Edited #{@name}" : "Created #{@name}"
    $repo.add(@name)
    $repo.commit(message)
  end
 
  def tracked?
    begin
      return false if $repo.log.size == 0
      $repo.log.first.gtree.children.keys.include?(@name)
    rescue
      return false
    end
  end
 
  def to_s
    "<li><strong><a href='/#{@name}'>#{@name}</a></strong> — <a href='/e/#{@name}'>edit</a></li>"
  end
end
 
get('/') { redirect '/' + HOMEPAGE }
get('/_stylesheet.css') { Sass::Engine.new(File.read(__FILE__).gsub(/.*__END__/m, '')).render }
 
get '/_list' do
  if $repo.log.size == 0
    @pages = []
  else
    @pages = $repo.log.first.gtree.children.map { |name, blob| Page.new(name) }
  end
  
  haml(list)
end
 
get '/:page' do
  @page = Page.new(params[:page])
  @page.tracked? ? haml(show) : redirect('/e/' + @page.name)
end
 
get '/e/:page' do
  @page = Page.new(params[:page])
  haml(edit)
end
 
post '/e/:page' do
  @page = Page.new(params[:page])
  @page.body = params[:body]
  redirect '/' + @page.name
end
 
def layout(title, content)
  %Q(
%html
%head
%title #{title}
%link{:rel => 'stylesheet', :href => '/_stylesheet.css', :type => 'text/css', :media => 'screen'}
%meta{'http-equiv' => 'Content-Type', :content => 'text/html; charset=utf-8'}
 
%body
#navigation
%a{:href => '/'} Home
%a{:href => '/_list'} List
#{content}
)
end
 
def show
  layout(@page.name, %q(
%a{:href => '/e/' + @page.name, :class => 'edit_link'} edit this page
%h1{:class => 'page_title'}= @page.name
#page_content= @page.body
))
end
 
def edit
  layout("Editing #{@page.name}", %q(
%h1
Editing
= @page.name
%a{:href => 'javascript:history.back()', :class => 'cancel'} Cancel
%form{ :method => 'POST', :action => '/e/' + params[:page]}
%p
~"<textarea name='body' rows='25' cols='130'>#{@page.raw_body}</textarea>"
%p
%input{:type => :submit, :value => 'Save as the newest version', :class => :submit}
))
end
 
def list
  layout('Listing pages', %q{
%h1 All pages
- if @pages.empty?
%p No pages found.
- else
%ul= @pages.each(&:to_s)
})
end
 
__END__
body
:font
family: Verdana, Arial, "Bitstream Vera Sans", Helvetica, sans-serif
size: 14px
color: black
line-height: 160%
background-color: white
margin: 2em
 
#navigation
a
background-color: #e0e0e0
color: black
text-decoration: none
padding: 2px
padding: 5px
border-bottom: 1px black solid
 
h1
display: block
padding-bottom: 5px
 
a
color: black
 
.submit
font-size: large
font-weight: bold
 
.page_title
font-size: xx-large
 
.edit_link
color: black
font-size: 14px
font-weight: bold
background-color: #e0e0e0
font-variant: small-caps
text-decoration: none
 
.cancel
background-color: #e0e0e0
font-weight: normal
text-decoration: none
font-size: 14px
 
.cancel:before
content: "("
 
.cancel:after
content: ")"