ichiban 0.0.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/ichiban/command.rb +13 -1
- data/lib/ichiban/config.rb +7 -17
- data/lib/ichiban/deleter.rb +24 -0
- data/lib/ichiban/dependencies.rb +33 -0
- data/lib/ichiban/file.rb +115 -0
- data/lib/ichiban/helpers.rb +6 -10
- data/lib/ichiban/html_compiler.rb +61 -0
- data/lib/ichiban/logger.rb +59 -3
- data/lib/ichiban/markdown.rb +34 -0
- data/lib/ichiban/watcher.rb +35 -3
- data/lib/ichiban.rb +44 -17
- metadata +123 -74
- data/.gitignore +0 -5
- data/Gemfile +0 -4
- data/README +0 -56
- data/bin/ichiban.rb +0 -6
- data/ichiban.gemspec +0 -25
- data/klass.rb +0 -7
- data/lib/ichiban/compilation.rb +0 -93
- data/lib/ichiban/erb_page.rb +0 -16
- data/lib/ichiban/files.rb +0 -105
- data/lib/ichiban/layouts.rb +0 -10
- data/lib/ichiban/loading.rb +0 -19
- data/lib/ichiban/mapping.rb +0 -38
- data/lib/ichiban/path.rb +0 -55
- data/lib/ichiban/script_runner.rb +0 -33
- data/lib/ichiban/tasks.rb +0 -23
- data/lib/ichiban/version.rb +0 -3
- data/sample/Rakefile +0 -2
- data/sample/compiled/about.html +0 -13
- data/sample/compiled/bad.html +0 -0
- data/sample/compiled/images/check.png +0 -0
- data/sample/compiled/index.html +0 -13
- data/sample/compiled/javascripts/interaction.js +0 -1
- data/sample/compiled/staff/_employee.html +0 -13
- data/sample/compiled/staff/andre-marques.html +0 -13
- data/sample/compiled/staff/index.html +0 -17
- data/sample/compiled/staff/jarrett-colby.html +0 -13
- data/sample/compiled/stylesheets/reset.css +0 -1
- data/sample/compiled/stylesheets/screen.css +0 -1
- data/sample/config.rb +0 -3
- data/sample/content/about.html +0 -1
- data/sample/content/bad.html +0 -3
- data/sample/content/index.html +0 -1
- data/sample/content/staff/_employee.html +0 -1
- data/sample/content/staff/index.html +0 -6
- data/sample/data/employees.csv +0 -2
- data/sample/errors/404.html +0 -1
- data/sample/helpers/staff_helper.rb +0 -5
- data/sample/images/check.png +0 -0
- data/sample/javascripts/interaction.js +0 -1
- data/sample/layouts/default.html +0 -13
- data/sample/models/employee.rb +0 -16
- data/sample/scripts/bad.rb +0 -1
- data/sample/scripts/staff.rb +0 -8
- data/sample/stylesheets/reset.css +0 -1
- data/sample/stylesheets/screen.scss +0 -5
- data/spec/integration_spec.rb +0 -89
- data/spec/path_spec.rb +0 -15
- data/spec/spec_helper.rb +0 -19
data/lib/ichiban/command.rb
CHANGED
@@ -1,11 +1,23 @@
|
|
1
1
|
module Ichiban
|
2
2
|
class Command
|
3
3
|
def initialize(args)
|
4
|
+
@task = args.shift
|
4
5
|
@args = args
|
5
6
|
end
|
6
7
|
|
8
|
+
def print_usage
|
9
|
+
puts "Usage: ichiban <command>"
|
10
|
+
puts " Available commands: watch"
|
11
|
+
end
|
12
|
+
|
7
13
|
def run
|
8
|
-
|
14
|
+
Ichiban.project_root = Dir.getwd
|
15
|
+
case @task
|
16
|
+
when 'watch'
|
17
|
+
Ichiban::Watcher.new.start
|
18
|
+
else
|
19
|
+
print_usage
|
20
|
+
end
|
9
21
|
end
|
10
22
|
end
|
11
23
|
end
|
data/lib/ichiban/config.rb
CHANGED
@@ -5,27 +5,17 @@ module Ichiban
|
|
5
5
|
@config
|
6
6
|
end
|
7
7
|
|
8
|
-
def self.configure_for_project(project_root)
|
9
|
-
config.project_root = project_root
|
10
|
-
config_file = File.join(project_root, 'config.rb')
|
11
|
-
raise "#{config_file} must exist" unless File.exists?(config_file)
|
12
|
-
load config_file
|
13
|
-
end
|
14
|
-
|
15
|
-
# It's a bit messy to have this class method that's just an alias to a method on the config object.
|
16
|
-
# But so many different bits of code (including client code) need to know the project root, it makes
|
17
|
-
# pragmatic sense to have a really compact way to get it.
|
18
|
-
def self.project_root
|
19
|
-
config.project_root
|
20
|
-
end
|
21
|
-
|
22
8
|
class Config
|
23
|
-
attr_accessor :project_root
|
24
|
-
|
25
9
|
attr_writer :relative_url_root
|
26
10
|
|
11
|
+
def self.load_file
|
12
|
+
config_file = ::File.join(Ichiban.project_root, 'config.rb')
|
13
|
+
raise "#{config_file} must exist" unless ::File.exists?(config_file)
|
14
|
+
load config_file
|
15
|
+
end
|
16
|
+
|
27
17
|
def relative_url_root
|
28
|
-
@relative_url_root || raise(
|
18
|
+
@relative_url_root || raise("Ichiban.config.relative_url_root not set. Set inside block in config.rb like this: cfg.relative_url_root = '/'")
|
29
19
|
end
|
30
20
|
end
|
31
21
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Ichiban
|
2
|
+
class Deleter
|
3
|
+
# Deletes a file's associated destination file, if any.
|
4
|
+
def delete_dest(path)
|
5
|
+
file = Ichiban::File.from_abs(path)
|
6
|
+
# file will be nil if the path doesn't map to a known subclass of Ichiban::File. Furthermore,
|
7
|
+
# even if file is not nil, it may be a kind of Ichiban::File that does not have a destination.
|
8
|
+
if file and file.has_dest?
|
9
|
+
dest = file.dest
|
10
|
+
else
|
11
|
+
dest = nil
|
12
|
+
end
|
13
|
+
if dest and ::File.exists?(dest)
|
14
|
+
puts 'yep'
|
15
|
+
FileUtils.rm(dest)
|
16
|
+
else
|
17
|
+
puts 'nope'
|
18
|
+
end
|
19
|
+
|
20
|
+
# Log the deletion(s)
|
21
|
+
Ichiban.logger.deletion(path, dest)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Ichiban
|
2
|
+
module Dependencies
|
3
|
+
@graphs = {}
|
4
|
+
|
5
|
+
# graph_file_path is an absolute path.
|
6
|
+
def self.graph(graph_file_path)
|
7
|
+
ensure_graph_initialized(graph_file_path)
|
8
|
+
@graphs[graph_file_path]
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.ensure_graph_initialized(graph_file_path)
|
12
|
+
unless @graphs[graph_file_path]
|
13
|
+
if ::File.exists?(graph_file_path)
|
14
|
+
@graphs[graph_file_path] = JSON.parse(::File.read(graph_file_path))
|
15
|
+
else
|
16
|
+
@graphs[graph_file_path] = {}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Loads the graph from disk if it's not already in memory. Updates the graph. Writes the new
|
22
|
+
# graph to disk. graph_file_path is an absolute path.
|
23
|
+
def self.update(graph_file_path, ind, dep)
|
24
|
+
ensure_graph_initialized(graph_file_path)
|
25
|
+
graph = @graphs[graph_file_path]
|
26
|
+
graph[ind] ||= []
|
27
|
+
graph[ind] << dep unless graph[ind].include?(dep)
|
28
|
+
::File.open(graph_file_path, 'w') do |f|
|
29
|
+
f << JSON.generate(graph)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/ichiban/file.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
module Ichiban
|
2
|
+
class File
|
3
|
+
attr_reader :abs
|
4
|
+
|
5
|
+
# Returns an absolute path in the compiled directory
|
6
|
+
def dest
|
7
|
+
::File.join(Ichiban.project_root, 'compiled', dest_rel_to_compiled)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Returns a new instance based on an absolute path. Will automatically pick the right subclass.
|
11
|
+
# Return nil if the file is not recognized.
|
12
|
+
def self.from_abs(abs)
|
13
|
+
rel = abs.slice(Ichiban.project_root.length..-1) # Relative to project root
|
14
|
+
rel.sub!(/^\//, '') # Remove leading slash
|
15
|
+
if rel.start_with?('html') and rel.end_with?('.html')
|
16
|
+
Ichiban::HTMLFile.new(rel)
|
17
|
+
elsif rel.start_with?('layouts') and rel.end_with?('.html')
|
18
|
+
Ichiban::LayoutFIle.new(rel)
|
19
|
+
elsif rel.start_with?('assets/js')
|
20
|
+
Ichiban::JSFile.new(rel)
|
21
|
+
elsif rel.start_with?('assets/css') and rel.end_with?('.css')
|
22
|
+
Ichiban::CSSFile.new(rel)
|
23
|
+
elsif rel.start_with?('assets/css') and rel.end_with?('.scss')
|
24
|
+
Ichiban::SCSSFile.new(rel)
|
25
|
+
elsif rel.start_with?('assets/img')
|
26
|
+
Ichiban::ImageFile.new(rel)
|
27
|
+
elsif rel.start_with?('assets/misc')
|
28
|
+
Ichiban::MiscAssetFile.new(rel)
|
29
|
+
elsif rel.start_with?('models')
|
30
|
+
Ichiban::ModelFile.new(rel)
|
31
|
+
elsif rel.start_with?('data')
|
32
|
+
Ichiban::DataFile.new(rel)
|
33
|
+
elsif rel.start_with?('scripts')
|
34
|
+
Ichiban::ScriptFile.new(rel)
|
35
|
+
elsif rel.start_with?('helpers')
|
36
|
+
Ichiban::HelperFile.new(rel)
|
37
|
+
else
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def has_dest?
|
43
|
+
respond_to?(:dest_rel_to_compiled)
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize(rel)
|
47
|
+
@rel = rel
|
48
|
+
@abs = ::File.join(Ichiban.project_root, rel)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns a new path where the old extension is replaced with new_ext
|
52
|
+
def replace_ext(path, new_ext)
|
53
|
+
path.sub(/\..+$/, '.' + new_ext)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class HTMLFile < File
|
58
|
+
def dest_rel_to_compiled
|
59
|
+
d = @rel.slice('html/'.length..-1)
|
60
|
+
(d.end_with?('.markdown') or d.end_with?('.md')) ? replace_ext(d, 'html') : d
|
61
|
+
end
|
62
|
+
|
63
|
+
def update
|
64
|
+
Ichiban::HTMLCompiler.new(self).compile
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class LayoutFile < File
|
69
|
+
end
|
70
|
+
|
71
|
+
class JSFile < File
|
72
|
+
def dest_rel_to_compiled
|
73
|
+
File.join('js', @rel.slice('assets/js/'.length..-1))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class CSSFile < File
|
78
|
+
def dest_rel_to_compiled
|
79
|
+
File.join('css', @rel.slice('assets/css/'.length..-1))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class SCSSFile < File
|
84
|
+
def dest_rel_to_compiled
|
85
|
+
replace_ext(
|
86
|
+
File.join('css', @rel.slice('assets/css/'.length..-1)),
|
87
|
+
'css'
|
88
|
+
)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class ImageFile < File
|
93
|
+
def dest_rel_to_compiled
|
94
|
+
File.join('img', @rel.slice('assets/img/'.length..-1))
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class MiscAssetFile < File
|
99
|
+
def dest_rel_to_compiled
|
100
|
+
@rel.slice('assets/misc/'.length..-1)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class ModelFile < File
|
105
|
+
end
|
106
|
+
|
107
|
+
class DataFile < File
|
108
|
+
end
|
109
|
+
|
110
|
+
class ScriptFile < File
|
111
|
+
end
|
112
|
+
|
113
|
+
class HelperFile < File
|
114
|
+
end
|
115
|
+
end
|
data/lib/ichiban/helpers.rb
CHANGED
@@ -13,10 +13,6 @@ module Ichiban
|
|
13
13
|
@_erb_out << str
|
14
14
|
end
|
15
15
|
|
16
|
-
def content_for(ivar_name, &block)
|
17
|
-
instance_variable_set '@' + ivar_name, capture(&block)
|
18
|
-
end
|
19
|
-
|
20
16
|
def content_tag(*args)
|
21
17
|
options = args.extract_options!
|
22
18
|
name = args.shift
|
@@ -32,7 +28,7 @@ module Ichiban
|
|
32
28
|
|
33
29
|
def javascript_include_tag(js_file)
|
34
30
|
js_file = js_file + '.js' unless js_file.end_with?('.js')
|
35
|
-
path = normalize_path(File.join('/javascripts', js_file))
|
31
|
+
path = normalize_path(::File.join('/javascripts', js_file))
|
36
32
|
content_tag 'script', 'type' => 'text/javascript', 'src' => path
|
37
33
|
end
|
38
34
|
|
@@ -42,7 +38,7 @@ module Ichiban
|
|
42
38
|
|
43
39
|
alias_method :layouts, :layout
|
44
40
|
|
45
|
-
def
|
41
|
+
def _limit_options(hash, keys = [])
|
46
42
|
keys = keys.collect(&:to_s)
|
47
43
|
hash.inject({}) do |result, (key, value)|
|
48
44
|
result[key] = value if (keys.include?(key.to_s) or (block_given? and yield(key, value)))
|
@@ -86,11 +82,11 @@ module Ichiban
|
|
86
82
|
# If you don't specify a section, and your URLs don't have leading slashes,
|
87
83
|
# the hrefs will use relative URLs.
|
88
84
|
def nav(items, options = {})
|
89
|
-
ul_options =
|
85
|
+
ul_options = _limit_options(options, %w(id class)) { |key, value| key.to_s.start_with?('data-') }
|
90
86
|
content_tag('ul', ul_options) do
|
91
87
|
items.inject('') do |lis, (text, path, attrs)|
|
92
88
|
if options[:section]
|
93
|
-
path = File.join(options[:section], path)
|
89
|
+
path = ::File.join(options[:section], path)
|
94
90
|
end
|
95
91
|
path = normalize_path(path)
|
96
92
|
lis + content_tag('li', (attrs or {})) do
|
@@ -108,7 +104,7 @@ module Ichiban
|
|
108
104
|
# Otherwise, it will remain relative.
|
109
105
|
def normalize_path(path)
|
110
106
|
if path.start_with?('/')
|
111
|
-
File.join(relative_url_root, path)
|
107
|
+
::File.join(relative_url_root, path)
|
112
108
|
else
|
113
109
|
path
|
114
110
|
end
|
@@ -131,7 +127,7 @@ module Ichiban
|
|
131
127
|
|
132
128
|
def stylesheet_link_tag(css_file, media = 'screen')
|
133
129
|
css_file = css_file + '.css' unless css_file.end_with?('.css')
|
134
|
-
href = normalize_path(File.join('/stylesheets', css_file))
|
130
|
+
href = normalize_path(::File.join('/stylesheets', css_file))
|
135
131
|
tag 'link', 'href' => href, 'type' => 'text/css', 'rel' => 'stylesheet', 'media' => media
|
136
132
|
end
|
137
133
|
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Ichiban
|
2
|
+
class HTMLCompiler
|
3
|
+
def compile
|
4
|
+
::File.open(@html_file.dest, 'w') do |f|
|
5
|
+
f << compile_to_str
|
6
|
+
end
|
7
|
+
Ichiban.logger.compilation(@html_file.abs, @html_file.dest)
|
8
|
+
end
|
9
|
+
|
10
|
+
def compile_to_str
|
11
|
+
# Compile the HTML of the content page, but not the layouts (yet)
|
12
|
+
ctx = Ichiban::HTMLCompiler::Context.new(:_current_path => @html_file.dest_rel_to_compiled)
|
13
|
+
inner_html = Eruby.new(::File.read(@html_file.abs)).evaluate(ctx)
|
14
|
+
|
15
|
+
# Compile Markdown if necessary
|
16
|
+
if (@html_file.abs.end_with?('.markdown') or @html_file.abs.end_with?('.md'))
|
17
|
+
inner_html = Ichiban::Markdown.compile(inner_html) # Will look for installed Markdown gems
|
18
|
+
end
|
19
|
+
|
20
|
+
# Layouts
|
21
|
+
wrap_in_layouts(ctx, inner_html)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Takes an instance of Ichiban::HTMLFile
|
25
|
+
def initialize(html_file)
|
26
|
+
@html_file = html_file
|
27
|
+
end
|
28
|
+
|
29
|
+
def wrap_in_layouts(ctx, inner_rhtml)
|
30
|
+
ctx.layout_stack.reverse.inject(inner_rhtml) do |html, layout_name|
|
31
|
+
layout_path = ::File.join(Ichiban.project_root, 'layouts', layout_name + '.html')
|
32
|
+
unless ::File.exists?(layout_path)
|
33
|
+
raise "Layout does not exist: #{layout_path}"
|
34
|
+
end
|
35
|
+
eruby = Eruby.new(
|
36
|
+
::File.read(layout_path),
|
37
|
+
:filename => layout_path
|
38
|
+
)
|
39
|
+
html = eruby.evaluate(ctx) { html }
|
40
|
+
Ichiban::Dependencies.update('.layout_dependencies.json', layout_name, @html_file.abs)
|
41
|
+
html
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Eruby < Erubis::Eruby
|
46
|
+
def add_preamble(src)
|
47
|
+
src << "@_erb_out = _buf = '';"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Context < Erubis::Context
|
52
|
+
include Ichiban::Helpers
|
53
|
+
include Erubis::XmlHelper
|
54
|
+
include ERB::Util # Give us #h
|
55
|
+
|
56
|
+
def layout_stack
|
57
|
+
@_layout_stack or ['default']
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/ichiban/logger.rb
CHANGED
@@ -4,16 +4,72 @@ module Ichiban
|
|
4
4
|
end
|
5
5
|
|
6
6
|
class Logger
|
7
|
+
def self.ansi?
|
8
|
+
@ansi
|
9
|
+
end
|
10
|
+
|
11
|
+
def ansi?
|
12
|
+
self.class.ansi?
|
13
|
+
end
|
14
|
+
|
7
15
|
def compilation(src, dst)
|
8
|
-
|
16
|
+
src = src.slice(Ichiban.project_root.length + 1..-1)
|
17
|
+
dst = dst.slice(Ichiban.project_root.length + 1..-1)
|
18
|
+
msg = "#{src} -> #{dst}"
|
19
|
+
if ansi?
|
20
|
+
msg = ANSI.color(msg, :green)
|
21
|
+
end
|
22
|
+
out msg
|
23
|
+
end
|
24
|
+
|
25
|
+
def deletion(src, dst = nil)
|
26
|
+
src = src.slice(Ichiban.project_root.length + 1..-1)
|
27
|
+
if dst
|
28
|
+
dst = dst.slice(Ichiban.project_root.length + 1..-1)
|
29
|
+
end
|
30
|
+
if dst
|
31
|
+
msg = "Deleted: #{src} -> #{dst}"
|
32
|
+
else
|
33
|
+
msg = "Deleted: #{src}"
|
34
|
+
end
|
35
|
+
if ansi?
|
36
|
+
msg = ANSI.color(msg, :cyan)
|
37
|
+
end
|
38
|
+
out msg
|
9
39
|
end
|
10
40
|
|
11
41
|
def exception(exc)
|
12
|
-
|
42
|
+
msg = "#{exc.class.to_s}: #{exc.message}\n" + exc.backtrace.collect { |line| ' ' + line }.join("\n")
|
43
|
+
if ansi?
|
44
|
+
msg = ANSI.color(msg, :red)
|
45
|
+
end
|
46
|
+
out msg
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize
|
50
|
+
@out = STDOUT
|
51
|
+
end
|
52
|
+
|
53
|
+
def out=(io)
|
54
|
+
@out = io
|
13
55
|
end
|
14
56
|
|
15
57
|
def out(msg)
|
16
|
-
puts msg
|
58
|
+
@out.puts msg
|
59
|
+
end
|
60
|
+
|
61
|
+
def warn(msg)
|
62
|
+
if ansi?
|
63
|
+
msg = ANSI.color(msg, :red)
|
64
|
+
end
|
65
|
+
out msg
|
66
|
+
end
|
67
|
+
|
68
|
+
begin
|
69
|
+
require 'ansi'
|
70
|
+
@ansi = true
|
71
|
+
rescue LoadError
|
72
|
+
Ichiban.logger.out("Try `gem install ansi` for colorized output")
|
17
73
|
end
|
18
74
|
end
|
19
75
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Ichiban
|
2
|
+
module Markdown
|
3
|
+
def self.compile(src)
|
4
|
+
require_markdown
|
5
|
+
case @strategy
|
6
|
+
when :redcarpet
|
7
|
+
@redcarpet.render(src)
|
8
|
+
when :maruku
|
9
|
+
Maruku.new(src).to_html
|
10
|
+
when :rdiscount
|
11
|
+
RDiscount.new(src).to_html
|
12
|
+
else
|
13
|
+
raise "unrecognized @strategy: #{@strategy}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.require_markdown
|
18
|
+
unless @markdown_loaded
|
19
|
+
case Ichiban.try_require('redcarpet', 'maruku', 'rdiscount')
|
20
|
+
when 'redcarpet'
|
21
|
+
@redcarpet = Redcarpet::Markdown.new(Redcarpet::Render::XHTML.new)
|
22
|
+
@strategy = :redcarpet
|
23
|
+
when 'maruku'
|
24
|
+
@strategy = :maruku
|
25
|
+
when 'rdiscount'
|
26
|
+
@strategy = :rdiscount
|
27
|
+
else
|
28
|
+
raise "Your Ichiban project contains at least one Markdown file. To process it, you need to install either the redcarpet or maruku gem."
|
29
|
+
end
|
30
|
+
@markdown_loaded = true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/ichiban/watcher.rb
CHANGED
@@ -1,7 +1,39 @@
|
|
1
1
|
module Ichiban
|
2
|
-
class Watcher
|
3
|
-
def
|
4
|
-
|
2
|
+
class Watcher
|
3
|
+
def initialize(options = {})
|
4
|
+
@options = {
|
5
|
+
:latency => 0.5
|
6
|
+
}.merge(options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def start
|
10
|
+
@listener = Listen.to(
|
11
|
+
::File.join(Ichiban.project_root, 'html')#,
|
12
|
+
#::File.join(Ichiban.project_root, 'assets')
|
13
|
+
)
|
14
|
+
.ignore(/.listen_test$/)
|
15
|
+
.latency(@options[:latency])
|
16
|
+
.change do |modified, added, deleted|
|
17
|
+
begin
|
18
|
+
(modified + added).each do |path|
|
19
|
+
if file = Ichiban::File.from_abs(path)
|
20
|
+
file.update
|
21
|
+
end
|
22
|
+
end
|
23
|
+
rescue => exc
|
24
|
+
Ichiban.logger.exception(exc)
|
25
|
+
end
|
26
|
+
deleted.each do |path|
|
27
|
+
Ichiban::Deleter.new.delete(path)
|
28
|
+
end
|
29
|
+
end.start(false) # nonblocking
|
30
|
+
end
|
31
|
+
|
32
|
+
def stop
|
33
|
+
if @listener
|
34
|
+
@listener.stop
|
35
|
+
@listener = nil
|
36
|
+
end
|
5
37
|
end
|
6
38
|
end
|
7
39
|
end
|
data/lib/ichiban.rb
CHANGED
@@ -1,25 +1,52 @@
|
|
1
|
-
|
1
|
+
# Standard lib
|
2
2
|
require 'fileutils'
|
3
|
+
require 'json'
|
4
|
+
require 'erb' # Just for the helpers
|
5
|
+
|
6
|
+
# Gems
|
3
7
|
require 'active_support/core_ext/class/attribute'
|
4
8
|
require 'active_support/core_ext/object/blank'
|
5
9
|
require 'active_support/inflector'
|
6
|
-
require 'erubis'
|
7
|
-
require 'maruku'
|
8
10
|
require 'sass'
|
11
|
+
require 'listen'
|
12
|
+
require 'erubis'
|
13
|
+
require 'rake'
|
9
14
|
|
10
|
-
# Order matters!
|
11
|
-
require 'ichiban/command'
|
12
|
-
require 'ichiban/layouts'
|
13
|
-
require 'ichiban/helpers'
|
14
|
-
require 'ichiban/compilation'
|
15
|
+
# Ichiban files. Order matters!
|
15
16
|
require 'ichiban/config'
|
16
|
-
require 'ichiban/erb_page'
|
17
|
-
require 'ichiban/files'
|
18
17
|
require 'ichiban/logger'
|
19
|
-
require 'ichiban/
|
20
|
-
require 'ichiban/
|
21
|
-
require 'ichiban/
|
22
|
-
require 'ichiban/
|
23
|
-
require 'ichiban/
|
24
|
-
require 'ichiban/
|
25
|
-
require 'ichiban/
|
18
|
+
require 'ichiban/command'
|
19
|
+
require 'ichiban/watcher'
|
20
|
+
require 'ichiban/deleter'
|
21
|
+
require 'ichiban/file'
|
22
|
+
require 'ichiban/helpers'
|
23
|
+
require 'ichiban/html_compiler'
|
24
|
+
require 'ichiban/markdown'
|
25
|
+
require 'ichiban/dependencies'
|
26
|
+
require 'ichiban/helpers'
|
27
|
+
|
28
|
+
module Ichiban
|
29
|
+
# In addition to setting the variable, this loads the config file
|
30
|
+
def self.project_root=(path)
|
31
|
+
@project_root = path
|
32
|
+
if path # It's valid to set project_root to nil, though this would likely only happen in tests
|
33
|
+
Ichiban::Config.load_file
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.project_root
|
38
|
+
@project_root
|
39
|
+
end
|
40
|
+
|
41
|
+
# Try to load the libraries
|
42
|
+
def self.try_require(*gems)
|
43
|
+
gems.each do |gem|
|
44
|
+
begin
|
45
|
+
require gem
|
46
|
+
return gem
|
47
|
+
rescue LoadError
|
48
|
+
end
|
49
|
+
end
|
50
|
+
false
|
51
|
+
end
|
52
|
+
end
|