docwu 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,24 +1,36 @@
1
1
  # doc wu
2
2
 
3
- This project rocks and uses MIT-LICENSE.
3
+ This project rocks and uses MIT-LICENSE. Docwu mains Documents Work Up!
4
4
 
5
5
  ## A markdown doc generations
6
6
 
7
7
  ## 结构
8
8
 
9
9
  ```
10
- workspace
10
+ - workspace
11
11
 
12
- - assets:
13
- + javascripts:
14
- + stylesheets:
15
- + images:
16
- - sources:
17
- - layouts:
18
- - default.mustache
19
- - pages:
20
- - index.mustache
21
- - posts:
22
- -
12
+ assets/
13
+ files/
14
+ images/
15
+ javascripts/
16
+ application.js
17
+ document_folder.js
18
+ document_post.js
19
+ stylesheets/
20
+ application.css
21
+ document_folder.css
22
+ document_post.css
23
+ ▸ doc/
24
+ ▾ layouts/
25
+ ▸ partials/
26
+ folder.mustache
27
+ post.mustache
28
+ ▾ pages/
29
+ index.markdown
30
+ .gitignore
31
+ config.yml
32
+ Gemfile
33
+ Gemfile.lock
34
+ worker*
23
35
 
24
36
  ```
data/bin/docwu ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'docwu'
4
+
5
+ Docwu.start('.')
data/lib/docwu/config.rb CHANGED
@@ -12,34 +12,47 @@ module Docwu
12
12
  end
13
13
  end
14
14
 
15
- #
16
- # src_paths
17
- # asset_paths
18
- # layout_paths
19
- # output_path
20
- #
21
15
  class Config
22
- attr_reader :src_paths, :asset_paths, :layout_paths, :output_path, :data
16
+ # attr_reader :src_paths, :asset_paths, :layout_paths, :output_path, :data
23
17
 
24
- def data= a
25
- @data ||= a
18
+ attr_reader :routes, :params, :worker, :workspace, :docwu_env, :logger
19
+
20
+ def logger= a
21
+ @logger ||= (a || ::Logger.new(STDOUT))
22
+ end
23
+
24
+ def routes= a
25
+ @routes ||= a
26
+ end
27
+
28
+ def params= a={}
29
+ @params ||= a
26
30
  end
27
31
 
28
- def src_paths= a
29
- @src_paths ||= a
32
+ def worker= a
33
+ @worker ||= a
30
34
  end
31
35
 
32
- def asset_paths= a
33
- @asset_paths ||= a
36
+ def workspace= a
37
+ @workspace ||= a
34
38
  end
35
39
 
36
- def layout_paths= a
37
- @layout_paths ||= a
40
+ def docwu_env= a
41
+ @docwu_env ||= 'development'
38
42
  end
39
43
 
40
- def output_path= a
41
- @output_path ||= a
44
+ def topics_path
45
+ @topics_path ||= ("#{self.workspace}/topics")
42
46
  end
47
+
48
+ def layouts_path
49
+ @layouts_path ||= ("#{self.workspace}/layouts")
50
+ end
51
+
52
+ def deploy_path
53
+ @deploy_path ||= ("#{self.workspace}/_deploy")
54
+ end
55
+
43
56
  end
44
57
  end
45
58
 
data/lib/docwu/folder.rb CHANGED
@@ -1,42 +1,111 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Docwu
2
3
  class Folder
3
4
  # 一个文件夹下面可能会有很多文件或文件夹的
4
- attr_reader :posts, :folders, :parent, :path, :worker, :dir
5
+ attr_reader :posts, :folders, :parent, :worker, :name,
6
+ :dest, :path, :src, :url, :index_post, :index_dest,
7
+ :parents, :content_data
5
8
 
6
9
  def initialize attrs={}
7
- @path = attrs[:path]
8
10
  @worker = attrs[:worker]
9
11
  @parent = attrs[:parent]
10
- @house = attrs[:house]
11
12
 
12
- @dir = attrs[:dir]
13
+ @parents = if @parent.nil?
14
+ []
15
+ else
16
+ @parent.parents.dup << @parent
17
+ end
18
+
19
+ @src = attrs[:src]
20
+ @path = attrs[:path]
21
+ @url = "/#{@path}/index.html"
22
+
23
+ @name = ::Docwu::Utils.filename(@path)
24
+
25
+ @dest = "#{self.worker.deploy_path}/#{self.path}"
26
+ @index_dest = "#{self.dest}/index.html"
27
+ # -------------------------------------
13
28
 
14
29
  @posts = []
15
30
  @folders = []
16
31
 
17
- ::Dir.glob("#{self.path}/*").each do |_path|
18
- _dir = _path.sub(self.path, '')
32
+ ::Dir.glob("#{self.src}/*").each do |_src|
33
+ _name = "#{_src.sub("#{self.src}/", '')}"
34
+
35
+ if File.exists?(_src)
36
+ if File.file?(_src) # 如果一个文件
37
+ _post = ::Docwu::Post.new(:src => _src, :parent => self, :worker => self.worker, :path => "#{self.path}/#{_name}")
19
38
 
