gibier 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/bin/console +14 -0
  3. data/bin/gibier +5 -0
  4. data/bin/setup +8 -0
  5. data/lib/gibier.rb +8 -0
  6. data/lib/gibier/cli.rb +95 -0
  7. data/lib/gibier/render.rb +234 -0
  8. data/lib/gibier/slide_helper.rb +25 -0
  9. data/lib/gibier/slide_loader.rb +77 -0
  10. data/lib/gibier/version.rb +3 -0
  11. data/template/app.rb +25 -0
  12. data/template/gh_pages/index.haml +13 -0
  13. data/template/gh_pages/slide.haml +18 -0
  14. data/template/project/Gemfile +8 -0
  15. data/template/project/app/page_base.rb +46 -0
  16. data/template/project/app/slide.rb +204 -0
  17. data/template/project/app/track_field.rb +43 -0
  18. data/template/project/assets/css/application.css +219 -0
  19. data/template/project/assets/css/highlight.css +101 -0
  20. data/template/project/assets/fonts/Inconsolata-Regular.ttf +0 -0
  21. data/template/project/assets/images/flag.png +0 -0
  22. data/template/project/assets/images/hunter.png +0 -0
  23. data/template/project/assets/images/rabbit.png +0 -0
  24. data/template/project/assets/images/turtle.png +0 -0
  25. data/template/project/assets/images/usagitokame.png +0 -0
  26. data/template/project/config.ru +35 -0
  27. data/template/project/data/sample/css/custom.css +0 -0
  28. data/template/project/data/sample/images/gibier.jpg +0 -0
  29. data/template/project/data/sample/images/youchan.jpg +0 -0
  30. data/template/project/data/sample/script.md +7 -0
  31. data/template/project/data/sample/slide.md +59 -0
  32. data/template/project/server.rb +76 -0
  33. data/template/project/views/index.haml +13 -0
  34. data/template/project/views/script.haml +10 -0
  35. data/template/project/views/slide.haml +15 -0
  36. data/template/script.rb +24 -0
  37. metadata +320 -0
@@ -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
@@ -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
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'gibier'
4
+
5
+ Gibier::Cli.start(ARGV)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,8 @@
1
+ require "gibier/version"
2
+
3
+ module Gibier
4
+ end
5
+
6
+ require "gibier/slide_helper"
7
+ require "gibier/slide_loader"
8
+ require 'gibier/cli'
@@ -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