sprockets-commoner 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.nvmrc +1 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +3 -0
- data/README.md +205 -0
- data/Rakefile +10 -0
- data/circle.yml +13 -0
- data/js/babel-plugin-sprockets-commoner-internal/.gitignore +2 -0
- data/js/babel-plugin-sprockets-commoner-internal/README.md +24 -0
- data/js/babel-plugin-sprockets-commoner-internal/index.js +265 -0
- data/js/babel-plugin-sprockets-commoner-internal/package.json +14 -0
- data/js/babel-plugin-sprockets-commoner/README.md +3 -0
- data/js/babel-plugin-sprockets-commoner/index.js +7 -0
- data/js/babel-plugin-sprockets-commoner/package.json +5 -0
- data/lib/sprockets/commoner.rb +15 -0
- data/lib/sprockets/commoner/bundle.rb +57 -0
- data/lib/sprockets/commoner/processor.rb +174 -0
- data/lib/sprockets/commoner/railtie.rb +11 -0
- data/lib/sprockets/commoner/version.rb +5 -0
- data/sprockets-commoner.gemspec +37 -0
- metadata +185 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7be0d75114fb75a73b272d1493290b864cce8455
|
4
|
+
data.tar.gz: 3c98183d4ecfc9ab3824ece0acf091255f9df219
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6985592443fef03121a57c8a8e1f3c37e684a2fedb0561014f8c242f2629fccf6dc2f3c30789494b4a41eececaccde49424a40b858b7a7e11ad3c204093da44e
|
7
|
+
data.tar.gz: 16d3679cb215ca29fd2c8b1513cfb09704096ab31cf368ad42e5a7c8b6a41bbd13e3344ddfc0bbd89ee9f38119428f257ba3b4ab9749dec58dd896c2d3cf9307
|
data/.gitignore
ADDED
data/.nvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
v5.8.0
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at bouke@shopify.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,205 @@
|
|
1
|
+
# Sprockets::Commoner
|
2
|
+
|
3
|
+
`Sprockets::Commoner` is a gem that enables JavaScript package and Babel transformation in Sprockets.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
* Compile JavaScript modules into a single bundle.
|
8
|
+
* Run Babel transforms.
|
9
|
+
* Easy setup. We adhere to the Rails Way™ and don't require any additional configuration for the simplest and most common set ups.
|
10
|
+
* Integrate tightly into Sprockets/Rails. You can use any of Sprockets' features like ERB inside your files without having to jump through crazy hoops.
|
11
|
+
* Designed to emit code that compresses incredibly well. The code generated will be smaller than webpack or browserify.
|
12
|
+
* Use `process.env` inside your JavaScript. This will also run on anything in `node_modules` (e.g. Babel), to ensure dependencies are also compressed optimally.
|
13
|
+
* Automatic deduplication of Babel helpers. No need to use `babel-runtime`, as commoner will automatically detect which helpers are used and share them between modules in a way that compressed very well.
|
14
|
+
|
15
|
+
## Setup
|
16
|
+
|
17
|
+
### Requirements
|
18
|
+
|
19
|
+
1. Ruby v2+.
|
20
|
+
2. Rails/Any other application that uses Sprockets.
|
21
|
+
2. NPM v3+. We only support version 3 because commoner doesn't do any sort of deduplication of dependencies, so you could end up with a huge bundle if you don't want out. We only test against version 3, so you will definitely run into issues when running version 2.
|
22
|
+
3. We recommend and support version 4+ of Node.js.
|
23
|
+
|
24
|
+
### 10-second simple set up
|
25
|
+
|
26
|
+
To get started, let's begin with the simplest possible set up: just enabling resolving of `require`.
|
27
|
+
|
28
|
+
1. Add `sprockets-commoner` to Gemfile, run `bundle install`, and restart your Rails server.
|
29
|
+
1. Add package.json with `babel-core` version 6 and any packages you want. For the example, we'll use the excellent [lodash](https://lodash.com) library. `npm install -S babel-core@6 lodash`
|
30
|
+
1. `require` your client-side JavaScript packages from `application.js`!
|
31
|
+
```
|
32
|
+
var _ = require('lodash');
|
33
|
+
|
34
|
+
console.log(_.map([1, 2, 3], function(n) { return n * 3; }));
|
35
|
+
```
|
36
|
+
|
37
|
+
### Enabling Babel transforms
|
38
|
+
|
39
|
+
1. Install any Babel plugins or presets you want to use. We'll use the default ES2015 preset; `npm install babel-preset-es2015`.
|
40
|
+
1. Add a `.babelrc` with you required configuration. We just need to do `echo '{presets: ["es2015"]}' > .babelrc`.
|
41
|
+
1. Use any feature you want! For example, let's use `import` and arrow functions in our `application.js`:
|
42
|
+
|
43
|
+
```
|
44
|
+
import {map} from 'lodash';
|
45
|
+
|
46
|
+
console.log(map([1, 2, 3], (n) => n * 3));
|
47
|
+
```
|
48
|
+
|
49
|
+
### Advanced configuration
|
50
|
+
|
51
|
+
#### Fine-tuned selection of files to process
|
52
|
+
|
53
|
+
By default, commoner will process any file under the application root directory. If you want more fine-tuned control over which files to process, you can specify which paths to include or exclude. To do so, you will need to re-register the Sprockets processor. For example:
|
54
|
+
|
55
|
+
```
|
56
|
+
# In config/initializers/sprockets_commoner.rb
|
57
|
+
Rails.application.config.assets.configure do |env|
|
58
|
+
env.unregister_postprocessor('application/javascript', Sprockets::Commoner::Processor)
|
59
|
+
env.register_postprocessor('application/javascript', Sprockets::Commoner::Processor.new(
|
60
|
+
env.root,
|
61
|
+
# include, exclude, and babel_exclude patterns can be path prefixes or regexes.
|
62
|
+
# Explicitely list paths to include. The default is `[env.root]`
|
63
|
+
include: ['app/assets/javascripts/subdirectory'],
|
64
|
+
# List files to ignore and not process require calls or apply any Babel transforms to. Default is empty.
|
65
|
+
exclude: [/ignored/],
|
66
|
+
# Anything listed in babel_exclude has its require calls resolved, but no transforms listed in .babelrcs applied.
|
67
|
+
# Default is [/node_modules/]
|
68
|
+
babel_exclude: [/node_modules/]
|
69
|
+
))
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
## Testing with Teaspoon
|
74
|
+
|
75
|
+
Teaspoon is not compatible with commoner by default. Under `test/demo` you can find a demo Rails application, containing a setup with Teaspoon. The key change is a custom boot partial and JavaScript file, found under `spec/javascripts/fixtures/teaspoon/suite`. Simply copy those two files under `fixtures/teaspoon/suite` in your JavaScript tests, make necessary changes to `boot.js.erb` to point to your test files, and you should be good to go.
|
76
|
+
|
77
|
+
## CoffeeScript interoperability
|
78
|
+
|
79
|
+
Commoner is designed from the start to facilitate a transition from CoffeeScript to ES2015.
|
80
|
+
|
81
|
+
### Importing CoffeeScript files
|
82
|
+
|
83
|
+
Any JavaScript file can `require` a CoffeeScript file, which will cause that CoffeeScript file to be scanned for a global variable reference and the `require` call to be replaced with a reference.
|
84
|
+
If we have the following two files:
|
85
|
+
|
86
|
+
```
|
87
|
+
# file.coffee
|
88
|
+
class window.ImportantClass
|
89
|
+
```
|
90
|
+
|
91
|
+
```
|
92
|
+
// main.js
|
93
|
+
var klass = require('./file');
|
94
|
+
|
95
|
+
new klass();
|
96
|
+
```
|
97
|
+
|
98
|
+
Then the second file will just be compiled down to `new window.ImportantClass()`. Importing global references works for global assignments and class definitions.
|
99
|
+
|
100
|
+
### Expose
|
101
|
+
|
102
|
+
We have added a custom directive that makes it very easy to expose an ES2015 module to the global namespace so it can be used by CoffeeScript files or any other code. For example:
|
103
|
+
|
104
|
+
```
|
105
|
+
'expose window.MyClass`;
|
106
|
+
|
107
|
+
export default class MyClass {}
|
108
|
+
```
|
109
|
+
|
110
|
+
`expose` will use the default export if available, otherwise the whole module namespace will be assigned to the global variable. For example:
|
111
|
+
|
112
|
+
```
|
113
|
+
// constants.js
|
114
|
+
'expose window.Constants';
|
115
|
+
|
116
|
+
export const A = 1;
|
117
|
+
export const B = 2;
|
118
|
+
export const C = 3;
|
119
|
+
```
|
120
|
+
|
121
|
+
This will make `window.Constants` equal `{A: 1, B: 2, C: 3}`.
|
122
|
+
|
123
|
+
## Methodology
|
124
|
+
|
125
|
+
Commoner registers a postprocessor that takes any `application/javascript` file and passes it through Babel.
|
126
|
+
|
127
|
+
### `require` support
|
128
|
+
|
129
|
+
`Sprockets::Commoner` enables support for `require()` by replacing `require` function calls with variable references. It does this by assigning every file a unique identifier based on their filename. For example, if the file you're referencing is located at `<root>/node_modules/package/index.js` it will get the name `__commoner_module__node_modules$package$index_js`. Any file that then `require`s this specific file will have that `require` call replaced with the identifier.
|
130
|
+
reference.
|
131
|
+
|
132
|
+
The Babel plugin also communicates back any files that were required to make sure they are included by Sprockets. `Sprockets::Commoner` depends on the topological ordering that Sprockets does to make sure any module that is needed is instantiated before it is used.
|
133
|
+
|
134
|
+
### Example
|
135
|
+
|
136
|
+
After the regular Babel plugins are done doing their thing, `babel-plugin-commoner-internal` kicks in, which is commoner's plugin that does the actual resolving. This plugin does the following things:
|
137
|
+
|
138
|
+
* It finds any `require` calls and rewires them to variable references (as detailed in [`require` support](#require-support))
|
139
|
+
* It wraps the module in a function and supplies it with `module` and `exports`. The end value of `module.exports` gets assigned to the module identifier, which is referenced by other files (as specified in '`require` support') Example:
|
140
|
+
|
141
|
+
```
|
142
|
+
var __commoner_module__node_modules$package$index_js = __commoner_initialize_module__(function (module, exports) {
|
143
|
+
exports.default = 123;
|
144
|
+
});
|
145
|
+
```
|
146
|
+
* If these is an expose directive at the top of the file, it assigns `module.exports` to the specified variable. For example, if the top of the file contains `'expose window.Whatever';` it will assign `exports.default` if there is a default, otherwise it just assigns `exports`. Therefore if our file has `expose window.Whatever` and no default, it will get `window.Whatever = exports;` appended to it.
|
147
|
+
|
148
|
+
#### Bundling
|
149
|
+
|
150
|
+
After all the files have been transformed, there is a bundle step which combines all of the processed JavaScript modules together. It then prepends an initializer function and all the Babel helpers (which are shared between all modules).
|
151
|
+
|
152
|
+
For example, if we have the following two files:
|
153
|
+
|
154
|
+
```
|
155
|
+
// module.js
|
156
|
+
export default function a() {
|
157
|
+
return 1;
|
158
|
+
};
|
159
|
+
```
|
160
|
+
|
161
|
+
```
|
162
|
+
// application.js
|
163
|
+
import a from './module';
|
164
|
+
|
165
|
+
a();
|
166
|
+
```
|
167
|
+
|
168
|
+
We will end up with the following (browser-runnable) file:
|
169
|
+
|
170
|
+
```
|
171
|
+
!function() {
|
172
|
+
var __commoner_initialize_module__ = function(f) {
|
173
|
+
var module = {exports: {}};
|
174
|
+
f.call(module.exports, module, module.exports);
|
175
|
+
return module.exports;
|
176
|
+
};
|
177
|
+
var global = window;
|
178
|
+
var __commoner_helper__interopRequireDefault = function (obj) {
|
179
|
+
return obj && obj.__esModule ? obj : {
|
180
|
+
default: obj
|
181
|
+
};
|
182
|
+
};
|
183
|
+
var __commoner_module__app$assets$javascripts$module_js = __commoner_initialize_module__(function (module, exports) {
|
184
|
+
"use strict";
|
185
|
+
|
186
|
+
Object.defineProperty(exports, "__esModule", {
|
187
|
+
value: true
|
188
|
+
});
|
189
|
+
exports.default = a;
|
190
|
+
function a() {
|
191
|
+
return 1;
|
192
|
+
};
|
193
|
+
});
|
194
|
+
var __commoner_module__app$assets$javascripts$application_js = __commoner_initialize_module__(function (module, exports) {
|
195
|
+
'use strict';
|
196
|
+
|
197
|
+
var _module2 = __commoner_helper__interopRequireDefault(__commoner_module__app$assets$javascripts$module_js);
|
198
|
+
|
199
|
+
(0, _module2.default)();
|
200
|
+
});
|
201
|
+
}();
|
202
|
+
```
|
203
|
+
|
204
|
+
This file is meant to be compressed, and does incredibly well when processed by UglifyJS.
|
205
|
+
|
data/Rakefile
ADDED
data/circle.yml
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# babel-plugin-commoner
|
2
|
+
|
3
|
+
## Usage
|
4
|
+
|
5
|
+
`babel-plugin-commoner` should be included in your `.babelrc` by adding `commoner`. You can't install it through npm, but this directory is automatically added to the path by the Sprockets plugin.
|
6
|
+
|
7
|
+
## Options
|
8
|
+
|
9
|
+
* `globals`: A mapping of module name to global variable name, which will ovveride any import of that package with a global variable reference.
|
10
|
+
|
11
|
+
## Example
|
12
|
+
|
13
|
+
```json
|
14
|
+
{
|
15
|
+
presets: ["es2015"],
|
16
|
+
plugins: [
|
17
|
+
["commoner", {
|
18
|
+
globals: {
|
19
|
+
"jquery": "$"
|
20
|
+
}
|
21
|
+
}]
|
22
|
+
]
|
23
|
+
}
|
24
|
+
```
|
@@ -0,0 +1,265 @@
|
|
1
|
+
'use strict';
|
2
|
+
if (typeof Object.assign != 'function') {
|
3
|
+
(function () {
|
4
|
+
Object.assign = function (target) {
|
5
|
+
'use strict';
|
6
|
+
if (target === undefined || target === null) {
|
7
|
+
throw new TypeError('Cannot convert undefined or null to object');
|
8
|
+
}
|
9
|
+
|
10
|
+
var output = Object(target);
|
11
|
+
for (var index = 1; index < arguments.length; index++) {
|
12
|
+
var source = arguments[index];
|
13
|
+
if (source !== undefined && source !== null) {
|
14
|
+
for (var nextKey in source) {
|
15
|
+
if (source.hasOwnProperty(nextKey)) {
|
16
|
+
output[nextKey] = source[nextKey];
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
return output;
|
22
|
+
};
|
23
|
+
})();
|
24
|
+
}
|
25
|
+
|
26
|
+
var fs = require('fs');
|
27
|
+
var dirname = require('path').dirname;
|
28
|
+
var resolve = require('browser-resolve').sync;
|
29
|
+
|
30
|
+
module.exports = function (context) {
|
31
|
+
var t = context.types;
|
32
|
+
var exposeTemplate = context.template("$0 = exports['default'] != null ? exports['default'] : exports;");
|
33
|
+
|
34
|
+
var opts = null;
|
35
|
+
var rootRegex = null;
|
36
|
+
var identifierRegex = null;
|
37
|
+
|
38
|
+
function createIdentifierRegex() {
|
39
|
+
var globals = ['window'].concat(opts.globalNamespaces).map(function(namespace) {
|
40
|
+
return namespace + '\\.';
|
41
|
+
});
|
42
|
+
|
43
|
+
// Construct regex with prefixes which denote globals (like window.Something, @Something, or anything else in opts.globalNamespaces)
|
44
|
+
var globalObject = '(?:@|' + globals.join('|') + ')';
|
45
|
+
var validIdentifier = '[a-zA-Z][_a-zA-Z0-9]*';
|
46
|
+
// Look for identifiers that look like 'window.Something' or 'Shopify.Something'
|
47
|
+
var validAssignment = '(' + globalObject + validIdentifier + '(?:\\.' + validIdentifier + ')*)';
|
48
|
+
// Look for 'window.Something =' or 'class window.Something'
|
49
|
+
return '^(?:(?:' + validAssignment + '\\s*=)|(?:class ' + validAssignment + '))';
|
50
|
+
}
|
51
|
+
|
52
|
+
/*
|
53
|
+
* BIGGEST HACK OF __ALL_TIME__
|
54
|
+
* If we're requiring a CoffeeScript file, we're going to be assuming that we're assigning to the global namespace in that file.
|
55
|
+
* so, use a RegExp to find out that variable definition. (yep)
|
56
|
+
*/
|
57
|
+
function findDeclarationInCoffeeFile(path) {
|
58
|
+
var contents = fs.readFileSync(path);
|
59
|
+
var identifiers = [];
|
60
|
+
|
61
|
+
for (var regexp = new RegExp(identifierRegex, 'gm'), find = regexp.exec(contents); find != null; find = regexp.exec(contents)) {
|
62
|
+
identifiers.push(find[1] || find[2]);
|
63
|
+
}
|
64
|
+
|
65
|
+
if (identifiers.length === 0) {
|
66
|
+
throw new Error('No identifiers found in ' + path);
|
67
|
+
} else if (identifiers.length > 1) {
|
68
|
+
throw new Error('Multiple identifiers found in ' + path);
|
69
|
+
}
|
70
|
+
|
71
|
+
return identifiers[0].replace(/^@/, 'window.');
|
72
|
+
}
|
73
|
+
|
74
|
+
function isRequire(path) {
|
75
|
+
return path.isCallExpression() && path.get('callee').isIdentifier({ name: 'require' }) && !path.scope.hasBinding('require');
|
76
|
+
}
|
77
|
+
|
78
|
+
// Get the target path from a require call
|
79
|
+
function requireTarget(path) {
|
80
|
+
var evaluate = path.get('arguments')[0].evaluate();
|
81
|
+
if (!evaluate.confident || path.node.arguments.length !== 1) {
|
82
|
+
return null;
|
83
|
+
}
|
84
|
+
|
85
|
+
var target = evaluate.value;
|
86
|
+
if (typeof target !== 'string') {
|
87
|
+
throw new Error('Invalid require call, string expected');
|
88
|
+
}
|
89
|
+
return target;
|
90
|
+
}
|
91
|
+
|
92
|
+
// Find any 'expose <name>' directive and get back the value of '<name>'
|
93
|
+
function findExpose(directives) {
|
94
|
+
var result = void 0;
|
95
|
+
for (var i = 0; i < directives.length; i++) {
|
96
|
+
if (result = /^expose ([A-Za-z\.]+)$/.exec(directives[i].value.value)) {
|
97
|
+
directives.splice(i, 1);
|
98
|
+
return result[1];
|
99
|
+
}
|
100
|
+
}
|
101
|
+
return null;
|
102
|
+
}
|
103
|
+
|
104
|
+
|
105
|
+
// Transform a path into a variable name
|
106
|
+
function pathToIdentifier(path) {
|
107
|
+
var escapedPath = path.replace(rootRegex, '').replace(/[^a-zA-Z0-9_]/g, function (match) {
|
108
|
+
if (match === '/') {
|
109
|
+
return '$';
|
110
|
+
} else {
|
111
|
+
return '_';
|
112
|
+
}
|
113
|
+
});
|
114
|
+
return '__commoner_module__' + escapedPath;
|
115
|
+
}
|
116
|
+
|
117
|
+
function resolveTarget(file, path) {
|
118
|
+
var name = void 0;
|
119
|
+
if (opts.globals != null && (name = opts.globals[path]) != null) {
|
120
|
+
return name;
|
121
|
+
} else {
|
122
|
+
var resolvedPath = resolve(path, opts);
|
123
|
+
file.metadata.required.push(resolvedPath);
|
124
|
+
|
125
|
+
// Check if the path is under sourceRoot
|
126
|
+
var root = file.opts.sourceRoot;
|
127
|
+
if (!rootRegex.test(resolvedPath)) {
|
128
|
+
throw new Error("Cannot find module '" + path + "' from '" + dirname(file.opts.filename) + "' under '" + root + "'");
|
129
|
+
}
|
130
|
+
|
131
|
+
if (/\.coffee$/.test(resolvedPath)) {
|
132
|
+
// If it's a coffee script file, look for global variable assignments
|
133
|
+
return findDeclarationInCoffeeFile(resolvedPath);
|
134
|
+
} else {
|
135
|
+
// Otherwise we just look for the module by referencing its Special Identifier™
|
136
|
+
return pathToIdentifier(resolvedPath);
|
137
|
+
}
|
138
|
+
}
|
139
|
+
}
|
140
|
+
|
141
|
+
var callRewriter = {
|
142
|
+
VariableDeclarator: function VariableDeclarator(path, state) {
|
143
|
+
var init = path.get('init');
|
144
|
+
if (!isRequire(init)) {
|
145
|
+
return;
|
146
|
+
}
|
147
|
+
var binding = path.scope.getBinding(path.node.id.name);
|
148
|
+
if (!binding.constant) {
|
149
|
+
return;
|
150
|
+
}
|
151
|
+
|
152
|
+
var target = requireTarget(init);
|
153
|
+
if (target == null) {
|
154
|
+
return;
|
155
|
+
}
|
156
|
+
|
157
|
+
var name = resolveTarget(state.file, target);
|
158
|
+
path.scope.rename(name);
|
159
|
+
path.scope.rename(path.node.id.name, name);
|
160
|
+
path.remove();
|
161
|
+
},
|
162
|
+
CallExpression: function CallExpression(path, state) {
|
163
|
+
if (!isRequire(path)) {
|
164
|
+
return;
|
165
|
+
}
|
166
|
+
|
167
|
+
var target = requireTarget(path);
|
168
|
+
if (target == null) {
|
169
|
+
return;
|
170
|
+
}
|
171
|
+
|
172
|
+
var replacement = resolveTarget(state.file, target);
|
173
|
+
switch (path.parent.type) {
|
174
|
+
case "ExpressionStatement":
|
175
|
+
// We just need to know there's a dependency, we can remove it then
|
176
|
+
path.remove();
|
177
|
+
break;
|
178
|
+
default:
|
179
|
+
// Otherwise we just look for the module by referencing its Special Identifier™
|
180
|
+
path.replaceWith(t.identifier(replacement));
|
181
|
+
break;
|
182
|
+
}
|
183
|
+
}
|
184
|
+
};
|
185
|
+
|
186
|
+
return {
|
187
|
+
pre: function pre(file) {
|
188
|
+
if (file.metadata.required == null) {
|
189
|
+
file.metadata.required = [];
|
190
|
+
}
|
191
|
+
},
|
192
|
+
|
193
|
+
visitor: {
|
194
|
+
MemberExpression: function MemberExpression(path) {
|
195
|
+
if (path.get("object").matchesPattern("process.env")) {
|
196
|
+
var key = path.toComputedKey();
|
197
|
+
if (t.isStringLiteral(key)) {
|
198
|
+
path.replaceWith(t.valueToNode(process.env[key.value]));
|
199
|
+
}
|
200
|
+
}
|
201
|
+
},
|
202
|
+
UnaryExpression: function UnaryExpression(path) {
|
203
|
+
if (!path.node.operator === 'typeof') {
|
204
|
+
return;
|
205
|
+
}
|
206
|
+
|
207
|
+
var argument = path.get('argument');
|
208
|
+
if (!path.get('argument').isIdentifier()) {
|
209
|
+
return;
|
210
|
+
}
|
211
|
+
|
212
|
+
var name = path.node.argument.name;
|
213
|
+
if (name !== 'module' && name !== 'exports') {
|
214
|
+
return;
|
215
|
+
}
|
216
|
+
|
217
|
+
if (path.scope.hasBinding(name)) {
|
218
|
+
return;
|
219
|
+
}
|
220
|
+
|
221
|
+
path.replaceWith(t.stringLiteral('object'));
|
222
|
+
},
|
223
|
+
Program: {
|
224
|
+
exit: function exit(path, state) {
|
225
|
+
// Get options from commoner-options and merge them with the options
|
226
|
+
// that were passed to this plugin in .babelrc
|
227
|
+
opts = {
|
228
|
+
globalNamespaces: [],
|
229
|
+
// We can get these from Sprockets
|
230
|
+
extensions: ['.js', '.json', '.coffee', '.js.erb', '.coffee.erb']
|
231
|
+
};
|
232
|
+
|
233
|
+
// Look for the sprockets-commoner plugin for extra options
|
234
|
+
state.file.opts.plugins.map(function (plugin) {
|
235
|
+
return plugin[1];
|
236
|
+
}).filter(function (opts) {
|
237
|
+
return opts != null && opts.__commoner_options;
|
238
|
+
}).forEach(function (plugin) {
|
239
|
+
return Object.assign(opts, plugin);
|
240
|
+
});
|
241
|
+
|
242
|
+
Object.assign(opts, state.opts, { basedir: dirname(state.file.opts.filename) });
|
243
|
+
rootRegex = new RegExp('^' + state.file.opts.sourceRoot + '/');
|
244
|
+
identifierRegex = createIdentifierRegex();
|
245
|
+
|
246
|
+
// Signal back to Sprockets that we're rewiring
|
247
|
+
state.file.metadata.commonerEnabled = true;
|
248
|
+
|
249
|
+
var node = path.node;
|
250
|
+
var identifier = pathToIdentifier(state.file.opts.filename);
|
251
|
+
var expose = findExpose(node.directives);
|
252
|
+
if (expose != null) {
|
253
|
+
node.body.push(exposeTemplate(t.identifier(expose)));
|
254
|
+
}
|
255
|
+
|
256
|
+
// Transform module to a variable assignment.
|
257
|
+
// This variable is then referenced by any dependant children.
|
258
|
+
node.body = [t.variableDeclaration('var', [t.variableDeclarator(t.identifier(identifier), t.callExpression(t.identifier('__commoner_initialize_module__'), [t.functionExpression(null, [t.identifier('module'), t.identifier('exports')], t.blockStatement(node.body, node.directives))]))])];
|
259
|
+
node.directives = [];
|
260
|
+
path.traverse(callRewriter, state);
|
261
|
+
}
|
262
|
+
}
|
263
|
+
}
|
264
|
+
};
|
265
|
+
};
|
@@ -0,0 +1,14 @@
|
|
1
|
+
{
|
2
|
+
"name": "babel-plugin-sprockets-commoner-internal",
|
3
|
+
"private": true,
|
4
|
+
"description": "Find require calls and resolve the library they're calling.",
|
5
|
+
"scripts": {
|
6
|
+
"test": "NODE_ENV=test mocha"
|
7
|
+
},
|
8
|
+
"devDependencies": {
|
9
|
+
"babel-core": "^6.2.1",
|
10
|
+
"babel-plugin-transform-es2015-arrow-functions": "^6.5.2",
|
11
|
+
"babel-plugin-transform-es2015-modules-commonjs": "^6.2.1",
|
12
|
+
"mocha": "^2.3.4"
|
13
|
+
}
|
14
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'sprockets'
|
2
|
+
require 'sprockets/commoner/processor'
|
3
|
+
require 'sprockets/commoner/bundle'
|
4
|
+
|
5
|
+
module Sprockets
|
6
|
+
module Commoner
|
7
|
+
end
|
8
|
+
|
9
|
+
register_postprocessor 'application/javascript', ::Sprockets::Commoner::Processor
|
10
|
+
register_bundle_metadata_reducer 'application/javascript', :commoner_enabled, false, :|
|
11
|
+
register_bundle_metadata_reducer 'application/javascript', :commoner_used_helpers, Set.new, :+
|
12
|
+
register_bundle_processor 'application/javascript', ::Sprockets::Commoner::Bundle
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'sprockets/commoner/railtie' if defined?(Rails)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'schmooze'
|
2
|
+
|
3
|
+
module Sprockets
|
4
|
+
module Commoner
|
5
|
+
class Bundle < Schmooze::Base
|
6
|
+
dependencies generator: 'babel-generator.default',
|
7
|
+
babelHelpers: 'babel-helpers',
|
8
|
+
t: 'babel-types'
|
9
|
+
|
10
|
+
method :generate_helpers, <<-JS
|
11
|
+
function(helpers) {
|
12
|
+
if (helpers.length === 0) {
|
13
|
+
return '';
|
14
|
+
}
|
15
|
+
var declaration = t.variableDeclaration('var',
|
16
|
+
helpers.map(function(helper) {
|
17
|
+
return t.variableDeclarator(t.identifier('__commoner_helper__' + helper), babelHelpers.get(helper));
|
18
|
+
})
|
19
|
+
);
|
20
|
+
return generator(declaration).code;
|
21
|
+
}
|
22
|
+
JS
|
23
|
+
|
24
|
+
PRELUDE = <<-JS.freeze
|
25
|
+
!function() {
|
26
|
+
var __commoner_initialize_module__ = function(f) {
|
27
|
+
var module = {exports: {}};
|
28
|
+
f.call(module.exports, module, module.exports);
|
29
|
+
return module.exports;
|
30
|
+
};
|
31
|
+
var global = window;
|
32
|
+
JS
|
33
|
+
|
34
|
+
OUTRO = <<-JS.freeze
|
35
|
+
|
36
|
+
}();
|
37
|
+
JS
|
38
|
+
def self.instance(env)
|
39
|
+
@instance ||= new(env.root)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.call(input)
|
43
|
+
instance(input[:environment]).call(input)
|
44
|
+
end
|
45
|
+
|
46
|
+
def call(input)
|
47
|
+
return unless input[:metadata][:commoner_enabled]
|
48
|
+
|
49
|
+
used_helpers = input[:metadata][:commoner_used_helpers]
|
50
|
+
helpers = generate_helpers(used_helpers.to_a)
|
51
|
+
{
|
52
|
+
data: "#{PRELUDE}#{helpers}\n#{input[:data]}#{OUTRO}"
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'schmooze'
|
2
|
+
require 'open3'
|
3
|
+
|
4
|
+
module Sprockets
|
5
|
+
module Commoner
|
6
|
+
class Processor < Schmooze::Base
|
7
|
+
BABELRC_FILE = '.babelrc'.freeze
|
8
|
+
PACKAGE_JSON = 'package.json'.freeze
|
9
|
+
JS_PACKAGE_PATH = File.expand_path('../../../js', __dir__)
|
10
|
+
ALLOWED_EXTENSIONS = /\.js(?:\.erb)?\z/
|
11
|
+
|
12
|
+
dependencies babel: 'babel-core', commoner: 'babel-plugin-sprockets-commoner-internal'
|
13
|
+
|
14
|
+
method :version, 'function() { return [process.version, babel.version]; }'
|
15
|
+
method :transform, %q{function(code, opts, commonerOpts) {
|
16
|
+
try {
|
17
|
+
var file = new babel.File(opts);
|
18
|
+
|
19
|
+
// The actual helpers are generated in bundle.rb
|
20
|
+
file.set("helperGenerator", function(name) { return babel.types.identifier('__commoner_helper__' + name); });
|
21
|
+
|
22
|
+
var commonerPlugin = babel.OptionManager.normalisePlugin(commoner);
|
23
|
+
file.buildPluginsForOptions({plugins: [[commonerPlugin, commonerOpts]]});
|
24
|
+
|
25
|
+
return file.wrap(code, function () {
|
26
|
+
file.addCode(code);
|
27
|
+
file.parseCode(code);
|
28
|
+
return file.transform();
|
29
|
+
});
|
30
|
+
} catch (err) {
|
31
|
+
if (err.codeFrame != null) {
|
32
|
+
err.message += "\n";
|
33
|
+
err.message += err.codeFrame;
|
34
|
+
}
|
35
|
+
throw err;
|
36
|
+
}
|
37
|
+
}}
|
38
|
+
def self.instance(env)
|
39
|
+
@instance ||= new(env.root)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.call(input)
|
43
|
+
instance(input[:environment]).call(input)
|
44
|
+
end
|
45
|
+
|
46
|
+
attr_reader :include, :exclude, :babel_exclude
|
47
|
+
def initialize(root, include: [root], exclude: [], babel_exclude: [/node_modules/])
|
48
|
+
@include = include.map {|path| expand_to_root(path, root) }
|
49
|
+
@exclude = exclude.map {|path| expand_to_root(path, root) }
|
50
|
+
@babel_exclude = babel_exclude.map {|path| expand_to_root(path, root) }
|
51
|
+
super(root, 'NODE_PATH' => JS_PACKAGE_PATH)
|
52
|
+
end
|
53
|
+
|
54
|
+
def call(input)
|
55
|
+
@cache_key ||= [
|
56
|
+
self.class.name,
|
57
|
+
version,
|
58
|
+
VERSION,
|
59
|
+
].freeze
|
60
|
+
|
61
|
+
filename = input[:filename]
|
62
|
+
|
63
|
+
return unless should_process?(filename)
|
64
|
+
|
65
|
+
@env = input[:environment]
|
66
|
+
@required = input[:metadata][:required].to_a
|
67
|
+
insertion_index = @required.index(input[:uri]) || -1
|
68
|
+
@dependencies = Set.new(input[:metadata][:dependencies])
|
69
|
+
|
70
|
+
|
71
|
+
babel_config = babelrc_data(filename)
|
72
|
+
|
73
|
+
result = input[:cache].fetch([filename, @cache_key, input[:data], babel_config]) do
|
74
|
+
transform(input[:data], options(input), paths: @env.paths)
|
75
|
+
end
|
76
|
+
|
77
|
+
if result['metadata'].has_key?('required')
|
78
|
+
result['metadata']['required'].each do |r|
|
79
|
+
asset = resolve(r, accept: input[:content_type], pipeline: :self)
|
80
|
+
@required.insert(insertion_index, asset)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
{
|
85
|
+
data: result['code'],
|
86
|
+
dependencies: @dependencies,
|
87
|
+
required: Set.new(@required),
|
88
|
+
|
89
|
+
commoner_used_helpers: Set.new(input[:metadata][:commoner_used_helpers]) + result['metadata']['usedHelpers'],
|
90
|
+
commoner_enabled: input[:metadata][:commoner_enabled] | result['metadata']['commonerEnabled'],
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
def expand_to_root(path, root)
|
96
|
+
if path.is_a?(String)
|
97
|
+
File.expand_path(path, root)
|
98
|
+
else
|
99
|
+
path
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def should_process?(filename)
|
104
|
+
return false unless ALLOWED_EXTENSIONS =~ filename
|
105
|
+
return false unless self.include.empty? || match_any?(self.include, filename)
|
106
|
+
return false if match_any?(self.exclude, filename)
|
107
|
+
true
|
108
|
+
end
|
109
|
+
|
110
|
+
def match_any?(patterns, filename)
|
111
|
+
patterns.any? { |pattern| pattern_match(pattern, filename) }
|
112
|
+
end
|
113
|
+
|
114
|
+
def pattern_match(pattern, filename)
|
115
|
+
if pattern.is_a?(String)
|
116
|
+
filename.start_with?(pattern)
|
117
|
+
else
|
118
|
+
pattern === filename
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def babelrc_data(filename)
|
123
|
+
while filename != (filename = File.dirname(filename))
|
124
|
+
begin
|
125
|
+
name = File.join(filename, BABELRC_FILE)
|
126
|
+
data = File.read(name)
|
127
|
+
depend_on_file(name)
|
128
|
+
return data
|
129
|
+
rescue Errno::ENOENT
|
130
|
+
name = File.join(filename, PACKAGE_JSON)
|
131
|
+
data = package_babel_data(name)
|
132
|
+
if data
|
133
|
+
depend_on_file(name)
|
134
|
+
return JSON.dump(data)
|
135
|
+
else
|
136
|
+
nil
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
return nil
|
141
|
+
end
|
142
|
+
|
143
|
+
def package_babel_data(filename)
|
144
|
+
return JSON.parse(File.read(filename))['babel']
|
145
|
+
rescue Errno::ENOENT
|
146
|
+
return nil
|
147
|
+
end
|
148
|
+
|
149
|
+
def options(input)
|
150
|
+
# TODO(bouk): Fix sourcemaps. Sourcemaps are only available in Sprockets v4
|
151
|
+
{
|
152
|
+
'ast' => false,
|
153
|
+
'babelrc' => !match_any?(self.babel_exclude, input[:filename]),
|
154
|
+
'filename' => input[:filename],
|
155
|
+
'filenameRelative' => PathUtils.split_subpath(input[:load_path], input[:filename]),
|
156
|
+
'moduleRoot' => nil,
|
157
|
+
'sourceRoot' => @env.root,
|
158
|
+
}
|
159
|
+
end
|
160
|
+
|
161
|
+
def resolve(path, **kargs)
|
162
|
+
uri, deps = @env.resolve!(path, load_paths: [@env.root], **kargs)
|
163
|
+
@dependencies.merge(deps)
|
164
|
+
uri
|
165
|
+
end
|
166
|
+
|
167
|
+
def depend_on_file(path)
|
168
|
+
uri, deps = @env.resolve!(path, load_paths: [@env.root])
|
169
|
+
@dependencies.merge(deps)
|
170
|
+
uri
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Sprockets
|
2
|
+
module Commoner
|
3
|
+
class Railtie < ::Rails::Railtie
|
4
|
+
initializer 'sprockets-commoner' do
|
5
|
+
# We need to disable debugging because otherwise Rails will include each file individually, while we need everything to be bundled up together into a single file.
|
6
|
+
config.assets.debug = false
|
7
|
+
config.assets.paths << 'node_modules'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sprockets/commoner/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "sprockets-commoner"
|
8
|
+
spec.version = Sprockets::Commoner::VERSION
|
9
|
+
spec.authors = ["Bouke van der Bijl"]
|
10
|
+
spec.homepage = 'https://github.com/Shopify/sprockets-commoner'
|
11
|
+
spec.email = ["bouke@shopify.com"]
|
12
|
+
spec.license = 'MIT'
|
13
|
+
|
14
|
+
spec.summary = %q{Use Babel in Sprockets to compile modules for the browser}
|
15
|
+
spec.description = %q{Sprockets::Commoner uses Node.JS to compile ES2015+ files to ES5 using Babel directly from NPM, without vendoring it.}
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
18
|
+
# delete this section to allow pushing this gem to any host.
|
19
|
+
if spec.respond_to?(:metadata)
|
20
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
21
|
+
else
|
22
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
23
|
+
end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|script|js\/babel-plugin-sprockets-commoner-internal\/test)/}) }
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
spec.add_dependency "sprockets", ">= 3", "< 4"
|
30
|
+
spec.add_dependency "schmooze", "~> 0.1.5"
|
31
|
+
|
32
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
33
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
34
|
+
spec.add_development_dependency "coffee-script", "~> 2.4"
|
35
|
+
spec.add_development_dependency "uglifier", "~> 2.7"
|
36
|
+
spec.add_development_dependency "pry", "~> 0.10"
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sprockets-commoner
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bouke van der Bijl
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-05-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sprockets
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '4'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '4'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: schmooze
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 0.1.5
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.1.5
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '10.0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '10.0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: minitest
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '5.0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '5.0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: coffee-script
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '2.4'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '2.4'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: uglifier
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '2.7'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '2.7'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: pry
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0.10'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0.10'
|
117
|
+
description: Sprockets::Commoner uses Node.JS to compile ES2015+ files to ES5 using
|
118
|
+
Babel directly from NPM, without vendoring it.
|
119
|
+
email:
|
120
|
+
- bouke@shopify.com
|
121
|
+
executables: []
|
122
|
+
extensions: []
|
123
|
+
extra_rdoc_files: []
|
124
|
+
files:
|
125
|
+
- ".gitignore"
|
126
|
+
- ".nvmrc"
|
127
|
+
- CODE_OF_CONDUCT.md
|
128
|
+
- Gemfile
|
129
|
+
- README.md
|
130
|
+
- Rakefile
|
131
|
+
- circle.yml
|
132
|
+
- js/babel-plugin-sprockets-commoner-internal/.gitignore
|
133
|
+
- js/babel-plugin-sprockets-commoner-internal/README.md
|
134
|
+
- js/babel-plugin-sprockets-commoner-internal/index.js
|
135
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/browser-resolve/LICENSE
|
136
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/browser-resolve/README.md
|
137
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/browser-resolve/empty.js
|
138
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/browser-resolve/index.js
|
139
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/browser-resolve/package.json
|
140
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/resolve/LICENSE
|
141
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/resolve/README.md
|
142
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/resolve/index.js
|
143
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/resolve/lib/async.js
|
144
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/resolve/lib/caller.js
|
145
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/resolve/lib/core.js
|
146
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/resolve/lib/core.json
|
147
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/resolve/lib/node-modules-paths.js
|
148
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/resolve/lib/sync.js
|
149
|
+
- js/babel-plugin-sprockets-commoner-internal/node_modules/resolve/package.json
|
150
|
+
- js/babel-plugin-sprockets-commoner-internal/package.json
|
151
|
+
- js/babel-plugin-sprockets-commoner/README.md
|
152
|
+
- js/babel-plugin-sprockets-commoner/index.js
|
153
|
+
- js/babel-plugin-sprockets-commoner/package.json
|
154
|
+
- lib/sprockets/commoner.rb
|
155
|
+
- lib/sprockets/commoner/bundle.rb
|
156
|
+
- lib/sprockets/commoner/processor.rb
|
157
|
+
- lib/sprockets/commoner/railtie.rb
|
158
|
+
- lib/sprockets/commoner/version.rb
|
159
|
+
- sprockets-commoner.gemspec
|
160
|
+
homepage: https://github.com/Shopify/sprockets-commoner
|
161
|
+
licenses:
|
162
|
+
- MIT
|
163
|
+
metadata:
|
164
|
+
allowed_push_host: https://rubygems.org
|
165
|
+
post_install_message:
|
166
|
+
rdoc_options: []
|
167
|
+
require_paths:
|
168
|
+
- lib
|
169
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - ">="
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '0'
|
179
|
+
requirements: []
|
180
|
+
rubyforge_project:
|
181
|
+
rubygems_version: 2.5.1
|
182
|
+
signing_key:
|
183
|
+
specification_version: 4
|
184
|
+
summary: Use Babel in Sprockets to compile modules for the browser
|
185
|
+
test_files: []
|