20
- if File.exists?(_path)
21
- if File.file?(_path) # 如果一个文件
22
- @posts << ::Docwu::Post.new(:path => _path, :parent => self, :worker => self.worker, :dir => _dir)
23
- elsif File.directory?(_path) # 如果是一个文件夹
24
- @folders << self.class.new(:path => _path, :parent => self, :worker => self.worker, :dir => _dir)
39
+ if _post.index?
40
+ @index_post = _post
41
+ else
42
+ @posts << _post
43
+ end
44
+ elsif File.directory?(_src) # 如果是一个文件夹
45
+ @folders << self.class.new(:src => _src, :parent => self, :worker => self.worker, :path => "#{self.path}/#{_name}")
25
46
  end
26
47
  end
27
48
  end
49
+
50
+ self.posts.sort! { |a, b| b.ranking <=> a.ranking }
51
+ self.posts.sort! { |a, b| b.datetime <=> a.datetime }
52
+
53
+ # TODO: 是否从index文件中读取data呢?
54
+ end
55
+
56
+ def parent_datas
57
+ self.parents.map(&:to_data)
58
+ end
59
+
60
+ # 转为数据
61
+ def to_data
62
+ {
63
+ 'name' => self.name,
64
+ 'url' => self.url,
65
+ 'title' => self.name,
66
+ 'folders' => self.folders.map(&:to_data),
67
+ 'posts' => self.posts.map(&:to_data)
68
+ }
69
+ end
70
+
71
+ def index_page_data
72
+ if self.has_index?
73
+ self.index_post.page_data
74
+ else
75
+ {}
76
+ end
28
77
  end
29
78
 
30
- def generate space=nil
79
+ def generate
80
+ _prepare_data
81
+
82
+ # TODO: index : 需要生成首页!
83
+ _template = if self.has_index?
84
+ self.worker.layouts[self.index_post.layout]
85
+ end
86
+
87
+ _template ||= self.worker.layouts['folder']
88
+
89
+ ::Docwu::Render.generate(
90
+ :content_data => self.content_data,
91
+ :dest => self.index_dest,
92
+ :template => _template
93
+ )
94
+
31
95
  self.folders.each do |folder|
32
- folder.generate space
96
+ folder.generate
33
97
  end
34
98
 
35
99
  self.posts.each do |post|
36
- post.generate space
100
+ post.generate
37
101
  end
38
102
  end
39
103
 
104
+ # 有首页文件了
105
+ def has_index?
106
+ !!(self.index_post)
107
+ end
108
+
40
109
  def folder?
41
110
  true
42
111
  end
@@ -47,5 +116,20 @@ module Docwu
47
116
 
48
117
  private
49
118
 
119
+ def _prepare_data
120
+ @content_data = ::Docwu::Utils.hash_deep_merge(self.worker.data, {
121
+ 'reader' => {
122
+ 'folder' => self.to_data,
123
+ 'folders' => self.parent_datas
124
+ }
125
+ })
126
+
127
+ # puts ""
128
+ # puts ""
129
+ # puts ""
130
+ # puts ""
131
+ # pp @content_data
132
+ end
133
+
50
134
  end
51
135
  end
data/lib/docwu/post.rb CHANGED
@@ -1,61 +1,132 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Docwu
2
3
  class Post
3
4
  # 一个文件夹下面可能会有很多文件或文件夹的
4
- attr_reader :parent, :path, :worker, :house, :dir, :content_data
5
+ attr_reader :parent,
6
+ :worker, # worker对象
7
+ :content_data,
8
+ :dest, # 目标地址
9
+ :path, # 访问地址
10
+ :src, # 原文件地址
11
+ :url, # URL 地址
12
+ :content_type,
13
+ :name,
14
+ :file_name, # 文件名
15
+ :datetime,
16
+ :ranking
17
+
18
+ def parents
19
+ if self.parent.nil?
20
+ []
21
+ else
22
+ self.parent.parents.dup << self.parent
23
+ end
24
+ end
25
+
26
+ def parent_datas
27
+ self.parents.map(&:to_data)
28
+ end
5
29
 
6
30
  def initialize attrs={}
7
- @path = attrs[:path]
8
- @house = attrs[:house]
9
31
  @parent = attrs[:parent]
32
+
10
33
  @worker = attrs[:worker]
11
34
 
12
- @dir = attrs[:dir]
35
+ @src = attrs[:src]
13
36
 
14
37
  _parse_content = self.parse_content
15
38
 
16
- @content_data = {}
39
+ # 将合并来自worker的数据
40
+ @content_data = ::Docwu::Utils.hash_deep_merge(self.worker.data, 'page' => _parse_content[:data]) # 来自页面的数据
41
+
42
+ @content_type = @content_data['content_type'] || 'html'
43
+
44
+ _extend_name = case self.content_type
45
+ when 'html'
46
+ 'html'
47
+ else
48
+ 'html'
49
+ end
50
+
51
+ # URL ---------------------------------
52
+ _filename_extless = ::Docwu::Utils.filename_extless(attrs[:path])
53
+
54
+ @path = "#{_filename_extless}.#{_extend_name}"
55
+ @url = "/#{@path}"
56
+ @dest = "#{self.worker.deploy_path}/#{self.path}"
57
+
58
+ @file_name = ::Docwu::Utils.filename(_filename_extless)
17
59
 
