[Pkg-javascript-commits] [node-dryice] 01/01: Imported Upstream version 0.4.10
Leo Iannacone
l3on-guest at moszumanska.debian.org
Wed Apr 30 10:15:00 UTC 2014
This is an automated email from the git hooks/post-receive script.
l3on-guest pushed a commit to branch master
in repository node-dryice.
commit 66f7c2632e8b7b1c585ae1962c572aa03c8f471e
Author: Leo Iannacone <l3on at ubuntu.com>
Date: Wed Apr 30 11:59:05 2014 +0200
Imported Upstream version 0.4.10
---
LICENSE | 202 ++++++++
README.md | 346 +++++++++++++
lib/dryice/index.js | 1149 ++++++++++++++++++++++++++++++++++++++++++++
lib/dryice/mini_require.js | 190 ++++++++
package.json | 23 +
5 files changed, 1910 insertions(+)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6074b6c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,346 @@
+DryIce
+======
+
+DryIce is a CommonJS/RequireJS packaging tool for browser scripts.
+
+It is basically just a copy function. It takes input from a set of input files,
+which can be specified in various ways, optionally filters them and outputs them
+to something else.
+
+DryIce is licensed under the Apache License version 2
+
+
+Why?
+----
+
+RequireJS has a build tool which is nice and works well, but it requires Rhino
+and therefore Java. With DryIce, your whole build process can be in JavaScript.
+
+DryIce produces a single file output that can include binary files (by base64
+encoding them)
+
+
+How to install DryIce
+---------------------
+
+ sudo npm install dryice
+
+
+How does it work?
+-----------------
+
+To copy a single file:
+
+ copy({
+ source: 'foo.txt',
+ dest: 'bar.txt'
+ });
+
+To cat a bunch of files together:
+
+ copy({
+ source: [ 'file1.js', 'file2.js' ],
+ dest: 'output.js'
+ });
+
+To cat together all the files in a directory:
+
+ copy({
+ source: { root:'src' },
+ dest: 'built.js'
+ });
+
+As above, but only use the JavaScript files:
+
+ copy({
+ source: { root:'src', include:/.*\.js$/ },
+ dest: 'built.js'
+ });
+
+As above, but exclude tests:
+
+ copy({
+ source: { root:'src', include:/.*\.js$/: exclude:/test/ },
+ dest: 'built.js'
+ });
+
+If your set of files is very custom:
+
+ copy({
+ source: function() {
+ var files = [ 'file1.js' ];
+ if (baz) files.push('file2.js');
+ return files;
+ },
+ dest: 'built.js'
+ });
+
+We can filter the files on the way:
+
+ copy({
+ source: /src/.*\.js$/,
+ filter: copy.filter.uglifyjs,
+ dest: 'built.js'
+ });
+
+This includes running multiple custom filters:
+
+ copy({
+ source: 'src/index.html',
+ filter: [
+ function(data) {
+ return data.replace(/Sun/, 'Oracle');
+ },
+ htmlCompressor
+ ],
+ dest: 'war/index.html'
+ });
+
+Results can be stored and then used/reused:
+
+ var sources = copy.createDataObject();
+ copy({
+ source: { root: 'src1' },
+ dest: sources
+ });
+ copy({
+ source: { root: 'src2' },
+ dest: sources
+ });
+ copy({
+ source: sources,
+ dest: 'sources-uncompressed.js'
+ });
+ copy({
+ source: sources,
+ filter: copy.filter.uglifyjs,
+ dest: 'sources.js'
+ });
+
+Data objects are just JS objects with a 'value' member, so you can do all sorts
+of things with them:
+
+ var test = copy.createDataObject();
+ copy({
+ source: 'README.txt',
+ dest: test
+ });
+ console.log(test.value);
+
+Or:
+
+ copy({
+ source: { value: 'Hello, World!' },
+ dest: 'basic.txt'
+ });
+
+And you can mix and match your inputs:
+
+ copy({
+ source: [
+ 'somefile.txt',
+ thingDataObject,
+ { root: 'src', include: /.*\.js$/ },
+ function() { return 'wibble.sh'; }
+ ],
+ dest: 'mess.bin'
+ });
+
+Common JS project dependency tracking:
+
+ var project = copy.createCommonJsProject({
+ roots: [
+ '/path/to/source/tree/lib',
+ '/some/other/project/lib'
+ ]
+ });
+ copy({
+ source: copy.source.commonjs({
+ project: project,
+ require: [ 'main', 'plugin/main' ]
+ }),
+ dest: ''
+ });
+
+This digs around in the project source trees specified in the project for
+modules named in the 'require' statement. When it finds them it looks through
+them for require statements, and finds those, and so on.
+
+
+Formal Parameter Description
+----------------------------
+
+The copy function takes a single parameter which is an object with 2 or 3
+members: `source`, `dest` and optionally `filter`.
+
+### source
+
+There are 6 ways to specify the input source(s)
+
+* A *string* is expected to point to a filename.
+ At some stage we may allow them to point at directories too, however this
+ can be achieved today using a find object (see below)
+
+* A *find object* points to a directory with 2 optional RegExps specifying what
+ to exclude and include. e.g.
+
+ { root: '/' } -> The entire filesystem
+ { root: 'src', include: /.*\.js$/ } -> All the JavaScript files in 'src'
+ { root: 'src', exclude: /test/ } -> All non-test files under 'src'
+
+* A *data object* - something with a 'value' property.
+ The implementation of `copy.createDataObject()` is simply
+ `return { value: '' };`. We've batted around some ideas which involve making
+ `copy.createDataObject()` smarter than it currently is, so it is advised to
+ use this method rather than doing it yourself.
+
+* A *based object*. A based object is one with `base` and `path` members. They
+ are roughly the same as the string baseObj.base + baseObj.path. Based objects
+ are important when using CommonJS filters, because it tells the filter where
+ the root of the hierarchy is, which lets us know the module name.
+ For example:
+
+ { base: '/etc', path:PATH } where BASE+PATH = filename
+
+* An *array* containing input source entries. The array does not have to be
+ homogeneous.
+
+* A *function* which returns any input source entries.
+
+### filter
+
+The filter member is optional. If it exists, it should contain either a function
+or an array of functions. The function should have the following signature:
+
+ function filter(value, location) {
+ ..
+ return 'some string';
+ }
+
+Where the parameters are as follows:
+
+* value. Either a string or a node Buffer. Most filters will work only with
+ strings, so they should begin:
+
+ if (typeof value !== 'string') {
+ value = value.toString();
+ }
+
+ Some filters will only work with Buffers (for example the base64 encoding
+ filter) so they should begin:
+
+ if (typeof value === 'string') {
+ throw new Error('base64 filter needs to be the first in a filter set');
+ }
+
+ At some stage we may allow filters to be marked up as to their requirements.
+
+* location. This will be (where possible) a based object or it could be a
+ string if a based object is not available. It will be common to use one of the
+ following idioms to work on a filename:
+
+ if (location.base) {
+ location = location.path;
+ }
+
+ or
+
+ if (location.base) {
+ location = location.base + location.path;
+ }
+
+There are 2 points in a copy run where filters could be used, either before the
+individual sources are concatenated, or after. Some filters should be used in
+before (like common-js munging filters) and some afterwards (like compressors).
+
+The default is to run filters after concatenation (when the location parameter
+will be undefined). To run filters before concatenation, the filter should be
+marked with `onRead = true`. For example:
+
+ function makeBlank(value, location) {
+ return '';
+ }
+ makeBlank.onRead = true;
+
+DryIce currently comes with 4 filters:
+
+* _copy.filter.uglifyjs_: Calls uglify on the input.
+* _copy.filter.addDefines_: Wraps the input to inline files fetched using
+ RequireJSs text import feature.
+* _copy.filter.base64_: Similar to addDefines, but assumes the input is
+ binary and should be base64 encoded.
+* _copy.filter.moduleDefines_: Replaces define lines to include the module name
+ e.g. `define(function(export, require, module) { ... });` is turned into
+ `define('module/name', function(export, require, module) { ... });`
+
+
+### dest
+
+The dest property should be either a filename to which the output should be
+written (existing files will be over-written without warning), or a data object
+to which the data should be appended.
+
+CommonJS Projects
+-----------------
+
+CommonJS projects take a single object with the following properties:
+
+* `roots`: This is required. An array of directories that should be searched for
+ your required modules and dependencies.
+
+* `ignores`: This is optional. An array of modules or dependencies that are
+ required by your project that you would not like to be included in the
+ build. For example, if you were making a build which did not need to support
+ IE, you could do something like the following
+
+ copy.createCommonJsProject({
+ roots: [ '/path/to/project' ],
+ ignores: [ 'dom/ie-compat', 'event/ie-compat' ]
+ });
+
+ then wherever you had `require('dom/ie-compat')` or
+ `require('event/ie-compat')` inside your build, `undefined` would be returned
+ by `require`.
+
+Where (is the project going)?
+-----------------------------
+
+DryIce is useful in combining scripts for the browser, but it could also be
+used in a similar role on the server, we just need to enable 'pass through
+requires'.
+
+There are some tweaks we'd still like to make to enable more filters and
+multiple destinations:
+
+To recursively copy a directory:
+
+ copy({ source: 'foo', destDir: 'bar' });
+
+To rename files as we copy them:
+
+ copy({
+ source: { root:'src', include:/.*\.png$/ },
+ destDir: { root:'built', replace:/png$/, with:'png.bak' }
+ });
+
+To create a tarball (this is only missing the targz filter):
+
+ var version = copy.createDataObject();
+ copy({ source: 'VERSION.txt', dest: version });
+ copy({
+ source: { root:'.' },
+ filter: [ targz ],
+ dest: 'scp://example.com/upload/myproject-' + version + '.tar.gz'
+ });
+
+I don't suppose you would ever actually want to do this, but in theory you
+could even do this:
+
+ copy({
+ source: { root:'src', include:/.*\.java$/ },
+ filter: javac,
+ destDir: { root:'classes', replace:/java$/, with:'class' }
+ });
+
+(Actually there would be issues with ordering that would make this hard, and
+Ant/Maven/etc is probably better. This is an illustration dammit!)
diff --git a/lib/dryice/index.js b/lib/dryice/index.js
new file mode 100644
index 0000000..b391558
--- /dev/null
+++ b/lib/dryice/index.js
@@ -0,0 +1,1149 @@
+/*
+ * Copyright 2012, Mozilla Foundation and contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var fs = require("fs");
+var path = require("path");
+var ujs = require("uglify-js");
+
+if (!fs.existsSync) {
+ fs.existsSync = path.existsSync;
+}
+
+/**
+ * See https://github.com/mozilla/dryice for usage instructions.
+ */
+function copy(obj) {
+ var filters = copy.filterFactory(obj.filter);
+ var source = copy.sourceFactory(obj.source, filters);
+ var dest = copy.destFactory(obj.dest, filters);
+ dest.processSource(source);
+}
+
+/**
+ * A Location is a base and a path which together point to a file or directory.
+ * It's useful to be able to know in copy operations relative to some project
+ * root to be able to remember where in a destination the file should go
+ */
+function Location(base, somePath) {
+ if (base == null) {
+ throw new Error('base == null');
+ }
+ this.base = base;
+ this.path = somePath;
+}
+
+Location.prototype.isLocation = true;
+
+Object.defineProperty(Location.prototype, 'fullname', {
+ get: function() {
+ return path.join(this.base, this.path);
+ }
+});
+
+Object.defineProperty(Location.prototype, 'dirname', {
+ get: function() {
+ return path.dirname(this.fullname);
+ }
+});
+
+/**
+ * Select the correct implementation of Source for the given source property
+ */
+copy.sourceFactory = function(source, filters) {
+ if (source == null) {
+ throw new Error('Missing source');
+ }
+
+ if (source.isSource) {
+ return source;
+ }
+
+ if (typeof source === 'string') {
+ if (copy.isDirectory(source)) {
+ return new copy.DirectorySource(source, null, null, filters);
+ }
+ else {
+ return new copy.FileSource(new Location('', source), filters);
+ }
+ }
+
+ if (Array.isArray(source)) {
+ return new copy.ArraySource(source, filters);
+ }
+
+ if (typeof source === 'function') {
+ return new copy.FunctionSource(source, filters);
+ }
+
+ if (source.root != null) {
+ if (source.require != null) {
+ var project = new CommonJsProject([ source.root ]);
+ return new copy.CommonJsSource(project, source.require, filters);
+ }
+
+ return new copy.DirectorySource(source.root, source.include, source.exclude, filters);
+ }
+
+ if (source.base != null && source.path != null) {
+ return new copy.FileSource(new Location(source.base, source.path), filters);
+ }
+
+ if (typeof source.value === 'string') {
+ return new copy.ValueSource(source.value, null, filters);
+ }
+
+ if (source.project != null && source.require != null) {
+ return new copy.CommonJsSource(source.project, source.require, filters);
+ }
+
+ throw new Error('Can\'t handle type of source: ' + typeof source);
+};
+
+copy.debug = false;
+
+/**
+ * Abstract Source.
+ * Concrete implementations of Source should define the 'get' property.
+ */
+copy.Source = function() {
+};
+
+/**
+ * @return Either another source, an array of other sources or a string value
+ * when there is nothing else to dig into
+ */
+Object.defineProperty(copy.Source.prototype, 'get', {
+ get: function() {
+ throw new Error('Source.get is not implemented');
+ }
+});
+
+copy.Source.prototype.isSource = true;
+
+copy.Source.prototype._runFilters = function(value, location) {
+ this._filters.forEach(function(filter) {
+ if (filter.onRead) {
+ value = filter(value, location);
+ }
+ }, this);
+ return value;
+};
+
+/**
+ * Default encoding for all sources
+ */
+copy.Source.prototype.encoding = 'utf8';
+
+/**
+ * An ArraySource is simply an array containing things that can resolve to
+ * implementations of Source when passed to copy.sourceFactory()
+ */
+copy.ArraySource = function(array, filters) {
+ copy.Source.call(this);
+ this._array = array;
+ this._filters = filters;
+};
+
+copy.ArraySource.prototype = Object.create(copy.Source.prototype);
+
+Object.defineProperty(copy.ArraySource.prototype, 'get', {
+ get: function() {
+ return this._array.map(function(member) {
+ return copy.sourceFactory(member, this._filters);
+ }, this);
+ }
+});
+
+/**
+ * A FunctionSource is something that can be called to resolve to another
+ * Source implementation
+ */
+copy.FunctionSource = function(func, filters) {
+ copy.Source.call(this);
+ this._func = func;
+ this._filters = filters;
+};
+
+copy.FunctionSource.prototype = Object.create(copy.Source.prototype);
+
+Object.defineProperty(copy.FunctionSource.prototype, 'get', {
+ get: function() {
+ return copy.sourceFactory(this._func(), this._filters);
+ }
+});
+
+/**
+ * A Source that finds files under a given directory with specified include /
+ * exclude patterns.
+ * @param root The root in the filesystem under which the files exist
+ * @param filterOrInclude
+ */
+copy.DirectorySource = function(root, filterOrInclude, exclude, filters) {
+ copy.Source.call(this);
+ this._filters = filters;
+
+ this.root = root;
+ if (this.root instanceof CommonJsProject) {
+ this.root = this.root.roots;
+ }
+
+ if (Array.isArray(this.root)) {
+ this.root.map(function(r) {
+ return ensureTrailingSlash(r);
+ });
+ }
+
+ if (typeof filterOrInclude === 'function') {
+ this._searchFilter = filterOrInclude;
+ }
+ else {
+ this._searchFilter = this._createFilter(filterOrInclude, exclude);
+ }
+};
+
+copy.DirectorySource.prototype = Object.create(copy.Source.prototype);
+
+Object.defineProperty(copy.DirectorySource.prototype, 'get', {
+ get: function() {
+ return this._findMatches(this.root, '/');
+ }
+});
+
+copy.DirectorySource.prototype._findMatches = function(root, path) {
+ var sources = [];
+
+ if (Array.isArray(root)) {
+ root.forEach(function(r) {
+ var matches = this._findMatches(r, path);
+ sources.push.apply(sources, matches);
+ }, this);
+ return sources;
+ }
+
+ root = ensureTrailingSlash(root);
+ path = ensureTrailingSlash(path);
+
+ if (copy.isDirectory(root + path)) {
+ fs.readdirSync(root + path).forEach(function(entry) {
+ var stat = fs.statSync(root + path + entry);
+ if (stat.isFile()) {
+ if (this._searchFilter(path + entry)) {
+ var location = new Location(root, path + entry);
+ sources.push(new copy.FileSource(location, this._filters));
+ }
+ }
+ else if (stat.isDirectory()) {
+ var matches = this._findMatches(root, path + entry);
+ sources.push.apply(sources, matches);
+ }
+ }, this);
+ }
+
+ return sources;
+};
+
+copy.DirectorySource.prototype._createFilter = function(include, exclude) {
+ return function(pathname) {
+ function noPathMatch(pattern) {
+ return !pattern.test(pathname);
+ }
+ if (include instanceof RegExp) {
+ if (noPathMatch(include)) {
+ return false;
+ }
+ }
+ if (typeof include === 'string') {
+ if (noPathMatch(new RegExp(include))) {
+ return false;
+ }
+ }
+ if (Array.isArray(include)) {
+ if (include.every(noPathMatch)) {
+ return false;
+ }
+ }
+
+ function pathMatch(pattern) {
+ return pattern.test(pathname);
+ }
+ if (exclude instanceof RegExp) {
+ if (pathMatch(exclude)) {
+ return false;
+ }
+ }
+ if (typeof exclude === 'string') {
+ if (pathMatch(new RegExp(exclude))) {
+ return false;
+ }
+ }
+ if (Array.isArray(exclude)) {
+ if (exclude.some(pathMatch)) {
+ return false;
+ }
+ }
+
+ return true;
+ };
+};
+
+/**
+ * A FileSource gets data directly from a file. It has 2 parts to the filename,
+ * a base and path members, where filename = base + path.
+ * FileSources are important when using CommonJS filters, because it tells the
+ * filter where the root of the hierarchy is, which lets us know the module
+ * name.
+ * If there is no base to the filename, use a base of ''.
+ */
+copy.FileSource = function(location, filters) {
+ copy.Source.call(this);
+ this.location = location;
+ this.name = location.fullname;
+ this._filters = filters;
+};
+
+copy.FileSource.prototype = Object.create(copy.Source.prototype);
+
+Object.defineProperty(copy.FileSource.prototype, 'get', {
+ get: function() {
+ var read = fs.readFileSync(this.name);
+ return this._runFilters(read, this.location);
+ }
+});
+
+/**
+ *
+ */
+copy.ValueSource = function(value, location, filters) {
+ copy.Source.call(this);
+ this._value = value;
+ this._location = location;
+ this._filters = filters;
+};
+
+copy.ValueSource.prototype = Object.create(copy.Source.prototype);
+
+Object.defineProperty(copy.ValueSource.prototype, 'get', {
+ get: function() {
+ return this._runFilters(this._value, this._location);
+ }
+});
+
+/**
+ * Read modules from a CommonJS Project using a require property.
+ */
+copy.CommonJsSource = function(project, require, filters) {
+ copy.Source.call(this);
+ this._project = project;
+ this._filters = filters;
+
+ if (!project instanceof CommonJsProject) {
+ throw new Error('commonjs project should be a CommonJsProject');
+ }
+
+ if (typeof require === 'string') {
+ this._require = [ require ];
+ }
+ else if (Array.isArray(require)) {
+ this._require = require;
+ }
+ else {
+ throw new Error('Expected commonjs args to have string/array require.');
+ }
+};
+
+copy.CommonJsSource.prototype = Object.create(copy.Source.prototype);
+
+Object.defineProperty(copy.CommonJsSource.prototype, 'get', {
+ get: function() {
+ this._require.forEach(function(moduleName) {
+ this._project.require(moduleName);
+ }, this);
+ return this._project.getCurrentModules().map(function(location) {
+ return new copy.FileSource(location, this._filters);
+ }.bind(this));
+ }
+});
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+copy.filterFactory = function(filter) {
+ if (filter == null) {
+ return [];
+ }
+
+ if (typeof filter === 'function') {
+ return [ filter ];
+ }
+
+ if (Array.isArray(filter)) {
+ return filter;
+ }
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Select the correct implementation of Destination for the given dest property
+ */
+copy.destFactory = function(dest, filters) {
+ if (dest == null) {
+ throw new Error('Missing dest');
+ }
+
+ if (dest.isDestination) {
+ return dest;
+ }
+
+ if (dest.value != null) {
+ return new copy.ValueDestination(dest, filters);
+ }
+
+ if (typeof dest === 'string') {
+ if (copy.isDirectory(dest)) {
+ return new copy.DirectoryDestination(dest, filters);
+ }
+ else {
+ return new copy.FileDestination(dest, filters);
+ }
+ }
+
+ if (Array.isArray(dest)) {
+ return new copy.ArrayDestination(dest, filters);
+ }
+
+ throw new Error('Can\'t handle type of dest: ' + typeof dest);
+};
+
+/**
+ * Abstract Destination.
+ * Concrete implementations of Destination should define the 'processSource'
+ * function.
+ */
+copy.Destination = function() {
+};
+
+copy.Destination.prototype.isDestination = true;
+
+/**
+ * @return Either another dest, an array of other sources or a string value
+ * when there is nothing else to dig into
+ */
+copy.Destination.prototype.processSource = function(source) {
+ throw new Error('Destination.processSource() is not implemented');
+};
+
+/**
+ * Helper function to convert an input source to a single string value
+ */
+copy.Destination.prototype._sourceToOutput = function(source) {
+ var data = source.get;
+
+ if (data.isSource) {
+ return this._sourceToOutput(data);
+ }
+
+ if (Array.isArray(data)) {
+ var value = '';
+ data.forEach(function(s) {
+ value += this._sourceToOutput(s);
+ }, this);
+ return value;
+ }
+
+ if (typeof data === 'string') {
+ return data;
+ }
+
+ // i.e. a Node Buffer
+ if (typeof data.toString === 'function') {
+ return data.toString();
+ }
+
+ throw new Error('Unexpected value from source.get');
+};
+
+copy.Destination.prototype._runFilters = function(value) {
+ this._filters.forEach(function(filter) {
+ if (!filter.onRead) {
+ value = filter(value);
+ }
+ }, this);
+ return value;
+};
+
+/**
+ * A Destination that concatenates the sources and writes them to a single
+ * output file.
+ */
+copy.FileDestination = function(filename, filters) {
+ this._filename = filename;
+ this._filters = filters;
+};
+
+copy.FileDestination.prototype = Object.create(copy.Destination.prototype);
+
+copy.FileDestination.prototype.processSource = function(source) {
+ var data = this._sourceToOutput(source);
+ data = this._runFilters(data);
+ copy._writeToFile(this._filename, data);
+};
+
+/**
+ * A Destination that copies the sources to new files in an alternate directory
+ * structure.
+ */
+copy.DirectoryDestination = function(dirname, filters) {
+ this.name = dirname;
+ this._filters = filters;
+};
+
+copy.DirectoryDestination.prototype = Object.create(copy.Destination.prototype);
+
+copy.DirectoryDestination.prototype.processSource = function(source) {
+ var data = source.get;
+ if (typeof data === 'string') {
+ throw new Error('Can\'t write raw data to a directory');
+ }
+ else if (data.isSource) {
+ var destfile = path.join(this.name, data.location.path);
+ var output = this._runFilters(data.get);
+ copy._writeToFile(destfile, output, data.encoding);
+ }
+ else if (Array.isArray(data)) {
+ data.forEach(function(s) {
+ var destfile = path.join(this.name, s.location.path);
+ var output = this._runFilters(s.get);
+ copy._writeToFile(destfile, output, s.encoding);
+ }, this);
+ }
+ else {
+ throw new Error('data is not a source, string, nor can it be converted');
+ }
+};
+
+/**
+ * ArrayDestination is a Destination that can feed sources to a number of child
+ * Destinations.
+ */
+copy.ArrayDestination = function(array, filters) {
+ this._array = array;
+ this._filters = filters;
+};
+
+copy.ArrayDestination.prototype = Object.create(copy.Destination.prototype);
+
+copy.ArrayDestination.prototype.processSource = function(source) {
+ this._array.forEach(function(member) {
+ var dest = copy.destFactory(member, this._filters);
+ dest.processSource(source);
+ }, this);
+};
+
+/**
+ * A Destination that concatenates the sources and writes them to a single
+ * value object.
+ */
+copy.ValueDestination = function(value, filters) {
+ this._value = value;
+ this._filters = filters;
+};
+
+copy.ValueDestination.prototype = Object.create(copy.Destination.prototype);
+
+copy.ValueDestination.prototype.processSource = function(source) {
+ var data = this._sourceToOutput(source);
+ data = this._runFilters(data);
+ this._value.value += data;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Check to see if fullPath refers to a directory
+ */
+copy.isDirectory = function(fullPath) {
+ return fs.existsSync(fullPath) && fs.statSync(fullPath).isDirectory();
+};
+
+copy._writeToFile = function(filename, data, encoding) {
+ if (fs.existsSync(filename)) {
+ if (!fs.statSync(filename).isFile()) {
+ throw new Error('Refusing to remove non file: ' + filename);
+ }
+ fs.unlinkSync(filename);
+ }
+ var parent = path.dirname(filename);
+ if (!fs.existsSync(parent)) {
+ copy.mkdirSync(parent, 0755);
+ }
+ fs.writeFileSync(filename, data, encoding);
+ if (copy.debug) {
+ console.log('- wrote ' + data.length + ' bytes to ' + filename);
+ }
+};
+
+copy.mkdirSync = function(dirname, mode) {
+ if (copy.isDirectory(dirname)) {
+ return;
+ }
+ var parent = path.dirname(dirname);
+ if (!fs.existsSync(parent)) {
+ copy.mkdirSync(parent, mode);
+ }
+ if (!fs.existsSync(dirname)) {
+ fs.mkdirSync(dirname, mode);
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * A holder is an in-memory store of a result of a copy operation.
+ * <pre>
+ * var holder = copy.createDataObject();
+ * copy({ source: 'x.txt', dest: holder });
+ * copy({ source: 'y.txt', dest: holder });
+ * copy({ source: holder, dest: 'z.txt' });
+ * </pre>
+ */
+copy.createDataObject = function() {
+ return { value: '' };
+};
+
+/**
+ * Read mini_require.js to go with the required modules.
+ */
+copy.getMiniRequire = function() {
+ return {
+ value: fs.readFileSync(__dirname + '/mini_require.js').toString('utf8')
+ };
+};
+
+/**
+ * Keep track of the files in a project
+ */
+function CommonJsProject(opts) {
+ this.roots = opts.roots;
+ this.aliases = opts.aliases;
+ this.textPluginPattern = opts.textPluginPattern || /^text!/;
+
+ opts.roots = this.roots.map(function(root) {
+ if (!copy.isDirectory(root)) {
+ throw new Error('Each commonjs root should be a directory: ' + root);
+ }
+ return ensureTrailingSlash(root);
+ }, this);
+
+ // A module is a Location that also has dep
+ this.currentModules = {};
+ this.ignoredModules = {};
+}
+
+CommonJsProject.prototype.report = function() {
+ var reply = 'CommonJS project at ' + this.roots.join(', ') + '\n';
+
+ reply += '- Required modules:\n';
+ var moduleNames = Object.keys(this.currentModules);
+ if (moduleNames.length > 0) {
+ moduleNames.forEach(function(module) {
+ var deps = Object.keys(this.currentModules[module].deps).length;
+ reply += ' - ' + module + ' (' + deps +
+ (deps === 1 ? ' dependency' : ' dependencies') + ')\n';
+ }, this);
+ }
+ else {
+ reply += ' - None\n';
+ }
+
+ reply += '- Ignored modules:\n';
+ var ignoredNames = Object.keys(this.ignoredModules);
+ if (ignoredNames.length > 0) {
+ ignoredNames.forEach(function(moduleName) {
+ reply += ' - ' + moduleName + '\n';
+ }, this);
+ }
+ else {
+ reply += ' - None\n';
+ }
+
+ return reply;
+};
+
+/**
+ * Create an experimental GraphML string declaring the node dependencies.
+ */
+CommonJsProject.prototype.getDependencyGraphML = function() {
+ var nodes = '';
+ var edges = '';
+ var moduleNames = Object.keys(this.currentModules);
+ moduleNames.forEach(function(moduleName) {
+ nodes += ' <node id="' + moduleName + '">\n';
+ nodes += ' <data key="d0">\n';
+ nodes += ' <y:ShapeNode>\n';
+ nodes += ' <y:NodeLabel textColor="#000000">' + moduleName + '</y:NodeLabel>\n';
+ nodes += ' </y:ShapeNode>\n';
+ nodes += ' </data>\n';
+ nodes += ' </node>\n';
+ var deps = Object.keys(this.currentModules[moduleName].deps);
+ deps.forEach(function(dep) {
+ edges += ' <edge source="' + moduleName + '" target="' + dep + '"/>\n';
+ });
+ }, this);
+
+ var reply = '<?xml version="1.0" encoding="UTF-8"?>\n';
+ reply += '<graphml\n';
+ reply += ' xmlns="http://graphml.graphdrawing.org/xmlns/graphml"\n';
+ reply += ' xmlns:y="http://www.yworks.com/xml/graphml"\n';
+ reply += ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n';
+ reply += ' xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns/graphml http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"\n';
+ reply += ' >\n';
+ reply += ' <key id="d0" for="node" yfiles.type="nodegraphics"/>\n';
+ reply += ' <key id="d1" for="edge" yfiles.type="edgegraphics"/>\n';
+ reply += ' <graph id="commonjs" edgedefault="undirected">\n';
+ reply += nodes;
+ reply += edges;
+ reply += ' </graph>\n';
+ reply += '</graphml>\n';
+ return reply;
+};
+
+CommonJsProject.prototype.assumeAllFilesLoaded = function() {
+ Object.keys(this.currentModules).forEach(function(moduleName) {
+ this.ignoredModules[moduleName] = this.currentModules[moduleName];
+ }, this);
+ this.currentModules = {};
+};
+
+CommonJsProject.prototype.clone = function() {
+ var clone = new CommonJsProject({
+ roots: this.roots,
+ textPluginPattern: this.textPluginPattern
+ });
+
+ clone.aliases = this.aliases;
+
+ Object.keys(this.currentModules).forEach(function(moduleName) {
+ clone.currentModules[moduleName] = this.currentModules[moduleName];
+ }, this);
+
+ Object.keys(this.ignoredModules).forEach(function(moduleName) {
+ clone.ignoredModules[moduleName] = this.ignoredModules[moduleName];
+ }, this);
+
+ return clone;
+};
+
+CommonJsProject.prototype.addRoot = function(root) {
+ this.roots.push(root);
+};
+
+function findModuleAt(module, base, somePath) {
+ if (base == null) {
+ throw new Error('base == null for ' + somePath);
+ }
+ // Checking for absolute requires and relative requires that previously
+ // had been resolved to absolute paths.
+ if (/^\//.test(somePath)) {
+ if (isFile(somePath)) {
+ console.log('Warning - using location with base = "/"');
+ return new Location('/', somePath);
+ }
+ }
+
+ if (isFile(path.join(base, somePath))) {
+ if (module) {
+ console.log('- Found several matches for ' + somePath +
+ ' (ignoring 2nd)');
+ console.log(' - ' + module.fullname);
+ console.log(' - ' + path.join(base, somePath));
+ }
+ else {
+ module = new Location(base, somePath);
+ }
+ }
+
+ return module;
+}
+
+function relative(pathA, pathB) {
+ pathA = pathA.split(/[\/\\]+/);
+ pathB = pathB.split(/[\/\\]+/);
+ var aLen = pathA.length;
+ var bLen = pathB.length;
+
+ // Increment i to the first place where the paths diverge.
+ for (var i = 0; i < aLen && i < bLen && pathA[i] === pathB[i]; i++) {
+ }
+
+ // Remove the redundant parts of the paths.
+ function isntEmptyString(s) {
+ return s !== '';
+ }
+ pathA = pathA.slice(i).filter(isntEmptyString);
+ pathB = pathB.slice(i).filter(isntEmptyString);
+
+ var result = [];
+ for (i = 0; i < pathA.length; i++) {
+ result.push('..');
+ }
+ return result.concat(pathB).join('/');
+}
+
+function normalizeRequire(module, moduleName) {
+ if (moduleName.indexOf("!") !== -1) {
+ var chunks = moduleName.split("!");
+ return normalizeRequire(module, chunks[0]) + "!" +
+ normalizeRequire(module, chunks[1]);
+ }
+
+ if (moduleName.charAt(0) == ".") {
+ var requirersDirectory = module.dirname;
+ var pathToRequiredModule = path.join(requirersDirectory, moduleName);
+ // The call to `define` which makes the module being
+ // relatively required isn't the full relative path,
+ // but the path relative from the base.
+ return relative(module.base, pathToRequiredModule);
+ }
+ else {
+ return moduleName;
+ }
+}
+
+function findRequires(module) {
+ var code = fs.readFileSync(module.fullname).toString();
+ var ast;
+ try {
+ ast = ujs.parser.parse(code, false);
+ }
+ catch (ex) {
+ console.error('- Failed to compile ' + module.path + ': ' + ex);
+ return;
+ }
+
+ var reply = [];
+ var walkers = {
+ call: function(expr, args) {
+ // If anyone redefines 'require' we won't notice. We could maintain a
+ // list of declared variables in the current scope so we can detect this.
+ // A similar system could have us tracking calls to require via a
+ // different name. that was a useful escape system, but now we detect
+ // computed requires, it's not needed.
+ if (expr[1] === 'define') {
+ var params = null;
+ if (args[0][0] === 'array') {
+ params = args[0][1];
+ }
+ else if (args[0][0] === 'string' && args[1][0] == 'array') {
+ params = args[1][1];
+ }
+ else {
+ console.log('- ' + module.path + ' has define(...) ' +
+ 'with non-array parameter. Ignoring requirement.');
+ return;
+ }
+
+ if (params) {
+ for (var i = 0; i < params.length; i++) {
+ param = params[i];
+ if (param[0] === 'string') {
+ reply.push(normalizeRequire(module, param[1]));
+ }
+ else {
+ console.log('- ' + module.path + ' has define(...) ' +
+ 'with non-string parameter. Ignoring requirement.');
+ }
+ }
+ }
+ }
+ if (expr[1] === 'require') {
+ if (args[0][0] === 'string') {
+ reply.push(normalizeRequire(module, args[0][1]));
+ }
+ else {
+ console.log('- ' + module.path + ' has require(...) ' +
+ 'with non-string parameter. Ignoring requirement.');
+ }
+ }
+ }
+ };
+
+ var walker = ujs.uglify.ast_walker();
+ walker.with_walkers(walkers, function() {
+ return walker.walk(ast);
+ });
+
+ return reply;
+}
+
+CommonJsProject.prototype.require = function(moduleName) {
+ var module = this.currentModules[moduleName];
+ if (module) {
+ return module;
+ }
+ module = this.ignoredModules[moduleName];
+ if (module) {
+ return module;
+ }
+
+ // Apply aliases on module path.
+ if (this.aliases) {
+ var parts = moduleName.split("/");
+ var moduleName = parts.pop();
+
+ var self = this;
+ var resolved = parts.map(function(part) {
+ var alias = self.aliases[part];
+ return alias ? alias : part;
+ });
+
+ var moduleUrl = ensureTrailingSlash(resolved.join("/"));
+ moduleName = moduleUrl + moduleName;
+ }
+
+ // Find which of the packages it is in
+ this.roots.forEach(function(base) {
+ if (this.textPluginPattern.test(moduleName)) {
+ var modulePath = moduleName.replace(this.textPluginPattern, '');
+ module = findModuleAt(module, base, modulePath);
+ if (module) {
+ module.isText = true;
+ }
+ } else {
+ module = findModuleAt(module, base, moduleName + '.js');
+ if (!module) {
+ module = findModuleAt(module, base, moduleName + '/index.js');
+ }
+ }
+ }, this);
+
+ if (!module) {
+ console.error('Failed to find module: ' + moduleName);
+ return;
+ }
+
+ module.deps = {};
+ this.currentModules[moduleName] = module;
+
+ if (!module.isText) {
+ // require() all this modules requirements
+ findRequires(module).forEach(function(moduleName) {
+ module.deps[moduleName] = 1;
+ this.require(moduleName);
+ }, this);
+ }
+};
+
+CommonJsProject.prototype.getCurrentModules = function() {
+ return Object.keys(this.currentModules).map(function(moduleName) {
+ return this.currentModules[moduleName];
+ }, this);
+};
+
+/**
+ *
+ */
+copy.createCommonJsProject = function(opts) {
+ return new CommonJsProject(opts);
+};
+
+/**
+ * Different types of source
+ */
+copy.source = {};
+
+/**
+ * @deprecated
+ */
+copy.source.commonjs = function(obj) {
+ console.log('copy.source.commonjs is deprecated, ' +
+ 'pass { project:... includes:...} directly as a source');
+ return obj;
+};
+
+/**
+ * File filters
+ */
+copy.filter = {};
+
+copy.filter.debug = function(input, source) {
+ source = source || 'unknown';
+ module = source.path ? source.path : source;
+ return input;
+};
+copy.filter.debug.onRead = true;
+
+/**
+ * Compress the given input code using UglifyJS.
+ *
+ * @param string input
+ * @return string output
+ */
+copy.filter.uglifyjs = function(input) {
+ if (typeof input !== 'string') {
+ input = input.toString();
+ }
+
+ var opt = copy.filter.uglifyjs.options;
+ var ast;
+ try {
+ ast = ujs.parser.parse(input, opt.parse_strict_semicolons);
+ }
+ catch (ex) {
+ console.error('- Failed to compile code: ' + ex);
+ return input;
+ }
+
+ if (opt.mangle) {
+ ast = ujs.uglify.ast_mangle(ast, opt.mangle_toplevel);
+ }
+
+ if (opt.squeeze) {
+ ast = ujs.uglify.ast_squeeze(ast, opt.squeeze_options);
+ if (opt.squeeze_more) {
+ ast = ujs.uglify.ast_squeeze_more(ast);
+ }
+ }
+
+ return ujs.uglify.gen_code(ast, opt.beautify);
+};
+copy.filter.uglifyjs.onRead = false;
+/**
+ * UglifyJS filter options.
+ */
+copy.filter.uglifyjs.options = {
+ parse_strict_semicolons: false,
+
+ /**
+ * The beautify argument used for process.gen_code(). See the UglifyJS
+ * documentation.
+ */
+ beautify: false,
+ mangle: true,
+ mangle_toplevel: false,
+ squeeze: true,
+
+ /**
+ * The options argument used for process.ast_squeeze(). See the UglifyJS
+ * documentation.
+ */
+ squeeze_options: {},
+
+ /**
+ * Tells if you want to perform potentially unsafe compression.
+ */
+ squeeze_more: false
+};
+
+/**
+ * A filter to munge CommonJS headers
+ */
+copy.filter.addDefines = function(input, source) {
+ if (typeof input !== 'string') {
+ input = input.toString();
+ }
+
+ if (!source) {
+ throw new Error('Missing filename for moduleDefines');
+ }
+
+ var module = source.isLocation ? source.path : source;
+
+ input = input.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
+ input = '"' + input.replace(/\n/g, '\\n" +\n "') + '"';
+
+ return 'define("text!' + module + '", [], ' + input + ');\n\n';
+};
+copy.filter.addDefines.onRead = true;
+
+/**
+ * Like addDefines, but adds base64 encoding
+ */
+copy.filter.base64 = function(input, source) {
+ if (typeof input === 'string') {
+ throw new Error('base64 filter needs to be the first in a filter set');
+ }
+
+ if (!source) {
+ throw new Error('Missing filename for moduleDefines');
+ }
+
+ var module = source.isLocation ? source.path : source;
+
+ if (module.substr(-4) === '.png') {
+ input = 'data:image/png;base64,' + input.toString('base64');
+ }
+ else if (module.substr(-4) === '.gif') {
+ input = 'data:image/gif;base64,' + input.toString('base64');
+ }
+ else {
+ throw new Error('Only gif/png supported by base64 filter: ' + source);
+ }
+
+ return 'define("text!' + module + '", [], "' + input + '");\n\n';
+};
+copy.filter.base64.onRead = true;
+
+/**
+ * Munge define lines to add module names
+ */
+copy.filter.moduleDefines = function(input, source) {
+ if (!source) {
+ console.log('- Source without filename passed to moduleDefines().' +
+ ' Skipping addition of define(...) wrapper.');
+ return input;
+ }
+
+ if (source.isText) {
+ return copy.filter.addDefines(input, source);
+ }
+
+ if (typeof input !== 'string') {
+ input = input.toString();
+ }
+
+ var deps = source.deps ? Object.keys(source.deps) : [];
+ deps = deps.length ? (", '" + deps.join("', '") + "'") : "";
+
+ var module = source.isLocation ? source.path : source;
+ module = module.replace(/\.js$/, '');
+
+ return input.replace(/\bdefine\s*\(\s*function\s*\(require,\s*exports,\s*module\)\s*\{/,
+ "define('" + module + "', ['require', 'exports', 'module' " + deps + "], function(require, exports, module) {");
+};
+copy.filter.moduleDefines.onRead = true;
+
+/**
+ * Why does node throw an exception for statSync(), especially when it has no
+ * exists()?
+ */
+function isFile(fullPath) {
+ return fs.existsSync(fullPath) && fs.statSync(fullPath).isFile();
+}
+
+/**
+ * Add a trailing slash to s directory path if needed
+ */
+function ensureTrailingSlash(filename) {
+ if (filename.length > 0 && filename.substr(-1) !== '/') {
+ filename += '/';
+ }
+ return filename;
+}
+
+
+exports.copy = copy;
diff --git a/lib/dryice/mini_require.js b/lib/dryice/mini_require.js
new file mode 100644
index 0000000..82b1fd4
--- /dev/null
+++ b/lib/dryice/mini_require.js
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2012, Mozilla Foundation and contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Define a module along with a payload.
+ * @param moduleName Name for the payload
+ * @param deps Ignored. For compatibility with CommonJS AMD Spec
+ * @param payload Function with (require, exports, module) params
+ */
+function define(moduleName, deps, payload) {
+ if (typeof moduleName != "string") {
+ throw new Error("Error: Module name is not a string");
+ }
+
+ if (arguments.length == 2) {
+ payload = deps;
+ }
+ else {
+ payload.deps = deps;
+ }
+
+ if (define.debugDependencies) {
+ console.log("define: " + moduleName + " -> " + payload.toString()
+ .slice(0, 40).replace(/\n/, '\\n').replace(/\r/, '\\r') + "...");
+ }
+
+ if (moduleName in define.modules) {
+ throw new Error("Error: Redefining module: " + moduleName);
+ }
+
+ // Mark the payload so we know we need to call it to get the real module
+ payload.__uncompiled = true;
+ define.modules[moduleName] = payload;
+}
+
+/**
+ * The global store of un-instantiated modules
+ */
+define.modules = {};
+
+/**
+ * Should we console.log on module definition/instantiation/requirement?
+ */
+define.debugDependencies = false;
+
+
+(function() {
+
+/**
+ * We invoke require() in the context of a Domain so we can have multiple
+ * sets of modules running separate from each other.
+ * This contrasts with JSMs which are singletons, Domains allows us to
+ * optionally load a CommonJS module twice with separate data each time.
+ * Perhaps you want 2 command lines with a different set of commands in each,
+ * for example.
+ */
+function Domain() {
+ this.modules = {};
+
+ if (define.debugDependencies) {
+ this.depth = "";
+ }
+}
+
+/**
+ * Lookup module names and resolve them by calling the definition function if
+ * needed.
+ * There are 2 ways to call this, either with an array of dependencies and a
+ * callback to call when the dependencies are found (which can happen
+ * asynchronously in an in-page context) or with a single string an no
+ * callback where the dependency is resolved synchronously and returned.
+ * The API is designed to be compatible with the CommonJS AMD spec and
+ * RequireJS.
+ * @param deps A name, or array of names for the payload
+ * @param callback Function to call when the dependencies are resolved
+ * @return The module required or undefined for array/callback method
+ */
+Domain.prototype.require = function(config, deps, callback) {
+ if (arguments.length <= 2) {
+ callback = deps;
+ deps = config;
+ config = undefined;
+ }
+
+ if (Array.isArray(deps)) {
+ var params = deps.map(function(dep) {
+ return this.lookup(dep);
+ }, this);
+ if (callback) {
+ callback.apply(null, params);
+ }
+ return undefined;
+ }
+ else {
+ return this.lookup(deps);
+ }
+};
+
+/**
+ * Lookup module names and resolve them by calling the definition function if
+ * needed.
+ * @param moduleName A name for the payload to lookup
+ * @return The module specified by aModuleName or null if not found
+ */
+Domain.prototype.lookup = function(moduleName) {
+ if (moduleName in this.modules) {
+ var module = this.modules[moduleName];
+ if (define.debugDependencies) {
+ console.log(this.depth + " Using module: " + moduleName);
+ }
+ return module;
+ }
+
+ if (!(moduleName in define.modules)) {
+ throw new Error("Missing module: " + moduleName);
+ }
+
+ var module = define.modules[moduleName];
+
+ if (define.debugDependencies) {
+ console.log(this.depth + " Compiling module: " + moduleName);
+ }
+
+ if (module.__uncompiled) {
+ if (define.debugDependencies) {
+ this.depth += ".";
+ }
+
+ var exports = {};
+ try {
+ var params = module.deps.map(function(dep) {
+ if (dep === "require") {
+ return this.require.bind(this);
+ }
+ if (dep === "exports") {
+ return exports;
+ }
+ if (dep === "module") {
+ return { id: moduleName, uri: "" };
+ }
+ return this.lookup(dep);
+ }.bind(this));
+
+ var reply = module.apply(null, params);
+ module = (reply !== undefined) ? reply : exports;
+ }
+ catch (ex) {
+ console.error("Error using module: " + moduleName, ex);
+ throw ex;
+ }
+
+ if (define.debugDependencies) {
+ this.depth = this.depth.slice(0, -1);
+ }
+ }
+
+ // cache the resulting module object for next time
+ this.modules[moduleName] = module;
+
+ return module;
+};
+
+/**
+ * Expose the Domain constructor and a global domain (on the define function
+ * to avoid exporting more than we need. This is a common pattern with
+ * require systems)
+ */
+define.Domain = Domain;
+define.globalDomain = new Domain();
+
+})();
+
+/**
+ * Expose a default require function which is the require of the global
+ * sandbox to make it easy to use.
+ */
+var require = define.globalDomain.require.bind(define.globalDomain);
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..03512d6
--- /dev/null
+++ b/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "dryice",
+ "description": "A CommonJS/RequireJS packaging tool for browser scripts",
+ "keywords": [ "build", "commonjs", "requirejs" ],
+ "version": "0.4.10",
+ "homepage": "https://github.com/joewalker/dryice",
+ "author": "Joe Walker <joe at getahead.org>",
+ "contributors": [ ],
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/mozilla/dryice.git"
+ },
+ "bugs": { "url": "http://github.com/mozilla/dryice/issues" },
+ "directories": { "lib" : "./lib" },
+ "main": "./lib/dryice/index.js",
+ "engines": { "node" : ">=0.6.0" },
+ "licenses": [
+ { "type": "Apache-2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0" }
+ ],
+ "dependencies": {
+ "uglify-js": "~1.3.4"
+ }
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-dryice.git
More information about the Pkg-javascript-commits
mailing list