palimpsest 0.0.1
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 +7 -0
- data/.gitignore +18 -0
- data/.kateproject +4 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +4 -0
- data/Guardfile +10 -0
- data/LICENSE.txt +20 -0
- data/README.md +70 -0
- data/Rakefile +7 -0
- data/lib/palimpsest/assets.rb +189 -0
- data/lib/palimpsest/environment.rb +263 -0
- data/lib/palimpsest/utility.rb +69 -0
- data/lib/palimpsest/version.rb +4 -0
- data/lib/palimpsest.rb +9 -0
- data/palimpsest.gemspec +40 -0
- data/spec/assets_spec.rb +360 -0
- data/spec/environment_spec.rb +305 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/utility_spec.rb +56 -0
- metadata +297 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bb9471fad6a53da1e1cc97a04c7883e81bfa6756
|
4
|
+
data.tar.gz: ad2694a1fecbbe589e1bd2287d003398c0d4408c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 44c0455bd09f9084fbb2b90cd24c97f833ccb2e70594788a0632846955db6a8dd23b43425ac4e68a740a1c0c0a5c9b8c5c05e91bc831c50a4fdaf6cc413aa2fd
|
7
|
+
data.tar.gz: 6e9e38fa4cead06576012f74eda7cc94baf115578be4fd282a810ae7586d13dcbe19a0ccdc595e76cd4bf7ea51bd520a156023f6ad69228eb09a7264fd759431
|
data/.gitignore
ADDED
data/.kateproject
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Palimpsest ChangeLog
|
2
|
+
|
3
|
+
## 0.0.1
|
4
|
+
|
5
|
+
Initial release.
|
6
|
+
|
7
|
+
- Populating working environment from git repo or directory.
|
8
|
+
- Flexible asset pipeline with sprockets.
|
9
|
+
* `Palimpsest::Assets` class can be used standalone.
|
10
|
+
* Environment automatically compiles assets referenced in source files.
|
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
guard :rspec, cli: '--color --format Fuubar' do
|
2
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
3
|
+
watch(%r{^lib/palimpsest/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
4
|
+
watch(%r{^spec/.+_spec\.rb$})
|
5
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
6
|
+
end
|
7
|
+
|
8
|
+
guard :yard do
|
9
|
+
watch(%r{^lib/(.+)\.rb$})
|
10
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Evan Boyd Sosenko
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Palimpsest
|
2
|
+
|
3
|
+
by Evan Boyd Sosenko.
|
4
|
+
|
5
|
+
_No web framework, no problem: Palimpsest gives any custom or legacy project a modern workflow and toolset._
|
6
|
+
|
7
|
+
Built flexible, simple, and customizable.
|
8
|
+
Palimpsest runs on top of any project and acts as a post processor for your code.
|
9
|
+
Features a [Sprockets](https://github.com/sstephenson/sprockets) asset pipeline
|
10
|
+
and easy integration with [Kit](https://github.com/razor-x/kit).
|
11
|
+
|
12
|
+
[](https://gemnasium.com/razor-x/palimpsest)
|
13
|
+
[](https://travis-ci.org/razor-x/palimpsest)
|
14
|
+
[](https://coveralls.io/r/razor-x/palimpsest)
|
15
|
+
[](https://codeclimate.com/github/razor-x/palimpsest)
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
Add this line to your application's Gemfile:
|
20
|
+
|
21
|
+
gem 'palimpsest'
|
22
|
+
|
23
|
+
And then execute:
|
24
|
+
|
25
|
+
````bash
|
26
|
+
$ bundle
|
27
|
+
````
|
28
|
+
|
29
|
+
Or install it yourself as:
|
30
|
+
|
31
|
+
````bash
|
32
|
+
$ gem install palimpsest
|
33
|
+
````
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
**Palimpsest should not be considered stable until version 0.1.0 is released.**
|
38
|
+
|
39
|
+
### Documentation
|
40
|
+
|
41
|
+
_Comprehensive documentation and examples will be added to this REAME soon._
|
42
|
+
|
43
|
+
_For now, reference the YARD documentation below._
|
44
|
+
|
45
|
+
The primary documentation for Palimpsest is this README and the YARD source documentation.
|
46
|
+
|
47
|
+
YARD documentation for all gem versions is hosted on the [Palimpsest gem page](https://rubygems.org/gems/palimpsest).
|
48
|
+
Documentation for the latest commits is hosted on [the RubyDoc.info project page](http://rubydoc.info/github/razor-x/palimpsest/frames).
|
49
|
+
|
50
|
+
## Development
|
51
|
+
|
52
|
+
### Source Repository
|
53
|
+
|
54
|
+
The [Palimpsest source](https://github.com/razor-x/palimpsest) is hosted at github.
|
55
|
+
To clone the project run
|
56
|
+
|
57
|
+
````bash
|
58
|
+
$ git clone git@github.com:razor-x/palimpsest.git
|
59
|
+
````
|
60
|
+
|
61
|
+
## License
|
62
|
+
|
63
|
+
Palimpsest is licensed under the MIT license.
|
64
|
+
|
65
|
+
## Warranty
|
66
|
+
|
67
|
+
This software is provided "as is" and without any express or
|
68
|
+
implied warranties, including, without limitation, the implied
|
69
|
+
warranties of merchantibility and fitness for a particular
|
70
|
+
purpose.
|
data/Rakefile
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
require 'open3'
|
3
|
+
require 'sprockets'
|
4
|
+
|
5
|
+
module Palimpsest
|
6
|
+
|
7
|
+
# Flexible asset pipeline using Sprockets.
|
8
|
+
# Paths are loaded into a `Sprockets::Environment` (relative to {#directory} if given).
|
9
|
+
# Asset tags are used in source code and replaced
|
10
|
+
# with generated asset path or compiled source if `inline` is used.
|
11
|
+
#
|
12
|
+
# For example, if type is set to `:javascripts` the following replacements would be made:
|
13
|
+
#
|
14
|
+
# [% javascript app %] -> app-9413c7f112033f0c6f2a8e8dd313399c18d93878.js
|
15
|
+
# [% javascript lib/jquery %] -> lib/jquery-e2a8cde3f5b3cdb011e38a673556c7a94729e0d1.js
|
16
|
+
# [% javascript inline tracking %] -> <compiled source of tracking.js asset>
|
17
|
+
#
|
18
|
+
class Assets
|
19
|
+
|
20
|
+
# Default {#options}.
|
21
|
+
DEFAULT_OPTIONS = {
|
22
|
+
# default path to output all saved assets (relative to directory)
|
23
|
+
output: '',
|
24
|
+
|
25
|
+
# assume assets will be served under this url
|
26
|
+
# e.g. `https://cdn.example.com/`
|
27
|
+
cdn: '',
|
28
|
+
|
29
|
+
# keyword to use in asset tag for inline assets
|
30
|
+
inline: 'inline',
|
31
|
+
|
32
|
+
# if true, also generate a gzipped asset
|
33
|
+
gzip: false,
|
34
|
+
|
35
|
+
# include hash in asset name
|
36
|
+
hash: true,
|
37
|
+
|
38
|
+
# opening and closing brackets for asset source tags
|
39
|
+
src_pre: '[%',
|
40
|
+
src_post: '%]',
|
41
|
+
|
42
|
+
# allowed options for `Sprockets::Environment`
|
43
|
+
sprockets_options: [ :js_compressor, :css_compressor ]
|
44
|
+
}
|
45
|
+
|
46
|
+
# @!attribute directory
|
47
|
+
# @return [String] directory which all paths will be relative to if set
|
48
|
+
#
|
49
|
+
# @!attribute paths
|
50
|
+
# @return [Array] paths to load into sprockets environment
|
51
|
+
#
|
52
|
+
# @!attribute type
|
53
|
+
# @return [Symbol] type of asset
|
54
|
+
attr_accessor :directory, :paths, :type
|
55
|
+
|
56
|
+
def initialize directory: '', options: {}, paths: {}
|
57
|
+
self.options options
|
58
|
+
self.directory = directory
|
59
|
+
self.paths = paths
|
60
|
+
end
|
61
|
+
|
62
|
+
# Uses {DEFAULT_OPTIONS} as initial value.
|
63
|
+
# @param options [Hash] merged with current options
|
64
|
+
# @return [Hash] current options
|
65
|
+
def options options={}
|
66
|
+
@options ||= DEFAULT_OPTIONS
|
67
|
+
@options = @options.merge options
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [Sprockets::Environment] the current sprockets environment
|
71
|
+
def sprockets
|
72
|
+
@sprockets ||= Sprockets::Environment.new
|
73
|
+
end
|
74
|
+
|
75
|
+
# Load options into the sprockets environment.
|
76
|
+
# Values are loaded from {#options}.
|
77
|
+
def load_options
|
78
|
+
options[:sprockets_options].each do |opt|
|
79
|
+
sprockets.send "#{opt}=".to_sym, options[opt] if options[opt]
|
80
|
+
end
|
81
|
+
return self
|
82
|
+
end
|
83
|
+
|
84
|
+
# Load paths into the sprockets environment.
|
85
|
+
# Values are loaded from {#paths}.
|
86
|
+
def load_paths
|
87
|
+
paths.each do |path|
|
88
|
+
sprockets.append_path "#{directory + '/' unless directory.empty?}#{path}"
|
89
|
+
end
|
90
|
+
return self
|
91
|
+
end
|
92
|
+
|
93
|
+
# @return [Sprockets::Environment] sprockets environment with {#options} and {#paths} loaded
|
94
|
+
def assets
|
95
|
+
unless @loaded
|
96
|
+
load_options
|
97
|
+
load_paths
|
98
|
+
end
|
99
|
+
@loaded = true
|
100
|
+
sprockets
|
101
|
+
end
|
102
|
+
|
103
|
+
# Write a target asset to file with a hashed name.
|
104
|
+
# @param target [String] logical path to asset
|
105
|
+
# @param gzip [Boolean] if the asset should be gzipped
|
106
|
+
# @param hash [Boolean] if the asset name should include the hash
|
107
|
+
# @return [String, nil] the relative path to the written asset or `nil` if no such asset
|
108
|
+
def write target, gzip: options[:gzip], hash: options[:hash]
|
109
|
+
asset = assets[target]
|
110
|
+
|
111
|
+
return if asset.nil?
|
112
|
+
|
113
|
+
name = hash ? asset.digest_path : asset.logical_path.to_s
|
114
|
+
name = "#{options[:output]}/#{name}" unless options[:output].empty?
|
115
|
+
|
116
|
+
path = directory.empty? ? '' : "#{directory}/"
|
117
|
+
path << name
|
118
|
+
|
119
|
+
asset.write_to "#{path}.gz", compress: true if gzip
|
120
|
+
asset.write_to path
|
121
|
+
name
|
122
|
+
end
|
123
|
+
|
124
|
+
# (see #update_source)
|
125
|
+
# @note this modifies the `source` `String` in place
|
126
|
+
def update_source! source
|
127
|
+
# e.g. /\[%\s+javascript\s+((\S+)\s?(\S+))\s+%\]/
|
128
|
+
regex = /#{Regexp.escape options[:src_pre]}\s+#{type.to_s.singularize}\s+((\S+)\s?(\S+))\s+#{Regexp.escape options[:src_post]}/
|
129
|
+
source.gsub! regex do
|
130
|
+
if $2 == options[:inline]
|
131
|
+
assets[$3].to_s
|
132
|
+
else
|
133
|
+
asset = write $1
|
134
|
+
|
135
|
+
# @todo raise warning or error if asset not found
|
136
|
+
p "asset not found: #{$1}" and next if asset.nil?
|
137
|
+
|
138
|
+
options[:cdn].empty? ? asset : options[:cdn] + asset
|
139
|
+
end
|
140
|
+
end
|
141
|
+
return true
|
142
|
+
end
|
143
|
+
|
144
|
+
# Replaces all asset tags in source string with asset path or asset source.
|
145
|
+
# Writes any referenced assets to disk.
|
146
|
+
# @param source [String] code to find and replace asset tags
|
147
|
+
# @return [String] copy of `source` with asset tags replaced
|
148
|
+
def update_source source
|
149
|
+
s = source
|
150
|
+
update_source! s
|
151
|
+
s
|
152
|
+
end
|
153
|
+
|
154
|
+
# Scans all non-binary files under `path` ({#directory} by default) for asset tags.
|
155
|
+
# Uses current asset {#type} (if set) and {#options}.
|
156
|
+
# @param path [String] where to look for source files
|
157
|
+
# @return [Array] files with asset tags
|
158
|
+
def find_tags path: directory
|
159
|
+
self.class.find_tags path, type, options
|
160
|
+
end
|
161
|
+
|
162
|
+
# Scans all non-binary files under `path` for asset tags.
|
163
|
+
# @param path [String] where to look for source files
|
164
|
+
# @param type [String, nil] only look for asset tags with this type (or any type if `nil`)
|
165
|
+
# @param options [Hash] merged with {DEFAULT_OPTIONS}
|
166
|
+
# (see #find_tags)
|
167
|
+
def self.find_tags path, type=nil, options={}
|
168
|
+
raise ArgumentError, 'path cannot be empty' if path.empty?
|
169
|
+
|
170
|
+
options = DEFAULT_OPTIONS.merge options
|
171
|
+
pre = Regexp.escape options[:src_pre]
|
172
|
+
post= Regexp.escape options[:src_post]
|
173
|
+
|
174
|
+
cmd = [ 'grep' ]
|
175
|
+
cmd.concat [ '-l', '-I', '-r', '-E' ]
|
176
|
+
cmd << \
|
177
|
+
if type.nil?
|
178
|
+
pre + '(.*?)' + post
|
179
|
+
else
|
180
|
+
pre + '\s+' + type.to_s + '\s+(.*?)' + post
|
181
|
+
end
|
182
|
+
cmd << path
|
183
|
+
|
184
|
+
files = []
|
185
|
+
Open3.capture2(*cmd).first.each_line { |l| files << l.chomp unless l.empty? }
|
186
|
+
files
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,263 @@
|
|
1
|
+
require 'grit'
|
2
|
+
|
3
|
+
module Palimpsest
|
4
|
+
|
5
|
+
# An environment is populated with the contents of
|
6
|
+
# a site's repository at a specified commit.
|
7
|
+
# The environment's files are rooted in a temporary {#directory}.
|
8
|
+
# An environment is the primary way to interact with a site's files.
|
9
|
+
#
|
10
|
+
# An environment loads a {#config} file from the working {#directory};
|
11
|
+
# by default, `palimpsest_config.yml`.
|
12
|
+
#
|
13
|
+
# Paths are all relative to the working {#directory}.
|
14
|
+
#
|
15
|
+
# ````yml
|
16
|
+
# palimpsest_config.yml
|
17
|
+
#
|
18
|
+
# # asset settings
|
19
|
+
# :assets:
|
20
|
+
# # all options are passed to `Palimpsest::Assets#options` and will use those defaults if unset
|
21
|
+
# # unless otherwise mentioned, options can be set or overridden per asset type
|
22
|
+
# :options:
|
23
|
+
# # opening and closing brackets for asset source tags
|
24
|
+
# # global option only: cannot be overridden per asset type
|
25
|
+
# :src_pre: "[%"
|
26
|
+
# :src_post: "%]"
|
27
|
+
#
|
28
|
+
# # relative directory to save compiled assets
|
29
|
+
# :output: compiled
|
30
|
+
#
|
31
|
+
# # assume assets will be served under here
|
32
|
+
# :cdn: https://cdn.example.com/
|
33
|
+
#
|
34
|
+
# # compiled asset names include a uniqe hash by default
|
35
|
+
# # this can be toggled off
|
36
|
+
# :hash: false
|
37
|
+
#
|
38
|
+
# # directories to scan for files with asset tags
|
39
|
+
# :sources:
|
40
|
+
# # putting assets/stylesheets first would allow asset tags,
|
41
|
+
# # e.g. for images, to be used in your stylesheets
|
42
|
+
# - assets/stylesheets
|
43
|
+
# - public
|
44
|
+
# - app/src
|
45
|
+
#
|
46
|
+
# # all other keys are asset types
|
47
|
+
# :javascripts:
|
48
|
+
# :options:
|
49
|
+
# :js_compressor: :uglifier
|
50
|
+
# # these paths are loaded into the sprockets environment
|
51
|
+
# :paths:
|
52
|
+
# - assets/javascripts
|
53
|
+
# - other/javascripts
|
54
|
+
#
|
55
|
+
# # this is another asset type which will have it's own namespace
|
56
|
+
# :stylesheets:
|
57
|
+
# :options:
|
58
|
+
# :css_compressor: :sass
|
59
|
+
#
|
60
|
+
# :paths:
|
61
|
+
# - assets/stylesheets
|
62
|
+
# # images can be part of the asset pipeline
|
63
|
+
# :images:
|
64
|
+
# # options can be overridden per type
|
65
|
+
# :options:
|
66
|
+
# :output: images
|
67
|
+
# :paths:
|
68
|
+
# - assets/images
|
69
|
+
# ````
|
70
|
+
class Environment
|
71
|
+
|
72
|
+
# Default {#options}.
|
73
|
+
DEFAULT_OPTIONS = {
|
74
|
+
# all environment's temporary directories will be rooted under here
|
75
|
+
tmp_dir: '/tmp',
|
76
|
+
|
77
|
+
# prepended to the name of the environment's working directory
|
78
|
+
dir_prefix: 'palimpsest_',
|
79
|
+
|
80
|
+
# name of config file to load, relative to environment's working directory
|
81
|
+
config_file: 'palimpsest_config.yml'
|
82
|
+
}
|
83
|
+
|
84
|
+
# @!attribute site
|
85
|
+
# @return site to build the environment with
|
86
|
+
#
|
87
|
+
# @!attribute treeish
|
88
|
+
# @return [String] the reference used to pick the commit to build the environment with
|
89
|
+
#
|
90
|
+
# @!attribute [r] directory
|
91
|
+
# @return [String] the environment's working directory
|
92
|
+
#
|
93
|
+
# @!attribute [r] populated
|
94
|
+
# @return [Boolean] true if the site's repo has been extracted
|
95
|
+
attr_reader :site, :treeish, :directory, :populated
|
96
|
+
|
97
|
+
def initialize site: nil, treeish: 'master', options: {}
|
98
|
+
@populated = false
|
99
|
+
self.options options
|
100
|
+
self.site = site if site
|
101
|
+
self.treeish = treeish
|
102
|
+
end
|
103
|
+
|
104
|
+
# Uses {DEFAULT_OPTIONS} as initial value.
|
105
|
+
# @param options [Hash] merged with current options
|
106
|
+
# @return [Hash] current options
|
107
|
+
def options options={}
|
108
|
+
@options ||= DEFAULT_OPTIONS
|
109
|
+
@options = @options.merge options
|
110
|
+
end
|
111
|
+
|
112
|
+
def site= site
|
113
|
+
raise RuntimeError, "Cannot redefine 'site' once populated" if populated
|
114
|
+
@site = site
|
115
|
+
end
|
116
|
+
|
117
|
+
def treeish= treeish
|
118
|
+
raise RuntimeError, "Cannot redefine 'treeish' once populated" if populated
|
119
|
+
raise TypeError unless treeish.is_a? String
|
120
|
+
@treeish = treeish
|
121
|
+
end
|
122
|
+
|
123
|
+
def directory
|
124
|
+
raise RuntimeError if site.nil?
|
125
|
+
if @directory.nil?
|
126
|
+
@directory = Palimpsest::Utility.make_random_directory options[:tmp_dir], "#{options[:dir_prefix]}#{site.name}_"
|
127
|
+
else
|
128
|
+
@directory
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Removes the environment's working directory.
|
133
|
+
def cleanup
|
134
|
+
FileUtils.remove_entry_secure directory if @directory
|
135
|
+
@directory = nil
|
136
|
+
@populated = false
|
137
|
+
return self
|
138
|
+
end
|
139
|
+
|
140
|
+
# Extracts the site's files from repository to the working directory.
|
141
|
+
def populate from: :repo
|
142
|
+
cleanup if populated
|
143
|
+
raise RuntimeError, "Cannot populate without 'site'" if site.nil?
|
144
|
+
|
145
|
+
case from
|
146
|
+
when :repo
|
147
|
+
raise RuntimeError, "Cannot populate without 'treeish'" if treeish.empty?
|
148
|
+
Palimpsest::Utility.extract_repo site.repo, treeish, directory
|
149
|
+
when :source
|
150
|
+
FileUtils.cp_r Dir["#{site.source}/*"], directory
|
151
|
+
end
|
152
|
+
|
153
|
+
@populated = true
|
154
|
+
return self
|
155
|
+
end
|
156
|
+
|
157
|
+
# @return [Hash] configuration loaded from {#options}`[:config_file]` under {#directory}
|
158
|
+
def config
|
159
|
+
populate unless populated
|
160
|
+
@config = YAML.load_file "#{directory}/#{options[:config_file]}"
|
161
|
+
validate_config if @config
|
162
|
+
end
|
163
|
+
|
164
|
+
# @return [Array<Palimpsest::Assets>] assets with settings and paths loaded from config
|
165
|
+
def assets
|
166
|
+
@assets = []
|
167
|
+
|
168
|
+
config[:assets].each do |type, opt|
|
169
|
+
next if [ :sources ].include? type
|
170
|
+
next if opt[:paths].nil?
|
171
|
+
|
172
|
+
assets = Palimpsest::Assets.new directory: directory, paths: opt[:paths]
|
173
|
+
assets.options config[:assets][:options] unless config[:assets][:options].nil?
|
174
|
+
assets.options opt[:options] unless opt[:options].nil?
|
175
|
+
assets.type = type
|
176
|
+
@assets << assets
|
177
|
+
end unless config[:assets].nil?
|
178
|
+
|
179
|
+
@assets
|
180
|
+
end
|
181
|
+
|
182
|
+
# @return [Array] all source files with asset tags
|
183
|
+
def sources_with_assets
|
184
|
+
return [] if config[:assets].nil?
|
185
|
+
return [] if config[:assets][:sources].nil?
|
186
|
+
|
187
|
+
@sources_with_assets = []
|
188
|
+
|
189
|
+
opts = {}
|
190
|
+
[ :src_pre, :src_post ].each do |opt|
|
191
|
+
opts[opt] = config[:assets][:options][opt] unless config[:assets][:options][opt].nil?
|
192
|
+
end unless config[:assets][:options].nil?
|
193
|
+
|
194
|
+
config[:assets][:sources].each do |path|
|
195
|
+
@sources_with_assets << Palimpsest::Assets.find_tags("#{directory}/#{path}", nil, opts)
|
196
|
+
end
|
197
|
+
|
198
|
+
@sources_with_assets.flatten
|
199
|
+
end
|
200
|
+
|
201
|
+
# Finds all assets in {#sources_with_assets} and
|
202
|
+
# generates the assets and updates the sources.
|
203
|
+
def compile_assets
|
204
|
+
sources_with_assets.each do |file|
|
205
|
+
source = File.read file
|
206
|
+
assets.each { |a| a.update_source! source }
|
207
|
+
Palimpsest::Utility.write source, file
|
208
|
+
end
|
209
|
+
return self
|
210
|
+
end
|
211
|
+
|
212
|
+
private
|
213
|
+
|
214
|
+
# Checks the config file for invalid settings.
|
215
|
+
#
|
216
|
+
# - Checks that paths are not absolute or use `../` or `~/`.
|
217
|
+
def validate_config
|
218
|
+
message = 'bad path in config'
|
219
|
+
|
220
|
+
def safe_path?(path) Palimpsest::Utility.safe_path?(path) end
|
221
|
+
|
222
|
+
# Checks the option in the asset key.
|
223
|
+
def validate_asset_options opts
|
224
|
+
opts.each do |k,v|
|
225
|
+
raise RuntimeError, 'bad option in config' if k == :sprockets_options
|
226
|
+
raise RuntimeError, message if k == :output && ! safe_path?(v)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
@config[:assets].each do |k, v|
|
231
|
+
|
232
|
+
# process @config[:assets][:options] then go to the next option
|
233
|
+
if k == :options
|
234
|
+
validate_asset_options v
|
235
|
+
next
|
236
|
+
end unless v.nil?
|
237
|
+
|
238
|
+
# process @config[:assets][:sources] then go to the next option
|
239
|
+
if k == :sources
|
240
|
+
v.each_with_index do |source, i|
|
241
|
+
raise RuntimeError, message unless safe_path? source
|
242
|
+
end
|
243
|
+
next
|
244
|
+
end
|
245
|
+
|
246
|
+
# process each asset type in @config[:assets]
|
247
|
+
v.each do |asset_key, asset_value|
|
248
|
+
# process :options
|
249
|
+
if asset_key == :options
|
250
|
+
validate_asset_options asset_value
|
251
|
+
next
|
252
|
+
end unless asset_value.nil?
|
253
|
+
|
254
|
+
# process each asset path
|
255
|
+
asset_value.each_with_index do |path, i|
|
256
|
+
raise RuntimeError, message unless safe_path? path
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end unless @config[:assets].nil?
|
260
|
+
@config
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|