18
- self.content_data.merge!(_parse_content[:data])
60
+ @name = self.file_name
61
+ @datetime = self.page_data['datetime'] # 创建时间
62
+ @ranking = self.page_data['ranking'].to_i # 创建时间
63
+
64
+ # puts "post to: -----------------> desc: #{self.dest}"
65
+ # puts " src: #{self.src}"
66
+ # puts " path: #{self.path}"
67
+ # puts " url: #{self.url}"
68
+ # -------------------------------------
69
+ end
70
+
71
+ def template
72
+ self.worker.layouts[self.layout] || self.worker.layouts['post'] || self.worker.layouts['application']
73
+ end
74
+
75
+ # 是否是首页?
76
+ def index?
77
+ self.file_name == 'index'
19
78
  end
20
79
 
21
80
  def layout
22
- self.worker.layouts[self.content_data['layout']] || self.worker.layouts['default.mustache']
81
+ self.page_data['layout']
82
+ end
83
+
84
+ def outline
85
+ @outline ||= self.page_data['outline'].to_s
86
+ end
87
+
88
+ def to_data
89
+ introduction_size = 32
90
+
91
+ introduction = "#{self.outline[0, introduction_size]}#{' ...' if self.outline.size > introduction_size}"
92
+
93
+ {
94
+ 'name' => self.name,
95
+ 'url' => self.url,
96
+ 'title' => self.title,
97
+ 'outline' => self.outline,
98
+ 'introduction' => introduction
99
+ }
100
+ end
101
+
102
+ # 页面数据
103
+ def page_data
104
+ self.content_data['page'] ||= {}
105
+ end
106
+
107
+ def title
108
+ self.page_data['title'] || self.url
23
109
  end
24
110
 
25
111
  # 渲染
26
- def generate space=nil
112
+ def generate
113
+ _prepare_data
114
+
27
115
  _parse_content = self.parse_content
28
116
 
29
117
  _content_text = _parse_content[:text]
30
118
 
31
- _template = ::Docwu::Utils.read_file(self.layout)
32
-
33
119
  _path = self.path
34
- _dest = self.dest(space)
35
-
36
- puts " -> generate post: form #{_path} to #{_dest}"
37
- puts " layout: #{self.layout}"
120
+ _dest = self.dest
38
121
 
39
122
  ::Docwu::Render.generate(
40
123
  :content_text => _content_text,
41
124
  :content_data => self.content_data,
42
125
  :dest => _dest,
43
- :template => _template
126
+ :template => self.template
44
127
  )
45
128
  end
46
129
 
47
- def dest space
48
- _dest = "#{self.worker.output_path}"
49
-
50
- if space
51
- _dest << "/#{space}"
52
- end
53
-
54
- _dest << self.dir
55
-
56
- _dest
57
- end
58
-
59
130
  def folder?
60
131
  false
61
132
  end
@@ -63,23 +134,34 @@ module Docwu
63
134
  def post?
64
135
  true
65
136
  end
66
-
137
+
67
138
  # 解析正文
68
139
  def parse_content
69
- _content = ::File.read(self.path)
140
+ _content = ::File.read(self.src)
141
+
142
+ ::Docwu::Utils.parse_marked_content(_content)
143
+ end
144
+
145
+ def has_folder?
146
+ self.parent.is_a?(::Docwu::Folder)
147
+ end
148
+
149
+ private
70
150
 
71
- _content_text = ''
72
- _content_data = {}
151
+ def _prepare_data
152
+ self.content_data['reader'] ||= {}
73
153
 
74
- _parse_content = _content.to_s.split(/---+\n/)
154
+ _data = {
155
+ 'folders' => self.parent_datas,
156
+ 'post' => self.to_data
157
+ }
75
158
 
76
- if _parse_content.size > 2 && _parse_content.first.to_s == ''
77
- _content_text << _parse_content[2]
78
- # 从上下文中读取配置
79
- _content_data.merge!(::YAML.load(_parse_content[1]))
159
+ if self.has_folder?
160
+ (_data['folder'] ||= {}).merge!(self.parent.to_data)
80
161
  end
81
162
 
82
- {:data => _content_data, :text => _content_text}
163
+ # 合并, datas
164
+ self.content_data['reader'].merge!(_data)
83
165
  end
84
166
  end
85
167
  end
data/lib/docwu/render.rb CHANGED
@@ -1,3 +1,8 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'redcarpet'
3
+ require 'coderay'
4
+ require "nokogiri"
5
+
1
6
  module Docwu
2
7
  class Render
3
8
  class << self
@@ -6,30 +11,62 @@ module Docwu
6
11
  end
7
12
  end
8
13
 
