UNPKG

ams

Version:

ams - asset management system - plugin enabled build tool with jquery like API

324 lines (275 loc) 8.65 kB
var n = require('natives'), $ = require('sharedjs'); /** * Sync files search. * @param {string} root root directory. * @param {RegExp=} pattern optional regexp to filter files. * @param {boolean=} rec optional recursively. * @return {Array} files list of files with abs paths. * @export */ exports.findSync = function find(root, pattern, rec) { if (typeof pattern === 'boolean') { rec = pattern; pattern = undefined; } var files = []; n.fs.readdirSync(root).forEach(function(file) { var path = n.path.join(root, file); if (n.fs.statSync(path).isDirectory() && rec) { files = files.concat(find(path, pattern, rec)); } if (!pattern || pattern.test(path)) { files.push(path); } }); return files; }; /** * Create a directory, recursive if needed * @param {string} path absolute path to the dir. * @param {string|number=} mode default to 511 in dec is 0777 in octal. * @export */ exports.mkdirSync = function(path, mode) { var curesolvedPath = ''; path.split('/').forEach(function(name) { if (!name) { return; } curesolvedPath += '/' + name; var stat; try { stat = n.fs.statSync(curesolvedPath); } catch (e) { // nothing there, make a dir n.fs.mkdirSync(curesolvedPath, mode || 511); } if (stat && stat.isFile()) { throw new Error('there is a file in the way: ' + curesolvedPath); } }); }; /** * Remove files and directories. * @param {string} root path to the dir where to search. * @param {RegExp=} pattern regexp to filter files. */ exports.rmSync = function rmSync(root, pattern) { try { n.fs.statSync(root); } catch (e) { // directory doesn't exist return; } n.fs.readdirSync(root).forEach(function(filename) { var path = n.path.join(root, filename); if (pattern && !pattern.test(path)) { return; } if (n.fs.statSync(path).isFile()) { n.fs.unlinkSync(path); } else { rmSync(path); n.fs.rmdirSync(path); } }); }; /** * Copy files and directories. * @param {string} src absolute path to the src dir. * @param {string} target absolute path to the target dir. * @param {RegExp=} pattern optional regexp to filter dirs or files. * @return {Object} src and target files. * @export */ exports.copySync = function(src, target, pattern) { var srcPaths = exports.findSync(src, pattern, true), targetPaths = []; function copy(i) { if (!srcPaths[i]) { return; } var srcPath = srcPaths[i], relPath = srcPath.replace(src, ''), targetPath = targetPaths[i] = n.path.join(target, relPath); if (n.fs.statSync(srcPath).isDirectory()) { exports.mkdirSync(targetPath); } else { exports.mkdirSync(n.path.dirname(targetPath)); n.fs.writeFileSync( targetPath, n.fs.readFileSync(srcPath) ); } ++i; copy(i); } copy(0); return { src: srcPaths, target: targetPaths }; }; /** * Resolve a path like browser would resolve it + consider require like `paths`. * TODO rewrite this mess! * * @param {string} path to resolve. * @param {string} hostFilePath path to the file, which is trying to resolve. * @param {string} root path to the root dir. * @param {Array=} lookup paths where we should look for the file * if the path doesn't start with "." or "/". * @return {string|boolean} absolute path to file or false if not resolved. */ exports.resolvePath = function(path, hostFilePath, root, lookup) { var resolvedPath, firstChar; // its remote url if (/^\w+:\/\//.test(path)) { return false; } // remove query from path path = path.replace(/(.*)[\?|#].*/, '$1'); firstChar = path.substr(0, 1); // path is absolute, find it in the root // /path/to/file.css if (firstChar === '/') { // check if the path is already the correct one try { if (n.fs.statSync(path).isFile()) { resolvedPath = path; } } catch(e) {} if (!resolvedPath) { resolvedPath = n.path.join(root, path); } // path is relative, try to find it in the current dir // ./path/to/file.css, ../path/to/file.css } else if (firstChar === '.') { resolvedPath = n.path.join(n.path.dirname(hostFilePath), path); // use lookup } else if (Array.isArray(lookup)) { lookup.some(function(lookupPath) { var curResolvedPath = n.path.join(lookupPath, path); try { if (n.fs.statSync(curResolvedPath).isFile()) { resolvedPath = curResolvedPath; return true; } } catch (e) {} }); } try { if (!n.fs.statSync(resolvedPath).isFile()) { throw new Error('is not a file') } } catch(e) { // add 'index.js' file and try again if (!n.path.extname(path)) { try { return exports.resolvePath(n.path.join(path,'index.js'), hostFilePath, root, lookup); } catch(e) {} } // add '.js' extention and try again if (!/\.js$/.test(path)) { return exports.resolvePath(path + '.js', hostFilePath, root, lookup); } throw new Error( 'resolved path is wrong.\n' + 'resolved path: ' + resolvedPath + '\n' + 'path: ' + path + '\n' + 'file: ' + hostFilePath + '\n' ); } return resolvedPath; }; /** * Merge 2 urls without to overwrite anything, but concatenate. * @param {string} url 1. * @param {string} url 2. * @return {string} new url */ function mergeUrls(url1, url2) { var obj1 = n.url.parse(url1, true), obj2 = n.url.parse(url2, true), obj = {}; $.each(obj1, function(val, key) { if (val) { obj[key] = val; } }); $.each(obj2, function(val, key) { if (val) { obj[key] = val; } }); if (obj1.pathname.substr(-1) == '/' && obj2.pathname[0] == '/') { obj1.pathname = obj1.pathname.substr(0, obj1.pathname.length - 1); } obj.pathname = obj1.pathname + obj2.pathname; delete obj.path; delete obj.host; return n.url.format(obj); } /** * Resolve url considering a root dir, paths array and optionally host. * * Don't add host to unresolvable urls, becuase you can end up with doubled host * in case where url is a variable passed to the template and containing baseUrl * already. * * <img src="${url}"> -> build -> <img src="http://nodejs.org/${url}"> * -> <img src="http://nodejs.org/http://nodejs.org/${url}"> * * TODO rewrite this mess! * * @param {string} url to resolve. * @param {string} path to the file within the url has been found. * @param {string} root directory relative to which the url pathname shold be resolved. * @param {Array} node like lookup paths to resolve the path. * @param {Object=} `host` which have to be added to the path, `verbose` - log errors. * @return {String} resolved url. */ exports.resolveUrl = function(url, path, root, paths, o) { var pathname; if (/^\w+:\/\//.test(url)) { return url; } paths = paths.slice(0); // add dirname of the file to lookup array // to look in currend dir first // f.e. url("a.png"); // otherwise the file will not be found like its expected in browser env. paths.unshift(n.path.dirname(path)); try { pathname = exports.resolvePath(url, path, root, paths); } catch(err) { if (o.verbose) { console.error(err.message); } } if (typeof pathname == 'string') { // make the url relative to root paths.slice(1).forEach(function(path) { pathname = pathname.replace(path, ''); }); // add query back if (url.indexOf('?') >= 0) { pathname += url.substr(url.indexOf('?')); } // add hash back if (url.indexOf('#') >= 0) { pathname += url.substr(url.indexOf('#')); } // add host if (o.host) { url = mergeUrls(o.host, pathname); } else { url = pathname; } } else { pathname = url; } return url; };