middleman-wizard-template 1.0.0.pre.1 → 1.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.
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()