@marko/prettyprint
Version:
Prettyprint Marko template files in the syntax of your choice
264 lines (218 loc) • 7.22 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
const fs = require("fs");
const chalk = require("chalk");
const nodePath = require("path");
const Minimatch = require("minimatch").Minimatch;
const details = require("../package.json");
const markoPrettyprint = require("./");
const cwd = process.cwd();
const mmOptions = {
matchBase: true,
dot: true,
flipNegate: true
};
exports.parse = function parse(argv) {
const options = require("argly").createParser({
"--help": {
type: "boolean",
description: "Show this help message"
},
"--files --file -f *": {
type: "string[]",
description: "A set of directories or files to pretty print"
},
"--ignore -i": {
type: "string[]",
description: 'An ignore rule (default: --ignore "/node_modules" ".*")'
},
"--syntax -s": {
type: "string",
description: 'The syntax (either "html" or "concise"). Defaults to "html"'
},
"--max-len": {
type: "int",
description: "The maximum line length. Defaults to 80"
},
"--no-semi": {
type: "boolean",
description: "If set, will format JS without semicolons"
},
"--single-quote": {
type: "boolean",
description: "If set, will prefer single quotes"
},
"--version -v": {
type: "boolean",
descrption: `print ${details.name} version`
}
}).usage("Usage: $0 <pattern> [options]").example("Prettyprint a single template", "$0 template.marko").example("Prettyprint a single template", "$0 template.marko").example("Prettyprint all templates in the current directory", "$0 .").example("Prettyprint multiple templates", "$0 template.marko src/ foo/").validate(function (result) {
if (result.version) {
console.log(`v${details.version}`);
process.exit(0);
}
if (result.help) {
this.printUsage();
process.exit(0);
}
if (!result.files || result.files.length === 0) {
this.printUsage();
process.exit(1);
}
}).onError(function (err) {
this.printUsage();
if (err) {
console.log();
console.log(err);
}
process.exit(1);
}).parse(argv);
return options;
};
exports.run = function run(options) {
options = _objectSpread({
syntax: "html",
maxLen: 80,
noSemi: false,
singleQuote: false,
ignore: ["/node_modules", ".*"]
}, options);
options.ignore = options.ignore.filter(s => (s = s.trim()) && !s.match(/^#/));
options.ignore = options.ignore.map(pattern => new Minimatch(pattern, mmOptions));
const found = {};
const errors = {};
let foundCount = 0;
let updateCount = 0;
if (options.files && options.files.length) {
walk(options.files, {
file(file) {
const basename = nodePath.basename(file);
if (basename.endsWith(".marko")) {
foundCount++;
prettyprint(file, options);
}
}
});
}
if (foundCount) {
const errorEntries = Object.entries(errors);
if (errorEntries.length) {
for (let [path, error] of errorEntries) {
console.error("\n" + chalk.red(path) + "\n" + error);
}
console.log(chalk.bold.red(`\nPrettyprinted ${updateCount} of ${foundCount} template(s) with ${errorEntries.length} error(s)`));
} else {
console.log(chalk.bold.green(`\nPrettyprinted ${updateCount} of ${foundCount} template(s)!`));
}
} else {
console.log(chalk.bold.yellow(`No templates found!`));
}
function prettyprint(path) {
if (found[path]) {
return;
}
found[path] = true;
const relative = relativePath(path);
const src = fs.readFileSync(path, {
encoding: "utf8"
});
try {
const outputSrc = markoPrettyprint(src, {
syntax: options.syntax,
maxLen: options.maxLen,
noSemi: options.noSemi,
singleQuote: options.singleQuote,
filename: path
});
if (src !== outputSrc) {
updateCount++;
fs.writeFileSync(path, outputSrc, {
encoding: "utf8"
});
console.log(relative);
} else {
console.log(chalk.dim(relative));
}
} catch (e) {
errors[relative] = e;
console.log(chalk.red(relative));
}
}
function isIgnored(path, dir, stat) {
if (path.startsWith(dir)) {
path = path.substring(dir.length);
}
path = path.replace(/\\/g, "/");
let ignore = false;
const ignoreRulesLength = options.ignore.length;
for (let i = 0; i < ignoreRulesLength; i++) {
const rule = options.ignore[i];
let match = rule.match(path);
if (!match && stat && stat.isDirectory()) {
try {
stat = fs.statSync(path);
} catch (e) {// if the file doesn't exist it won't match
}
if (stat && stat.isDirectory()) {
match = rule.match(path + "/");
}
}
if (match) {
if (rule.negate) {
ignore = false;
} else {
ignore = true;
}
}
}
return ignore;
}
function walk(files, opts) {
if (!files || files.length === 0) {
throw "No files provided";
}
if (!Array.isArray(files)) {
files = [files];
}
var fileCallback = opts.file;
function walkDir(dir) {
var children = fs.readdirSync(dir);
if (children.length) {
children.forEach(function (basename) {
var file = nodePath.join(dir, basename);
var stat;
try {
stat = fs.statSync(file);
} catch (e) {
return;
}
if (!isIgnored(file, dir, stat)) {
if (stat.isDirectory()) {
walkDir(file);
} else {
fileCallback(file);
}
}
});
}
}
for (var i = 0; i < files.length; i++) {
var file = nodePath.resolve(cwd, files[i]);
var stat = fs.statSync(file);
if (stat.isDirectory()) {
walkDir(file);
} else {
fileCallback(file);
}
}
}
};
function relativePath(path) {
if (path.startsWith(cwd)) {
return path.substring(cwd.length + 1);
}
return path;
}