jing 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +24 -9
- data/lib/jing.rb +87 -50
- data/lib/jing/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44ebf6b1808776a35ea1a2e98e7ec1738c2be1735ef7c9143c6e3f50a61668cf
|
4
|
+
data.tar.gz: '09fbb03a85e717c4211961e7f6cc247d8ac88bf5bb5c43fa56bbfa770526a33b'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40f13f6dfae9ff73d0c448559fd11dbef242ee545d31015cbabacc48528ee8bde845ee7d87b3a26b160d4d5c09cd653e081a8759aca58cb9f38dc16785ff632b
|
7
|
+
data.tar.gz: cbdf1e238a9f58035826d92981676dbeb906b632a543a4597519c2796ee25e701d706bc3baede9ca3954869f2f09fe9b03719b4fd482eee92f1678a5758ce24b
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -29,23 +29,36 @@ Or install it yourself as:
|
|
29
29
|
|
30
30
|
call `jing` on the command line or have a look at the code (it's tiny) :)
|
31
31
|
|
32
|
-
|
33
|
-
Creates a new folder `mypage` with a basic setup:
|
32
|
+
Creates a new folder `mypage` or updates an existing one and adds a basic setup:
|
34
33
|
|
35
34
|
$ jing create mypage
|
36
35
|
$ cd mypage
|
37
|
-
|
36
|
+
|
38
37
|
Build the current project:
|
39
|
-
|
38
|
+
|
40
39
|
$ jing build
|
41
|
-
|
40
|
+
|
42
41
|
Automatically build the page whenever a file in the project folder changes:
|
43
42
|
|
44
43
|
$ jing watch
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
$ jing watch -full_build true # to not skip uglifying js files (slower)
|
45
|
+
|
46
|
+
Serves the current projects _dst folder on `http://0.0.0.0:8000`:
|
47
|
+
|
48
48
|
$ jing serve
|
49
|
+
$ jing serve -no_auto_reload true # to not inject auto page reload code into html files
|
50
|
+
$ jing serve -port 1234 -root somepath # to change port and root directory
|
51
|
+
|
52
|
+
Options that work in all commands:
|
53
|
+
-src somepath # changes the source folder - default: ./ (current folder)
|
54
|
+
-dst somepath # changes the output folder - default: ./_dst
|
55
|
+
-layouts folder # changes the layouts folder - default: ./_layouts
|
56
|
+
-partials folder # changes the partials folder - default: ./_partials
|
57
|
+
|
58
|
+
|
59
|
+
Show current version
|
60
|
+
|
61
|
+
$ jing version
|
49
62
|
|
50
63
|
File endings work like Russian dolls: They get converted from outer to inner. Rails folks should be somewhat familiar with that but here it's a bit stricter.
|
51
64
|
|
@@ -55,6 +68,8 @@ Folders starting with `_` have special meaning, they generally won't get copied
|
|
55
68
|
|
56
69
|
`_layouts` holds layouts (TODO: explanation)
|
57
70
|
|
71
|
+
`_dst' holds the generated site
|
72
|
+
|
58
73
|
`.meta.yml` holds global meta variables available in templates when not overwritten
|
59
74
|
|
60
75
|
~~I'll try and add a basic example project soon.~~ Check out the examples folder. If you feel like giving this a try and have questions feel free to open an issue or reach out otherwise. Pull requests welcome too.
|
@@ -63,7 +78,7 @@ Folders starting with `_` have special meaning, they generally won't get copied
|
|
63
78
|
|
64
79
|
Extending is fairly easy.
|
65
80
|
|
66
|
-
`@converters` variable in the initialize method holds a bunch of converters. Just add one in the spirit of the others.
|
81
|
+
`@converters` variable in the initialize method holds a bunch of converters. Just add one in the spirit of the others.
|
67
82
|
|
68
83
|
Class methods that end in a bang `!` automatically are registered as cli commands. If you wish to add a command just add a bang-method and you should be done.
|
69
84
|
|
data/lib/jing.rb
CHANGED
@@ -1,8 +1,29 @@
|
|
1
|
-
|
1
|
+
%w[jing/version erb yaml fileutils time webrick bundler/inline].each { |e| require e }
|
2
|
+
gemfile { source('https://rubygems.org')
|
3
|
+
%w[filewatcher sassc typescript-node uglifier kramdown].each { |e| gem e }
|
4
|
+
}
|
2
5
|
|
3
|
-
|
6
|
+
module SymbolizeHelper
|
7
|
+
extend self
|
8
|
+
def symbolize_recursive(hash)
|
9
|
+
{}.tap{ |h| hash.each { |key, value| h[key.to_sym] = transform(value) } }
|
10
|
+
end
|
11
|
+
private
|
12
|
+
def transform(thing)
|
13
|
+
return symbolize_recursive(thing) if thing.is_a?(Hash)
|
14
|
+
return thing.map { |v| transform(v) } if thing.is_a?(Array)
|
15
|
+
thing
|
16
|
+
end
|
17
|
+
refine Hash do
|
18
|
+
def deep_symbolize_keys
|
19
|
+
SymbolizeHelper.symbolize_recursive(self)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
4
23
|
|
5
24
|
module Jing
|
25
|
+
using SymbolizeHelper
|
26
|
+
|
6
27
|
class Jing
|
7
28
|
attr_accessor :converters, :converter_extensions
|
8
29
|
|
@@ -11,44 +32,36 @@ module Jing
|
|
11
32
|
@dst = File.expand_path(opts[:dst] || File.join(@src, '_dst'))
|
12
33
|
@layouts = opts[:layouts] || '_layouts'
|
13
34
|
@partials = opts[:partials] || '_partials'
|
14
|
-
@
|
15
|
-
|
16
|
-
|
17
|
-
ERB.new(body).result(
|
18
|
-
}
|
19
|
-
|
35
|
+
@converters = {
|
36
|
+
%w[erb] => ->(body, meta, ctx){
|
37
|
+
ctx.local_variable_set(:meta, meta)
|
38
|
+
ERB.new(body).result(ctx)
|
39
|
+
},
|
40
|
+
%w[html htm] => ->(body, meta, ctx){
|
41
|
+
ctx.local_variable_set(:meta, meta)
|
20
42
|
if meta[:layout] && layout = Dir[File.join(@src, @layouts, "#{meta[:layout]}.*")].first
|
21
|
-
|
22
|
-
ERB.new(
|
43
|
+
ctx.local_variable_set(:body, body)
|
44
|
+
ERB.new(load_content(layout, meta)[:body]).result(ctx)
|
23
45
|
else
|
24
|
-
ERB.new(body).result(
|
46
|
+
ERB.new(body).result(ctx)
|
25
47
|
end
|
26
|
-
}
|
27
|
-
|
28
|
-
load_gem 'sassc'
|
48
|
+
},
|
49
|
+
%w[scss sass css] => ->(body, meta, ctx){
|
29
50
|
SassC::Engine.new(body, style: (meta[:style] || :compressed)).render
|
30
|
-
}
|
31
|
-
|
32
|
-
load_gem 'typescript-node'
|
51
|
+
},
|
52
|
+
%w[ts] =>->(body, meta, ctx){
|
33
53
|
TypeScript::Node.compile(body, '--target', (meta[:style] || 'ES5'))
|
34
|
-
}
|
35
|
-
|
36
|
-
load_gem 'uglifier'
|
54
|
+
},
|
55
|
+
%w[js] => ->(body, meta, ctx){
|
37
56
|
Uglifier.compile(body, harmony: true, compress: false, mangle: false, output: {ascii_only: true})
|
38
|
-
}
|
39
|
-
|
40
|
-
load_gem 'kramdown'
|
57
|
+
},
|
58
|
+
%w[md markdown] => ->(body, meta, ctx){
|
41
59
|
Kramdown::Document.new(body).to_html
|
42
|
-
}
|
43
|
-
|
60
|
+
}
|
61
|
+
}
|
44
62
|
|
45
|
-
@converter_extensions = @converters.
|
46
|
-
|
47
|
-
@meta = YAML.load(File.read(main_meta_file)).map { |k,v| [k.to_sym,v] }.to_h if File.exist?(main_meta_file)
|
48
|
-
end
|
49
|
-
|
50
|
-
def load_gem(name, opts={})
|
51
|
-
@loaded_gems[name] ||= gemfile { source(opts.delete(:source)||'https://rubygems.org'); gem(name, opts) }
|
63
|
+
@converter_extensions = @converters.keys.flatten
|
64
|
+
File.join(@src, '.meta.yml').tap{|e| @meta = File.exist?(e) ? YAML.load(File.read(e)).deep_symbolize_keys : {}}
|
52
65
|
end
|
53
66
|
|
54
67
|
def active_exts(file)
|
@@ -62,15 +75,15 @@ module Jing
|
|
62
75
|
end
|
63
76
|
|
64
77
|
def load_content(file, meta={})
|
65
|
-
body = File.open(file, 'rb').read
|
66
|
-
return {body: body, meta: meta} unless @converter_extensions.include?(File.extname(file)[1..-1])
|
78
|
+
body = File.open(file, 'rb'){|f|f.read}
|
79
|
+
return {body: body, meta: meta.deep_symbolize_keys} unless @converter_extensions.include?(File.extname(file)[1..-1])
|
67
80
|
body.match(/^(?:(---\s*\n.*?\n?)^(?:---\s*$\n?))?(.*)$/m)
|
68
81
|
meta.merge!(YAML.load($1).map { |k,v| [k.to_sym,v] }.to_h) if $1
|
69
|
-
{body: $2, meta: meta}
|
82
|
+
{body: $2, meta: meta.deep_symbolize_keys}
|
70
83
|
end
|
71
84
|
|
72
85
|
def render(file, meta={})
|
73
|
-
|
86
|
+
unless File.file?(file)
|
74
87
|
file = Dir[File.join(@src, @partials, "#{file}.*")].first
|
75
88
|
else
|
76
89
|
meta.merge!(file: file)
|
@@ -80,19 +93,19 @@ module Jing
|
|
80
93
|
body = content[:body]
|
81
94
|
exts = active_exts(file)
|
82
95
|
exts.each do |ext|
|
83
|
-
converter = @converters.find { |
|
84
|
-
body = converter ? converter
|
96
|
+
converter = @converters[@converters.keys.find { |k| k.include?(ext) }]
|
97
|
+
body = converter ? converter.call(body, content[:meta], binding) : body
|
85
98
|
end
|
86
|
-
puts "#{'%.4fs' % (Time.now-t)}\t#{file[@src.size+1..-1]} >#{exts.join('>')}> #{dstname(file, @dst)[@dst.size+1..-1]} (#{(body.size/1024.0)
|
99
|
+
puts "#{'%.4fs' % (Time.now-t)}\t#{file[@src.size+1..-1]} >#{exts.join('>')}> #{dstname(file, @dst)[@dst.size+1..-1]} (#{ '%.2fkb' % (body.size/1024.0)})"
|
87
100
|
body
|
88
101
|
rescue => e
|
89
102
|
puts "Error\t#{file[@src.size+1..-1]}\n\t#{e.message}\n#{e.backtrace.map{|x| "\t#{x}"}.join("\n")}"
|
90
103
|
end
|
91
104
|
|
92
105
|
def build!(opts={})
|
93
|
-
t = Time.now
|
94
|
-
FileUtils.
|
95
|
-
Dir.mkdir(@dst)
|
106
|
+
t,s = Time.now, 0
|
107
|
+
FileUtils.rm_rf("#{@dst}/.", secure: true)
|
108
|
+
Dir.mkdir(@dst) unless File.exist?(@dst)
|
96
109
|
Dir[File.join(@src, '**', '*')].each do |file|
|
97
110
|
next unless File.file?(file)
|
98
111
|
dir = File.dirname(file)[@src.size+1..-1]
|
@@ -100,18 +113,16 @@ module Jing
|
|
100
113
|
outfile = dstname(file, File.join(*[@dst, dir].compact))
|
101
114
|
out = render(file, @meta.merge(layout: dir))
|
102
115
|
FileUtils.mkdir_p(File.dirname(outfile))
|
103
|
-
File.open(outfile, 'wb').write(out)
|
116
|
+
File.open(outfile, 'wb'){|f|s+=f.write(out)}
|
104
117
|
end
|
105
|
-
puts "#{'%.4fs' % (Time.now-t)} total"
|
118
|
+
puts "#{'%.4fs' % (Time.now-t)}, #{'%.2fkb' % (s/1024.0)} total"
|
106
119
|
end
|
107
120
|
|
108
121
|
def watch!(opts={})
|
109
|
-
@converters
|
110
|
-
@converters<<{extensions: %w[js], handler: ->(body, meta, ctx){body}}
|
122
|
+
@converters[%w[js]] = ->(body, meta, ctx){puts 'skipping uglyfier'; body} unless opts[:full_build]
|
111
123
|
build!(opts)
|
112
|
-
load_gem('filewatcher')
|
113
124
|
Filewatcher.new([@src, '**', '*']).watch do |filename, event|
|
114
|
-
unless
|
125
|
+
unless filename.start_with?(@dst)
|
115
126
|
puts "\nWATCHED: #{filename}\t#{event}\t#{Time.now}"
|
116
127
|
build!(opts)
|
117
128
|
end
|
@@ -119,13 +130,39 @@ module Jing
|
|
119
130
|
end
|
120
131
|
|
121
132
|
def serve!(opts={})
|
122
|
-
|
133
|
+
api_route = opts[:api_route] || '/_J_I_N_G_'
|
134
|
+
inter = opts[:interval] || 2000
|
135
|
+
script = "<script>((t)=>{setInterval(()=>{fetch('#{api_route}').then(r=>r.json()).then((j)=>{if(Date.parse(j.modified)>t){fetch(document.location.pathname).then((r)=>{if(r.ok)window.location.reload(true)})}})}, #{inter})})(new Date().getTime())</script>"
|
136
|
+
srv = WEBrick::HTTPServer.new(Port: opts[:port] || 8000, DocumentRoot: opts[:root] || @dst)
|
137
|
+
|
138
|
+
srv.mount_proc('/') do |rq, rs|
|
139
|
+
path = File.join(@dst, rq.path == '/' ? '/index.html' : rq.path)
|
140
|
+
raise WEBrick::HTTPStatus::NotFound, "`#{rq.path}' not found." unless File.exist?(path)
|
141
|
+
st = File::stat(path)
|
142
|
+
rs['etag'] = sprintf("%x-%x-%x", st.ino, st.size, st.mtime.to_i)
|
143
|
+
rs['content-type'] = WEBrick::HTTPUtils::mime_type(path, WEBrick::HTTPUtils::DefaultMimeTypes)
|
144
|
+
rs['last-modified'] = st.mtime.httpdate
|
145
|
+
if rs['content-type'] == 'text/html'
|
146
|
+
rs.body = File.open(path, "rb").read.gsub(/(<\/body>)/im){"\n#{script}\n#{$1}"}
|
147
|
+
rs['content-length'] = rs.body.size.to_s
|
148
|
+
else
|
149
|
+
rs['content-length'] = st.size.to_s
|
150
|
+
rs.body = File.open(path, "rb")
|
151
|
+
end
|
152
|
+
end unless opts[:no_auto_reload]
|
153
|
+
|
154
|
+
srv.mount_proc(api_route) do |req, res|
|
155
|
+
res['Content-Type'] = 'application/json'
|
156
|
+
res.body = {modified: File.stat(@dst).ctime.iso8601}.to_json
|
157
|
+
end
|
158
|
+
trap('INT'){ srv.stop }
|
159
|
+
srv.start
|
123
160
|
end
|
124
161
|
|
125
162
|
def create!(opts={})
|
126
163
|
abort("usage: #{File.basename($0)} create -name <pathname>") unless opts[:name]
|
127
164
|
[@layouts, @partials].each { |e| FileUtils.mkdir_p(File.join(opts[:name], e)) }
|
128
|
-
File.write(File.join(opts[:name], '.meta.yml'), "---\ngenerator: jing
|
165
|
+
File.write(File.join(opts[:name], '.meta.yml'), "---\ngenerator: jing\nname: #{File.basename(opts[:name])}\n---\n")
|
129
166
|
end
|
130
167
|
|
131
168
|
def version!(opts={})
|
data/lib/jing/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pachacamac
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-03-
|
11
|
+
date: 2019-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|