linner 0.5.1 → 0.6.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.
- checksums.yaml +4 -4
- data/CHANGELOG +3 -0
- data/README.md +2 -1
- data/docs/config.md +18 -0
- data/lib/linner.rb +31 -0
- data/lib/linner/environment.rb +4 -0
- data/lib/linner/sprite.rb +124 -0
- data/lib/linner/templates/app/images/logo.png +0 -0
- data/lib/linner/templates/app/styles/app.scss +1 -0
- data/lib/linner/templates/app/views/index.html +1 -1
- data/lib/linner/templates/config.yml +28 -16
- data/lib/linner/version.rb +1 -1
- data/spec/linner/sprites_spec.rb +23 -0
- metadata +8 -5
- data/lib/linner/templates/app/styles/app.sass +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f40ea1d47371f91db7d8a653f4b8e30b7e2748d4
|
4
|
+
data.tar.gz: 422e0dbbc14c7420296ae953b08a89ac2d1a88c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9cbf841d6560337ced7e9fcd4577464e49e5aaa77ad1ba06c8911bbfabcb9afd05dcda48d372a5047dddeeb46a04289d577739a5924f2e9712624775bfc3041
|
7
|
+
data.tar.gz: b3f075eb30fb16b459d0ad0ec702cf7a2d8fbbfcc8f3e71a04faa3e23b1534a229660a2558bfe1e43ab0d5e13da71f2112916827f81d5a03487008645c3ac0db
|
data/CHANGELOG
CHANGED
data/README.md
CHANGED
@@ -16,7 +16,8 @@ Linner is a full-featured HTML5 application assembler.
|
|
16
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
|
+
* Supports `precompile` Javascript Templates from `src` to `desc`.
|
20
|
+
* Supports `sprite` PNG images from `src` to `desc`.
|
20
21
|
* Supports Real-time `concat` by `$ linner watch`.
|
21
22
|
* Supports `compress` by `$ linner build`.
|
22
23
|
* Supports `LiveReload` with [LiveReload Chrome Extention](https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei).
|
data/docs/config.md
CHANGED
@@ -53,6 +53,8 @@ the default configuration defines four groups: `scripts`, `styles`, `images` and
|
|
53
53
|
|
54
54
|
`precompile` defines precompile strategy of javascript templates for Linner. The `Dir.glob` of `value` will be concat to `key`
|
55
55
|
|
56
|
+
`sprite` defines sprite strategy of images for Linner. The `Dir.glob` of `value` will be sprite to `key`
|
57
|
+
|
56
58
|
`order` defines the order of this group files, and It's very useful when you `concat` your files. for example:
|
57
59
|
|
58
60
|
```yaml
|
@@ -64,6 +66,22 @@ order:
|
|
64
66
|
|
65
67
|
In the above example, if a group contains 5 files, `vendor/jquery-1.10.2.js` will be the first, and `vendor/underscore.js` will be the last file.
|
66
68
|
|
69
|
+
## `sprites`
|
70
|
+
|
71
|
+
`sprites` defines application sprite stategy. `sprites` support pseudo class of css, if your file's basename end with `_active`, the generated css will be `.active`. if your file's basename end with `_hover`, the generated css will be `:hover`, eg: `arrow_hover.png` will be `.selector-arrow:hover { ... }`
|
72
|
+
|
73
|
+
Example:
|
74
|
+
|
75
|
+
```yaml
|
76
|
+
sprites:
|
77
|
+
# sprite image output path
|
78
|
+
path: "/images/"
|
79
|
+
# css selector
|
80
|
+
selector: ".icon-"
|
81
|
+
# css url background: url(/images/icon.png)
|
82
|
+
url: "http://s3.amazonaws.com/"
|
83
|
+
```
|
84
|
+
|
67
85
|
## `modules`
|
68
86
|
|
69
87
|
`modules` defines application module strategy, The default wrapper is `cmd`.
|
data/lib/linner.rb
CHANGED
@@ -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/sprite"
|
8
9
|
require "linner/bundler"
|
9
10
|
require "linner/reactor"
|
10
11
|
require "linner/wrapper"
|
@@ -68,6 +69,7 @@ module Linner
|
|
68
69
|
def perform(*asset)
|
69
70
|
env.groups.each do |config|
|
70
71
|
precompile(config) if config["precompile"]
|
72
|
+
sprite(config) if config["sprite"]
|
71
73
|
end
|
72
74
|
env.groups.each do |config|
|
73
75
|
copy(config) if config["copy"]
|
@@ -106,6 +108,14 @@ module Linner
|
|
106
108
|
end
|
107
109
|
end
|
108
110
|
|
111
|
+
def sprite(config)
|
112
|
+
config["sprite"].each do |dest, pattern|
|
113
|
+
matches = Dir.glob(pattern).sort_by(&:downcase)
|
114
|
+
next if matches.select { |p| cache.miss? p }.empty?
|
115
|
+
paint_sprite(dest, matches)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
109
119
|
def revision
|
110
120
|
dump_manifest
|
111
121
|
[env.revision].flatten.each do |rev|
|
@@ -115,6 +125,27 @@ module Linner
|
|
115
125
|
end
|
116
126
|
end
|
117
127
|
|
128
|
+
def paint_sprite(dest, images)
|
129
|
+
images = images.map do |path|
|
130
|
+
ImageProxy.new(path, ChunkyPNG::Image.from_file(path))
|
131
|
+
end
|
132
|
+
sprite = Sprite.new(images).pack!
|
133
|
+
map = ChunkyPNG::Image.new(sprite.root[:w], sprite.root[:h], ChunkyPNG::Color::TRANSPARENT)
|
134
|
+
|
135
|
+
sprite.images.each do |image|
|
136
|
+
map.compose!(image.image, image.left, image.top)
|
137
|
+
end
|
138
|
+
|
139
|
+
name = File.basename(dest).sub(/[^.]+\z/, "png")
|
140
|
+
path = File.join(env.public_folder, env.sprites["path"], File.basename(dest).sub(/[^.]+\z/, "png"))
|
141
|
+
FileUtils.mkdir_p File.dirname(path)
|
142
|
+
map.save path
|
143
|
+
|
144
|
+
asset = Asset.new(File.join env.public_folder, dest)
|
145
|
+
asset.content = sprite.generate_style(env.sprites, name)
|
146
|
+
asset.write
|
147
|
+
end
|
148
|
+
|
118
149
|
def write_template(dest, child_assets)
|
119
150
|
asset = Asset.new(File.join env.public_folder, dest)
|
120
151
|
content = child_assets.inject("") {|s, m| s << cache[m].content}
|
data/lib/linner/environment.rb
CHANGED
@@ -0,0 +1,124 @@
|
|
1
|
+
module Linner
|
2
|
+
ImageProxy = Struct.new(:path, :image, :top, :left) do
|
3
|
+
def width
|
4
|
+
image.width
|
5
|
+
end
|
6
|
+
|
7
|
+
def height
|
8
|
+
image.height
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Sprite
|
13
|
+
|
14
|
+
attr_accessor :root, :images
|
15
|
+
|
16
|
+
def initialize(images)
|
17
|
+
@images = images.sort do |a, b|
|
18
|
+
diff = [b.width, b.height].max <=> [a.width, a.height].max
|
19
|
+
diff = [b.width, b.height].min <=> [a.width, a.height].min if diff.zero?
|
20
|
+
diff = b.height <=> a.height if diff.zero?
|
21
|
+
diff = b.width <=> a.width if diff.zero?
|
22
|
+
diff
|
23
|
+
end
|
24
|
+
|
25
|
+
@root = { :x => 0, :y => 0, :w => @images.first.width, :h => @images.first.height}
|
26
|
+
end
|
27
|
+
|
28
|
+
def pack!
|
29
|
+
@images.each do |image|
|
30
|
+
if block = find_block(@root, image)
|
31
|
+
place_image(block, image)
|
32
|
+
split_block(block, image)
|
33
|
+
else
|
34
|
+
@root = expand_root(@root, image)
|
35
|
+
redo
|
36
|
+
end
|
37
|
+
end
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def generate_style(config, name)
|
42
|
+
selector = config["selector"] || ".icon-"
|
43
|
+
@images.inject("") do |style, image|
|
44
|
+
logical_path = Asset.new(image.path).logical_path
|
45
|
+
selector_with_pseudo_class = logical_path.chomp(File.extname(logical_path))
|
46
|
+
.gsub("/", "-")
|
47
|
+
.gsub("_active", ".active")
|
48
|
+
.gsub("_hover", ":hover")
|
49
|
+
.gsub("_", "-")
|
50
|
+
style <<
|
51
|
+
"#{selector}#{selector_with_pseudo_class} {
|
52
|
+
width: #{image.width}px;
|
53
|
+
height: #{image.height}px;
|
54
|
+
background: url(#{File.join config['url'], name}) -#{image.left}px -#{image.top}px no-repeat;
|
55
|
+
}
|
56
|
+
"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def find_block(root, image)
|
62
|
+
if root[:used]
|
63
|
+
find_block(root[:right], image) || find_block(root[:down], image)
|
64
|
+
elsif (image.width <= root[:w]) && (image.height <= root[:h])
|
65
|
+
root
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def place_image(block, image)
|
70
|
+
image.top = block[:y]
|
71
|
+
image.left = block[:x]
|
72
|
+
end
|
73
|
+
|
74
|
+
def split_block(block, image)
|
75
|
+
block[:used] = true
|
76
|
+
block[:down] = {:x => block[:x], :y => block[:y] + image.width, :w => block[:w], :h => block[:h] - image.height}
|
77
|
+
block[:right] = {:x => block[:x] + image.width, :y => block[:y], :w => block[:w] - image.width, :h => image.height}
|
78
|
+
end
|
79
|
+
|
80
|
+
def expand_root(root, image)
|
81
|
+
can_expand_down = (image.width <= root[:w])
|
82
|
+
can_expand_right = (image.height <= root[:h])
|
83
|
+
|
84
|
+
should_expand_down = can_expand_down && (root[:w] >= (root[:h] + image.height))
|
85
|
+
should_expand_right = can_expand_right && (root[:h] >= (root[:w] + image.width))
|
86
|
+
|
87
|
+
if should_expand_right
|
88
|
+
expand_right(root, image.width)
|
89
|
+
elsif should_expand_down
|
90
|
+
expand_down(root, image.height)
|
91
|
+
elsif can_expand_right
|
92
|
+
expand_right(root, image.width)
|
93
|
+
elsif can_expand_down
|
94
|
+
expand_down(root, image.height)
|
95
|
+
else
|
96
|
+
raise RuntimeError, "Crashed!"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def expand_right(root, width)
|
101
|
+
Hash[
|
102
|
+
:used => true,
|
103
|
+
:x => 0,
|
104
|
+
:y => 0,
|
105
|
+
:w => root[:w] + width,
|
106
|
+
:h => root[:h],
|
107
|
+
:down => root,
|
108
|
+
:right => { :x => root[:w], :y => 0, :w => width, :h => root[:h] }
|
109
|
+
]
|
110
|
+
end
|
111
|
+
|
112
|
+
def expand_down(root, height)
|
113
|
+
Hash[
|
114
|
+
:used => true,
|
115
|
+
:x => 0,
|
116
|
+
:y => 0,
|
117
|
+
:w => root[:w],
|
118
|
+
:h => root[:h] + height,
|
119
|
+
:down => { :x => 0, :y => root[:h], :w => root[:w], :h => height },
|
120
|
+
:right => root
|
121
|
+
]
|
122
|
+
end
|
123
|
+
end # Sprite
|
124
|
+
end # Linner
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
@import "icons";
|
@@ -12,7 +12,7 @@
|
|
12
12
|
<!--[if lt IE 7]>
|
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
|
+
<div class="icon-logo"></div>
|
16
16
|
<script src="/scripts/vendor.js"></script>
|
17
17
|
<script src="/scripts/app.js"></script>
|
18
18
|
<script src="/scripts/templates.js"></script>
|
@@ -2,38 +2,50 @@ paths:
|
|
2
2
|
public: "public"
|
3
3
|
groups:
|
4
4
|
scripts:
|
5
|
+
paths:
|
6
|
+
- app/scripts
|
5
7
|
concat:
|
6
8
|
"/scripts/app.js": "app/**/*.{js,coffee}"
|
7
9
|
"/scripts/vendor.js": "vendor/**/*.{js,coffee}"
|
8
10
|
order:
|
9
|
-
-
|
10
|
-
-
|
11
|
-
-
|
11
|
+
- vendor/jquery-1.10.2.js
|
12
|
+
- ...
|
13
|
+
- app/scripts/app.coffee
|
12
14
|
styles:
|
15
|
+
paths:
|
16
|
+
- app/styles
|
13
17
|
concat:
|
14
18
|
"/styles/app.css": "app/styles/**/[a-z]*.{css,scss,sass}"
|
15
19
|
images:
|
16
|
-
|
17
|
-
|
20
|
+
paths:
|
21
|
+
- app/images
|
22
|
+
sprite:
|
23
|
+
"../app/images/icons.scss": "app/images/**/*.png"
|
18
24
|
views:
|
25
|
+
paths:
|
26
|
+
- app/views
|
19
27
|
copy:
|
20
28
|
"/": "app/views/**/*.html"
|
21
29
|
templates:
|
22
30
|
paths:
|
23
|
-
-
|
31
|
+
- app/templates
|
24
32
|
precompile:
|
25
33
|
"/scripts/templates.js": "app/templates/**/*.hbs"
|
26
34
|
modules:
|
27
|
-
wrapper:
|
28
|
-
ignored:
|
29
|
-
definition:
|
30
|
-
|
35
|
+
wrapper: cmd
|
36
|
+
ignored: vendor/**/*
|
37
|
+
definition: /scripts/app.js
|
38
|
+
sprites:
|
39
|
+
url: /images/
|
40
|
+
path: /images/
|
41
|
+
selector: .icon-
|
42
|
+
revision: index.html
|
31
43
|
notification: true
|
32
44
|
bundles:
|
33
|
-
|
34
|
-
version:
|
35
|
-
url:
|
36
|
-
|
37
|
-
version:
|
38
|
-
url:
|
45
|
+
jquery.js:
|
46
|
+
version: 1.10.2
|
47
|
+
url: http://code.jquery.com/jquery-1.10.2.js
|
48
|
+
handlebars.js:
|
49
|
+
version: 1.0.0
|
50
|
+
url: https://raw.github.com/wycats/handlebars.js/1.0.0/dist/handlebars.runtime.js
|
39
51
|
|
data/lib/linner/version.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Sprite do
|
4
|
+
before(:all) do
|
5
|
+
MockImage = Struct.new :width, :height, :top, :left
|
6
|
+
@sprites = Environment.new(root.join "config.yml").sprites
|
7
|
+
image0 = MockImage.new 2, 3
|
8
|
+
image1 = MockImage.new 5, 3
|
9
|
+
image2 = MockImage.new 6, 2
|
10
|
+
image3 = MockImage.new 2, 24
|
11
|
+
image4 = MockImage.new 1, 3
|
12
|
+
@images = [image0, image1, image2, image3, image4]
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should be an empty hash" do
|
16
|
+
@sprites.should eql(Hash.new)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should be fit in blocks" do
|
20
|
+
sprites = Sprite.new(@images)
|
21
|
+
sprites.pack!
|
22
|
+
end
|
23
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: linner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Saito
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: reel
|
@@ -263,10 +263,12 @@ files:
|
|
263
263
|
- lib/linner/helper.rb
|
264
264
|
- lib/linner/notifier.rb
|
265
265
|
- lib/linner/reactor.rb
|
266
|
+
- lib/linner/sprite.rb
|
266
267
|
- lib/linner/template.rb
|
267
268
|
- lib/linner/templates/app/images/.gitkeep
|
269
|
+
- lib/linner/templates/app/images/logo.png
|
268
270
|
- lib/linner/templates/app/scripts/app.coffee
|
269
|
-
- lib/linner/templates/app/styles/app.
|
271
|
+
- lib/linner/templates/app/styles/app.scss
|
270
272
|
- lib/linner/templates/app/templates/welcome.hbs
|
271
273
|
- lib/linner/templates/app/views/index.html
|
272
274
|
- lib/linner/templates/bin/server
|
@@ -283,6 +285,7 @@ files:
|
|
283
285
|
- spec/linner/bundler_spec.rb
|
284
286
|
- spec/linner/environment_spec.rb
|
285
287
|
- spec/linner/helper_spec.rb
|
288
|
+
- spec/linner/sprites_spec.rb
|
286
289
|
- spec/linner/template_spec.rb
|
287
290
|
- spec/linner/wrapper_spec.rb
|
288
291
|
- spec/spec_helper.rb
|
@@ -309,7 +312,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
309
312
|
version: '0'
|
310
313
|
requirements: []
|
311
314
|
rubyforge_project:
|
312
|
-
rubygems_version: 2.
|
315
|
+
rubygems_version: 2.0.14
|
313
316
|
signing_key:
|
314
317
|
specification_version: 4
|
315
318
|
summary: HTML5 Application Assembler
|
@@ -320,7 +323,7 @@ test_files:
|
|
320
323
|
- spec/linner/bundler_spec.rb
|
321
324
|
- spec/linner/environment_spec.rb
|
322
325
|
- spec/linner/helper_spec.rb
|
326
|
+
- spec/linner/sprites_spec.rb
|
323
327
|
- spec/linner/template_spec.rb
|
324
328
|
- spec/linner/wrapper_spec.rb
|
325
329
|
- spec/spec_helper.rb
|
326
|
-
has_rdoc:
|
File without changes
|