14
+ #
15
+ # usage:
16
+ # ::Docwu::Render.generate(
17
+ # :content_data => ''
18
+ # )
19
+ # options:
20
+ # - content_data
21
+ # - content_text
22
+ # - dest
23
+ # - template
24
+ #
9
25
  def generate(options={})
10
26
  content_data = options[:content_data] || {}
11
27
  content_text = options[:content_text] || ''
12
28
  content_result = ''
13
29
  dest = options[:dest]
30
+ template = options[:template]
14
31
 
15
32
  # 读取标记类型
16
33
  marktype = (content_data['marktype'] || 'markdown').to_s
17
- content_type = (content_data['content_type'] || 'html').to_s
34
+
35
+ # 目录
36
+ _catalogs = []
18
37
 
19
38
  case marktype
20
39
  when 'markdown'
21
40
  _mark_options = [:hard_wrap, :autolink, :no_intraemphasis, :fenced_code, :gh_blockcode]
22
41
 
23
- content_result << ::RedcarpetCompat.new(content_text, *_mark_options).to_html
42
+ _html = ::RedcarpetCompat.new(content_text, *_mark_options).to_html
43
+
44
+ # 获取一个html代码的目录结果
45
+ _catalogs_result = ::Docwu::Utils.html_catalogable(_html)
46
+
47
+ _catalogs = _catalogs_result['catalogs']
48
+
49
+ content_result << ::Docwu::Utils.syntax_highlighter(_catalogs_result['html'])
24
50
  else
25
51
  # FIXME: no
26
52
  end
27
53
 
28
- content_data['content'] = content_result
54
+ content_data['page'] ||= {}
55
+
56
+ # 正文
57
+ content_data['page']['content'] = content_result
58
+ content_data['page']['content_present?'] = content_result.size > 0
59
+
60
+ # 目录
61
+ content_data['page']['catalogs'] = _catalogs
62
+
63
+ ::Docwu::Utils.formated_hashed!(content_data)
64
+
65
+ # pp content_data
66
+ # puts "#{template}"
29
67
 
30
- puts " --------------------> write to: #{dest}, #{content_result}"
31
68
  # 页面的内容
32
- # ::Docwu::Utils.write_file dest, ::MustacheRender::Mustache.render(template, data.merge('page' => context_data))
69
+ ::Docwu::Utils.write_file dest, ::MustacheRender::Mustache.render(template, content_data)
33
70
  end
34
71
 
35
72
  end
@@ -0,0 +1,6 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Docwu
3
+ class Route
4
+ end
5
+ end
6
+
data/lib/docwu/server.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  # http://tobyho.com/2009/09/16/http-server-in-5-lines-with/
2
3
  # https://github.com/rack/rack/blob/master/lib/rack/handler/thin.rb
3
4
  # https://github.com/macournoyer/thin/blob/master/lib/thin/server.rb
@@ -10,21 +11,24 @@ module Docwu
10
11
  #
11
12
  # Rack::Handler::Thin.run(staticMe, :port => 8080
12
13
 
14
+ require 'thin'
13
15
  require 'rack'
14
16
 
15
- def self.process(options={})
16
- options['destination'] ||= ::Docwu.config.output_path
17
+ def self.process(options={}, &block)
18
+ options['destination'] ||= ::Docwu.config.deploy_path
17
19
  destination = options['destination']
18
20
  FileUtils.mkdir_p(destination)
19
21
 
20
- options['port'] ||= 5656
21
- options['host'] ||= '0.0.0.0'
22
-
23
22
  staticMe = Rack::Builder.new do
24
23
  run Rack::Directory.new(destination)
25
24
  end
26
25
 
27
- Rack::Handler::Thin.run(staticMe, :Port => options['port'], :Host => options['host'])
26
+ pp options
27
+
28
+ ::Thin::Server.start(options.delete(:Host), options.delete(:Port), staticMe, options, &block)
29
+
30
+ # Rack::Handler::Thin.run(staticMe, options)
31
+
28
32
  # Rack::Handler::WEBrick.run(staticMe, :Port => options['port'], :Host => options['host'])
29
33
  # Rack::Handler::Mongrel.run(staticMe, :Port => options['port'], :Host => options['host'])
30
34
  end
