grunt-nuget-pack
Version:
Grunt task for creating nuget packages without using nuget.exe.
235 lines (181 loc) • 6.74 kB
JavaScript
var ZipWriter = require("moxie-zip").ZipWriter;
var XMLWriter = require("xml-writer");
var path = require("path");
var fs = require("fs");
module.exports = function(meta) {
var zip = new ZipWriter(), extensions = {nuspec: true};
var propsId = "7857dbf80735479b8ee19fa60cb8239e", excludePaths = {};
// MIT licensed by Sindre Sorhus https://github.com/sindresorhus/semver-regex
var semVerRegex = /\bv?(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?\b/ig;
function verifyMeta() {
if (!meta.id) {
throw new Error("Missing required package id.");
}
if (!/^[a-z0-9\.]+$/i.test(meta.id)) {
throw new Error("Package id isn't in a valid format.");
}
if (!meta.version) {
throw new Error("Missing required package version.");
}
if (!semVerRegex.test(meta.version)) {
throw new Error("Version isn't proper sem-ver \"x.x.x\".");
}
if (!meta.authors) {
throw new Error("Missing required package authors.");
}
if (!meta.description) {
throw new Error("Missing required package description.");
}
}
function getContentTypesXml() {
var xw = new XMLWriter(true, "utf-8");
xw.startDocument();
xw.startElement("Types");
xw.writeAttribute("xmlns", "http://schemas.openxmlformats.org/package/2006/content-types");
xw.startElement("Default");
xw.writeAttribute("Extension", "rels");
xw.writeAttribute("ContentType", "application/vnd.openxmlformats-package.relationships+xml");
xw.endElement();
for (var ext in extensions) {
xw.startElement("Default");
xw.writeAttribute("Extension", ext);
xw.writeAttribute("ContentType", "application/octet");
xw.endElement();
}
xw.startElement("Default");
xw.writeAttribute("Extension", "psmdcp");
xw.writeAttribute("ContentType", "application/vnd.openxmlformats-package.core-properties+xml");
xw.endElement();
xw.endDocument();
return xw.toString();
}
function getNuSpecXml() {
var properties = [
"id", "title", "version", "authors", "owners", "license", "licenseUrl",
"projectUrl", "icon", "iconUrl", "requireLicenseAcceptance",
"description", "summary", "releaseNotes", "copyright",
"language", "tags", "dependencies"
];
function normalizeVersionDep(version) {
version = version.replace(/\s+/, '');
if (!/^(\[[0-9\,\.]+\]|\([0-9\,\.]+\)|\([0-9\,\.]+\]|[0-9]+\.[0-9]+)$/.test(version)) {
throw new Error("Invalid version dependecy: " + version);
}
if (/^[0-9]+\.[0-9]+$/.test(version)) {
return version;
}
version = version[0] + version.substr(1, version.length - 2).split(',').join(', ') + version[version.length - 1];
return version;
}
var xw = new XMLWriter(true);
xw.startDocument();
xw.startElement("package");
xw.writeAttribute("xmlns", "http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd");
xw.startElement("metadata");
properties.forEach(function(property) {
if (property in meta) {
if (property == "dependencies") {
xw.startElement("dependencies");
meta[property].forEach(function(dep) {
xw.startElement("dependency");
xw.writeAttribute("id", dep.id);
if (dep.version) {
xw.writeAttribute("version", normalizeVersionDep(dep.version));
}
xw.endElement();
});
xw.endElement();
return;
}
if (property === "license") {
xw.startElement(property);
xw.writeAttribute("type", "expression");
xw.text(meta[property].toString());
xw.endElement();
return;
}
xw.writeElement(property, meta[property].toString());
}
});
xw.endDocument();
return xw.toString();
}
function getCorePropertiesXml() {
var xw = new XMLWriter(true, "utf-8");
function writeProp(name, value) {
if (value) {
xw.writeElement(name, value);
}
}
xw.startDocument();
xw.startElement("coreProperties");
xw.writeAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/");
xw.writeAttribute("xmlns:dcterms", "http://purl.org/dc/terms/");
xw.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
xw.writeAttribute("xmlns", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
writeProp("dc:creator", meta.authors);
writeProp("dc:description", meta.description);
writeProp("dc:identifier", meta.id);
writeProp("version", meta.version);
writeProp("dc:language", meta.language);
writeProp("keywords", meta.tags);
writeProp("lastModifiedBy", "NuGet, Version=2.8.50320.36, Culture=neutral, PublicKeyToken=null;Microsoft Windows NT 6.2.9200.0;.NET Framework 4");
xw.endDocument();
return xw.toString();
}
function getRelsXml() {
var xw = new XMLWriter(true, "utf-8");
xw.startDocument();
xw.startElement("Relationships");
xw.writeAttribute("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships");
xw.startElement("Relationship");
xw.writeAttribute("Type", "http://schemas.microsoft.com/packaging/2010/07/manifest");
xw.writeAttribute("Target", "/" + meta.id + ".nuspec");
xw.writeAttribute("Id", "R569c48f3cf1b4b14");
xw.endElement();
xw.startElement("Relationship");
xw.writeAttribute("Type", "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties");
xw.writeAttribute("Target", "/package/services/metadata/core-properties/" + propsId + ".psmdcp");
xw.writeAttribute("Id", "R9e8f0077d5174f67");
xw.endElement();
xw.endDocument();
return xw.toString();
}
this.addExcludes = function(excludes) {
if (Array.isArray(excludes)) {
excludes.forEach(function(excludePath) {
excludePaths[path.resolve(excludePath)] = true;
});
}
};
this.addFile = function(srcPath, destPath) {
function process(filePath, zipFilePath) {
var stat;
if (excludePaths[path.resolve(filePath)]) {
return;
}
stat = fs.statSync(filePath);
filePath = filePath.replace(/\\/g, '/');
zipFilePath = zipFilePath.replace(/\\/g, '/');
if (stat.isFile()) {
extensions[path.extname(filePath).substr(1)] = true;
zip.addFile(zipFilePath, filePath);
} else if (stat.isDirectory()) {
fs.readdirSync(filePath).forEach(function(fileName) {
if (fileName.charAt(0) != '.') {
process(path.join(filePath, fileName), path.join(zipFilePath, fileName));
}
});
}
}
process(srcPath, destPath);
};
this.saveAs = function(destPath, callback) {
verifyMeta();
zip.addData("[Content_Types].xml", getContentTypesXml());
zip.addData(meta.id + ".nuspec", getNuSpecXml());
zip.addData("package/services/metadata/core-properties/" + propsId + ".psmdcp", getCorePropertiesXml());
zip.addData("_rels/.rels", getRelsXml());
zip.saveAs(destPath, callback);
};
};