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.
Files changed (21) hide show
  1. data/.gitignore +4 -4
  2. data/lib/middleman-wizard-template/template.rb +1 -0
  3. data/lib/middleman-wizard-template/template/README.tt +25 -0
  4. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/closurebuilder.py +256 -0
  5. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree.py +189 -0
  6. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree.pyc +0 -0
  7. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree_test.py +127 -0
  8. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depswriter.py +202 -0
  9. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/jscompiler.py +71 -0
  10. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/jscompiler.pyc +0 -0
  11. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source.py +114 -0
  12. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source.pyc +0 -0
  13. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source_test.py +121 -0
  14. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/treescan.py +78 -0
  15. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/treescan.pyc +0 -0
  16. data/lib/middleman-wizard-template/template/config.tt +66 -0
  17. data/lib/middleman-wizard-template/template/shared/Gemfile.tt +2 -1
  18. data/lib/middleman-wizard-template/template/source/javascripts/app.js +3 -5
  19. data/lib/middleman-wizard-template/version.rb +1 -1
  20. metadata +21 -6
  21. data/lib/middleman-wizard-template/template/source/javascripts/_lib/asset_loader.js +0 -492
@@ -0,0 +1,127 @@
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
+
18
+ """Unit test for depstree."""
19
+
20
+ __author__ = 'nnaze@google.com (Nathan Naze)'
21
+
22
+
23
+ import unittest
24
+
25
+ import depstree
26
+
27
+
28
+ def _GetProvides(sources):
29
+ """Get all namespaces provided by a collection of sources."""
30
+
31
+ provides = set()
32
+ for source in sources:
33
+ provides.update(source.provides)
34
+ return provides
35
+
36
+
37
+ class MockSource(object):
38
+ """Mock Source file."""
39
+
40
+ def __init__(self, provides, requires):
41
+ self.provides = set(provides)
42
+ self.requires = set(requires)
43
+
44
+ def __repr__(self):
45
+ return 'MockSource %s' % self.provides
46
+
47
+
48
+ class DepsTreeTestCase(unittest.TestCase):
49
+ """Unit test for DepsTree. Tests several common situations and errors."""
50
+
51
+ def AssertValidDependencies(self, deps_list):
52
+ """Validates a dependency list.
53
+
54
+ Asserts that a dependency list is valid: For every source in the list,
55
+ ensure that every require is provided by a source earlier in the list.
56
+
57
+ Args:
58
+ deps_list: A list of sources that should be in dependency order.
59
+ """
60
+
61
+ for i in range(len(deps_list)):
62
+ source = deps_list[i]
63
+ previous_provides = _GetProvides(deps_list[:i])
64
+ for require in source.requires:
65
+ self.assertTrue(
66
+ require in previous_provides,
67
+ 'Namespace "%s" not provided before required by %s' % (
68
+ require, source))
69
+
70
+ def testSimpleDepsTree(self):
71
+ a = MockSource(['A'], ['B', 'C'])
72
+ b = MockSource(['B'], [])
73
+ c = MockSource(['C'], ['D'])
74
+ d = MockSource(['D'], ['E'])
75
+ e = MockSource(['E'], [])
76
+
77
+ tree = depstree.DepsTree([a, b, c, d, e])
78
+
79
+ self.AssertValidDependencies(tree.GetDependencies('A'))
80
+ self.AssertValidDependencies(tree.GetDependencies('B'))
81
+ self.AssertValidDependencies(tree.GetDependencies('C'))
82
+ self.AssertValidDependencies(tree.GetDependencies('D'))
83
+ self.AssertValidDependencies(tree.GetDependencies('E'))
84
+
85
+ def testCircularDependency(self):
86
+ # Circular deps
87
+ a = MockSource(['A'], ['B'])
88
+ b = MockSource(['B'], ['C'])
89
+ c = MockSource(['C'], ['A'])
90
+
91
+ tree = depstree.DepsTree([a, b, c])
92
+
93
+ self.assertRaises(depstree.CircularDependencyError,
94
+ tree.GetDependencies, 'A')
95
+
96
+ def testRequiresUndefinedNamespace(self):
97
+ a = MockSource(['A'], ['B'])
98
+ b = MockSource(['B'], ['C'])
99
+ c = MockSource(['C'], ['D']) # But there is no D.
100
+
101
+ def MakeDepsTree():
102
+ return depstree.DepsTree([a, b, c])
103
+
104
+ self.assertRaises(depstree.NamespaceNotFoundError, MakeDepsTree)
105
+
106
+ def testDepsForMissingNamespace(self):
107
+ a = MockSource(['A'], ['B'])
108
+ b = MockSource(['B'], [])
109
+
110
+ tree = depstree.DepsTree([a, b])
111
+
112
+ # There is no C.
113
+ self.assertRaises(depstree.NamespaceNotFoundError,
114
+ tree.GetDependencies, 'C')
115
+
116
+ def testMultipleRequires(self):
117
+ a = MockSource(['A'], ['B'])
118
+ b = MockSource(['B'], ['C'])
119
+ c = MockSource(['C'], [])
120
+ d = MockSource(['D'], ['B'])
121
+
122
+ tree = depstree.DepsTree([a, b, c, d])
123
+ self.AssertValidDependencies(tree.GetDependencies(['D', 'A']))
124
+
125
+
126
+ if __name__ == '__main__':
127
+ unittest.main()
@@ -0,0 +1,202 @@
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
+
18
+ """Generates out a Closure deps.js file given a list of JavaScript sources.
19
+
20
+ Paths can be specified as arguments or (more commonly) specifying trees
21
+ with the flags (call with --help for descriptions).
22
+
23
+ Usage: depswriter.py [path/to/js1.js [path/to/js2.js] ...]
24
+ """
25
+
26
+ import logging
27
+ import optparse
28
+ import os
29
+ import posixpath
30
+ import shlex
31
+ import sys
32
+
33
+ import source
34
+ import treescan
35
+
36
+
37
+ __author__ = 'nnaze@google.com (Nathan Naze)'
38
+
39
+
40
+ def MakeDepsFile(source_map):
41
+ """Make a generated deps file.
42
+
43
+ Args:
44
+ source_map: A dict map of the source path to source.Source object.
45
+
46
+ Returns:
47
+ str, A generated deps file source.
48
+ """
49
+
50
+ # Write in path alphabetical order
51
+ paths = sorted(source_map.keys())
52
+
53
+ lines = []
54
+
55
+ for path in paths:
56
+ js_source = source_map[path]
57
+
58
+ # We don't need to add entries that don't provide anything.
59
+ if js_source.provides:
60
+ lines.append(_GetDepsLine(path, js_source))
61
+
62
+ return ''.join(lines)
63
+
64
+
65
+ def _GetDepsLine(path, js_source):
66
+ """Get a deps.js file string for a source."""
67
+
68
+ provides = sorted(js_source.provides)
69
+ requires = sorted(js_source.requires)
70
+
71
+ return 'goog.addDependency(\'%s\', %s, %s);\n' % (path, provides, requires)
72
+
73
+
74
+ def _GetOptionsParser():
75
+ """Get the options parser."""
76
+
77
+ parser = optparse.OptionParser(__doc__)
78
+
79
+ parser.add_option('--output_file',
80
+ dest='output_file',
81
+ action='store',
82
+ help=('If specified, write output to this path instead of '
83
+ 'writing to standard output.'))
84
+ parser.add_option('--root',
85
+ dest='roots',
86
+ default=[],
87
+ action='append',
88
+ help='A root directory to scan for JS source files. '
89
+ 'Paths of JS files in generated deps file will be '
90
+ 'relative to this path. This flag may be specified '
91
+ 'multiple times.')
92
+ parser.add_option('--root_with_prefix',
93
+ dest='roots_with_prefix',
94
+ default=[],
95
+ action='append',
96
+ help='A root directory to scan for JS source files, plus '
97
+ 'a prefix (if either contains a space, surround with '
98
+ 'quotes). Paths in generated deps file will be relative '
99
+ 'to the root, but preceded by the prefix. This flag '
100
+ 'may be specified multiple times.')
101
+ parser.add_option('--path_with_depspath',
102
+ dest='paths_with_depspath',
103
+ default=[],
104
+ action='append',
105
+ help='A path to a source file and an alternate path to '
106
+ 'the file in the generated deps file (if either contains '
107
+ 'a space, surround with whitespace). This flag may be '
108
+ 'specified multiple times.')
109
+ return parser
110
+
111
+
112
+ def _NormalizePathSeparators(path):
113
+ """Replaces OS-specific path separators with POSIX-style slashes.
114
+
115
+ Args:
116
+ path: str, A file path.
117
+
118
+ Returns:
119
+ str, The path with any OS-specific path separators (such as backslash on
120
+ Windows) replaced with URL-compatible forward slashes. A no-op on systems
121
+ that use POSIX paths.
122
+ """
123
+ return path.replace(os.sep, posixpath.sep)
124
+
125
+
126
+ def _GetRelativePathToSourceDict(root, prefix=''):
127
+ """Scans a top root directory for .js sources.
128
+
129
+ Args:
130
+ root: str, Root directory.
131
+ prefix: str, Prefix for returned paths.
132
+
133
+ Returns:
134
+ dict, A map of relative paths (with prefix, if given), to source.Source
135
+ objects.
136
+ """
137
+ # Remember and restore the cwd when we're done. We work from the root so
138
+ # that paths are relative from the root.
139
+ start_wd = os.getcwd()
140
+ os.chdir(root)
141
+
142
+ path_to_source = {}
143
+ for path in treescan.ScanTreeForJsFiles('.'):
144
+ prefixed_path = _NormalizePathSeparators(os.path.join(prefix, path))
145
+ path_to_source[prefixed_path] = source.Source(source.GetFileContents(path))
146
+
147
+ os.chdir(start_wd)
148
+
149
+ return path_to_source
150
+
151
+
152
+ def _GetPair(s):
153
+ """Return a string as a shell-parsed tuple. Two values expected."""
154
+ try:
155
+ # shlex uses '\' as an escape character, so they must be escaped.
156
+ s = s.replace('\\', '\\\\')
157
+ first, second = shlex.split(s)
158
+ return (first, second)
159
+ except:
160
+ raise Exception('Unable to parse input line as a pair: %s' % s)
161
+
162
+
163
+ def main():
164
+ """CLI frontend to MakeDepsFile."""
165
+ logging.basicConfig(format=(sys.argv[0] + ': %(message)s'),
166
+ level=logging.INFO)
167
+ options, args = _GetOptionsParser().parse_args()
168
+
169
+ path_to_source = {}
170
+
171
+ # Roots without prefixes
172
+ for root in options.roots:
173
+ path_to_source.update(_GetRelativePathToSourceDict(root))
174
+
175
+ # Roots with prefixes
176
+ for root_and_prefix in options.roots_with_prefix:
177
+ root, prefix = _GetPair(root_and_prefix)
178
+ path_to_source.update(_GetRelativePathToSourceDict(root, prefix=prefix))
179
+
180
+ # Source paths
181
+ for path in args:
182
+ path_to_source[path] = source.Source(source.GetFileContents(path))
183
+
184
+ # Source paths with alternate deps paths
185
+ for path_with_depspath in options.paths_with_depspath:
186
+ srcpath, depspath = _GetPair(path_with_depspath)
187
+ path_to_source[depspath] = source.Source(source.GetFileContents(srcpath))
188
+
189
+ # Make our output pipe.
190
+ if options.output_file:
191
+ out = open(options.output_file, 'w')
192
+ else:
193
+ out = sys.stdout
194
+
195
+ out.write('// This file was autogenerated by %s.\n' % sys.argv[0])
196
+ out.write('// Please do not edit.\n')
197
+
198
+ out.write(MakeDepsFile(path_to_source))
199
+
200
+
201
+ if __name__ == '__main__':
202
+ main()
@@ -0,0 +1,71 @@
1
+ # Copyright 2010 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
+ """Utility to use the Closure Compiler CLI from Python."""
16
+
17
+ import distutils.version
18
+ import logging
19
+ import re
20
+ import subprocess
21
+
22
+
23
+ # Pulls a version number from the first line of 'java -version'
24
+ # See http://java.sun.com/j2se/versioning_naming.html to learn more about the
25
+ # command's output format.
26
+ _VERSION_REGEX = re.compile('"([0-9][.0-9]*)')
27
+
28
+
29
+ def _GetJavaVersion():
30
+ """Returns the string for the current version of Java installed."""
31
+ proc = subprocess.Popen(['java', '-version'], stderr=subprocess.PIPE)
32
+ unused_stdoutdata, stderrdata = proc.communicate()
33
+ version_line = stderrdata.splitlines()[0]
34
+ return _VERSION_REGEX.search(version_line).group(1)
35
+
36
+
37
+ def Compile(compiler_jar_path, source_paths, flags=None):
38
+ """Prepares command-line call to Closure Compiler.
39
+
40
+ Args:
41
+ compiler_jar_path: Path to the Closure compiler .jar file.
42
+ source_paths: Source paths to build, in order.
43
+ flags: A list of additional flags to pass on to Closure Compiler.
44
+
45
+ Returns:
46
+ The compiled source, as a string, or None if compilation failed.
47
+ """
48
+
49
+ # User friendly version check.
50
+ if not (distutils.version.LooseVersion(_GetJavaVersion()) >=
51
+ distutils.version.LooseVersion('1.6')):
52
+ logging.error('Closure Compiler requires Java 1.6 or higher. '
53
+ 'Please visit http://www.java.com/getjava')
54
+ return
55
+
56
+ args = ['java', '-jar', compiler_jar_path]
57
+ for path in source_paths:
58
+ args += ['--js', path]
59
+
60
+ if flags:
61
+ args += flags
62
+
63
+ logging.info('Compiling with the following command: %s', ' '.join(args))
64
+
65
+ proc = subprocess.Popen(args, stdout=subprocess.PIPE)
66
+ stdoutdata, unused_stderrdata = proc.communicate()
67
+
68
+ if proc.returncode != 0:
69
+ return
70
+
71
+ return stdoutdata
@@ -0,0 +1,114 @@
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
+ """Scans a source JS file for its provided and required namespaces.
17
+
18
+ Simple class to scan a JavaScript file and express its dependencies.
19
+ """
20
+
21
+ __author__ = 'nnaze@google.com'
22
+
23
+
24
+ import re
25
+
26
+ _BASE_REGEX_STRING = '^\s*goog\.%s\(\s*[\'"](.+)[\'"]\s*\)'
27
+ _PROVIDE_REGEX = re.compile(_BASE_REGEX_STRING % 'provide')
28
+ _REQUIRES_REGEX = re.compile(_BASE_REGEX_STRING % 'require')
29
+
30
+ # This line identifies base.js and should match the line in that file.
31
+ _GOOG_BASE_LINE = (
32
+ 'var goog = goog || {}; // Identifies this file as the Closure base.')
33
+
34
+
35
+ class Source(object):
36
+ """Scans a JavaScript source for its provided and required namespaces."""
37
+
38
+ # Matches a "/* ... */" comment.
39
+ # Note: We can't definitively distinguish a "/*" in a string literal without a
40
+ # state machine tokenizer. We'll assume that a line starting with whitespace
41
+ # and "/*" is a comment.
42
+ _COMMENT_REGEX = re.compile(
43
+ r"""
44
+ ^\s* # Start of a new line and whitespace
45
+ /\* # Opening "/*"
46
+ .*? # Non greedy match of any characters (including newlines)
47
+ \*/ # Closing "*/""",
48
+ re.MULTILINE | re.DOTALL | re.VERBOSE)
49
+
50
+ def __init__(self, source):
51
+ """Initialize a source.
52
+
53
+ Args:
54
+ source: str, The JavaScript source.
55
+ """
56
+
57
+ self.provides = set()
58
+ self.requires = set()
59
+
60
+ self._source = source
61
+ self._ScanSource()
62
+
63
+ def __str__(self):
64
+ return 'Source %s' % self._path
65
+
66
+ def GetSource(self):
67
+ """Get the source as a string."""
68
+ return self._source
69
+
70
+ @classmethod
71
+ def _StripComments(cls, source):
72
+ return cls._COMMENT_REGEX.sub('', source)
73
+
74
+ def _ScanSource(self):
75
+ """Fill in provides and requires by scanning the source."""
76
+
77
+ source = self._StripComments(self.GetSource())
78
+
79
+ source_lines = source.splitlines()
80
+ for line in source_lines:
81
+ match = _PROVIDE_REGEX.match(line)
82
+ if match:
83
+ self.provides.add(match.group(1))
84
+ match = _REQUIRES_REGEX.match(line)
85
+ if match:
86
+ self.requires.add(match.group(1))
87
+
88
+ # Closure's base file implicitly provides 'goog'.
89
+ for line in source_lines:
90
+ if line == _GOOG_BASE_LINE:
91
+ if len(self.provides) or len(self.requires):
92
+ raise Exception(
93
+ 'Base files should not provide or require namespaces.')
94
+ self.provides.add('goog')
95
+
96
+
97
+ def GetFileContents(path):
98
+ """Get a file's contents as a string.
99
+
100
+ Args:
101
+ path: str, Path to file.
102
+
103
+ Returns:
104
+ str, Contents of file.
105
+
106
+ Raises:
107
+ IOError: An error occurred opening or reading the file.
108
+
109
+ """
110
+ fileobj = open(path)
111
+ try:
112
+ return fileobj.read()
113
+ finally:
114
+ fileobj.close()