linner 0.4.6 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 22e8e5dc49bf60b631d9932980705923d288eb05
4
- data.tar.gz: d528f466a6cf1f464a602b40fd205ea051f40b8c
3
+ metadata.gz: d8883d113979a23a06f305ffaa96e7c224e3e08d
4
+ data.tar.gz: eae9dcb29be6f8b59a5696cc11d84504abc7145d
5
5
  SHA512:
6
- metadata.gz: 7de696f89676b8d83d6848cab9230e72bb4ad369dc2e537beefb5b723f6be54cca8f984c1d5447049a646a80cc27c1566b42f0dfeb3559d258581e3c42a555bc
7
- data.tar.gz: 8b9db856716048223a35fbd7117ce861ff7d9d3d66a449f1648316c8ed4f87ae056cee7930398d54709e1cef7774e3fbd0ebdd27d6eb66e8216bcaec2811862c
6
+ metadata.gz: a9e63c8c9c462d9faa0aecc39885f5e74429ee366d773eccc09c02d99b408628031d3ef4c6dd5429b3f86e90333ebd6b88c88d04bd8ad10b6af4d6e4d1d47cf1
7
+ data.tar.gz: 1d4fd2a6f5e681f9a0c7b361e5fde514a2efbfa32850b0f877c816aeb552db1baca5238a23afef2a429b63dadea92103640df9da0ac4b5747acf4b7fe9888b84
data/CHANGELOG CHANGED
@@ -1,3 +1,6 @@
1
+ v 0.5.0
2
+ - linner command now provides `check` and `install` commands to check and install vendor dependencies
3
+
1
4
  v 0.4.6
2
5
  - compat terminal-notifier with OS X mavericks
3
6
 
data/README.md CHANGED
@@ -13,9 +13,10 @@ Linner is a full-featured HTML5 application assembler.
13
13
  * Fast!
14
14
  * Supports `Sass`, `Compass` and `Coffee`.
15
15
  * Supports OS X Lion and Mountaion Lion Notifications.
16
- * Supports Modular Javascript, All your code will be wrap by `cmd`.
16
+ * Supports Modular Javascript, All your code will be wrapped by `cmd`.
17
17
  * Supports `concat` code by `config file` not `directive processor`.
18
18
  * Supports `copy` code from `src` to `dest`.
19
+ * Supports `precompile` Javascript Templates from `src` to `desc`
19
20
  * Supports Real-time `concat` by `$ linner watch`.
20
21
  * Supports `compress` by `$ linner build`.
21
22
  * Supports `LiveReload` with [LiveReload Chrome Extention](https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei).
@@ -4,6 +4,14 @@
4
4
 
5
5
  Create new brunch project.
6
6
 
7
+ ## `linner check`
8
+
9
+ Check linner bundles
10
+
11
+ ## `linner install`
12
+
13
+ Install linner bundles
14
+
7
15
  ## `linner watch`
8
16
 
9
17
  Watch linner directory and rebuild if something changed.
@@ -51,6 +51,8 @@ the default configuration defines four groups: `scripts`, `styles`, `images` and
51
51
 
52
52
  `copy` defines copy strategy of files in Linner. The `Dir.glob` of `value` will be copy to `key` folder.
53
53
 
54
+ `precompile` defines precompile strategy of javascript templates for Linner. The `Dir.glob` of `value` will be concat to `key`
55
+
54
56
  `order` defines the order of this group files, and It's very useful when you `concat` your files. for example:
55
57
 
56
58
  ```yaml
@@ -102,3 +104,25 @@ Default:
102
104
  ```yaml
103
105
  notification: true
