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.
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