@@ -0,0 +1,93 @@
1
+ module Docwu
2
+ class Topic
3
+ attr_reader :worker, :dest, :path, :src, :url, :content_data, :file_name, :name, :title
4
+
5
+ def initialize attrs={}
6
+ @worker = attrs[:worker]
7
+
8
+ @path = attrs[:path]
9
+ @src = attrs[:src]
10
+
11
+ _parse_content = self.parse_content
12
+
13
+ # 将合并来自worker的数据
14
+ @content_data = ::Docwu::Utils.hash_deep_merge(self.worker.data, 'page' => _parse_content[:data]) # 来自页面的数据
15
+
16
+ # URL ---------------------------------
17
+ _filename_extless = ::Docwu::Utils.filename_extless(self.path)
18
+
19
+ @url = "/#{@path}"
20
+ @dest = "#{self.worker.deploy_path}/#{self.path}"
21
+
22
+ @file_name = ::Docwu::Utils.filename(_filename_extless)
23
+
24
+ @name = self.content_data['page']['name'] || self.file_name
25
+
26
+ # -------------------------------------
27
+ end
28
+
29
+ # 页面数据
30
+ def page_data
31
+ self.content_data['page'] ||= {}
32
+ end
33
+
34
+ def title
35
+ self.page_data['title'] || self.url
36
+ end
37
+
38
+ def url
39
+ self.path
40
+ end
41
+
42
+ def to_data
43
+ {
44
+ 'name' => self.name,
45
+ 'url' => self.url,
46
+ 'title' => self.title
47
+ }
48
+ end
49
+
50
+ def generate
51
+ _prepare_data
52
+
53
+ _parse_content = self.parse_content
54
+
55
+ _content_text = _parse_content[:text]
56
+
57
+ ::Docwu::Render.generate(
58
+ :content_text => _content_text,
59
+ :content_data => self.content_data,
60
+ :dest => self.dest,
61
+ :template => self.template
62
+ )
63
+ end
64
+
65
+ def layout
66
+ self.page_data['layout']
67
+ end
68
+
69
+ def template
70
+ self.worker.layouts[self.layout] || self.worker.layouts['topic'] || self.worker.layouts['application']
71
+ end
72
+
73
+ # 解析正文
74
+ def parse_content
75
+ _content = ::File.read(self.src)
76
+
77
+ ::Docwu::Utils.parse_marked_content(_content)
78
+ end
79
+
80
+ private
81
+
82
+ def _prepare_data
83
+ self.content_data['reader'] ||= {}
84
+
85
+ _data = {
86
+ 'topic' => self.to_data
87
+ }
88
+
89
+ # 合并, datas
90
+ self.content_data['reader'].merge!(_data)
91
+ end
92
+ end
93
+ end
data/lib/docwu/utils.rb CHANGED
@@ -1,12 +1,64 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Docwu
2
3
  class Utils
3
4
  class << self
5
+ def hash_deep_merge(hash, other_hash)
6
+ hash.merge(other_hash) do |key, oldval, newval|
7
+ oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
8
+ newval = newval.to_hash if newval.respond_to?(:to_hash)
9
+ oldval.class.to_s == 'Hash' && newval.class.to_s == 'Hash' ? self.hash_deep_merge(oldval, newval) : newval
10
+ end
11
+ end
12
+
13
+ def hash_deep_merge!(hash, other_hash)
14
+ hash.replace(self.hash_deep_merge(hash, other_hash))
15
+ end
16
+
17
+ def formated_hashed! hash={}
18
+ hash.replace(self.formated_hashed(hash))
19
+ end
20
+
21
+ # 将hash中所有非hash的类型,转为hash, 以便前端调用
22
+ def formated_hashed hash={}
23
+ _res = {}
24
+
25
+ hash.each do |key, value|
26
+ if value.is_a?(Array)
27
+ _res[key] = value.map do |_val|
28
+ if _val.is_a?(Hash)
29
+ self.formated_hashed(_val)
30
+ else
31
+ {'value' => _val}
32
+ end
33
+ end
34
+
35
+ _res["#{key}_any?"] = value.any?
36
+ _res["#{key}_count"] = value.size
37
+
38
+ elsif value.is_a?(Hash)
39
+ _res[key] = self.formated_hashed(value)
40
+ else
41
+ _res[key] = value
42
+ end
43
+ end
44
+
45
+ _res
46
+ end
47
+
48
+ # 获取文件名
49
+ def filename path=''
50
+ path.split('/').last
51
+ end
52
+
53
+ def filename_extless _path=''
54
+ _path.chomp(File.extname(_path))
55
+ end
4
56
 
5
57
  def read_file path
6
58
  ::File.read(path)
7
59
  end
8
60
 
9
- def write_file path, content=''
61
+ def write_file dst, content=''
10
62
  ::FileUtils.mkdir_p(::File.dirname(dst))
11
63
 
12
64
  file = ::File.new(dst, 'w')
@@ -20,7 +72,117 @@ module Docwu
20
72
  ::FileUtils.cp_r(src, dst)
21
73
  end
22
74
 
