gibier 0.8.0
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.
- checksums.yaml +7 -0
- data/bin/console +14 -0
- data/bin/gibier +5 -0
- data/bin/setup +8 -0
- data/lib/gibier.rb +8 -0
- data/lib/gibier/cli.rb +95 -0
- data/lib/gibier/render.rb +234 -0
- data/lib/gibier/slide_helper.rb +25 -0
- data/lib/gibier/slide_loader.rb +77 -0
- data/lib/gibier/version.rb +3 -0
- data/template/app.rb +25 -0
- data/template/gh_pages/index.haml +13 -0
- data/template/gh_pages/slide.haml +18 -0
- data/template/project/Gemfile +8 -0
- data/template/project/app/page_base.rb +46 -0
- data/template/project/app/slide.rb +204 -0
- data/template/project/app/track_field.rb +43 -0
- data/template/project/assets/css/application.css +219 -0
- data/template/project/assets/css/highlight.css +101 -0
- data/template/project/assets/fonts/Inconsolata-Regular.ttf +0 -0
- data/template/project/assets/images/flag.png +0 -0
- data/template/project/assets/images/hunter.png +0 -0
- data/template/project/assets/images/rabbit.png +0 -0
- data/template/project/assets/images/turtle.png +0 -0
- data/template/project/assets/images/usagitokame.png +0 -0
- data/template/project/config.ru +35 -0
- data/template/project/data/sample/css/custom.css +0 -0
- data/template/project/data/sample/images/gibier.jpg +0 -0
- data/template/project/data/sample/images/youchan.jpg +0 -0
- data/template/project/data/sample/script.md +7 -0
- data/template/project/data/sample/slide.md +59 -0
- data/template/project/server.rb +76 -0
- data/template/project/views/index.haml +13 -0
- data/template/project/views/script.haml +10 -0
- data/template/project/views/slide.haml +15 -0
- data/template/script.rb +24 -0
- metadata +320 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f2c145bc519db0917358e75d76d5865b3a8a1da2
|
4
|
+
data.tar.gz: e427319ab75b34e7ce5f046c3ea052e1bd19c955
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a2c4d87985b5a11e0a62f1322aaa809edd7b1a9800dba1f140c38252d3cd20157cfee191823b914fad2f8ff2b9aea58c9a676ea7df636d1cab048bec598fc1f1
|
7
|
+
data.tar.gz: 863719dbeb82a79007af47f551066a731269927b296cb059b104acd068e3fcd133a23ab1a35d9085199245004e29c2952d471508fe2a9eb2d3034da4ff65a34e
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "gibier"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/gibier
ADDED
data/bin/setup
ADDED
data/lib/gibier.rb
ADDED
data/lib/gibier/cli.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'pathname'
|
4
|
+
require 'rouge'
|
5
|
+
require 'opal'
|
6
|
+
require 'haml'
|
7
|
+
|
8
|
+
module Gibier
|
9
|
+
class Cli < Thor
|
10
|
+
desc 'new', 'create new project'
|
11
|
+
|
12
|
+
def new(name)
|
13
|
+
puts "Create new project '#{name}'"
|
14
|
+
|
15
|
+
FileUtils.mkdir name
|
16
|
+
dir = Dir.new(__dir__+'/../../template/project')
|
17
|
+
dir.each do |file|
|
18
|
+
next if file == '..'
|
19
|
+
FileUtils.cp_r(dir.path + '/' + file, name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'highlight', 'generate highlight.css'
|
24
|
+
|
25
|
+
def highlight
|
26
|
+
puts Rouge::Themes::Base16.mode(:dark).render(scope: '.highlight')
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'ghpages', 'create static pages'
|
30
|
+
|
31
|
+
def ghpages
|
32
|
+
puts "Create static pages"
|
33
|
+
|
34
|
+
FileUtils.mkdir_p 'docs'
|
35
|
+
assets_dir = Dir.new(__dir__ + '/../../template/project/assets')
|
36
|
+
FileUtils.cp_r(assets_dir.path, 'docs')
|
37
|
+
|
38
|
+
slide_loader = Gibier::SlideLoader.new
|
39
|
+
Gibier::SlideHelper.each_slides('data') do |name|
|
40
|
+
slide_loader.init_slide(name)
|
41
|
+
|
42
|
+
FileUtils.mkdir_p "docs/assets/#{name}"
|
43
|
+
FileUtils.cp_r("data/#{name}/css", "docs/assets/#{name}")
|
44
|
+
FileUtils.cp_r("data/#{name}/images", "docs/assets/#{name}")
|
45
|
+
|
46
|
+
FileUtils.mkdir_p "docs/#{name}"
|
47
|
+
convert_html(File.expand_path('../../../template/gh_pages/slide.haml', __FILE__), "docs/#{name}/index.html", slide_name: name)
|
48
|
+
|
49
|
+
FileUtils.mkdir_p "docs/assets/#{name}/javascripts"
|
50
|
+
build(name, "docs/assets/#{name}/javascripts/application.js")
|
51
|
+
end
|
52
|
+
|
53
|
+
convert_html(File.expand_path('../../../template/gh_pages/index.haml', __FILE__), "docs/index.html", slides: slide_loader.slides)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def convert_html(haml_file, html_file, **instance_vars)
|
59
|
+
File.open(html_file, "w") do |f|
|
60
|
+
engine = Haml::Engine.new(File.read(haml_file))
|
61
|
+
context = Object.new
|
62
|
+
instance_vars.each do |key, value|
|
63
|
+
context.instance_variable_set(:"@#{key}", value)
|
64
|
+
end
|
65
|
+
f.write engine.render(context) # Tilt::StringTemplate.new().render
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def build(name, filename)
|
70
|
+
builder = Opal::Builder.new
|
71
|
+
|
72
|
+
use_gem(builder, 'opal-browser', 'opal')
|
73
|
+
use_gem(builder, 'opal-router', 'opal')
|
74
|
+
use_gem(builder, 'hyalite', 'client')
|
75
|
+
|
76
|
+
builder.append_paths './app'
|
77
|
+
builder.use_gem 'gibier'
|
78
|
+
builder.use_gem 'paggio'
|
79
|
+
builder.build "./app/slides/#{name}/app.rb"
|
80
|
+
|
81
|
+
File.open(filename, 'w') do |file|
|
82
|
+
file.write builder.to_s
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
def use_gem(builder, name, opal_path)
|
88
|
+
spec = Gem::Specification.find_by_name name
|
89
|
+
lib_path = Pathname.new spec.full_require_paths.first
|
90
|
+
opal_path = lib_path.parent + opal_path
|
91
|
+
builder.append_paths opal_path.to_s
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
@@ -0,0 +1,234 @@
|
|
1
|
+
require 'unindent'
|
2
|
+
require 'rouge'
|
3
|
+
require 'redcarpet'
|
4
|
+
|
5
|
+
class String
|
6
|
+
def escape
|
7
|
+
if self =~ /<a>(.*)<\/a>/
|
8
|
+
"a(#{$1})"
|
9
|
+
elsif self =~ /<p>(.*)<img>(.*)<\/img><\/p>/
|
10
|
+
"p(#{$1}, img(#{$2}))"
|
11
|
+
elsif self =~ /<div>(.*)<\/div>/
|
12
|
+
"div(#{$1})"
|
13
|
+
elsif self =~ /<strong>(.*)<\/strong>/
|
14
|
+
"strong(nil, \"#{$1}\")"
|
15
|
+
else
|
16
|
+
"\"#{self.gsub(/\"/, "\\\"").gsub(/\\/, "\\\\")}\""
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module Gibier
|
22
|
+
class Renderer < Redcarpet::Render::Base
|
23
|
+
def self.create(name)
|
24
|
+
Class.new(Renderer) do
|
25
|
+
def self.page_name
|
26
|
+
@page_name
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.page_name=(name)
|
30
|
+
@page_name = name
|
31
|
+
end
|
32
|
+
|
33
|
+
def page_name
|
34
|
+
self.class.page_name
|
35
|
+
end
|
36
|
+
end.tap{|c| c.page_name = name }
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize
|
40
|
+
super
|
41
|
+
@enter_title_page = false
|
42
|
+
@enter_page = false
|
43
|
+
@page_count = 0
|
44
|
+
clear_list_state
|
45
|
+
end
|
46
|
+
|
47
|
+
def clear_list_state
|
48
|
+
@enter_list = false
|
49
|
+
@list_depth = 0
|
50
|
+
end
|
51
|
+
|
52
|
+
[
|
53
|
+
# block-level calls
|
54
|
+
:block_quote,
|
55
|
+
|
56
|
+
# span-level calls
|
57
|
+
:autolink,
|
58
|
+
:underline, :raw_html,
|
59
|
+
:triple_emphasis, :strikethrough,
|
60
|
+
:superscript, :highlight,
|
61
|
+
|
62
|
+
# footnotes
|
63
|
+
:footnotes, :footnote_def, :footnote_ref,
|
64
|
+
|
65
|
+
# low level rendering
|
66
|
+
#:entity, :normal_text
|
67
|
+
].each do |method|
|
68
|
+
define_method method do |*args|
|
69
|
+
"#{method} #{args.first}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def hrule
|
74
|
+
clear_list_state
|
75
|
+
"".tap do |result|
|
76
|
+
if @enter_title_page || @enter_page
|
77
|
+
result <<
|
78
|
+
<<EOD
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
EOD
|
84
|
+
@enter_title_page = @enter_page = false
|
85
|
+
end
|
86
|
+
|
87
|
+
result << <<EOD
|
88
|
+
class Gibier::Page#{@page_count} < Gibier::PageBase
|
89
|
+
def content
|
90
|
+
[].tap do |children|
|
91
|
+
EOD
|
92
|
+
|
93
|
+
@enter_page = true
|
94
|
+
@page_count += 1
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def header(text, header_level)
|
99
|
+
clear_list_state
|
100
|
+
|
101
|
+
if header_level > 3
|
102
|
+
return " children << h#{header_level}(nil, #{text.escape})\n"
|
103
|
+
end
|
104
|
+
|
105
|
+
"".tap do |result|
|
106
|
+
if @enter_title_page || @enter_page
|
107
|
+
result <<
|
108
|
+
<<EOD
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
EOD
|
114
|
+
@enter_title_page = @enter_page = false
|
115
|
+
end
|
116
|
+
|
117
|
+
if header_level == 1
|
118
|
+
@enter_title_page = true
|
119
|
+
@title = text.escape
|
120
|
+
else
|
121
|
+
@enter_page = true
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
result <<
|
126
|
+
<<EOD
|
127
|
+
class Gibier::Page#{@page_count} < Gibier::PageBase
|
128
|
+
def header
|
129
|
+
h#{header_level}(nil, #{text.escape})
|
130
|
+
end
|
131
|
+
|
132
|
+
def content
|
133
|
+
[].tap do |children|
|
134
|
+
EOD
|
135
|
+
|
136
|
+
@page_count += 1
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def doc_footer(*args)
|
141
|
+
<<EOD
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
Gibier.page_count = #{@page_count}
|
147
|
+
Gibier.title = #{@title}
|
148
|
+
EOD
|
149
|
+
end
|
150
|
+
|
151
|
+
def list_item(item, orderd)
|
152
|
+
"".tap do |result|
|
153
|
+
if item =~ /.*\n +children << /
|
154
|
+
result << item.sub(/(.*)\n +children << /) { " li(nil, #{$1.strip.escape}),\n " }.rstrip
|
155
|
+
result << ",\n"
|
156
|
+
@enter_list = false
|
157
|
+
else
|
158
|
+
result << " li(nil, #{item.strip.escape}),\n"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def list(text, ordered)
|
164
|
+
"".tap do |result|
|
165
|
+
result << " children << ul(nil,\n"
|
166
|
+
result << text.sub(/,\n\z/, "\n")
|
167
|
+
result << " )\n"
|
168
|
+
@enter_list = false
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def link(link, title, content)
|
173
|
+
link or return
|
174
|
+
"<a>{href: #{link.escape}, target: \"_blank\"}, #{content.escape}</a>"
|
175
|
+
end
|
176
|
+
|
177
|
+
def image(link, title, alt_text)
|
178
|
+
href = "\#{Gibier.assets_path}/images/#{link}"
|
179
|
+
"<p>{class: \"#{alt_text}\"}<img>{src: #{href.escape}}</img></p>"
|
180
|
+
end
|
181
|
+
|
182
|
+
def block_code(code, language)
|
183
|
+
clear_list_state
|
184
|
+
|
185
|
+
formatter = Rouge::Formatters::HTML.new(css_class: 'highlight', line_numbers: true)
|
186
|
+
lexer = case language
|
187
|
+
when 'ruby'
|
188
|
+
Rouge::Lexers::Ruby.new
|
189
|
+
when 'javascript'
|
190
|
+
Rouge::Lexers::Javascript.new
|
191
|
+
else
|
192
|
+
Rouge::Lexers::PlainText.new
|
193
|
+
end
|
194
|
+
highlight = formatter.format(lexer.lex(code))
|
195
|
+
" children << code({ dangerouslySetInnerHTML: { __html: %q{#{highlight}} } })\n"
|
196
|
+
end
|
197
|
+
|
198
|
+
def block_html(html)
|
199
|
+
clear_list_state
|
200
|
+
" children << code({ dangerouslySetInnerHTML: { __html: %q{#{html}} } })\n"
|
201
|
+
end
|
202
|
+
|
203
|
+
def emphasis(*args)
|
204
|
+
"# #{args}"
|
205
|
+
end
|
206
|
+
|
207
|
+
def double_emphasis(*args)
|
208
|
+
"<strong>#{args.first}</strong>"
|
209
|
+
end
|
210
|
+
|
211
|
+
def paragraph(text)
|
212
|
+
lines = text.split(/ $/)
|
213
|
+
if text[0] == '%'
|
214
|
+
class_name = text[1...text.index(':')]
|
215
|
+
lines[0] = lines.first[(lines.first.index(':') + 1)...lines.first.length].lstrip
|
216
|
+
" children << p({className:\"#{class_name}\"}, #{lines.map{|l| l.escape}.join(',Hyalite.create_element(\'br\'),')})\n"
|
217
|
+
else
|
218
|
+
" children << p(nil, #{lines.map{|l| l.escape}.join(',Hyalite.create_element(\'br\'),')})\n"
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def table(header, body)
|
223
|
+
"#{header}#{body}"
|
224
|
+
end
|
225
|
+
|
226
|
+
def table_row(content)
|
227
|
+
content + "\n"
|
228
|
+
end
|
229
|
+
|
230
|
+
def table_cell(content, alignment)
|
231
|
+
content + "\t"
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Gibier
|
2
|
+
class SlideHelper
|
3
|
+
def self.each_slides(dir = 'data')
|
4
|
+
Dir.foreach(dir) do |dir_name|
|
5
|
+
if !dir_name.start_with?('.') && File.directory?("#{dir}/#{dir_name}")
|
6
|
+
yield dir_name
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.slides(dir = 'data')
|
12
|
+
SlideIterator.new(dir).to_enum
|
13
|
+
end
|
14
|
+
|
15
|
+
class SlideIterator
|
16
|
+
def initialize(dir)
|
17
|
+
@dir = dir
|
18
|
+
end
|
19
|
+
|
20
|
+
def each(&block)
|
21
|
+
SlideHelper.each_slides(@dir, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'rouge'
|
2
|
+
require 'fssm'
|
3
|
+
require 'eventmachine'
|
4
|
+
require 'redcarpet'
|
5
|
+
|
6
|
+
require_relative './render'
|
7
|
+
|
8
|
+
module Gibier
|
9
|
+
class SlideLoader
|
10
|
+
|
11
|
+
attr_reader :slides
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@slides = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def init_slide(name)
|
18
|
+
Dir.mkdir('app/slides') unless Dir.exist?('app/slides')
|
19
|
+
Dir.mkdir('app/scripts') unless Dir.exist?('app/scripts')
|
20
|
+
Dir.mkdir(SlideLoader.src_path(name)) unless Dir.exist?(SlideLoader.src_path(name))
|
21
|
+
Dir.mkdir(SlideLoader.script_path(name)) unless Dir.exist?(SlideLoader.script_path(name))
|
22
|
+
|
23
|
+
File.foreach("data/#{name}/slide.md") do |line|
|
24
|
+
if line =~ /\A# (.+)/
|
25
|
+
@slides << {name: name, title: $1}
|
26
|
+
break
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
SlideLoader.load_slide(name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.load_slide(name)
|
34
|
+
File.open("#{src_path(name)}/pages.rb", "w+") do |f|
|
35
|
+
data = File.read("data/#{name}/slide.md")
|
36
|
+
markdown = Redcarpet::Markdown.new(Gibier::Renderer.create(name), fenced_code_blocks: true)
|
37
|
+
f.write markdown.render(data)
|
38
|
+
end
|
39
|
+
|
40
|
+
if File.exist?("data/#{name}/script.md")
|
41
|
+
File.open("#{script_path(name)}/script.html", "w+") do |f|
|
42
|
+
script = File.read("data/#{name}/script.md")
|
43
|
+
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML.new(hard_wrap: true), autolink: true, fenced_code_blocks: true)
|
44
|
+
f.write markdown.render(script)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
File.open("#{src_path(name)}/app.rb", "w+") do |f|
|
49
|
+
f.write Tilt::StringTemplate.new(File.expand_path('../../../template/app.rb', __FILE__)).render(Object.new, name: name)
|
50
|
+
end
|
51
|
+
|
52
|
+
File.open("#{src_path(name)}/script.rb", "w+") do |f|
|
53
|
+
f.write Tilt::StringTemplate.new(File.expand_path('../../../template/script.rb', __FILE__)).render(Object.new, name: name)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.src_path(name)
|
58
|
+
"app/slides/#{name}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.script_path(name)
|
62
|
+
"app/scripts/#{name}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_slide(name)
|
66
|
+
init_slide(name)
|
67
|
+
|
68
|
+
EM.defer do
|
69
|
+
FSSM.monitor("data/#{name}", %w(slide.md script.md)) do
|
70
|
+
update {|base, relative| Gibier::SlideLoader.load_slide(name) }
|
71
|
+
delete {|base, relative|}
|
72
|
+
create {|base, relative|}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|