middleman-wizard-template 1.0.0.pre.1 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -4
- data/lib/middleman-wizard-template/template.rb +1 -0
- data/lib/middleman-wizard-template/template/README.tt +25 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/closurebuilder.py +256 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree.py +189 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree.pyc +0 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree_test.py +127 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depswriter.py +202 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/jscompiler.py +71 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/jscompiler.pyc +0 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source.py +114 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source.pyc +0 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source_test.py +121 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/treescan.py +78 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/treescan.pyc +0 -0
- data/lib/middleman-wizard-template/template/config.tt +66 -0
- data/lib/middleman-wizard-template/template/shared/Gemfile.tt +2 -1
- data/lib/middleman-wizard-template/template/source/javascripts/app.js +3 -5
- data/lib/middleman-wizard-template/version.rb +1 -1
- metadata +21 -6
- data/lib/middleman-wizard-template/template/source/javascripts/_lib/asset_loader.js +0 -492
data/.gitignore
CHANGED
@@ -10,6 +10,7 @@ module Middleman
|
|
10
10
|
|
11
11
|
def build_scaffold
|
12
12
|
template "config.tt", File.join(location, "config.rb")
|
13
|
+
template "README.tt", File.join(location, "README.md")
|
13
14
|
directory "source", File.join(location, "source")
|
14
15
|
|
15
16
|
# empty_directory File.join(location, "source", options[:css_dir])
|
@@ -0,0 +1,25 @@
|
|
1
|
+
WIZARD PROJECT
|
2
|
+
-------------------
|
3
|
+
|
4
|
+
Middleman project for local development. Middleman brings it all together --> go into Goro branch.
|
5
|
+
|
6
|
+
## [Middleman](https://github.com/middleman/middleman)
|
7
|
+
|
8
|
+
```shell
|
9
|
+
cd MY_PROJECT
|
10
|
+
gem install bundler # May already be installed
|
11
|
+
bundle install --binstubs # Install Middleman and dependencies (Requires XCode Command-Line tool)
|
12
|
+
```
|
13
|
+
|
14
|
+
From within project directory:
|
15
|
+
|
16
|
+
```shell
|
17
|
+
bin/middleman server # Start the preview server
|
18
|
+
bin/middleman build # Build project to build/
|
19
|
+
```
|
20
|
+
|
21
|
+
By default, `middleman build` will generate a testing build with the site compiled through Closure Compiler. It is also possible to generate a "Goro-targeted" build which keeps unminified content, but remove shared layout:
|
22
|
+
|
23
|
+
```shell
|
24
|
+
GORO=1 bin/middleman build
|
25
|
+
```
|
data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/closurebuilder.py
ADDED
@@ -0,0 +1,256 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
#
|
3
|
+
# Copyright 2009 The Closure Library Authors. All Rights Reserved.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS-IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
"""Utility for Closure Library dependency calculation.
|
18
|
+
|
19
|
+
ClosureBuilder scans source files to build dependency info. From the
|
20
|
+
dependencies, the script can produce a manifest in dependency order,
|
21
|
+
a concatenated script, or compiled output from the Closure Compiler.
|
22
|
+
|
23
|
+
Paths to files can be expressed as individual arguments to the tool (intended
|
24
|
+
for use with find and xargs). As a convenience, --root can be used to specify
|
25
|
+
all JS files below a directory.
|
26
|
+
|
27
|
+
usage: %prog [options] [file1.js file2.js ...]
|
28
|
+
"""
|
29
|
+
|
30
|
+
__author__ = 'nnaze@google.com (Nathan Naze)'
|
31
|
+
|
32
|
+
|
33
|
+
import logging
|
34
|
+
import optparse
|
35
|
+
import os
|
36
|
+
import sys
|
37
|
+
|
38
|
+
import depstree
|
39
|
+
import jscompiler
|
40
|
+
import source
|
41
|
+
import treescan
|
42
|
+
|
43
|
+
|
44
|
+
def _GetOptionsParser():
|
45
|
+
"""Get the options parser."""
|
46
|
+
|
47
|
+
parser = optparse.OptionParser(__doc__)
|
48
|
+
parser.add_option('-i',
|
49
|
+
'--input',
|
50
|
+
dest='inputs',
|
51
|
+
action='append',
|
52
|
+
default=[],
|
53
|
+
help='One or more input files to calculate dependencies '
|
54
|
+
'for. The namespaces in this file will be combined with '
|
55
|
+
'those given with the -n flag to form the set of '
|
56
|
+
'namespaces to find dependencies for.')
|
57
|
+
parser.add_option('-n',
|
58
|
+
'--namespace',
|
59
|
+
dest='namespaces',
|
60
|
+
action='append',
|
61
|
+
default=[],
|
62
|
+
help='One or more namespaces to calculate dependencies '
|
63
|
+
'for. These namespaces will be combined with those given '
|
64
|
+
'with the -i flag to form the set of namespaces to find '
|
65
|
+
'dependencies for. A Closure namespace is a '
|
66
|
+
'dot-delimited path expression declared with a call to '
|
67
|
+
'goog.provide() (e.g. "goog.array" or "foo.bar").')
|
68
|
+
parser.add_option('--root',
|
69
|
+
dest='roots',
|
70
|
+
action='append',
|
71
|
+
default=[],
|
72
|
+
help='The paths that should be traversed to build the '
|
73
|
+
'dependencies.')
|
74
|
+
parser.add_option('-o',
|
75
|
+
'--output_mode',
|
76
|
+
dest='output_mode',
|
77
|
+
type='choice',
|
78
|
+
action='store',
|
79
|
+
choices=['list', 'script', 'compiled'],
|
80
|
+
default='list',
|
81
|
+
help='The type of output to generate from this script. '
|
82
|
+
'Options are "list" for a list of filenames, "script" '
|
83
|
+
'for a single script containing the contents of all the '
|
84
|
+
'files, or "compiled" to produce compiled output with '
|
85
|
+
'the Closure Compiler. Default is "list".')
|
86
|
+
parser.add_option('-c',
|
87
|
+
'--compiler_jar',
|
88
|
+
dest='compiler_jar',
|
89
|
+
action='store',
|
90
|
+
help='The location of the Closure compiler .jar file.')
|
91
|
+
parser.add_option('-f',
|
92
|
+
'--compiler_flags',
|
93
|
+
dest='compiler_flags',
|
94
|
+
default=[],
|
95
|
+
action='append',
|
96
|
+
help='Additional flags to pass to the Closure compiler. '
|
97
|
+
'To pass multiple flags, --compiler_flags has to be '
|
98
|
+
'specified multiple times.')
|
99
|
+
parser.add_option('--output_file',
|
100
|
+
dest='output_file',
|
101
|
+
action='store',
|
102
|
+
help=('If specified, write output to this path instead of '
|
103
|
+
'writing to standard output.'))
|
104
|
+
|
105
|
+
return parser
|
106
|
+
|
107
|
+
|
108
|
+
def _GetInputByPath(path, sources):
|
109
|
+
"""Get the source identified by a path.
|
110
|
+
|
111
|
+
Args:
|
112
|
+
path: str, A path to a file that identifies a source.
|
113
|
+
sources: An iterable collection of source objects.
|
114
|
+
|
115
|
+
Returns:
|
116
|
+
The source from sources identified by path, if found. Converts to
|
117
|
+
absolute paths for comparison.
|
118
|
+
"""
|
119
|
+
for js_source in sources:
|
120
|
+
# Convert both to absolute paths for comparison.
|
121
|
+
if os.path.abspath(path) == os.path.abspath(js_source.GetPath()):
|
122
|
+
return js_source
|
123
|
+
|
124
|
+
|
125
|
+
def _GetClosureBaseFile(sources):
|
126
|
+
"""Given a set of sources, returns the one base.js file.
|
127
|
+
|
128
|
+
Note that if zero or two or more base.js files are found, an error message
|
129
|
+
will be written and the program will be exited.
|
130
|
+
|
131
|
+
Args:
|
132
|
+
sources: An iterable of _PathSource objects.
|
133
|
+
|
134
|
+
Returns:
|
135
|
+
The _PathSource representing the base Closure file.
|
136
|
+
"""
|
137
|
+
base_files = [
|
138
|
+
js_source for js_source in sources if _IsClosureBaseFile(js_source)]
|
139
|
+
|
140
|
+
if not base_files:
|
141
|
+
logging.error('No Closure base.js file found.')
|
142
|
+
sys.exit(1)
|
143
|
+
if len(base_files) > 1:
|
144
|
+
logging.error('More than one Closure base.js files found at these paths:')
|
145
|
+
for base_file in base_files:
|
146
|
+
logging.error(base_file.GetPath())
|
147
|
+
sys.exit(1)
|
148
|
+
return base_files[0]
|
149
|
+
|
150
|
+
|
151
|
+
def _IsClosureBaseFile(js_source):
|
152
|
+
"""Returns true if the given _PathSource is the Closure base.js source."""
|
153
|
+
return (os.path.basename(js_source.GetPath()) == 'base.js' and
|
154
|
+
js_source.provides == set(['goog']))
|
155
|
+
|
156
|
+
|
157
|
+
class _PathSource(source.Source):
|
158
|
+
"""Source file subclass that remembers its file path."""
|
159
|
+
|
160
|
+
def __init__(self, path):
|
161
|
+
"""Initialize a source.
|
162
|
+
|
163
|
+
Args:
|
164
|
+
path: str, Path to a JavaScript file. The source string will be read
|
165
|
+
from this file.
|
166
|
+
"""
|
167
|
+
super(_PathSource, self).__init__(source.GetFileContents(path))
|
168
|
+
|
169
|
+
self._path = path
|
170
|
+
|
171
|
+
def GetPath(self):
|
172
|
+
"""Returns the path."""
|
173
|
+
return self._path
|
174
|
+
|
175
|
+
|
176
|
+
def main():
|
177
|
+
logging.basicConfig(format=(sys.argv[0] + ': %(message)s'),
|
178
|
+
level=logging.INFO)
|
179
|
+
options, args = _GetOptionsParser().parse_args()
|
180
|
+
|
181
|
+
# Make our output pipe.
|
182
|
+
if options.output_file:
|
183
|
+
out = open(options.output_file, 'w')
|
184
|
+
else:
|
185
|
+
out = sys.stdout
|
186
|
+
|
187
|
+
sources = set()
|
188
|
+
|
189
|
+
logging.info('Scanning paths...')
|
190
|
+
for path in options.roots:
|
191
|
+
for js_path in treescan.ScanTreeForJsFiles(path):
|
192
|
+
sources.add(_PathSource(js_path))
|
193
|
+
|
194
|
+
# Add scripts specified on the command line.
|
195
|
+
for js_path in args:
|
196
|
+
sources.add(_PathSource(js_path))
|
197
|
+
|
198
|
+
logging.info('%s sources scanned.', len(sources))
|
199
|
+
|
200
|
+
# Though deps output doesn't need to query the tree, we still build it
|
201
|
+
# to validate dependencies.
|
202
|
+
logging.info('Building dependency tree..')
|
203
|
+
tree = depstree.DepsTree(sources)
|
204
|
+
|
205
|
+
input_namespaces = set()
|
206
|
+
inputs = options.inputs or []
|
207
|
+
for input_path in inputs:
|
208
|
+
js_input = _GetInputByPath(input_path, sources)
|
209
|
+
if not js_input:
|
210
|
+
logging.error('No source matched input %s', input_path)
|
211
|
+
sys.exit(1)
|
212
|
+
input_namespaces.update(js_input.provides)
|
213
|
+
|
214
|
+
input_namespaces.update(options.namespaces)
|
215
|
+
|
216
|
+
if not input_namespaces:
|
217
|
+
logging.error('No namespaces found. At least one namespace must be '
|
218
|
+
'specified with the --namespace or --input flags.')
|
219
|
+
sys.exit(2)
|
220
|
+
|
221
|
+
# The Closure Library base file must go first.
|
222
|
+
base = _GetClosureBaseFile(sources)
|
223
|
+
deps = [base] + tree.GetDependencies(input_namespaces)
|
224
|
+
|
225
|
+
output_mode = options.output_mode
|
226
|
+
if output_mode == 'list':
|
227
|
+
out.writelines([js_source.GetPath() + '\n' for js_source in deps])
|
228
|
+
elif output_mode == 'script':
|
229
|
+
out.writelines([js_source.GetSource() for js_source in deps])
|
230
|
+
elif output_mode == 'compiled':
|
231
|
+
|
232
|
+
# Make sure a .jar is specified.
|
233
|
+
if not options.compiler_jar:
|
234
|
+
logging.error('--compiler_jar flag must be specified if --output is '
|
235
|
+
'"compiled"')
|
236
|
+
sys.exit(2)
|
237
|
+
|
238
|
+
compiled_source = jscompiler.Compile(
|
239
|
+
options.compiler_jar,
|
240
|
+
[js_source.GetPath() for js_source in deps],
|
241
|
+
options.compiler_flags)
|
242
|
+
|
243
|
+
if compiled_source is None:
|
244
|
+
logging.error('JavaScript compilation failed.')
|
245
|
+
sys.exit(1)
|
246
|
+
else:
|
247
|
+
logging.info('JavaScript compilation succeeded.')
|
248
|
+
out.write(compiled_source)
|
249
|
+
|
250
|
+
else:
|
251
|
+
logging.error('Invalid value for --output flag.')
|
252
|
+
sys.exit(2)
|
253
|
+
|
254
|
+
|
255
|
+
if __name__ == '__main__':
|
256
|
+
main()
|
@@ -0,0 +1,189 @@
|
|
1
|
+
# Copyright 2009 The Closure Library Authors. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS-IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
"""Class to represent a full Closure Library dependency tree.
|
17
|
+
|
18
|
+
Offers a queryable tree of dependencies of a given set of sources. The tree
|
19
|
+
will also do logical validation to prevent duplicate provides and circular
|
20
|
+
dependencies.
|
21
|
+
"""
|
22
|
+
|
23
|
+
__author__ = 'nnaze@google.com (Nathan Naze)'
|
24
|
+
|
25
|
+
|
26
|
+
class DepsTree(object):
|
27
|
+
"""Represents the set of dependencies between source files."""
|
28
|
+
|
29
|
+
def __init__(self, sources):
|
30
|
+
"""Initializes the tree with a set of sources.
|
31
|
+
|
32
|
+
Args:
|
33
|
+
sources: A set of JavaScript sources.
|
34
|
+
|
35
|
+
Raises:
|
36
|
+
MultipleProvideError: A namespace is provided by muplitple sources.
|
37
|
+
NamespaceNotFoundError: A namespace is required but never provided.
|
38
|
+
"""
|
39
|
+
|
40
|
+
self._sources = sources
|
41
|
+
self._provides_map = dict()
|
42
|
+
|
43
|
+
# Ensure nothing was provided twice.
|
44
|
+
for source in sources:
|
45
|
+
for provide in source.provides:
|
46
|
+
if provide in self._provides_map:
|
47
|
+
raise MultipleProvideError(
|
48
|
+
provide, [self._provides_map[provide], source])
|
49
|
+
|
50
|
+
self._provides_map[provide] = source
|
51
|
+
|
52
|
+
# Check that all required namespaces are provided.
|
53
|
+
for source in sources:
|
54
|
+
for require in source.requires:
|
55
|
+
if require not in self._provides_map:
|
56
|
+
raise NamespaceNotFoundError(require, source)
|
57
|
+
|
58
|
+
def GetDependencies(self, required_namespaces):
|
59
|
+
"""Get source dependencies, in order, for the given namespaces.
|
60
|
+
|
61
|
+
Args:
|
62
|
+
required_namespaces: A string (for one) or list (for one or more) of
|
63
|
+
namespaces.
|
64
|
+
|
65
|
+
Returns:
|
66
|
+
A list of source objects that provide those namespaces and all
|
67
|
+
requirements, in dependency order.
|
68
|
+
|
69
|
+
Raises:
|
70
|
+
NamespaceNotFoundError: A namespace is requested but doesn't exist.
|
71
|
+
CircularDependencyError: A cycle is detected in the dependency tree.
|
72
|
+
"""
|
73
|
+
if isinstance(required_namespaces, str):
|
74
|
+
required_namespaces = [required_namespaces]
|
75
|
+
|
76
|
+
deps_sources = []
|
77
|
+
|
78
|
+
for namespace in required_namespaces:
|
79
|
+
for source in DepsTree._ResolveDependencies(
|
80
|
+
namespace, [], self._provides_map, []):
|
81
|
+
if source not in deps_sources:
|
82
|
+
deps_sources.append(source)
|
83
|
+
|
84
|
+
return deps_sources
|
85
|
+
|
86
|
+
@staticmethod
|
87
|
+
def _ResolveDependencies(required_namespace, deps_list, provides_map,
|
88
|
+
traversal_path):
|
89
|
+
"""Resolve dependencies for Closure source files.
|
90
|
+
|
91
|
+
Follows the dependency tree down and builds a list of sources in dependency
|
92
|
+
order. This function will recursively call itself to fill all dependencies
|
93
|
+
below the requested namespaces, and then append its sources at the end of
|
94
|
+
the list.
|
95
|
+
|
96
|
+
Args:
|
97
|
+
required_namespace: String of required namespace.
|
98
|
+
deps_list: List of sources in dependency order. This function will append
|
99
|
+
the required source once all of its dependencies are satisfied.
|
100
|
+
provides_map: Map from namespace to source that provides it.
|
101
|
+
traversal_path: List of namespaces of our path from the root down the
|
102
|
+
dependency/recursion tree. Used to identify cyclical dependencies.
|
103
|
+
This is a list used as a stack -- when the function is entered, the
|
104
|
+
current namespace is pushed and popped right before returning.
|
105
|
+
Each recursive call will check that the current namespace does not
|
106
|
+
appear in the list, throwing a CircularDependencyError if it does.
|
107
|
+
|
108
|
+
Returns:
|
109
|
+
The given deps_list object filled with sources in dependency order.
|
110
|
+
|
111
|
+
Raises:
|
112
|
+
NamespaceNotFoundError: A namespace is requested but doesn't exist.
|
113
|
+
CircularDependencyError: A cycle is detected in the dependency tree.
|
114
|
+
"""
|
115
|
+
|
116
|
+
source = provides_map.get(required_namespace)
|
117
|
+
if not source:
|
118
|
+
raise NamespaceNotFoundError(required_namespace)
|
119
|
+
|
120
|
+
if required_namespace in traversal_path:
|
121
|
+
traversal_path.append(required_namespace) # do this *after* the test
|
122
|
+
|
123
|
+
# This must be a cycle.
|
124
|
+
raise CircularDependencyError(traversal_path)
|
125
|
+
|
126
|
+
# If we don't have the source yet, we'll have to visit this namespace and
|
127
|
+
# add the required dependencies to deps_list.
|
128
|
+
if source not in deps_list:
|
129
|
+
traversal_path.append(required_namespace)
|
130
|
+
|
131
|
+
for require in source.requires:
|
132
|
+
|
133
|
+
# Append all other dependencies before we append our own.
|
134
|
+
DepsTree._ResolveDependencies(require, deps_list, provides_map,
|
135
|
+
traversal_path)
|
136
|
+
deps_list.append(source)
|
137
|
+
|
138
|
+
traversal_path.pop()
|
139
|
+
|
140
|
+
return deps_list
|
141
|
+
|
142
|
+
|
143
|
+
class BaseDepsTreeError(Exception):
|
144
|
+
"""Base DepsTree error."""
|
145
|
+
|
146
|
+
def __init__(self):
|
147
|
+
Exception.__init__(self)
|
148
|
+
|
149
|
+
|
150
|
+
class CircularDependencyError(BaseDepsTreeError):
|
151
|
+
"""Raised when a dependency cycle is encountered."""
|
152
|
+
|
153
|
+
def __init__(self, dependency_list):
|
154
|
+
BaseDepsTreeError.__init__(self)
|
155
|
+
self._dependency_list = dependency_list
|
156
|
+
|
157
|
+
def __str__(self):
|
158
|
+
return ('Encountered circular dependency:\n%s\n' %
|
159
|
+
'\n'.join(self._dependency_list))
|
160
|
+
|
161
|
+
|
162
|
+
class MultipleProvideError(BaseDepsTreeError):
|
163
|
+
"""Raised when a namespace is provided more than once."""
|
164
|
+
|
165
|
+
def __init__(self, namespace, sources):
|
166
|
+
BaseDepsTreeError.__init__(self)
|
167
|
+
self._namespace = namespace
|
168
|
+
self._sources = sources
|
169
|
+
|
170
|
+
def __str__(self):
|
171
|
+
source_strs = map(str, self._sources)
|
172
|
+
|
173
|
+
return ('Namespace "%s" provided more than once in sources:\n%s\n' %
|
174
|
+
(self._namespace, '\n'.join(source_strs)))
|
175
|
+
|
176
|
+
|
177
|
+
class NamespaceNotFoundError(BaseDepsTreeError):
|
178
|
+
"""Raised when a namespace is requested but not provided."""
|
179
|
+
|
180
|
+
def __init__(self, namespace, source=None):
|
181
|
+
BaseDepsTreeError.__init__(self)
|
182
|
+
self._namespace = namespace
|
183
|
+
self._source = source
|
184
|
+
|
185
|
+
def __str__(self):
|
186
|
+
msg = 'Namespace "%s" never provided.' % self._namespace
|
187
|
+
if self._source:
|
188
|
+
msg += ' Required in %s' % self._source
|
189
|
+
return msg
|