104
106
  ```
107
+
108
+ ## `bundles`
109
+
110
+ `bundles` defines application's library dependencies, the dependencies will be copied to `vendor` folder.
111
+
112
+ For example:
113
+
114
+ ```yaml
115
+ bundles:
116
+ "jquery.js":
117
+ version: "1.10.2"
118
+ url: "http://code.jquery.com/jquery-1.10.2.js"
119
+ "underscore.js":
120
+ version: "1.5.2"
121
+ url: https://raw.github.com/jashkenas/underscore/1.5.2/underscore.js
122
+ "backbone.js":
123
+ version: "1.1.0"
124
+ url: "https://raw.github.com/jashkenas/backbone/1.1.0/backbone.js"
125
+ "handlebars.js":
126
+ version: "1.0.0"
127
+ url: "https://raw.github.com/wycats/handlebars.js/1.0.0/dist/handlebars.js"
128
+ ```
@@ -5,6 +5,7 @@ require "linner/command"
5
5
  require "linner/asset"
6
6
  require "linner/cache"
7
7
  require "linner/helper"
8
+ require "linner/bundler"
8
9
  require "linner/reactor"
9
10
  require "linner/wrapper"
10
11
  require "linner/template"
@@ -65,6 +66,9 @@ module Linner
65
66
  end
66
67
 
67
68
  def perform(*asset)
69
+ env.groups.each do |config|
70
+ precompile(config) if config["precompile"]
71
+ end
68
72
  env.groups.each do |config|
69
73
  copy(config) if config["copy"]
70
74
  concat(config) if config["concat"]
@@ -72,7 +76,7 @@ module Linner
72
76
  revision if compile? and env.revision
73
77
  end
74
78
 
75
- private
79
+ private
76
80
  def concat(config)
77
81
  config["concat"].each_with_index do |pair, index|
78
82
  dest, pattern, order = pair.first, pair.last, config["order"]||[]
@@ -94,6 +98,14 @@ private
94
98
  end
95
99
  end
96
100
 
101
+ def precompile(config)
102
+ config["precompile"].each do |dest, pattern|
103
+ matches = Dir.glob(pattern).sort_by(&:downcase)
104
+ next if matches.select { |p| cache.miss? p }.empty?
105
+ write_template(dest, matches)
106
+ end
107
+ end
108
+
97
109
  def revision
98
110
  dump_manifest
99
111
  [env.revision].flatten.each do |rev|
@@ -103,11 +115,17 @@ private
103
115
  end
104
116
  end
105
117
 
106
- private
118
+ def write_template(dest, child_assets)
119
+ asset = Asset.new(File.join env.public_folder, dest)
120
+ content = child_assets.inject("") {|s, m| s << cache[m].content}
121
+ asset.content = Wrapper::Template.definition(content)
122
+ asset.compress if compile?
123
+ asset.write
124
+ end
107
125
 
108
126
  def write_asset(dest, child_assets)
109
127
  asset = Asset.new(File.join env.public_folder, dest)
110
- definition = (asset.path == env.definition ? Wrapper.definition : "")
128
+ definition = (asset.path == env.definition ? Wrapper::Module.definition : "")
111
129
  asset.content = child_assets.inject(definition) {|s, m| s << cache[m].content}
112
130
  asset.compress if compile?
113
131
  asset.write
@@ -49,7 +49,11 @@ module Linner
49
49
  end
50
50
 
51
51
  def wrap(source)
52
- Wrapper.wrap(logical_path.chomp(File.extname logical_path), source)
52
+ if javascript?
53
+ Wrapper::Module.wrap(logical_path.chomp(File.extname logical_path), source)
54
+ else
55
+ Wrapper::Template.wrap(logical_path.chomp(File.extname logical_path), source)
56
+ end
53
57
  end
54
58
 
55
59
  def javascript?
@@ -60,8 +64,12 @@ module Linner
60
64
  Tilt[path] and Tilt[path].default_mime_type == "text/css"
61
65
  end
62
66
 
67
+ def template?
68
+ Tilt[path] and Tilt[path].default_mime_type == "text/template"
69
+ end
70
+
63
71
  def wrappable?
64
- !!(self.javascript? and !Linner.env.modules_ignored.include?(@path))
72
+ !!(self.javascript? and !Linner.env.modules_ignored.include?(@path) or self.template?)
65
73
  end
66
74
 
67
75
  def write
@@ -0,0 +1,66 @@
1
+ require "digest"
2
+ require "fileutils"
3
+ require "open-uri"
4
+
5
+ module Linner
6
+ class Bundler
7
+ VENDOR = Pathname(".").expand_path.join "vendor"
8
+ REPOSITORY = File.expand_path "~/.linner/bundles"
9
+
10
+ Bundle = Struct.new(:name, :version, :url) do
11
+ def path
12
+ File.join(REPOSITORY, name, version, File.basename(url))
13
+ end
14
+ end
15
+
16
+ def initialize(bundles)
17
+ @bundles = []
18
+ bundles.each do |name, props|
19
+ @bundles << Bundle.new(name, props["version"], props["url"])
20
+ end
21
+ end
22
+
23
+ def check
24
+ return [false, "Bundles didn't exsit!"] unless File.exists? REPOSITORY
25
+ @bundles.each do |bundle|
26
+ unless File.exists?(bundle.path) and File.exists?(File.join(VENDOR, bundle.name))
27
+ return [false, "Bundle #{bundle.name} v#{bundle.version} didn't match!"]
28
+ end
29
+ end
30
+ return [true, "Perfect bundled, ready to go!"]
31
+ end
32
+
33
+ def install
34
+ unless File.exists? REPOSITORY
35
+ FileUtils.mkdir_p(REPOSITORY)
36
+ end
37
+ @bundles.each do |bundle|
38
+ if bundle.version != "master"
39
+ next if File.exists?(bundle.path) and File.exists?(File.join(VENDOR, bundle.name))
40
+ end
41
+ puts "Installing #{bundle.name} #{bundle.version}..."
42
+ install_to_repository bundle.url, bundle.path
43
+ link_to_vendor bundle.path, File.join(VENDOR, bundle.name)
44
+ end
45
+ end
46
+
47
+ def perform
48
+ check and install
49
+ end
50
+
51
+ private
52
+ def install_to_repository(url, path)
53
+ FileUtils.mkdir_p File.dirname(path)
54
+ File.open(path, "w") do |dist|
55
+ open(url, "r:UTF-8") {|file| dist.write file.read}
56
+ end
57
+ end
58
+
59
+ def link_to_vendor(path, dist)
60
+ if !File.exist?(dist) or Digest::MD5.file(path).hexdigest != Digest::MD5.file(dist).hexdigest
61
+ FileUtils.mkdir_p File.dirname(dist)
62
+ FileUtils.cp path, dist
63
+ end
64
+ end
65
+ end
66
+ end
@@ -15,18 +15,37 @@ module Linner
15
15
  puts Linner::VERSION
16
16
  end
17
17
 
18
+ desc "check", "check dependencies"
19
+ def check
20
+ message = Linner::Bundler.new(env.bundles).check
21
+ puts (message.first ? "🍵 :" : "👻 :") + message.last
22
+ end
23
+
24
+ desc "install", "install dependencies"
25
+ def install
26
+ begin
27
+ Linner::Bundler.new(env.bundles).perform
28
+ rescue
29
+ puts "👻 : Install failed!"
30
+ puts $!
31
+ return
32
+ end
33
+ puts "🍵 : Perfect installed all bundles!"
34
+ end
35
+
18
36
  desc "build", "build assets"
19
37
  def build
20
38
  Linner.compile = true
21
39
  clean
22
- Notifier.profile { Linner.perform }
40
+ perform
23
41
  end
24
42
 
25
43
  desc "watch", "watch assets"
26
44
  def watch
27
45
  trap(:INT) { exit! }
28
46
  clean
29
- perform_proc.call
47
+ Linner::Bundler.new(env.bundles).perform
48
+ perform
30
49
  watch_for_perform
31
50
  watch_for_reload
32
51
  sleep
@@ -48,20 +67,20 @@ module Linner
48
67
  Linner.env
49
68
  end
50
69
 
51
- def perform_proc
52
- @proc ||= Proc.new do
53
- begin
54
- Notifier.profile{ Linner.perform }
55
- rescue
56
- Notifier.error $!
70
+ def perform
71
+ begin
72
+ Notifier.profile do
73
+ Linner.perform
57
74
  end
75
+ rescue
76
+ Notifier.error $!
58
77
  end
59
78
  end
60
79
 
61
80
  def watch_for_perform
62
81
  Listen.to env.watched_paths do |modified, added, removed|
63
82
  Linner.cache.expire_by(modified + added + removed)
64
- perform_proc.call
83
+ perform
65
84
  end
66
85
  end
67
86
 
@@ -5,7 +5,7 @@ module Linner
5
5
  class Compressor
6
6
 
7
7
  def self.compress(asset)
8
- if asset.javascript?
8
+ if asset.javascript? or asset.template?
9
9
  Uglifier.compile asset.content, comments: "none"
10
10
  elsif asset.stylesheet?
11
11
  CSSminify.new.compress asset.content
@@ -31,6 +31,10 @@ module Linner
31
31
  end
32
32
  end
33
33
 
34
+ def bundles
35
+ @env["bundles"] || []
36
+ end
37
+
34
38
  def modules_ignored
35
39
  Dir.glob(@env["modules"]["ignored"])
36
40
  end
@@ -1,6 +1,7 @@
1
1
  require "tilt"
2
2
  require "sass"
3
3
  require "compass"
4
+ require "handlebars.rb"
4
5
  require "coffee_script"
5
6
 
6
7
  module Tilt
@@ -30,8 +31,19 @@ module Tilt
30
31
  end
31
32
  end
32
33
 
34
+ class HandlebarsTemplate < Template
35
+ self.default_mime_type = 'text/template'
36
+
37
+ def prepare; end
38
+
39
+ def evaluate(scope, locals, &block)
40
+ @output ||= Handlebars.precompile(data)
41
+ end
42
+ end
43
+
33
44
  register CSSTemplate, "css"
34
45
  register JavascriptTemplate, "js"
46
+ register HandlebarsTemplate, "hbs", "handlebars"
35
47
 
36
48
  register CompassSassTemplate, "sass"
37
49
  prefer CompassSassTemplate
@@ -1,2 +1,3 @@
1
1
  module.exports = ->
2
+ $("body").append Handlebars.templates["welcome"]()
2
3
  console.info "log from app!"
@@ -0,0 +1 @@
1
+ <p>Hello world! This is Linner Boilerplate.</p>
@@ -13,10 +13,9 @@
13
13
  <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
14
14
  <![endif]-->
15
15
 
16
- <p>Hello world! This is Linner Boilerplate.</p>
17
-
18
16
  <script src="/scripts/vendor.js"></script>
19
17
  <script src="/scripts/app.js"></script>
18
+ <script src="/scripts/templates.js"></script>
20
19
  <script>require("app")()</script>
21
20
  </body>
22
21
  </html>
@@ -17,10 +17,23 @@ groups:
17
17
  "/images/": "app/images/**/*.{png,gif}"
18
18
  views:
19
19
  copy:
20
- "/": "app/views/**/*.{html,hbs}"
20
+ "/": "app/views/**/*.html"
21
+ templates:
22
+ paths:
23
+ - "app/templates"
24
+ precompile:
25
+ "/scripts/templates.js": "app/templates/**/*.hbs"
21
26
  modules:
22
27
  wrapper: "cmd"
23
28
  ignored: "vendor/**/*"
24
29
  definition: "/scripts/app.js"
25
30
  revision: "index.html"
26
31
  notification: true
32
+ bundles:
33
+ "jquery.js":
34
+ version: "1.10.2"
35
+ url: "http://code.jquery.com/jquery-1.10.2.js"
36
+ "handlebars.js":
37
+ version: "1.0.0"
38
+ url: "https://raw.github.com/wycats/handlebars.js/1.0.0/dist/handlebars.runtime.js"
39
+
@@ -0,0 +1 @@
1
+ .gitkeep
@@ -0,0 +1 @@
1
+ .gitkeep
@@ -1,3 +1,3 @@
1
1
  module Linner
2
- VERSION = "0.4.6"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -1,17 +1,32 @@
1
1
  module Linner
2
- class Wrapper
3
- WRAPPER =
4
- 'this.require.define({"%s":' +
5
- 'function(exports, require, module){' +
6
- '%s' +
7
- ";}});\n"
2
+ module Wrapper
3
+ class Module
4
+ def self.wrap(name, content)
5
+ <<-WRAPPER
6
+ this.require.define({"#{name}":function(exports, require, module){#{content};}});
7
+ WRAPPER
8
+ end
8
9
 
9
- def self.wrap(name, content)
10
- WRAPPER % [name, content]
10
+ def self.definition
11
+ File.read(File.join File.dirname(__FILE__), "../../vendor", "require_definition.js")
12
+ end
11
13
  end
12
14
 
13
- def self.definition
14
- File.read(File.join File.dirname(__FILE__), "../../vendor", "require_definition.js")
15
+ class Template
16
+ def self.wrap(name, content)
17
+ <<-WRAPPER
18
+ templates["#{name}"] = template(#{content});
19
+ WRAPPER
20
+ end
21
+
22
+ def self.definition(content)
23
+ <<-DEFINITION
24
+ (function() {
25
+ var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
26
+ #{content}
27
+ })();
28
+ DEFINITION
29
+ end
15
30
  end
16
31
  end
17
32
  end