Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding useful visitors for dependencies #20

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions lib/visitors/ATPEDependencies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright 2015 Amadeus s.a.s.
* 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 vm = require("vm");
var grunt = require('../grunt').grunt();

var evalJsonString = function (code) {
// note that JSON.parse is too strict compared to the Aria Templates eval
return vm.runInNewContext("(" + code + ")");
};

var classpathToLogicalPath = function (classpath, extension) {
return classpath.split(".").join("/") + extension;
};

var getJsonDependencies = function (json) {
var dependencies = [];

var processModules = function (modulesMap) {
if (!modulesMap) {
return;
}
for (var key in modulesMap) {
if (modulesMap.hasOwnProperty(key)) {
var curModule = modulesMap[key];
dependencies.push(classpathToLogicalPath(curModule.classpath, ".js"));
}
}
};

var processPlaceholder = function (placeholder) {
if (typeof placeholder == "object") {
if (placeholder.constructor.isArray) {
placeholder.forEach(processPlaceholder);
} else {
dependencies.push(classpathToLogicalPath(placeholder.template, ".tpl"));
}
}
};

if (json.pageComposition) {
// page definition
processModules(json.pageComposition.modules);
var placeholdersMap = json.pageComposition.placeholders;
for (var placeholder in placeholdersMap) {
if (placeholdersMap.hasOwnProperty(placeholder)) {
processPlaceholder(placeholdersMap[placeholder]);
}
}
dependencies.push(classpathToLogicalPath(json.pageComposition.template, ".tpl"));
} else if (json.containerId) {
// site configuration
processModules(json.commonModules);
}
return dependencies;
};

var ATPEDependencies = function (cfg) {
cfg = cfg || {};
this.files = cfg.files || ['**/*.json'];
this.mustExist = cfg.hasOwnProperty('mustExist') ? cfg.mustExist : true;
this.externalDependencies = cfg.hasOwnProperty('externalDependencies') ? cfg.externalDependencies : [];
};

ATPEDependencies.prototype.computeDependencies = function (packaging, inputFile) {
if (!inputFile.isMatch(this.files)) {
return;
}

var mustExist = this.mustExist;
var externalDependencies = this.externalDependencies;
var textContent = inputFile.getTextContent();
try {
var jsonContent = evalJsonString(textContent);
var dependencies = getJsonDependencies(jsonContent);
dependencies.forEach(function (dependency) {
var correspondingFile = packaging.getSourceFile(dependency);
if (correspondingFile) {
inputFile.addDependency(correspondingFile);
} else if (mustExist && !grunt.file.isMatch(externalDependencies, [dependency])) {
grunt.log.error(inputFile.logicalPath.yellow + " depends on " + dependency + " which cannot be found.");
}
});
} catch (error) {
grunt.log.error("ATPEDependencies: error when processing " + inputFile.logicalPath.yellow + ": " + error);
}
};

module.exports = ATPEDependencies;
75 changes: 75 additions & 0 deletions lib/visitors/DependenciesGraph.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2015 Amadeus s.a.s.
* 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 grunt = require('../grunt').grunt();
var path = require('path');

var normalizePath = function (filePath) {
return path.normalize(filePath).split(path.sep).join('/'); // only forward slashes for the web
};

var stringifyForDot = function (string) {
return '"' + string.replace(/"/g, "\"") + '"';
};

var DependenciesGraph = function (cfg) {
cfg = cfg || {};
this.sourceFiles = cfg.sourceFiles || ['**/*']; // source files to take into account in the graph
this.graphFile = cfg.graphFile || 'dependencies.gv'; // the graph file to write
this.graphFileEncoding = cfg.graphFileEncoding || null; // encoding of the graph file
this.outputDirectory = cfg.outputDirectory || null; // output directory of the graph file; if not specified, the
// global one is used
};

DependenciesGraph.prototype.onAfterBuild = function (packaging) {
var sourceFiles = packaging.sourceFiles;
var sourceFilesPatterns = this.sourceFiles;
var cache = {};
var output = ["digraph dependencies {\n"];

var processSourceFile = function (sourceFile) {
var logicalPath = sourceFile.logicalPath;
if (cache.hasOwnProperty(logicalPath)) {
return cache[logicalPath];
}
if (!sourceFile.isMatch(sourceFilesPatterns)) {
cache[logicalPath] = false;
return false;
}
cache[logicalPath] = true;
var dependencies = sourceFile.getDependencies().filter(processSourceFile);
var stringifiedName = stringifyForDot(normalizePath(sourceFile.logicalPath));
output.push(stringifiedName, ";\n");
dependencies.forEach(function (curDep) {
output.push(stringifiedName, " -> ", stringifyForDot(normalizePath(curDep.logicalPath)), ";\n");
});
return true;
};

for (var file in sourceFiles) {
if (sourceFiles.hasOwnProperty(file)) {
processSourceFile(sourceFiles[file]);
}
}

output.push("}\n");

var outputGraphFile = path.join(this.outputDirectory || packaging.outputDirectory, this.graphFile);
grunt.file.write(outputGraphFile, output.join(""), {
encoding : this.graphFileEncoding || grunt.file.defaultEncoding
});
};

module.exports = DependenciesGraph;