75
+ def syntax_highlighter(html)
76
+ doc = ::Nokogiri::HTML(html)
77
+
78
+ doc.search("//pre").each do |pre|
79
+ lang = pre.attr('lang')
80
+
81
+ if lang
82
+ _lang_class = pre.attr('class').to_s.split(' ').select {|_itm| _itm.include?('lang-') }.first
83
+
84
+ if _lang_class
85
+ lang = _lang_class.gsub('lang-', '')
86
+ end
87
+ end
88
+
89
+ # debugger
90
+ if pre_code=pre.css('code')
91
+ lang = pre_code.attr('class').to_s
92
+ end
93
+
94
+ unless lang
95
+ lang = :text
96
+ end
97
+
98
+ text = pre.text.rstrip
99
+
100
+ begin
101
+ pre.replace ::CodeRay.scan(text, lang).div.to_s
102
+ rescue Exception => error
103
+ # TODO: error log
104
+ # puts "#{__FILE__} syntax_highlighter error: \ntext => #{text} \nlang => #{lang}\n origin error:#{error}"
105
+ end
106
+ end
107
+
108
+ doc.css('body').inner_html.to_s
109
+ end
110
+
111
+ # 解析 mark
112
+ def parse_marked_content src_content=''
113
+ _content_text = ''
114
+ _content_data = {}
115
+
116
+ # 读取页面的配置
117
+ content_lines = src_content.split(/\n/) # 根据换行分割
118
+
119
+ _data_lines = []
120
+ _text_lines = []
121
+
122
+ _data_num_a = -1
123
+ _data_num_b = -1
124
+
125
+ content_lines.each_with_index do |line, index|
126
+ if line =~ /--+/
127
+ if _data_num_a == -1
128
+ _data_num_a = index
129
+ elsif _data_num_b == -1
130
+ _data_num_b = index
131
+ else
132
+ break
133
+ end
134
+ end
135
+ end
136
+
137
+ if _data_num_a > -1 && _data_num_b > -1
138
+ # 说明有配置信息
139
+ _yaml = ::YAML.load(content_lines[_data_num_a + 1, _data_num_b -1].join("\n"))
140
+
141
+ if _yaml.is_a?(Hash)
142
+ _content_data.merge!(_yaml)
143
+ end
144
+
145
+ _content_text = content_lines[_data_num_b + 1, content_lines.size].join("\n")
146
+ else # 无页面配置信息
147
+ _content_text = src_content
148
+ end
149
+
150
+ {:data => _content_data, :text => _content_text}
151
+
152
+ end
153
+
154
+ # 获取一个html代码的目录结果
155
+ def html_catalogable html=''
156
+ doc = ::Nokogiri::HTML(html)
157
+
158
+ paths = doc.xpath('//h1|//h2|//h3|//h4|//h5|//h6')
159
+
160
+ index = 1
161
+
162
+ catalogs = paths.map do |path|
163
+ _name = path.name
164
+ _text = path.text
165
+
166
+ _anchor = "markup-#{_name}-#{index}"
167
+
168
+ index += 1
169
+
170
+ path.replace("<#{_name}><a name='#{_anchor}'></a>#{_text}</#{_name}>")
171
+
172
+ {
173
+ 'text' => _text,
174
+ 'name' => _name,
175
+ 'anchor' => _anchor
176
+ }
177
+ end
178
+
179
+ {
180
+ 'catalogs' => catalogs,
181
+ 'html' => doc.css('body').inner_html.to_s
182
+ }
183
+ end
23
184
  end
185
+
24
186
  end
25
187
  end
26
188
 
data/lib/docwu/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module Docwu
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.3"
4
4
  end
data/lib/docwu/worker.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
+ require 'date'
2
3
  module Docwu
3
4
  class Worker
4
5
 
@@ -26,95 +27,95 @@ module Docwu
26
27
  # - layouts:
27
28
  # - application.mustache
28
29
  #
29
- # data:
30
- # src_paths
31
- # asset_paths
32
- # layout_paths
33
- # output_path
34
- #
35
- attr_reader :src_paths, # 源文件地址们
36
- :output_path, # 要输出的路径
37
- :folders, # 项目文件夹们
38
- :asset_paths, # assets路径
39
- :layouts, # layouts路径
40
- :data # 数据
41
30
 
42
- def initialize attrs={}
43
- @data = attrs[:data] || Docwu.config.data || {}
44
- @src_paths = attrs[:src_paths] || Docwu.config.src_paths
31
+ attr_reader :layouts, :data, :deploy_path, :folders, :topics
45
32
 
46
- # 关于目录
47
- @folders = {}
48
- @layouts = {}
33
+ def initialize
34
+ @deploy_path = ::Docwu.config.deploy_path # 部署路径
49
35
 
50
- # 静态文件目录 --------------------------------------------------------
51
- @asset_paths = []
36
+ @data = {
37
+ 'worker' => {
38
+ 'copyright' => {
39
+ 'year' => ::Date.today.year,
40
+ 'content' => 'document world util',
41
+ 'name' => 'Doc WU'
42
+ }
43
+ }
44
+ }
52
45
 
53
- (attrs[:asset_paths] || Docwu.config.asset_paths || []).each do |_path|
54
- if File.exists?(_path) && File.directory?(_path)
55
- @asset_paths < _path
56
- end
57
- end
46
+ ::Docwu::Utils.hash_deep_merge!(@data['worker'], ::Docwu.config.worker)
58
47
 
59
- layout_paths = attrs[:layout_paths] || Docwu.config.layout_paths || []
48
+ self.data['page'] ||= {}
60
49
 
61
- # 计算出当前所有的asset_paths
62
- @src_paths.each do |_space, _path|
63
- _asset_path = "#{_path}/assets"
50
+ self.data['reader'] ||= {}
64
51
 
65
- if File.exists?(_asset_path) && File.directory?(_asset_path)
66
- @asset_paths << _asset_path
67
- end
52
+ # 关于目录
53
+ @folders = []
54
+ @layouts = {}
55
+ @topics = []
68
56
 
