forked from ivanvanderbyl/ember-d3
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Imported code from ember-cli-d3-shape to load D3 v4
- Loading branch information
1 parent
1d8a85a
commit bed0e94
Showing
6 changed files
with
419 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,118 @@ | ||
/* jshint node: true */ | ||
/* jshint esnext: false */ | ||
'use strict'; | ||
|
||
var Funnel = require('broccoli-funnel'); | ||
var mergeTrees = require('broccoli-merge-trees'); | ||
var path = require('path'); | ||
var rename = require('broccoli-stew').rename; | ||
var AMDDefineFilter = require('./lib/amd-define-filter'); | ||
var fs = require('fs'); | ||
|
||
function lookupPackage(packageName) { | ||
var modulePath = require.resolve(packageName); | ||
var i = modulePath.lastIndexOf(path.sep + 'build'); | ||
return modulePath.slice(0, i); | ||
} | ||
|
||
module.exports = { | ||
name: 'ember-d3', | ||
|
||
included: function(app) { | ||
this._super.included(app); | ||
if (process.env.EMBER_CLI_FASTBOOT !== 'true') { | ||
isDevelopingAddon: function () { | ||
return false; | ||
}, | ||
|
||
d3Modules: [ | ||
|
||
// Imported from package.json | ||
], | ||
|
||
/** | ||
* `import()` taken from ember-cli 2.7 to allow nested addon usage. | ||
*/ | ||
import: function (asset, options) { | ||
var app = this.app; | ||
while (app.app) { | ||
app = app.app; | ||
} | ||
|
||
app.import(asset, options); | ||
}, | ||
|
||
// Fix for loading it in addons/engines | ||
if (typeof app.import !== 'function' && app.app) { | ||
app = app.app; | ||
included: function (app) { | ||
this._super.included && this._super.included.apply(this, arguments); | ||
this.app = app; | ||
|
||
while (app.app) { | ||
app = app.app; | ||
} | ||
|
||
var pkg = require(path.join(lookupPackage('d3'), 'package.json')); | ||
|
||
// Find all dependencies of `d3` | ||
this.d3Modules = Object.keys(pkg.dependencies).filter(function (name) { | ||
return /^d3\-/.test(name); | ||
}); | ||
|
||
// This essentially means we'll skip importing this package twice, if it's | ||
// a dependency of another package. | ||
if (!app.import) { | ||
if (this.isDevelopingAddon()) { | ||
console.log('[ember-cli-d3-shape] skipping included hook for', app.name); | ||
} | ||
|
||
app.import(app.bowerDirectory + '/d3/d3.js'); | ||
app.import('vendor/ember-d3/ember-d3-shim.js', { | ||
exports: { | ||
d3: ['default'] | ||
} | ||
}); | ||
return; | ||
} | ||
|
||
var _this = this; | ||
this.d3Modules.forEach(function (packageName) { | ||
_this.import(path.join('vendor', packageName, packageName + '.js')); | ||
}); | ||
}, | ||
|
||
treeForVendor: function() { | ||
return path.join(__dirname, 'client'); | ||
} | ||
treeForApp() { | ||
return null; | ||
}, | ||
|
||
treeForAddon() { | ||
return null; | ||
}, | ||
|
||
treeForVendor: function () { | ||
var trees = []; | ||
var d3PackagePath = lookupPackage('d3'); | ||
|
||
this.d3Modules.forEach(function (packageName) { | ||
// Import existing builds from node d3 packages, which are UMD packaged. | ||
var packageBuildPath = path.join('build', packageName + '.js'); | ||
|
||
var d3PathToSrc = path.join(d3PackagePath, 'node_modules', packageName); | ||
|
||
try { | ||
fs.statSync(path.join(d3PathToSrc)).isDirectory(); | ||
} catch (err) { | ||
d3PathToSrc = lookupPackage(packageName); | ||
} | ||
|
||
try { | ||
fs.statSync(path.join(d3PathToSrc, packageBuildPath)).isFile(); | ||
} catch (err) { | ||
console.error('[ERROR] D3 Package (' + packageName + ') is not built as expected, cannot continue. Please report this as a bug.'); | ||
return; | ||
} | ||
|
||
var tree = new Funnel(d3PathToSrc, { | ||
include: [packageBuildPath], | ||
destDir: '/' + packageName, | ||
annotation: 'Funnel: D3 Source [' + packageName + ']', | ||
}); | ||
|
||
var srcTree = new AMDDefineFilter(tree, packageName); | ||
trees.push(rename(srcTree, function () { | ||
return '/' + packageName + '/' + packageName + '.js'; | ||
})); | ||
}); | ||
|
||
return mergeTrees(trees); | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* jshint node: true */ | ||
'use strict'; | ||
|
||
var Filter = require('broccoli-filter'); | ||
var rewriteAMDFunction = require('./rewrite-amd-definition'); | ||
|
||
/** | ||
* Loading an actual AMD package using Ember's loader.js | ||
* requires some hacks. Basically proper AMD packages check for define.amd, which | ||
* loader.js doesn't define (because reasons). | ||
* | ||
* To get around this we define our own definition in the same way each Ember | ||
* package does. | ||
*/ | ||
|
||
function AMDDefineFilter(inputNode, packageName, options) { | ||
options = options || {}; | ||
Filter.call(this, inputNode, { | ||
annotation: options.annotation || 'Rewriting package: ' + packageName, | ||
}); | ||
this.packageName = packageName; | ||
} | ||
|
||
AMDDefineFilter.prototype = Object.create(Filter.prototype); | ||
AMDDefineFilter.prototype.constructor = AMDDefineFilter; | ||
AMDDefineFilter.prototype.processString = function (code) { | ||
return rewriteAMDFunction(code, this.packageName); | ||
}; | ||
|
||
module.exports = AMDDefineFilter; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* jshint node: true */ | ||
'use strict'; | ||
|
||
/* | ||
# Rewrite UMD -> AMD definition | ||
This library take a module definition in the UMD format and returns an Ember | ||
compatible AMD module containing the same module body. | ||
# Why do we need this? | ||
The UMD module definitions that D3 uses do a few checks to decide which loader | ||
it needs to support. When detecting AMD, it does this: | ||
`typeof define === 'function' && define.amd` | ||
Unfortunately Ember's define doesn't report being fully AMD compatible, as such | ||
`define.amd // undefined`. | ||
*/ | ||
|
||
var recast = require('recast'); | ||
var types = recast.types; | ||
var namedTypes = types.namedTypes; | ||
var b = recast.types.builders; | ||
|
||
function buildExportDefaultDefinition(packageName, deps, node) { | ||
return b.expressionStatement( | ||
b.callExpression( | ||
b.identifier('define'), [ | ||
b.literal(packageName), | ||
b.arrayExpression(deps.map(function (name) { return b.literal(name); })), | ||
|
||
node, | ||
] | ||
) | ||
); | ||
} | ||
|
||
function getDependenciesForDefine(node) { | ||
if (namedTypes.CallExpression.check(node)) { | ||
return node.arguments[0].elements.map(function (e) { return e.value; }); | ||
}else { | ||
return []; | ||
} | ||
} | ||
|
||
function isAMDFunctionBody(node) { | ||
return namedTypes.FunctionExpression.check(node) && | ||
node.id === null && | ||
!!node.params && | ||
namedTypes.Identifier.check(node.params[0]) && | ||
node.params[0].name === 'exports'; | ||
} | ||
|
||
function isDefineCallExpression(node) { | ||
return namedTypes.CallExpression.check(node) && | ||
node.callee.name === 'define' && | ||
!!node.arguments && | ||
namedTypes.ArrayExpression.check(node.arguments[0]) && | ||
node.arguments[0].elements[0].value === 'exports' && | ||
node.arguments[1].name === 'factory'; | ||
} | ||
|
||
module.exports = function rewriteAMDFunction(code, packageName) { | ||
var ast = recast.parse(code); | ||
var amdDependencies; | ||
var amdFunctionBody; | ||
|
||
types.visit(ast, { | ||
visitCallExpression: function (path) { | ||
if (isDefineCallExpression(path.node)) { | ||
amdDependencies = getDependenciesForDefine(path.node); | ||
} | ||
|
||
this.traverse(path); | ||
}, | ||
|
||
visitFunctionExpression: function (path) { | ||
if (isAMDFunctionBody(path.node)) { | ||
amdFunctionBody = path.node; | ||
} | ||
|
||
this.traverse(path); | ||
}, | ||
}); | ||
|
||
var newAST = buildExportDefaultDefinition(packageName, amdDependencies, amdFunctionBody); | ||
return recast.print(newAST).code; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Oops, something went wrong.