leandocument 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.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in leandocument.gemspec
4
+ gemspec
5
+
6
+ gem 'sinatra', :require => 'sinatra/base'
7
+ gem 'rdiscount', :require => 'rdiscount'
8
+ gem 'grit'
9
+ gem 'sinatra-partial'
10
+
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+ Copyright © 2012 Lean Document
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the “Software”), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in
12
+ all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
@@ -0,0 +1,22 @@
1
+ # Ruby library for LeanDocument.
2
+
3
+ ## INSTALL
4
+
5
+ > gem install leandocument
6
+
7
+ Not support currentry.
8
+
9
+ ## Usage
10
+
11
+ > $ cd **LEANDOCUMENT_DIR**
12
+ > $ leandocument
13
+
14
+ Open http://localhost:4567/
15
+
16
+ ## LICENSE
17
+
18
+ MIT License
19
+
20
+ ## Developer
21
+
22
+ Atsushi Nakatsugawa
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "leandocument/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "leandocument"
7
+ s.version = Leandocument::VERSION
8
+ s.authors = ["Atsushi Nakatsugawa"]
9
+ s.email = ["atsushi@moongift.jp"]
10
+ s.homepage = "http://leandocument.com/"
11
+ s.summary = "Ruby library for LeanDocument."
12
+ s.description = "Ruby command and Web viewer for LeanDocument."
13
+
14
+ s.rubyforge_project = "leandocument"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_dependency 'sinatra'
23
+ s.add_dependency 'grit'
24
+ s.add_dependency 'rdiscount'
25
+ s.add_dependency 'sinatra-partial'
26
+ # s.add_development_dependency "rspec"
27
+ # s.add_runtime_dependency "rest-client"
28
+ end
@@ -0,0 +1,16 @@
1
+ libdir = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
3
+ require "sinatra/base"
4
+ require 'sinatra/partial'
5
+ require "leandocument/version"
6
+ require "leandocument/server"
7
+ require "leandocument/document"
8
+ require "leandocument/blob_image"
9
+ require "leandocument/repository"
10
+ require "leandocument/render"
11
+ require "leandocument/render/markdown"
12
+ require "rdiscount"
13
+ require "yaml"
14
+ require 'grit'
15
+ require 'digest/md5'
16
+ require 'erb'
@@ -0,0 +1,41 @@
1
+ module Leandocument
2
+ class BlobImage
3
+ attr_accessor :path, :base_path, :repository, :commit, :web_path
4
+ def initialize(options = {})
5
+ self.path = options[:path]
6
+ self.base_path = options[:base_path] || Dir.pwd
7
+ self.web_path = "#{options[:web_path]}/"
8
+ self.repository = options[:repository]
9
+ self.commit = options[:commit]
10
+ end
11
+
12
+ def find_file(tree = nil, path = nil)
13
+ path = path || self.path
14
+ paths = path.split("/")
15
+ file_name = paths.last
16
+ paths = paths[0..-2]
17
+ (tree || self.commit.tree).contents.each do |content|
18
+ if paths.size > 0
19
+ return find_file(content, (paths[1..-1].push(file_name)).join("/")) if content.name == paths[0]
20
+ else
21
+ return content if content.name == file_name
22
+ end
23
+ end
24
+ end
25
+
26
+ def image
27
+ if self.commit
28
+ return find_file ? find_file.data : nil
29
+ end
30
+ f?? open(file_path).read : nil
31
+ end
32
+
33
+ def f?
34
+ File.exist?(file_path)
35
+ end
36
+
37
+ def file_path
38
+ "#{self.base_path}/#{self.path}"
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,168 @@
1
+ # -*- coding: utf-8 -*-
2
+ # LeanDocument::Document class is converter to text from file content for LeanDocument
3
+ #
4
+ # Usage:
5
+ # @doc = Document.new(:lang => "ja")
6
+ # puts @doc.to_html
7
+ module Leandocument
8
+ class Document
9
+ SETTING_FILE_NAME = "settings.yml"
10
+ SUPPORT_EXTENSIONS = %w(md textile markdown mdown rdoc org creole mediawiki)
11
+
12
+ # lang :: Document language. TODO support default language.
13
+ # settings :: LeanDocument Settings. TODO read settings.
14
+ # base_path :: Document path.
15
+ # indent :: Document indent. Child documents are plus on from parent. Then change to h[2-7] tag from h[1-6] tag. <h1> -> <h2>
16
+ attr_accessor :lang, :settings, :base_path, :indent, :extension, :web_path, :childs, :repository, :commit
17
+
18
+ # Generate Document class.
19
+ # ==== Args
20
+ # options :: lang:Default document language. base_path: Document path. indent: Document indent level.
21
+ # ==== Return
22
+ # New Leandocument Document class.
23
+ def initialize(options = {})
24
+ self.lang = options[:lang] || settings["default_locale"]
25
+ self.base_path = options[:base_path] || Dir.pwd
26
+ self.web_path = "#{options[:web_path]}/"
27
+ self.indent = options[:indent] || 1
28
+ self.settings = options[:settings] || load_config
29
+ self.extension = get_extension
30
+ self.childs = []
31
+ self.repository = options[:repository]
32
+ self.commit = options[:commit]
33
+ end
34
+
35
+ # Generate HTML content.
36
+ # ==== Return
37
+ # HTML content.
38
+ def to_html
39
+ page = render.to_html
40
+ path = File.dirname(file_path)
41
+ # Get child content.
42
+ # A reflexive.
43
+ dirs(path).each do |dir|
44
+ # Plus one indent from parent. Change h[1-6] tag to h[2-7] if indent is 1.
45
+ doc = Document.new :base_path => dir, :lang => self.lang, :indent => self.indent + 1, :settings => self.settings, :web_path => dir.gsub(self.base_path, ""), :commit => self.commit, :repository => self.repository
46
+ self.childs << doc
47
+ page += doc.to_html
48
+ end
49
+ page
50
+ end
51
+
52
+ def title
53
+ render.title
54
+ end
55
+
56
+ def toc
57
+ return @toc if @toc
58
+ @toc = render.toc
59
+ self.childs.each do |doc|
60
+ @toc += doc.toc
61
+ end
62
+ @toc
63
+ end
64
+
65
+ def toc=(toc)
66
+ @toc += toc
67
+ end
68
+
69
+ protected
70
+
71
+ def get_extension
72
+ SUPPORT_EXTENSIONS.each do |ext|
73
+ return ext if File.exist?(file_path(ext))
74
+ end
75
+ return nil
76
+ end
77
+
78
+ def load_config
79
+ path = "#{self.base_path}/#{SETTING_FILE_NAME}"
80
+ File.exist?(path) ? YAML.load_file(path) : {}
81
+ end
82
+
83
+ def file_name(ext = nil)
84
+ "README.#{self.lang}.#{ext ? ext : self.extension}"
85
+ end
86
+
87
+ # Return file path
88
+ # ==== Return
89
+ # Document file path
90
+ def file_path(ext = nil)
91
+ "#{self.base_path}/#{file_name(ext)}"
92
+ end
93
+
94
+ def find_content(tree = nil, path = nil)
95
+ path = path || self.web_path.gsub(/^\//, "")
96
+ paths = path.split("/")
97
+ (tree || self.commit.tree).contents.each do |content|
98
+ if paths.size > 0
99
+ return find_content(content, paths[1..-1].join("/")) if content.name == paths[0]
100
+ else
101
+ return content if content.name == file_name
102
+ end
103
+ end
104
+ end
105
+
106
+ # Return file content or blank string
107
+ # ==== Return
108
+ # File content. Or blank string if file not found.
109
+ def content
110
+ return @content if @content
111
+ if self.commit
112
+ @content = find_content ? find_content.data.force_encoding('UTF-8') : ""
113
+ else
114
+ @content = File.exist?(self.file_path) ? open(self.file_path).read.force_encoding('UTF-8') : ""
115
+ end
116
+ @content
117
+ end
118
+
119
+ def render
120
+ send("render_#{self.extension}")
121
+ end
122
+
123
+ # Return Markdown object from content.
124
+ # ==== Return
125
+ # Markdown object
126
+ def render_markdown
127
+ return @render if @render
128
+ @render = Markdown.new(:content => content, :indent => self.indent, :path => self.commit ? "/commits/#{self.commit.id}#{self.web_path}" : self.web_path)
129
+ @render
130
+ end
131
+ alias :render_md :render_markdown
132
+
133
+ def setting_value(*ary)
134
+ return nil unless self.settings
135
+ results = self.settings
136
+ ary.each do |key|
137
+ return nil unless results[key]
138
+ results = results[key]
139
+ end
140
+ results
141
+ end
142
+
143
+ # Judgment directry or not.
144
+ # ==== Args
145
+ # f :: File name, "." or ".."
146
+ # path :: Directory path.
147
+ # ==== Return
148
+ # directory path or nil.
149
+ def d(f, path)
150
+ return nil if f =~ /^\./
151
+ expand_path = File.expand_path(f, path)
152
+ File::ftype(expand_path) == "directory" ? expand_path : nil
153
+ end
154
+
155
+ # Return child directories from target directory
156
+ # ==== Args
157
+ # path :: Target directory
158
+ # ==== Return
159
+ # Array. Only child directories.
160
+ def dirs(path)
161
+ ary = Dir.entries(path).collect do |f|
162
+ d(f, path)
163
+ end
164
+ ary.delete(nil)
165
+ ary
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,22 @@
1
+ module Leandocument
2
+ class Render
3
+ attr_accessor :content, :indent, :path, :p_toc
4
+ def initialize(options = {})
5
+ self.content = options[:content]
6
+ self.indent = options[:indent]
7
+ self.path = options[:path]
8
+ end
9
+
10
+ def analyse_content
11
+ content = content_ary[1..-1].join("\n")
12
+ end
13
+
14
+ def content_ary
15
+ content.split(/\r\n|\r|\n/)
16
+ end
17
+
18
+ def title
19
+ content_ary[0]
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,28 @@
1
+ module Leandocument
2
+ class Markdown < Render
3
+ def to_html
4
+ RDiscount.new(exec_trans).to_html
5
+ end
6
+
7
+ # Convert to something from content.
8
+ # Currently, Change indent level.
9
+ # TODO support plugin and expand format.
10
+ # ==== Return
11
+ # Text content.
12
+ def exec_trans
13
+ content = indented_content
14
+ content = content.gsub(/^!\[(.*)\]\((.*)\)/, '![\\1]('+self.path+'\\2)') # For image
15
+ end
16
+
17
+ def indented_content
18
+ content = analyse_content
19
+ self.indent.times do |i|
20
+ content = content.to_s.gsub(/^#/, "##")
21
+ end
22
+ unless self.indent == 1
23
+ content = "#{"#"*self.indent}#{title}\n#{content}"
24
+ end
25
+ content
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,18 @@
1
+ module Leandocument
2
+ class Repository
3
+ attr_accessor :base_path, :repo
4
+
5
+ def initialize(options = {})
6
+ self.base_path = options[:base_path] || Dir.pwd
7
+ self.repo = Grit::Repo.new(self.base_path)
8
+ end
9
+
10
+ def commits(id = nil)
11
+ id.nil?? self.repo.commits : self.repo.commits(id)
12
+ end
13
+
14
+ def branches(id = nil)
15
+ id.nil?? self.repo.branches : self.repo.branches(id).first
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,73 @@
1
+ module Leandocument
2
+ # Your code goes here...
3
+ class Server < Sinatra::Base
4
+ register Sinatra::Partial
5
+ set :sessions, true
6
+ set :root, Dir.pwd
7
+ set :partial_template_engine, :erb
8
+ enable :partial_underscores
9
+ set :public_folder, File.dirname(File.dirname(File.dirname(__FILE__))) + '/public'
10
+ set :views, File.dirname(File.dirname(File.dirname(__FILE__))) + '/views'
11
+ def self.start
12
+ self.run!
13
+ end
14
+
15
+ get '/' do
16
+ @doc = Document.new(:lang => @env["HTTP_ACCEPT_LANGUAGE"][0,2])
17
+ erb :index
18
+ end
19
+
20
+ get '/commits' do
21
+ @repo = Repository.new
22
+ @commits = @repo.commits
23
+ erb :commits
24
+ end
25
+
26
+ get '/branches' do
27
+ @repo = Repository.new
28
+ erb :branches
29
+ end
30
+
31
+ get '/branches/:id' do
32
+ @repo = Repository.new
33
+ @commit = @repo.commits(params[:id]).first
34
+ @doc = Document.new(:lang => @env["HTTP_ACCEPT_LANGUAGE"][0,2], :repository => @repo, :commit => @commit)
35
+ erb :index
36
+ end
37
+
38
+ get '/branches/:id/commits' do
39
+ @repo = Repository.new
40
+ puts "params[:id] -> #{params[:id]}"
41
+ @commits = @repo.commits(params[:id])
42
+ puts "@commits -> #{@commits}"
43
+ erb :commits
44
+ end
45
+
46
+ get '/commits/:id' do
47
+ @repo = Repository.new
48
+ @commit = @repo.commits(params[:id]).first
49
+ @doc = Document.new(:lang => @env["HTTP_ACCEPT_LANGUAGE"][0,2], :repository => @repo, :commit => @commit)
50
+ erb :index
51
+ end
52
+
53
+ %w(png jpg gif jpeg).each do |ext|
54
+ get "/commits/:id/*.#{ext}" do
55
+ @repo = Repository.new
56
+ @commit = @repo.commits(params[:id]).first
57
+ path = "#{params[:splat].join("/")}.#{ext}"
58
+ @blob = BlobImage.new(:path => path, :commit => @commit, :repository => @repo)
59
+ if @blob.f?
60
+ content_type ext
61
+ @blob.image
62
+ end
63
+ end
64
+ get "/*.#{ext}" do
65
+ path = "#{params[:splat].join("/")}.#{ext}"
66
+ @blob = BlobImage.new(:path => path)
67
+ if @blob.f?
68
+ send_file @blob.file_path, :type => ext
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end