69
- _layout_path = "#{_path}/layouts"
57
+ # 布局模板
58
+ ::Docwu.config.routes['layouts'].each do |name, path|
59
+ _path = "#{::Docwu.config.layouts_path}/#{path}"
70
60
 
71
- if File.exists?(_layout_path) && File.directory?(_layout_path)
72
- layout_paths << _layout_path
61
+ if File.exists?(_path) && File.file?(_path)
62
+ @layouts[name] = File.read(_path)
73
63
  end
64
+ end
74
65
 
75
- _folder_path = "#{_path}/doc"
76
-
77
- puts " _folder_path---> #{_folder_path}"
66
+ # 原文件, 目标路径
67
+ ::Docwu.config.routes['topics'].each do |src, path|
68
+ _src_path = "#{::Docwu.config.topics_path}/#{src}"
78
69
 
79
- if File.exists?(_folder_path) && File.directory?(_folder_path)
80
- @folders[_space] = ::Docwu::Folder.new(:path => _folder_path, :worker => self, :dir => (_folder_path.sub(_path, '')))
70
+ if File.exists?(_src_path) && File.file?(_src_path)
71
+ @topics << ::Docwu::Topic.new(:src => _src_path, :path => path, :worker => self)
81
72
  end
82
73
  end
83
74
 
84
- layout_paths.each do |_path|
85
- Dir.glob("#{_path}/**/*").each do |_dir|
86
- if File.exists?(_dir) && File.file?(_dir)
87
- @layouts[_dir.sub("#{_path}/", '')] = _dir
88
- end
75
+ # 计算出当前所有的 folders 源, 目标
76
+ ::Docwu.config.routes['folders'].each do |_src, _path|
77
+ _folder_src = "#{plain_path("/#{_src}")}"
78
+
79
+ if File.exists?(_folder_src) && File.directory?(_folder_src)
80
+ @folders << ::Docwu::Folder.new(:src => _folder_src, :worker => self, :path => _path)
89
81
  end
90
82
  end
91
83
 
92
- @output_path = attrs[:output_path] || Docwu.config.output_path
84
+ # TODO: add 更多的全局数据
85
+
86
+ self.data['reader'].merge!(
87
+ 'global' => {
88
+ 'folders' => self.folders_data
89
+ }
90
+ )
93
91
 
94
- # puts self.output_path
95
- # puts self.folders
96
- # puts self.layouts
97
- # puts self.asset_paths
98
92
  end
99
93
 
100
94
  # 输出:
101
95
  # TODO: 先生成临时目录, 然后 -> deploy
102
96
  def generate
103
97
  # 删除要输出的路径
104
- FileUtils.rm_rf(self.output_path)
98
+ FileUtils.rm_rf(self.deploy_path)
105
99
 
106
100
  # 复制 assets 文件进去
107
- self.asset_paths.each do |_path|
108
- FileUtils.cp_r("#{_path}", "#{self.output_path}/")
101
+ FileUtils.cp_r("#{plain_path('/assets')}", "#{self.deploy_path}/")
102
+
103
+ self.folders.each do |folder|
104
+ folder.generate
109
105
  end
110
106
 
111
- self.folders.each do |space, folder|
112
- folder.generate space
107
+ self.topics.each do |topic|
108
+ topic.generate
113
109
  end
110
+ end
114
111
 
112
+ def plain_path(path)
113
+ "#{::Docwu.config.workspace}#{path}"
115
114
  end
116
115
 
117
- private
116
+ def folders_data
117
+ self.folders.map(&:to_data)
118
+ end
118
119
 
119
120
  end
120
121
  end
data/lib/docwu.rb CHANGED
@@ -1,23 +1,112 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  require "#{File.dirname(__FILE__)}/docwu/config"
3
+ require "#{File.dirname(__FILE__)}/docwu/route" # 定制页面路由器
4
+ require "#{File.dirname(__FILE__)}/docwu/topic"
3
5
  require "#{File.dirname(__FILE__)}/docwu/utils"
4
6
  require "#{File.dirname(__FILE__)}/docwu/worker"
5
7
  require "#{File.dirname(__FILE__)}/docwu/render"
6
8
  require "#{File.dirname(__FILE__)}/docwu/folder"
7
9
  require "#{File.dirname(__FILE__)}/docwu/post"
8
- require "#{File.dirname(__FILE__)}/docwu/category"
9
10
  require "#{File.dirname(__FILE__)}/docwu/server"
10
11
 
11
- require 'redcarpet'
12
- require 'coderay'
12
+ require 'pp'
13
13
  require 'yaml'
14
14
  require 'fileutils'
15
15
  require 'mustache_render'
16
+ require 'logger'
16
17
 
17
18
  module Docwu
18
19
 
