diff options
Diffstat (limited to 'misc/openlayers/tools/mergejs.py')
-rwxr-xr-x | misc/openlayers/tools/mergejs.py | 287 |
1 files changed, 0 insertions, 287 deletions
diff --git a/misc/openlayers/tools/mergejs.py b/misc/openlayers/tools/mergejs.py deleted file mode 100755 index 1b26f2e..0000000 --- a/misc/openlayers/tools/mergejs.py +++ /dev/null @@ -1,287 +0,0 @@ -#!/usr/bin/env python -# -# Merge multiple JavaScript source code files into one. -# -# Usage: -# This script requires source files to have dependencies specified in them. -# -# Dependencies are specified with a comment of the form: -# -# // @requires <file path> -# -# e.g. -# -# // @requires Geo/DataSource.js -# -# This script should be executed like so: -# -# mergejs.py <output.js> <directory> [...] -# -# e.g. -# -# mergejs.py openlayers.js Geo/ CrossBrowser/ -# -# This example will cause the script to walk the `Geo` and -# `CrossBrowser` directories--and subdirectories thereof--and import -# all `*.js` files encountered. The dependency declarations will be extracted -# and then the source code from imported files will be output to -# a file named `openlayers.js` in an order which fulfils the dependencies -# specified. -# -# -# Note: This is a very rough initial version of this code. -# -# -- Copyright 2005-2013 OpenLayers contributors / OpenLayers project -- -# - -# TODO: Allow files to be excluded. e.g. `Crossbrowser/DebugMode.js`? -# TODO: Report error when dependency can not be found rather than KeyError. - -import re -import os -import sys - -SUFFIX_JAVASCRIPT = ".js" - -RE_REQUIRE = "@requires?:?\s+(\S*)\s*\n" # TODO: Ensure in comment? - -class MissingImport(Exception): - """Exception raised when a listed import is not found in the lib.""" - -class SourceFile: - """ - Represents a Javascript source code file. - """ - - def __init__(self, filepath, source, cfgExclude): - """ - """ - self.filepath = filepath - self.source = source - - self.excludedFiles = [] - self.requiredFiles = [] - auxReq = re.findall(RE_REQUIRE, self.source) - for filename in auxReq: - if undesired(filename, cfgExclude): - self.excludedFiles.append(filename) - else: - self.requiredFiles.append(filename) - - self.requiredBy = [] - - - def _getRequirements(self): - """ - Extracts the dependencies specified in the source code and returns - a list of them. - """ - return self.requiredFiles - - requires = property(fget=_getRequirements, doc="") - - - -def usage(filename): - """ - Displays a usage message. - """ - print "%s [-c <config file>] <output.js> <directory> [...]" % filename - - -class Config: - """ - Represents a parsed configuration file. - - A configuration file should be of the following form: - - [first] - 3rd/prototype.js - core/application.js - core/params.js - # A comment - - [last] - core/api.js # Another comment - - [exclude] - 3rd/logger.js - exclude/this/dir - - All headings are required. - - The files listed in the `first` section will be forced to load - *before* all other files (in the order listed). The files in `last` - section will be forced to load *after* all the other files (in the - order listed). - - The files list in the `exclude` section will not be imported. - - Any text appearing after a # symbol indicates a comment. - - """ - - def __init__(self, filename): - """ - Parses the content of the named file and stores the values. - """ - lines = [re.sub("#.*?$", "", line).strip() # Assumes end-of-line character is present - for line in open(filename) - if line.strip() and not line.strip().startswith("#")] # Skip blank lines and comments - - self.forceFirst = lines[lines.index("[first]") + 1:lines.index("[last]")] - - self.forceLast = lines[lines.index("[last]") + 1:lines.index("[include]")] - self.include = lines[lines.index("[include]") + 1:lines.index("[exclude]")] - self.exclude = lines[lines.index("[exclude]") + 1:] - -def undesired(filepath, excludes): - # exclude file if listed - exclude = filepath in excludes - if not exclude: - # check if directory is listed - for excludepath in excludes: - if not excludepath.endswith("/"): - excludepath += "/" - if filepath.startswith(excludepath): - exclude = True - break - return exclude - - -def getNames (sourceDirectory, configFile = None): - return run(sourceDirectory, None, configFile, True) - - -def run (sourceDirectory, outputFilename = None, configFile = None, - returnAsListOfNames = False): - cfg = None - if configFile: - cfg = Config(configFile) - - allFiles = [] - - ## Find all the Javascript source files - for root, dirs, files in os.walk(sourceDirectory): - for filename in files: - if filename.endswith(SUFFIX_JAVASCRIPT) and not filename.startswith("."): - filepath = os.path.join(root, filename)[len(sourceDirectory)+1:] - filepath = filepath.replace("\\", "/") - if cfg and cfg.include: - if filepath in cfg.include or filepath in cfg.forceFirst: - allFiles.append(filepath) - elif (not cfg) or (not undesired(filepath, cfg.exclude)): - allFiles.append(filepath) - - ## Header inserted at the start of each file in the output - HEADER = "/* " + "=" * 70 + "\n %s\n" + " " + "=" * 70 + " */\n\n" - - files = {} - - ## Import file source code - ## TODO: Do import when we walk the directories above? - for filepath in allFiles: - print "Importing: %s" % filepath - fullpath = os.path.join(sourceDirectory, filepath).strip() - content = open(fullpath, "U").read() # TODO: Ensure end of line @ EOF? - files[filepath] = SourceFile(filepath, content, cfg.exclude) # TODO: Chop path? - - print - - from toposort import toposort - - complete = False - resolution_pass = 1 - - while not complete: - complete = True - - ## Resolve the dependencies - print "Resolution pass %s... " % resolution_pass - resolution_pass += 1 - - for filepath, info in files.items(): - for path in info.requires: - if not files.has_key(path): - complete = False - fullpath = os.path.join(sourceDirectory, path).strip() - if os.path.exists(fullpath): - print "Importing: %s" % path - content = open(fullpath, "U").read() # TODO: Ensure end of line @ EOF? - files[path] = SourceFile(path, content, cfg.exclude) # TODO: Chop path? - else: - raise MissingImport("File '%s' not found (required by '%s')." % (path, filepath)) - - # create dictionary of dependencies - dependencies = {} - for filepath, info in files.items(): - dependencies[filepath] = info.requires - - print "Sorting..." - order = toposort(dependencies) #[x for x in toposort(dependencies)] - - ## Move forced first and last files to the required position - if cfg: - print "Re-ordering files..." - order = cfg.forceFirst + [item - for item in order - if ((item not in cfg.forceFirst) and - (item not in cfg.forceLast))] + cfg.forceLast - - print - ## Output the files in the determined order - result = [] - - # Return as a list of filenames - if returnAsListOfNames: - for fp in order: - fName = os.path.normpath(os.path.join(sourceDirectory, fp)).replace("\\","/") - print "Append: ", fName - f = files[fp] - for fExclude in f.excludedFiles: - print " Required file \"%s\" is excluded." % fExclude - result.append(fName) - print "\nTotal files: %d " % len(result) - return result - - # Return as merged source code - for fp in order: - f = files[fp] - print "Exporting: ", f.filepath - for fExclude in f.excludedFiles: - print " Required file \"%s\" is excluded." % fExclude - result.append(HEADER % f.filepath) - source = f.source - result.append(source) - if not source.endswith("\n"): - result.append("\n") - - print "\nTotal files merged: %d " % len(files) - - if outputFilename: - print "\nGenerating: %s" % (outputFilename) - open(outputFilename, "w").write("".join(result)) - return "".join(result) - -if __name__ == "__main__": - import getopt - - options, args = getopt.getopt(sys.argv[1:], "-c:") - - try: - outputFilename = args[0] - except IndexError: - usage(sys.argv[0]) - raise SystemExit - else: - sourceDirectory = args[1] - if not sourceDirectory: - usage(sys.argv[0]) - raise SystemExit - - configFile = None - if options and options[0][0] == "-c": - configFile = options[0][1] - print "Parsing configuration file: %s" % filename - - run( sourceDirectory, outputFilename, configFile ) |