UNPKG

4.09 kBJavaScriptView Raw
1var EventEmitter = require('events').EventEmitter,
2_ = require('lodash'),
3path = require('path'),
4glob = require('glob'),
5slash = require('slash'),
6util = require('util');
7
8var ParticleLoader = function(options) {
9 this.root = options.root;
10 this.registry = {};
11 this.typeMap = {
12 'asset': 'assets',
13 'condition': 'conditions',
14 'helper': 'helpers',
15 'mapping': 'mappings',
16 'metadata': 'metadata',
17 'output': 'outputs',
18 'parameter': 'parameters',
19 'partial': 'partials',
20 'resource': 'resources',
21 'set': 'sets',
22 'template': 'cftemplates'
23 };
24
25 this.typeGlobs = {
26 'asset': ['','?(.hbs)]'],
27 'condition': ['','.*'],
28 'helper': ['.js'],
29 'mapping': ['','.*'],
30 'metadata': ['','.*'],
31 'output': ['','.*'],
32 'parameter': ['','.*'],
33 'partial': ['','.*'],
34 'resource': ['','.*'],
35 'set': ['','.*'],
36 'template': ['?(.hbs)']
37 };
38};
39util.inherits(ParticleLoader,EventEmitter);
40
41ParticleLoader.prototype.loadParticle = function(type,cModule,pPath,options) {
42 var opts = _.merge({
43 parentFile: null,
44 cModule: ''
45 },_.omit(options,_.isUndefined));
46
47 // Make Windows Happy
48 var particlePath = pPath.replace(/\//g,path.sep);
49
50 // Used to reduce the number of times this particle is searched for.
51 // TODO Possible to group by package instead of file?
52 var particleId = [opts.parentFile.path,cModule,particlePath].join(':');
53
54 this.registry[type] = this.registry[type] || {};
55
56 if (this.registry[type][particleId]) {
57 return this.registry[type][particleId];
58 }
59
60 var particle = {};
61
62 particle.modulePath = opts.parentFile.path.slice(0,opts.parentFile.path.lastIndexOf(path.join(path.sep,'particles',path.sep)));
63 if (cModule) {
64 particle.modulePath = path.join(particle.modulePath,'node_modules',cModule);
65 }
66
67 // This feels UGLY
68 // Walks the tree to find particles in parent node_modules directories
69 // TODO Got to be a better way to do this.
70 var done = false;
71 while (done === false) {
72 particle = _.merge(particle,this.genParticlePaths(particle,type,particlePath));
73
74 // TODO more efficient discovery?
75 var globFiles = _.map(this.typeGlobs[type], function(pattern) {
76 return glob.sync(particle.path+pattern);
77 });
78 var files = _.flatten(globFiles);
79 if (files[0]) {
80 particle.fsPath = files[0];
81 done = true;
82 }
83 else {
84 var lastNodeModules = particle.modulePath.lastIndexOf(path.join(path.sep,'node_modules'));
85 if (lastNodeModules < 0) {
86 done = true;
87 }
88 else {
89 particle.modulePath = particle.modulePath.slice(0,lastNodeModules);
90 var newNodeModules = particle.modulePath.lastIndexOf(path.join(path.sep,'node_modules'));
91 if (newNodeModules < 0) {
92 done = true;
93 }
94 else {
95 particle.modulePath = particle.modulePath.slice(0,newNodeModules+13);
96 particle.modulePath = path.join(particle.modulePath,cModule);
97 }
98 }
99 }
100 }
101 if (!particle.fsPath) {
102 throw new Error("particle load error: "+type+" "+particlePath+" refrenced in "+ opts.parentFile.path + " could not be found.");
103 }
104
105 this.registry[type][particleId] = particle;
106 this.emit('particle',particle);
107 return particle;
108};
109
110ParticleLoader.prototype.genParticlePaths = function(particle,type,particlePath) {
111
112 var pathObj = path.parse(path.join(particle.modulePath,'particles',this.typeMap[type],particlePath));
113 var realPath = path.format(pathObj);
114
115 var relativePathObj = path.parse(path.relative(path.resolve(process.cwd(),this.root),realPath));
116 var relativePath = path.format(relativePathObj);
117
118 var urlPath = slash(relativePath);
119
120 return {
121 pathObj: pathObj,
122 path: realPath,
123 relativePathObj: relativePathObj,
124 relativePath: relativePath,
125 urlPath: urlPath
126 };
127};
128
129ParticleLoader.prototype.processablePaths = function() {
130 var templatePaths = _.values(this.registry.template);
131 var assetPaths = _.values(this.registry.asset);
132
133 return _.pluck(_.flatten([templatePaths,assetPaths]),'path');
134};
135
136module.exports = ParticleLoader;
137