19
- def self.generate
20
- Docwu::Worker.new.generate
20
+ # 程序开始
21
+ def self.start(workspace)
22
+ _start_time = Time.now
23
+
24
+ args = ARGV
25
+
26
+ _command = args.shift
27
+
28
+ _useful_cmds = ['g', 'generate', 's', 'server', '-h', '--help']
29
+
30
+ unless _useful_cmds.include?(_command)
31
+ raise "command #{_command} is not available, not in (#{_useful_cmds.join('|')})"
32
+ end
33
+
34
+ _default_params = {
35
+ '-p' => [5656],
36
+ '-a' => ['0.0.0.0'],
37
+ '-c' => ["#{workspace}/config.yml"],
38
+ 'DOCWU_ENV' => ['development'],
39
+ '-d' => [(args.delete('-d') == '-d')]
40
+ }
41
+
42
+ if ['--help', '-h'].include?(_command)
43
+ puts "docwu:"
44
+
45
+ _default_params.each do |_cmd, _cfg|
46
+ puts " #{_cmd}, #{_cfg[1]} (default: #{_cfg[0]})"
47
+ end
48
+
49
+ exit
50
+ end
51
+
52
+ # 获取参数
53
+ params = Hash[args.each_slice(2).to_a]
54
+
55
+ _default_params.each do |_k, _v|
56
+ params[_k] = params[_k] || _v.first
57
+ end
58
+
59
+ params['-p'] = params['-p'].to_i
60
+
61
+ # 需要生成
62
+ _need_generate = ['g', 'generate', 's', 'server'].include?(_command)
63
+
64
+ # 需要开启server
65
+ _need_server = ['s', 'server'].include?(_command)
66
+
67
+ _config_file = params['-c']
68
+
69
+ _config = {}
70
+
71
+ if File.exists?(_config_file) && File.file?(_config_file)
72
+ _yml = YAML.load(File.read(_config_file))
73
+
74
+ if _yml.is_a?(Hash)
75
+ _config.merge!(_yml['docwu'] || {})
76
+ end
77
+ else
78
+ raise "#{_config_file} not exists!"
79
+ end
80
+
81
+ _logger = ::Logger.new(STDOUT)
82
+ _logger.level = ::Logger::INFO
83
+
84
+ # docwu 的配置
85
+ ::Docwu.configure do |config|
86
+ config.logger = _logger
87
+ config.params = params.freeze
88
+ config.routes = (_config['routes'] || {}).freeze
89
+ config.worker = (_config['worker'] || {}).freeze
90
+ config.workspace = "#{workspace}".freeze
91
+ end
92
+
93
+ ::MustacheRender.configure do |config|
94
+ config.file_template_root_path = ::Docwu.config.layouts_path
95
+ config.logger = ::Docwu.config.logger
96
+ end
97
+
98
+ if _need_generate
99
+ ::Docwu::Worker.new.generate
100
+
101
+ _logger.info("generate: success, #{Time.now - _start_time}")
102
+ end
103
+
104
+ if _need_server
105
+ ::Docwu::Server.process(
106
+ :Port => ::Docwu.config.params['-p'],
107
+ :Host => ::Docwu.config.params['-a']
108
+ )
109
+ end
21
110
  end
22
111
 
23
112
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docwu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-28 00:00:00.000000000 Z
12
+ date: 2013-08-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redcarpet
@@ -75,27 +75,46 @@ dependencies:
75
75
  - - ">="
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
- description: Description of Docfive.
78
+ - !ruby/object:Gem::Dependency
79
+ name: nokogiri
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: Description of Doc Work UP.
79
95
  email:
80
96
  - andywang7259@gmail.com
81
- executables: []
97
+ executables:
98
+ - docwu
82
99
  extensions: []
83
100
  extra_rdoc_files: []
84
101
  files:
85
102
  - lib/docwu/server.rb
103
+ - lib/docwu/route.rb
86
104
  - lib/docwu/render.rb
87
105
  - lib/docwu/config.rb
88
106
  - lib/docwu/utils.rb
89
107
  - lib/docwu/version.rb
108
+ - lib/docwu/topic.rb
90
109
  - lib/docwu/worker.rb
91
110
  - lib/docwu/post.rb
92
- - lib/docwu/category.rb
93
111
  - lib/docwu/folder.rb
94
112
  - lib/docwu.rb
95
113
  - lib/tasks/docwu_tasks.rake
96
114
  - MIT-LICENSE
97
115
  - Rakefile
98
116
  - README.md
117
+ - bin/docwu
99
118
  homepage: http://github.com/xiuxian123/docwu
100
119
  licenses: []
101
120
  post_install_message:
@@ -110,7 +129,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
110
129
  version: '0'
111
130
  segments:
112
131
  - 0
113
- hash: -1575743025569223070
132
+ hash: -3240824084123490041
114
133
  required_rubygems_version: !ruby/object:Gem::Requirement
115
134
  none: false
116
135
  requirements:
@@ -119,11 +138,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
138
  version: '0'
120
139
  segments:
121
140
  - 0
122
- hash: -1575743025569223070
141
+ hash: -3240824084123490041
123
142
  requirements: []
124
143
  rubyforge_project:
125
144
  rubygems_version: 1.8.25
126
145
  signing_key:
127
146
  specification_version: 3
128
- summary: Summary of Docfive.
147
+ summary: Summary of Doc Work UP.
129
148
  test_files: []
File without changes