sr / git-wiki
- Source
- Commits
- Network (44)
- Issues (0)
- Downloads (0)
- Wiki (1)
- Graphs
-
Tree:
ea533a2
Simon Rozet (author)
Thu Aug 28 03:51:37 -0700 2008
commit ea533a233e2c973f538c416bd28205c84624be1b
tree 399f26d02e0ad065656906d699313740f888fb79
parent ce3a6ff8516088bbf37254603a525ec7aca4ce6d
tree 399f26d02e0ad065656906d699313740f888fb79
parent ce3a6ff8516088bbf37254603a525ec7aca4ce6d
git-wiki / git-wiki.rb
| cd4545f4 » | Alex Payne | 2008-02-19 | 1 | #!/usr/bin/env ruby | |
| a40f8d3d » | Simon Rozet | 2008-08-26 | 2 | $:.unshift *Dir[File.dirname(__FILE__) + '/vendor/**/lib'].to_a | |
| 11f29a57 » | Simon Rozet | 2008-07-21 | 3 | %w(sinatra | |
| a40f8d3d » | Simon Rozet | 2008-08-26 | 4 | grit | |
| 11f29a57 » | Simon Rozet | 2008-07-21 | 5 | rubygems | |
| 6 | haml | ||||
| 7 | sass | ||||
| 2a23bc0a » | Simon Rozet | 2008-08-26 | 8 | bluecloth).each { |dependency| require dependency } | |
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 9 | ||
| e34a1f77 » | Simon Rozet | 2008-08-26 | 10 | begin | |
| 11 | require 'thin' | ||||
| 12 | rescue LoadError | ||||
| 13 | puts '# May I suggest you to use Thin?' | ||||
| 14 | end | ||||
| 15 | |||||
| 8e732dcc » | Simon Rozet | 2008-08-24 | 16 | class String | |
| 17 | def to_html | ||||
| 2a23bc0a » | Simon Rozet | 2008-08-26 | 18 | BlueCloth.new(self).to_html.linkify | |
| 8e732dcc » | Simon Rozet | 2008-08-24 | 19 | end | |
| 20 | |||||
| 21 | def linkify | ||||
| 22 | self.gsub(/([A-Z][a-z]+[A-Z][A-Za-z0-9]+)/) do |page| | ||||
| ea533a23 » | Simon Rozet | 2008-08-28 | 23 | %Q{<a class="#{Page.new(page).to_css_class}" href="/#{page}">#{page.titleize}</a>} | |
| 8e732dcc » | Simon Rozet | 2008-08-24 | 24 | end | |
| 25 | end | ||||
| 26 | |||||
| 27 | def titleize | ||||
| 28 | self.gsub(/([A-Z]+)([A-Z][a-z])/,'\1 \2').gsub(/([a-z\d])([A-Z])/,'\1 \2') | ||||
| 29 | end | ||||
| 44e73c3e » | Simon Rozet | 2008-08-26 | 30 | ||
| 31 | def without_ext | ||||
| 32 | self.sub(File.extname(self), '') | ||||
| 33 | end | ||||
| 8e732dcc » | Simon Rozet | 2008-08-24 | 34 | end | |
| 35 | |||||
| ea533a23 » | Simon Rozet | 2008-08-28 | 36 | class PageNotFound < Sinatra::NotFound | |
| 37 | attr_reader :name | ||||
| 38 | |||||
| 39 | def initialize(name) | ||||
| 40 | @name = name | ||||
| 41 | end | ||||
| 42 | end | ||||
| 43 | |||||
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 44 | class Page | |
| 91e11a63 » | Simon Rozet | 2008-03-08 | 45 | class << self | |
| 46 | attr_accessor :repo | ||||
| 47 | |||||
| 44e73c3e » | Simon Rozet | 2008-08-26 | 48 | def find_all | |
| ea533a23 » | Simon Rozet | 2008-08-28 | 49 | return [] if repo.tree.contents.empty? | |
| 50 | repo.tree.contents.collect { |blob| new(blob) } | ||||
| 44e73c3e » | Simon Rozet | 2008-08-26 | 51 | end | |
| ea533a23 » | Simon Rozet | 2008-08-28 | 52 | ||
| 53 | def find(name) | ||||
| 54 | page_blob = find_blob(name) | ||||
| 55 | raise PageNotFound.new(name) unless page_blob | ||||
| 56 | new(page_blob) | ||||
| 57 | end | ||||
| 58 | |||||
| 59 | def find_or_create(name) | ||||
| 60 | find(name) | ||||
| 61 | rescue PageNotFound | ||||
| 62 | new(create_blob_for(name)) | ||||
| 63 | end | ||||
| 64 | |||||
| 65 | private | ||||
| 66 | def find_blob(page_name) | ||||
| 67 | repo.tree/(page_name + PageExtension) | ||||
| 68 | end | ||||
| 69 | |||||
| 70 | def create_blob_for(page_name) | ||||
| 71 | Grit::Blob.create(repo, :name => page_name + PageExtension, :data => '') | ||||
| 72 | end | ||||
| c6d5d08a » | Simon Rozet | 2008-03-08 | 73 | end | |
| 74 | |||||
| ea533a23 » | Simon Rozet | 2008-08-28 | 75 | def initialize(blob) | |
| 76 | @blob = blob | ||||
| 77 | end | ||||
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 78 | ||
| ea533a23 » | Simon Rozet | 2008-08-28 | 79 | def new? | |
| 80 | body.nil? | ||||
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 81 | end | |
| 82 | |||||
| ea533a23 » | Simon Rozet | 2008-08-28 | 83 | def name | |
| 84 | @blob.name.without_ext | ||||
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 85 | end | |
| 86 | |||||
| ea533a23 » | Simon Rozet | 2008-08-28 | 87 | def body | |
| 88 | @blob.data | ||||
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 89 | end | |
| 90 | |||||
| ea533a23 » | Simon Rozet | 2008-08-28 | 91 | def update_content(new_content) | |
| 92 | return if new_content == content | ||||
| 93 | File.open(file_name, 'w') { |f| f << new_content } | ||||
| 44e73c3e » | Simon Rozet | 2008-08-26 | 94 | add_to_index_and_commit! | |
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 95 | end | |
| 96 | |||||
| ea533a23 » | Simon Rozet | 2008-08-28 | 97 | def to_html | |
| 98 | body.linkify.to_html | ||||
| 68eeb527 » | Simon Rozet | 2008-01-31 | 99 | end | |
| 100 | |||||
| 101 | def to_s | ||||
| 44e73c3e » | Simon Rozet | 2008-08-26 | 102 | name | |
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 103 | end | |
| 44e73c3e » | Simon Rozet | 2008-08-26 | 104 | ||
| ea533a23 » | Simon Rozet | 2008-08-28 | 105 | def to_css_class | |
| 106 | new? ? 'unknown' : 'exists' | ||||
| 107 | end | ||||
| 44e73c3e » | Simon Rozet | 2008-08-26 | 108 | ||
| ea533a23 » | Simon Rozet | 2008-08-28 | 109 | private | |
| 44e73c3e » | Simon Rozet | 2008-08-26 | 110 | def add_to_index_and_commit! | |
| ea533a23 » | Simon Rozet | 2008-08-28 | 111 | Dir.chdir(GitRepository) { Page.repo.add(@blob.name) } | |
| 44e73c3e » | Simon Rozet | 2008-08-26 | 112 | Page.repo.commit_index(commit_message) | |
| 113 | end | ||||
| 114 | |||||
| 115 | def file_name | ||||
| 116 | File.join(GitRepository, name + PageExtension) | ||||
| 117 | end | ||||
| 118 | |||||
| 119 | def commit_message | ||||
| ea533a23 » | Simon Rozet | 2008-08-28 | 120 | new? ? "Edited #{name}" : "Created #{name}" | |
| 44e73c3e » | Simon Rozet | 2008-08-26 | 121 | end | |
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 122 | end | |
| 123 | |||||
| 5b5675c7 » | Simon Rozet | 2008-03-28 | 124 | use_in_file_templates! | |
| 125 | |||||
| e8ace3b0 » | Simon Rozet | 2008-03-28 | 126 | configure do | |
| a8f960aa » | Simon Rozet | 2008-07-21 | 127 | GitRepository = ENV['GIT_WIKI_REPO'] || File.join(ENV['HOME'], 'wiki') | |
| f9fb79a4 » | Simon Rozet | 2008-08-08 | 128 | PageExtension = '.markdown' | |
| 735d262b » | Simon Rozet | 2008-06-06 | 129 | Homepage = 'Home' | |
| c0b58955 » | Simon Rozet | 2008-08-26 | 130 | set_option :haml, :format => :html4, | |
| 131 | :attr_wrapper => '"' | ||||
| e8ace3b0 » | Simon Rozet | 2008-03-28 | 132 | ||
| 889a63c8 » | Simon Rozet | 2008-08-26 | 133 | begin | |
| 134 | Page.repo = Grit::Repo.new(GitRepository) | ||||
| 135 | rescue Grit::InvalidGitRepositoryError, Grit::NoSuchPathError | ||||
| 735d262b » | Simon Rozet | 2008-06-06 | 136 | abort "#{GitRepository}: Not a git repository. Install your wiki with `rake bootstrap`" | |
| e8ace3b0 » | Simon Rozet | 2008-03-28 | 137 | end | |
| 138 | end | ||||
| 139 | |||||
| ea533a23 » | Simon Rozet | 2008-08-28 | 140 | error PageNotFound do | |
| 141 | page = request.env['sinatra.error'].name | ||||
| 142 | redirect "/e/#{page}" | ||||
| 143 | end | ||||
| 144 | |||||
| 16928c6a » | Simon Rozet | 2008-03-27 | 145 | helpers do | |
| 146 | def title(title=nil) | ||||
| 8e732dcc » | Simon Rozet | 2008-08-24 | 147 | @title = title.to_s unless title.nil? | |
| 16928c6a » | Simon Rozet | 2008-03-27 | 148 | @title | |
| 149 | end | ||||
| 60dfcabc » | Simon Rozet | 2008-03-28 | 150 | ||
| 151 | def list_item(page) | ||||
| c0b58955 » | Simon Rozet | 2008-08-26 | 152 | '<a class="page_name" href="/%s">%s</a>' % [page, page.name.titleize] | |
| 60dfcabc » | Simon Rozet | 2008-03-28 | 153 | end | |
| 16928c6a » | Simon Rozet | 2008-03-27 | 154 | end | |
| 155 | |||||
| 58912852 » | Simon Rozet | 2008-07-21 | 156 | before { content_type 'text/html', :charset => 'utf-8' } | |
| 4a2e99ae » | Simon Rozet | 2008-03-27 | 157 | ||
| 735d262b » | Simon Rozet | 2008-06-06 | 158 | get('/') { redirect '/' + Homepage } | |
| 4a2e99ae » | Simon Rozet | 2008-03-27 | 159 | ||
| f9fb79a4 » | Simon Rozet | 2008-08-08 | 160 | get '/_stylesheet.css' do | |
| ca42b9c3 » | Simon Rozet | 2008-04-20 | 161 | content_type 'text/css', :charset => 'utf-8' | |
| 162 | sass :stylesheet | ||||
| 4a2e99ae » | Simon Rozet | 2008-03-27 | 163 | end | |
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 164 | ||
| 68eeb527 » | Simon Rozet | 2008-01-31 | 165 | get '/_list' do | |
| c6d5d08a » | Simon Rozet | 2008-03-08 | 166 | @pages = Page.find_all | |
| 16928c6a » | Simon Rozet | 2008-03-27 | 167 | haml :list | |
| 68eeb527 » | Simon Rozet | 2008-01-31 | 168 | end | |
| 169 | |||||
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 170 | get '/:page' do | |
| ea533a23 » | Simon Rozet | 2008-08-28 | 171 | @page = Page.find(params[:page]) | |
| 172 | haml :show | ||||
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 173 | end | |
| 174 | |||||
| d47f5f25 » | Simon Rozet | 2008-03-27 | 175 | get '/:page.txt' do | |
| ea533a23 » | Simon Rozet | 2008-08-28 | 176 | @page = Page.find(params[:page]) | |
| ca42b9c3 » | Simon Rozet | 2008-04-20 | 177 | content_type 'text/plain', :charset => 'utf-8' | |
| ea533a23 » | Simon Rozet | 2008-08-28 | 178 | @page.content | |
| d47f5f25 » | Simon Rozet | 2008-03-27 | 179 | end | |
| 180 | |||||
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 181 | get '/e/:page' do | |
| ea533a23 » | Simon Rozet | 2008-08-28 | 182 | @page = Page.find_or_create(params[:page]) | |
| 16928c6a » | Simon Rozet | 2008-03-27 | 183 | haml :edit | |
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 184 | end | |
| 185 | |||||
| 186 | post '/e/:page' do | ||||
| ea533a23 » | Simon Rozet | 2008-08-28 | 187 | @page = Page.find_or_create(params[:page]) | |
| 188 | @page.update_content(params[:body]) | ||||
| 189 | redirect "/#{@page}" | ||||
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 190 | end | |
| 191 | |||||
| 16928c6a » | Simon Rozet | 2008-03-27 | 192 | __END__ | |
| 5108abaf » | Simon Rozet | 2008-05-04 | 193 | @@ layout | |
| 5b5675c7 » | Simon Rozet | 2008-03-28 | 194 | !!! strict | |
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 195 | %html | |
| 196 | %head | ||||
| 16928c6a » | Simon Rozet | 2008-03-27 | 197 | %title= title | |
| 198 | %link{:rel => 'stylesheet', :href => '/_stylesheet.css', :type => 'text/css'} | ||||
| 4a043b7d » | Simon Rozet | 2008-08-24 | 199 | - Dir[Sinatra.application.options.public + '/*.js'].reverse.each do |lib| | |
| 200 | %script{:src => "/#{File.basename(lib)}", :type => 'text/javascript'} | ||||
| 38c0188d » | Simon Rozet | 2008-03-27 | 201 | :javascript | |
| 202 | $(document).ready(function() { | ||||
| 735d262b » | Simon Rozet | 2008-06-06 | 203 | $.hotkeys.add('Ctrl+h', function() { document.location = '/#{Homepage}' }) | |
| b9bc2fe9 » | Simon Rozet | 2008-03-28 | 204 | $.hotkeys.add('Ctrl+l', function() { document.location = '/_list' }) | |
| 8e732dcc » | Simon Rozet | 2008-08-24 | 205 | ||
| 206 | /* title-case-ification */ | ||||
| 207 | document.title = document.title.toTitleCase(); | ||||
| 208 | $('h1:first').text($('h1:first').text().toTitleCase()); | ||||
| 209 | $('a').each(function(i) { | ||||
| 210 | var e = $(this) | ||||
| 211 | e.text(e.text().toTitleCase()); | ||||
| 212 | }) | ||||
| 38c0188d » | Simon Rozet | 2008-03-27 | 213 | }) | |
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 214 | %body | |
| 16928c6a » | Simon Rozet | 2008-03-27 | 215 | #content= yield | |
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 216 | ||
| 5108abaf » | Simon Rozet | 2008-05-04 | 217 | @@ show | |
| 8e732dcc » | Simon Rozet | 2008-08-24 | 218 | - title @page.name.titleize | |
| d47f5f25 » | Simon Rozet | 2008-03-27 | 219 | :javascript | |
| 220 | $(document).ready(function() { | ||||
| 221 | $.editable.addInputType('autogrow', { | ||||
| 222 | element : function(settings, original) { | ||||
| 223 | var textarea = $('<textarea>'); | ||||
| 224 | if (settings.rows) { | ||||
| 225 | textarea.attr('rows', settings.rows); | ||||
| 226 | } else { | ||||
| 227 | textarea.height(settings.height); | ||||
| 228 | } | ||||
| 229 | if (settings.cols) { | ||||
| 230 | textarea.attr('cols', settings.cols); | ||||
| 231 | } else { | ||||
| 232 | textarea.width(settings.width); | ||||
| 233 | } | ||||
| 234 | $(this).append(textarea); | ||||
| 235 | return(textarea); | ||||
| 236 | }, | ||||
| 237 | plugin : function(settings, original) { | ||||
| 238 | $('textarea', this).autogrow(settings.autogrow); | ||||
| 239 | } | ||||
| 240 | }); | ||||
| 241 | |||||
| 60dfcabc » | Simon Rozet | 2008-03-28 | 242 | $('#page_content').editable('/e/#{@page}', { | |
| 243 | loadurl: '/#{@page}.txt', | ||||
| e03a40e8 » | Simon Rozet | 2008-03-28 | 244 | submit: '<button class="submit" type="submit">Save as the newest version</button>', | |
| cc3f201f » | Simon Rozet | 2008-03-28 | 245 | cancel: '<a class="cancel" href="" style="margin-left: 5px;">cancel</a>', | |
| 38c0188d » | Simon Rozet | 2008-03-27 | 246 | event: 'dblclick', | |
| d47f5f25 » | Simon Rozet | 2008-03-27 | 247 | type: 'autogrow', | |
| 6ebfaa3d » | Simon Rozet | 2008-03-28 | 248 | cols: 84, | |
| 249 | rows: 20, | ||||
| d47f5f25 » | Simon Rozet | 2008-03-27 | 250 | name: 'body', | |
| 251 | onblur: 'ignore', | ||||
| 60dfcabc » | Simon Rozet | 2008-03-28 | 252 | tooltip: ' ', | |
| 38c0188d » | Simon Rozet | 2008-03-27 | 253 | indicator: 'Saving...', | |
| 254 | loadtext: '', | ||||
| d47f5f25 » | Simon Rozet | 2008-03-27 | 255 | cssclass: 'edit_form', | |
| 256 | }) | ||||
| 257 | }) | ||||
| 16928c6a » | Simon Rozet | 2008-03-27 | 258 | %h1= title | |
| c266faa8 » | Simon Rozet | 2008-05-13 | 259 | #page_content | |
| ea533a23 » | Simon Rozet | 2008-08-28 | 260 | ~"#{@page.to_html}" | |
| 3bdddd51 » | Simon Rozet | 2008-01-29 | 261 | ||
| 5108abaf » | Simon Rozet | 2008-05-04 | 262 | @@ edit | |
| 8e732dcc » | Simon Rozet | 2008-08-24 | 263 | - title "Editing #{@page.name.titleize}" | |
| 16928c6a » | Simon Rozet | 2008-03-27 | 264 | %h1= title | |
| c47205a1 » | Simon Rozet | 2008-03-28 | 265 | %form{:method => 'POST', :action => "/e/#{@page}"} | |
| d47f5f25 » | Simon Rozet | 2008-03-27 | 266 | %p | |
| ea533a23 » | Simon Rozet | 2008-08-28 | 267 | %textarea{:name => 'body', :rows => 20, :cols => 80}= @page.content | |
| d47f5f25 » | Simon Rozet | 2008-03-27 | 268 | %p | |
| 38c0188d » | Simon Rozet | 2008-03-27 | 269 | %input.submit{:type => :submit, :value => 'Save as the newest version'} | |
| bdd34406 » | Simon Rozet | 2008-03-28 | 270 | or | |
| c47205a1 » | Simon Rozet | 2008-03-28 | 271 | %a.cancel{:href=>"/#{@page}"} cancel | |
| 16928c6a » | Simon Rozet | 2008-03-27 | 272 | ||
| 5108abaf » | Simon Rozet | 2008-05-04 | 273 | @@ list | |
| 16928c6a » | Simon Rozet | 2008-03-27 | 274 | - title "Listing pages" | |
| 275 | %h1 All pages | ||||
| 276 | - if @pages.empty? | ||||
| 88d664e0 » | Bryan T. Richardson | 2008-08-20 | 277 | %p No pages found. | |
| 16928c6a » | Simon Rozet | 2008-03-27 | 278 | - else | |
| bdd34406 » | Simon Rozet | 2008-03-28 | 279 | %ul#pages_list | |
| f88d9eb3 » | Simon Rozet | 2008-08-26 | 280 | - @pages.each_with_index do |page, index| | |
| 281 | - if (index % 2) == 0 | ||||
| 282 | %li.odd= list_item(page) | ||||
| 283 | - else | ||||
| 284 | %li.even= list_item(page) | ||||
| 16928c6a » | Simon Rozet | 2008-03-27 | 285 | ||
| 5108abaf » | Simon Rozet | 2008-05-04 | 286 | @@ stylesheet | |
| 1dfbc578 » | Simon Rozet | 2008-02-26 | 287 | body | |
| 288 | :font | ||||
| 38c0188d » | Simon Rozet | 2008-03-27 | 289 | family: "Lucida Grande", Verdana, Arial, Bitstream Vera Sans, Helvetica, sans-serif | |
| 1dfbc578 » | Simon Rozet | 2008-02-26 | 290 | size: 14px | |
| 291 | color: black | ||||
| 292 | line-height: 160% | ||||
| 293 | background-color: white | ||||
| 38c0188d » | Simon Rozet | 2008-03-27 | 294 | margin: 0 | |
| 295 | padding: 0 | ||||
| 296 | #content | ||||
| 297 | padding: 2em | ||||
| 1dfbc578 » | Simon Rozet | 2008-02-26 | 298 | a | |
| 38c0188d » | Simon Rozet | 2008-03-27 | 299 | padding: 2px | |
| 300 | color: blue | ||||
| bdd34406 » | Simon Rozet | 2008-03-28 | 301 | &.exists | |
| 302 | &:hover | ||||
| 303 | background-color: blue | ||||
| 304 | text-decoration: none | ||||
| 305 | color: white | ||||
| 306 | &.unknown | ||||
| 307 | color: gray | ||||
| 308 | &:hover | ||||
| 309 | background-color: gray | ||||
| 310 | color: white | ||||
| 311 | text-decoration: none | ||||
| f88d9eb3 » | Simon Rozet | 2008-08-26 | 312 | &.cancel | |
| 313 | color: red | ||||
| 314 | &:hover | ||||
| 315 | text-decoration: none | ||||
| 316 | background-color: red | ||||
| 317 | color: white | ||||
| 38c0188d » | Simon Rozet | 2008-03-27 | 318 | textarea | |
| 319 | font-family: courrier | ||||
| 320 | font-size: 14px | ||||
| 321 | line-height: 18px | ||||
| f88d9eb3 » | Simon Rozet | 2008-08-26 | 322 | padding: 5px | |
| 323 | button.submit | ||||
| 38c0188d » | Simon Rozet | 2008-03-27 | 324 | font-weight: bold | |
| bdd34406 » | Simon Rozet | 2008-03-28 | 325 | ul#pages_list | |
| 326 | list-style-type: none | ||||
| 327 | margin: 0 | ||||
| 328 | padding: 0 | ||||
| 329 | li | ||||
| 330 | padding: 5px | ||||
| 331 | &.odd | ||||
| 332 | background-color: #D3D3D3 | ||||

