distinguish
Advanced tools
Comparing version 0.1.5 to 0.1.6
@@ -36,5 +36,10 @@ #!/usr/bin/env node | ||
var EMPTY_CONFIG = "exports.default = {\n incrementer: 'simple', // the incrementer to use ([minimal, simple, module])\n types: ['cls', 'id'], // the types to rename (e.g. CSS classes, IDs)\n\n inputDir: 'src/', // the input directory to use\n outputDir: 'out/', // the output directory to use\n\n exclude: [], // a regular expression array describing files to exclude from renaming\n};\n"; | ||
var RESET_TO_APPLY = '\nConfig changed. Run again to pull in latest config'; | ||
var POLL_INTERVAL = 50; // pool watch events for this many millseconds | ||
var DEFAULT_CONFIG_FN = 'distinguish.config.js'; | ||
var BINARY_NAME = 'distinguish'; | ||
var SPLASH_SCREEN = " _ _ _ _ _ _ \n | (_) | | (_) (_) | | \n __| |_ ___| |_ _ _ __ __ _ _ _ _ ___| |__ \n / _` | / __| __| | '_ \\ / _` | | | | / __| '_ \\ \n | (_| | \\__ \\ |_| | | | | (_| | |_| | \\__ \\ | | |\n \\__,_|_|___/\\__|_|_| |_|\\__, |\\__,_|_|___/_| |_|\n __/ | \n |___/ \n"; | ||
function configMissing(path) { | ||
return "Unable to read in " + path + ".\n \n Maybe you need to create a config file first by running:\n \n distinguish init\n "; | ||
} | ||
var CLIParser = /** @class */ (function () { | ||
@@ -174,2 +179,8 @@ function CLIParser(stream, fs, requireFn, dirname, join, cwd, returnOptsOnly, parent) { | ||
} | ||
if (this.consumeOption(['-w', '--watch'])) { | ||
expectConfig = true; | ||
opts.watch = true; | ||
this.advance(); | ||
continue; | ||
} | ||
if (this.consumeOption(['-n', '--incrementer'])) { | ||
@@ -205,2 +216,4 @@ expectIncrementer = true; | ||
opts.configFile = this.stream[0]; | ||
if (opts.configFile.startsWith('-')) | ||
return this.showUsage(); | ||
expectConfig = false; | ||
@@ -227,6 +240,12 @@ this.advance(); | ||
} | ||
if (!this.fs.existsSync(opts.configFile)) { | ||
if (!this.returnOptsOnly) { | ||
log_1.logStyle(log_1.FAIL, configMissing(opts.configFile)); | ||
} | ||
return this.showUsage(); | ||
} | ||
var settings = this.requireFn(opts.configFile)["default"]; | ||
if (settings == undefined) { | ||
if (!this.returnOptsOnly) { | ||
log_1.logStyle(log_1.FAIL, "Unable to read in " + opts.configFile + ".\n \nMaybe you need to create a config file first by running:\n\n distinguish init\n"); | ||
log_1.logStyle(log_1.FAIL, configMissing(opts.configFile)); | ||
} | ||
@@ -250,4 +269,34 @@ return this.showUsage(); | ||
console.log(); | ||
var distinguisher = new distinguisher_1.Distinguisher(opts, fs_1["default"], path_1["default"].dirname); | ||
distinguisher.run(); | ||
var distinguisher_2 = new distinguisher_1.Distinguisher(opts, this.fs, this.dirname, !this.returnOptsOnly); | ||
distinguisher_2.run(); | ||
if (opts.watch != null) { | ||
var chokidar = this.requireFn('chokidar'); | ||
var count_1 = 1; | ||
var timer_1 = setTimeout(function () { return (timer_1 = null); }, POLL_INTERVAL); | ||
chokidar | ||
.watch(opts.configFile) | ||
.on('change', function () { | ||
log_1.logStyle(log_1.FAIL, RESET_TO_APPLY); | ||
process.exit(0); | ||
}) | ||
.on('unlink', function () { | ||
log_1.logStyle(log_1.FAIL, RESET_TO_APPLY); | ||
process.exit(0); | ||
}); | ||
chokidar | ||
.watch(opts.inputDir, { ignored: opts.exclude != null ? opts.exclude : [] }) | ||
.on('all', function (event, path) { | ||
if (opts.configFile != null && path == opts.configFile) { | ||
log_1.logStyle(log_1.FAIL, RESET_TO_APPLY); | ||
process.exit(0); | ||
} | ||
if (timer_1 == null) { | ||
timer_1 = setTimeout(function () { | ||
log_1.logStyle(log_1.STATUS_BOLD, "\n\nFiles changed, re-distinguishing (#" + count_1++ + ")"); | ||
distinguisher_2.run(); | ||
timer_1 = null; | ||
}, POLL_INTERVAL); | ||
} | ||
}); | ||
} | ||
} | ||
@@ -257,3 +306,7 @@ return { opts: opts }; | ||
RenameCLI.prototype.showUsage = function () { | ||
return this.parent.showUsage(); | ||
if (!this.returnOptsOnly) { | ||
console.log("Usage: " + BINARY_NAME + " rename [options]\n\n rename and namespace files recursively in a directory\n\nOptions:\n -c, --config [fn] Load all the settings from a config file.\n (default if no value passed: " + DEFAULT_CONFIG_FN + ")\n\n -w, --watch Watch the input directory for any changes. Re-run\n automatically if anything changes in the input directory or\n any of its sub-directories.\n\nConfig options / overrides:\n -n, --incrementer <str> Specify the incrementer to use.\n Options are 'simple', 'module', or 'minimal'\n (default if no config specified: simple)\n\n -t, --types <list> Specify a list of types to rename\n (default if no config specified: cls,id)\n\n -i, --inputDir <dir> The input directory to use\n (this arg is mandatory if no config is specified)\n\n -o, --outputDir <dir> The output directory to use\n (this arg is mandatory if no config is specified)\n\n -e, --exclude <list> Regular expression of paths to exclude renaming.\n It is recommended to set this in a config file to\n have more control.\n (default: empty list)\n"); | ||
process.exit(1); | ||
} | ||
return { showUsage: 'rename' }; | ||
}; | ||
@@ -314,2 +367,5 @@ return RenameCLI; | ||
} | ||
if (this.consumeOption(['rename'])) { | ||
return new RenameCLI(this.stream.slice(1), this.fs, this.requireFn, this.dirname, this.join, this.cwd, this.returnOptsOnly, this).process(); | ||
} | ||
if (this.consumeOption(['help'])) { | ||
@@ -326,3 +382,3 @@ // Show help menus. | ||
} | ||
return new RenameCLI(this.stream, this.fs, this.requireFn, this.dirname, this.join, this.cwd, this.returnOptsOnly, this).process(); | ||
return this.showUsage(); | ||
}; | ||
@@ -329,0 +385,0 @@ CLI.prototype.showVersion = function () { |
@@ -56,6 +56,8 @@ "use strict"; | ||
var Distinguisher = /** @class */ (function () { | ||
function Distinguisher(distinguishConfig, fs, dirnameFn) { | ||
function Distinguisher(distinguishConfig, fs, dirnameFn, logging) { | ||
if (logging === void 0) { logging = true; } | ||
this.distinguishConfig = distinguishConfig; | ||
this.fs = fs; | ||
this.dirnameFn = dirnameFn; | ||
this.logging = logging; | ||
var incrementer = incrementers[distinguishConfig.incrementer]; | ||
@@ -69,3 +71,3 @@ this.rootRenamer = new renamer_1.Renamer(incrementer, distinguishConfig.types); | ||
if (filelist === void 0) { filelist = []; } | ||
var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e; | ||
var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e, e_6, _f, e_7, _g; | ||
if (!dir.endsWith('/')) | ||
@@ -78,68 +80,102 @@ dir += '/'; | ||
// Parse a namespec file to determine the renamer's new scope. | ||
var namespec = new namespec_1.NamespecParser(this.fs.readFileSync(namespecPath).toString()).parse(); | ||
// Set the namespace. | ||
renamer = renamer.namespace(renamer_1.Renamer.pathSpecToParts(namespec.namespace)); | ||
var namespec = null; | ||
try { | ||
// Set imports. | ||
for (var _f = __values(namespec.imports.entries()), _g = _f.next(); !_g.done; _g = _f.next()) { | ||
var _h = __read(_g.value, 2), importName = _h[0], importMap = _h[1]; | ||
try { | ||
for (var _j = __values(importMap.entries()), _k = _j.next(); !_k.done; _k = _j.next()) { | ||
var _l = __read(_k.value, 2), type = _l[0], names = _l[1]; | ||
try { | ||
for (var names_1 = __values(names), names_1_1 = names_1.next(); !names_1_1.done; names_1_1 = names_1.next()) { | ||
var name_1 = names_1_1.value; | ||
renamer["import"](importName, type, name_1); | ||
} | ||
} | ||
catch (e_3_1) { e_3 = { error: e_3_1 }; } | ||
finally { | ||
namespec = new namespec_1.NamespecParser(this.fs.readFileSync(namespecPath).toString()).parse(); | ||
} | ||
catch (e) { | ||
log_1.logStyle(log_1.FAIL, "Error parsing " + namespecPath + ": " + e); | ||
} | ||
if (namespec != null) { | ||
// Set the namespace. | ||
renamer = renamer.namespace(renamer_1.Renamer.pathSpecToParts(namespec.namespace)); | ||
try { | ||
// Set imports. | ||
for (var _h = __values(namespec.imports.entries()), _j = _h.next(); !_j.done; _j = _h.next()) { | ||
var _k = __read(_j.value, 2), importName = _k[0], importMap = _k[1]; | ||
try { | ||
for (var _l = __values(importMap.entries()), _m = _l.next(); !_m.done; _m = _l.next()) { | ||
var _o = __read(_m.value, 2), type = _o[0], names = _o[1]; | ||
try { | ||
if (names_1_1 && !names_1_1.done && (_c = names_1["return"])) _c.call(names_1); | ||
for (var names_1 = __values(names), names_1_1 = names_1.next(); !names_1_1.done; names_1_1 = names_1.next()) { | ||
var name_1 = names_1_1.value; | ||
renamer["import"](importName, type, name_1); | ||
} | ||
} | ||
finally { if (e_3) throw e_3.error; } | ||
catch (e_3_1) { e_3 = { error: e_3_1 }; } | ||
finally { | ||
try { | ||
if (names_1_1 && !names_1_1.done && (_c = names_1["return"])) _c.call(names_1); | ||
} | ||
finally { if (e_3) throw e_3.error; } | ||
} | ||
} | ||
} | ||
catch (e_2_1) { e_2 = { error: e_2_1 }; } | ||
finally { | ||
try { | ||
if (_m && !_m.done && (_b = _l["return"])) _b.call(_l); | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
} | ||
} | ||
catch (e_2_1) { e_2 = { error: e_2_1 }; } | ||
finally { | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_j && !_j.done && (_a = _h["return"])) _a.call(_h); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
try { | ||
// Set reserves. | ||
for (var _p = __values(namespec.reserves.entries()), _q = _p.next(); !_q.done; _q = _p.next()) { | ||
var _r = __read(_q.value, 2), type = _r[0], reserves = _r[1]; | ||
try { | ||
if (_k && !_k.done && (_b = _j["return"])) _b.call(_j); | ||
for (var _s = __values(reserves.values()), _t = _s.next(); !_t.done; _t = _s.next()) { | ||
var _u = __read(_t.value, 1), nameValue = _u[0]; | ||
renamer.reserve(type, nameValue); | ||
} | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
catch (e_5_1) { e_5 = { error: e_5_1 }; } | ||
finally { | ||
try { | ||
if (_t && !_t.done && (_e = _s["return"])) _e.call(_s); | ||
} | ||
finally { if (e_5) throw e_5.error; } | ||
} | ||
} | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_g && !_g.done && (_a = _f["return"])) _a.call(_f); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
try { | ||
// Set reserves. | ||
for (var _m = __values(namespec.reserves.entries()), _o = _m.next(); !_o.done; _o = _m.next()) { | ||
var _p = __read(_o.value, 2), type = _p[0], reserves = _p[1]; | ||
catch (e_4_1) { e_4 = { error: e_4_1 }; } | ||
finally { | ||
try { | ||
for (var _q = __values(reserves.values()), _r = _q.next(); !_r.done; _r = _q.next()) { | ||
var reserveName = _r.value; | ||
renamer.reserve(type, reserveName); | ||
} | ||
if (_q && !_q.done && (_d = _p["return"])) _d.call(_p); | ||
} | ||
catch (e_5_1) { e_5 = { error: e_5_1 }; } | ||
finally { | ||
finally { if (e_4) throw e_4.error; } | ||
} | ||
try { | ||
// Set declares. | ||
for (var _v = __values(Array.from(namespec.declares.entries())), _w = _v.next(); !_w.done; _w = _v.next()) { | ||
var _x = __read(_w.value, 2), type = _x[0], declares = _x[1]; | ||
try { | ||
if (_r && !_r.done && (_e = _q["return"])) _e.call(_q); | ||
for (var _y = __values(Array.from(declares.entries())), _z = _y.next(); !_z.done; _z = _y.next()) { | ||
var _0 = __read(_z.value, 2), nameValue = _0[0], varValue = _0[1]; | ||
renamer.declare(type, nameValue, varValue); | ||
} | ||
} | ||
finally { if (e_5) throw e_5.error; } | ||
catch (e_7_1) { e_7 = { error: e_7_1 }; } | ||
finally { | ||
try { | ||
if (_z && !_z.done && (_g = _y["return"])) _g.call(_y); | ||
} | ||
finally { if (e_7) throw e_7.error; } | ||
} | ||
} | ||
} | ||
} | ||
catch (e_4_1) { e_4 = { error: e_4_1 }; } | ||
finally { | ||
try { | ||
if (_o && !_o.done && (_d = _m["return"])) _d.call(_m); | ||
catch (e_6_1) { e_6 = { error: e_6_1 }; } | ||
finally { | ||
try { | ||
if (_w && !_w.done && (_f = _v["return"])) _f.call(_v); | ||
} | ||
finally { if (e_6) throw e_6.error; } | ||
} | ||
finally { if (e_4) throw e_4.error; } | ||
} | ||
@@ -149,3 +185,3 @@ } | ||
files.forEach(function (file) { | ||
var e_6, _a; | ||
var e_8, _a; | ||
var fn = "" + dir + file; | ||
@@ -159,3 +195,3 @@ try { | ||
} | ||
catch (e_6_1) { e_6 = { error: e_6_1 }; } | ||
catch (e_8_1) { e_8 = { error: e_8_1 }; } | ||
finally { | ||
@@ -165,3 +201,3 @@ try { | ||
} | ||
finally { if (e_6) throw e_6.error; } | ||
finally { if (e_8) throw e_8.error; } | ||
} | ||
@@ -182,3 +218,3 @@ if (_this.fs.statSync(fn).isDirectory()) { | ||
Distinguisher.prototype.run = function () { | ||
var e_7, _a, e_8, _b, e_9, _c; | ||
var e_9, _a, e_10, _b, e_11, _c; | ||
var startTime = Date.now(); | ||
@@ -195,8 +231,11 @@ try { | ||
var matches = getAllMatches(new RegExp("_(" + type + ")[$-]([a-zA-Z0-9_-]+)", 'g'), contents); | ||
for (var i = matches.length - 1; i >= 0; i--) { | ||
// Iterate in reverse order to safely overwrite. | ||
var offset = 0; | ||
for (var i = 0; i < matches.length; i++) { | ||
// Iterate in correct order and keep track of offset. | ||
hadMatches = true; // there was at least a match somewhere | ||
var _j = __read(matches[i], 3), fullMatch = _j[0], typeMatch = _j[1], name_2 = _j[2]; | ||
var index = matches[i].index; | ||
index -= offset; | ||
var renamed = renamer.addName(typeMatch, name_2); | ||
offset += fullMatch.length - renamed.length; | ||
contents = | ||
@@ -209,3 +248,3 @@ contents.substr(0, index) + | ||
} | ||
catch (e_8_1) { e_8 = { error: e_8_1 }; } | ||
catch (e_10_1) { e_10 = { error: e_10_1 }; } | ||
finally { | ||
@@ -215,5 +254,5 @@ try { | ||
} | ||
finally { if (e_8) throw e_8.error; } | ||
finally { if (e_10) throw e_10.error; } | ||
} | ||
if (hadMatches) { | ||
if (this.logging && hadMatches) { | ||
log_1.logStyle(log_1.STATUS, "Writing " + outputFile + " with namespace " + renamer.namespaces.join('/')); | ||
@@ -225,3 +264,3 @@ } | ||
} | ||
catch (e_7_1) { e_7 = { error: e_7_1 }; } | ||
catch (e_9_1) { e_9 = { error: e_9_1 }; } | ||
finally { | ||
@@ -231,8 +270,9 @@ try { | ||
} | ||
finally { if (e_7) throw e_7.error; } | ||
finally { if (e_9) throw e_9.error; } | ||
} | ||
var overallTime = Date.now() - startTime; | ||
log_1.logStyle(log_1.BOLD, "\nWrote output in " + overallTime / 1000 + "s"); | ||
if (this.logging) | ||
log_1.logStyle(log_1.BOLD, "\nWrote output in " + overallTime / 1000 + "s"); | ||
var danglers = this.rootRenamer.danglingImports(); | ||
if (danglers.length > 0) | ||
if (this.logging && danglers.length > 0) | ||
console.log('\n'); | ||
@@ -242,6 +282,8 @@ try { | ||
var _k = danglers_1_1.value, sourceNamespace = _k.sourceNamespace, importNamespace = _k.importNamespace, type = _k.type, name_3 = _k.name; | ||
log_1.logStyle(log_1.WARN, "Dangling import: " + sourceNamespace + " imports unused {type: " + type + ", name: " + name_3 + "} from " + importNamespace); | ||
if (this.logging) { | ||
log_1.logStyle(log_1.WARN, "Dangling import: " + sourceNamespace + " imports unused {type: " + type + ", name: " + name_3 + "} from " + importNamespace); | ||
} | ||
} | ||
} | ||
catch (e_9_1) { e_9 = { error: e_9_1 }; } | ||
catch (e_11_1) { e_11 = { error: e_11_1 }; } | ||
finally { | ||
@@ -251,3 +293,3 @@ try { | ||
} | ||
finally { if (e_9) throw e_9.error; } | ||
finally { if (e_11) throw e_11.error; } | ||
} | ||
@@ -254,0 +296,0 @@ }; |
@@ -19,4 +19,10 @@ "use strict"; | ||
this.reserved = new Set(); | ||
this.declared = new Map(); | ||
} | ||
Incrementer.prototype.next = function (name, renamer) { | ||
if (name != null) { | ||
var declared = this.declared.get(name); | ||
if (declared != null) | ||
return declared; | ||
} | ||
var renamed; | ||
@@ -31,2 +37,5 @@ do { | ||
}; | ||
Incrementer.prototype.declare = function (name, value) { | ||
this.declared.set(name, value); | ||
}; | ||
return Incrementer; | ||
@@ -33,0 +42,0 @@ }()); |
@@ -6,3 +6,4 @@ "use strict"; | ||
exports.FAIL = ['31', '1']; // red, bold | ||
exports.STATUS = ['37']; // gray | ||
exports.STATUS = ['90']; // gray | ||
exports.STATUS_BOLD = ['90', '1']; // gray, bold | ||
exports.WARN = ['95']; // magenta | ||
@@ -9,0 +10,0 @@ exports.BOLD = ['1']; // bold |
@@ -19,3 +19,23 @@ "use strict"; | ||
*/ | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
exports.__esModule = true; | ||
function extractVarValue(nameVar) { | ||
var index = nameVar.indexOf('='); | ||
return [nameVar.substr(0, index), nameVar.substr(index + 1)]; | ||
} | ||
var NamespecParser = /** @class */ (function () { | ||
@@ -80,16 +100,20 @@ function NamespecParser(specContents) { | ||
}; | ||
NamespecParser.prototype.consumeImportOrReserve = function () { | ||
NamespecParser.prototype.consumeMethod = function () { | ||
var result = this.consumeLine(/^from ([^ ]+) import$/, 'import'); | ||
if (result.contents == null) { | ||
result = this.consumeLine(/^(reserve)$/, 'reserve'); | ||
if (result.contents == null) { | ||
result = this.consumeLine(/^(declare)$/, 'declare'); | ||
} | ||
} | ||
return result; | ||
}; | ||
NamespecParser.prototype.consumeIndented = function (expectedWhitespace) { | ||
NamespecParser.prototype.consumeIndented = function (expectedWhitespace, equalsOk) { | ||
if (equalsOk === void 0) { equalsOk = false; } | ||
var type; | ||
if (expectedWhitespace == null) { | ||
type = this.consumeLine(/^([ \t]+)([a-zA-Z0-9_-]+)$/); | ||
type = this.consumeLine(new RegExp("^([ \\t]+)([a-zA-Z0-9_-]+" + (equalsOk ? '=.*' : '') + ")$")); | ||
} | ||
else { | ||
type = this.consumeLine(new RegExp("^(" + expectedWhitespace + ")([a-zA-Z0-9_-]+)$")); | ||
type = this.consumeLine(new RegExp("^(" + expectedWhitespace + ")([a-zA-Z0-9_-]+" + (equalsOk ? '=.*' : '') + ")$")); | ||
} | ||
@@ -104,2 +128,3 @@ if (type.allMatches == null) | ||
NamespecParser.prototype.parse = function () { | ||
var _a; | ||
var namespace = this.consumeNamespace(); | ||
@@ -110,6 +135,7 @@ var expectedTypeWhitespace = null; | ||
var reserves = new Map(); | ||
var result = { namespace: namespace, imports: imports, reserves: reserves }; | ||
var declares = new Map(); | ||
var result = { namespace: namespace, imports: imports, reserves: reserves, declares: declares }; | ||
while (true) { | ||
// Iterate through remaining file consuming import statements. | ||
var entryResult = this.consumeImportOrReserve(); | ||
var entryResult = this.consumeMethod(); | ||
if (entryResult.contents == null) { | ||
@@ -125,2 +151,3 @@ // If at end-of-file, successful parse! | ||
var reservedMap = null; | ||
var declaredMap = null; | ||
if (entryResult.flag == 'import') { | ||
@@ -137,3 +164,3 @@ var importNamespace = entryResult.contents; | ||
} | ||
else if (entryResult.flag != 'reserve') { | ||
else if (entryResult.flag != 'reserve' && entryResult.flag != 'declare') { | ||
throw new Error("Unexpected flag: " + entryResult.flag); | ||
@@ -153,6 +180,6 @@ } | ||
// If name indent level is unknown, search for more indented than type. | ||
name_1 = this.consumeIndented(expectedTypeWhitespace + '[ \t]+'); | ||
name_1 = this.consumeIndented(expectedTypeWhitespace + '[ \t]+', entryResult.flag == 'declare'); | ||
} | ||
else { | ||
name_1 = this.consumeIndented(expectedNameWhitespace); | ||
name_1 = this.consumeIndented(expectedNameWhitespace, entryResult.flag == 'declare'); | ||
} | ||
@@ -175,9 +202,23 @@ if (name_1 == null) | ||
else if (reserves != null) { | ||
// Add reserved. | ||
if (reserves.has(typeValue)) { | ||
var reservedSet = reserves.get(typeValue); | ||
reservedSet.add(nameValue); | ||
// Add reserved or declared. | ||
var varValue = void 0; | ||
if (entryResult.flag == 'declare') { | ||
// Parse out declare value | ||
_a = __read(extractVarValue(nameValue), 2), nameValue = _a[0], varValue = _a[1]; | ||
if (declares.has(typeValue)) { | ||
var declaredMap_1 = declares.get(typeValue); | ||
declaredMap_1.set(nameValue, varValue); | ||
} | ||
else { | ||
declares.set(typeValue, new Map([[nameValue, varValue]])); | ||
} | ||
} | ||
else { | ||
reserves.set(typeValue, new Set([nameValue])); | ||
if (reserves.has(typeValue)) { | ||
var reservedSet = reserves.get(typeValue); | ||
reservedSet.add(nameValue); | ||
} | ||
else { | ||
reserves.set(typeValue, new Set([nameValue])); | ||
} | ||
} | ||
@@ -184,0 +225,0 @@ } |
@@ -174,2 +174,9 @@ "use strict"; | ||
}; | ||
Renamer.prototype.declare = function (type, name, value) { | ||
console.log('DECLARE'); | ||
var typeMap = this.namingMaps.get(type); | ||
if (typeMap == null) | ||
throw new Error("Cannot declare: invalid type " + type); | ||
typeMap.set(name, value); | ||
}; | ||
Renamer.prototype.danglingImports = function () { | ||
@@ -176,0 +183,0 @@ var e_2, _a, e_3, _b, e_4, _c; |
@@ -310,3 +310,3 @@ "use strict"; | ||
}; | ||
var d = new distinguisher_1.Distinguisher(config, fs, fs.dirname); | ||
var d = new distinguisher_1.Distinguisher(config, fs, fs.dirname, false); | ||
d.run(); | ||
@@ -328,3 +328,3 @@ t.assertArrayEquals(fs.readdirSync('/'), ['out/', 'src/']); | ||
}; | ||
var d = new distinguisher_1.Distinguisher(config, fs, fs.dirname); | ||
var d = new distinguisher_1.Distinguisher(config, fs, fs.dirname, false); | ||
d.run(); | ||
@@ -357,3 +357,3 @@ t.assertEquals(fs.readFileSync('/out/index.html').toString(), '<div id="a" class="a">Content here</div>'); | ||
}; | ||
var d = new distinguisher_1.Distinguisher(config, fs, fs.dirname); | ||
var d = new distinguisher_1.Distinguisher(config, fs, fs.dirname, false); | ||
d.run(); | ||
@@ -395,5 +395,5 @@ t.assertEquals(fs.readFileSync('/out/index.html').toString(), toggleSrcIndex(indexClass)); | ||
t.assertObjectEquals(cli('help init'), { showUsage: 'init' }); | ||
t.assertObjectEquals(cli('help rename'), { showUsage: 'base' }); | ||
t.assertObjectEquals(cli('help rename'), { showUsage: 'rename' }); | ||
t.assertObjectEquals(cli('--invalid-option'), { showUsage: 'base' }); | ||
t.assertObjectEquals(cli('rename --invalid-option'), { showUsage: 'base' }); | ||
t.assertObjectEquals(cli('rename --invalid-option'), { showUsage: 'rename' }); | ||
// Version | ||
@@ -412,5 +412,5 @@ t.assertObjectEquals(cli('-v'), { showVersion: true }); | ||
t.test('distinguishCliRenameNoConfig', function () { | ||
var result = cli(''); | ||
var result = cli('rename'); | ||
// File won't exist yet. | ||
t.assertEquals(result.showUsage, 'base'); | ||
t.assertEquals(result.showUsage, 'rename'); | ||
}); | ||
@@ -429,10 +429,10 @@ function getConfig(incrementer, types, inputDir, outputDir, exclude) { | ||
for (var _b = __values([ | ||
'', | ||
'-c', | ||
'-c distinguish.config.js', | ||
'--config', | ||
'--config distinguish.config.js', | ||
'rename ', | ||
'rename -c', | ||
'rename -c distinguish.config.js', | ||
'rename --config', | ||
'rename --config distinguish.config.js', | ||
]), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var cmd = _c.value; | ||
var result = cli('', function (fs) { | ||
var result = cli(cmd, function (fs) { | ||
fs.writeFileSync('distinguish.config.js', getConfig()); | ||
@@ -465,4 +465,4 @@ }); | ||
for (var _b = __values([ | ||
'-c specification/config.js', | ||
'--config specification/config.js', | ||
'rename -c specification/config.js', | ||
'rename --config specification/config.js', | ||
]), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
@@ -495,3 +495,3 @@ var cmd = _c.value; | ||
t.test('distinguishCliRenameWithOverrides', function () { | ||
var result = cli('-c spec/settings/config.js -n minimal -t dog,cat,hen -i input/src/ -o dest/ -e dog,cat', function (fs) { | ||
var result = cli('rename -c spec/settings/config.js -n minimal -t dog,cat,hen -i input/src/ -o dest/ -e dog,cat', function (fs) { | ||
fs.writeFileSync('spec/settings/config.js', getConfig()); | ||
@@ -511,1 +511,18 @@ }); | ||
}); | ||
t.test('distinguishCliWatch', function () { | ||
var result = cli('rename -c spec/settings/config.js -w', function (fs) { | ||
fs.writeFileSync('spec/settings/config.js', getConfig()); | ||
}); | ||
// Let's check we get a matching config. | ||
t.assert(result.opts); | ||
var opts = result.opts; | ||
t.assertEquals(opts, { | ||
configFile: 'spec/settings/config.js', | ||
incrementer: 'simple', | ||
types: ['cls', 'id'], | ||
inputDir: 'src/', | ||
outputDir: 'out/', | ||
exclude: [], | ||
watch: true | ||
}); | ||
}); |
{ | ||
"name": "distinguish", | ||
"version": "0.1.5", | ||
"version": "0.1.6", | ||
"description": "Effortless renaming, minification, and namespacing for CSS class names, IDs, and just about anything else.", | ||
@@ -5,0 +5,0 @@ "main": "out/cli.js", |
import {Renamer} from './renamer'; | ||
import {NamespecParser} from './namespec'; | ||
import {NamespecParser, Namespec} from './namespec'; | ||
import { | ||
@@ -9,3 +9,3 @@ MinimalIncrementer, | ||
} from './incrementer'; | ||
import {logStyle, STATUS, WARN, BOLD} from './log'; | ||
import {logStyle, STATUS, WARN, BOLD, FAIL} from './log'; | ||
import {BaseFs} from './virtual-fs'; | ||
@@ -83,23 +83,37 @@ | ||
// Parse a namespec file to determine the renamer's new scope. | ||
const namespec = new NamespecParser( | ||
let namespec: Namespec | null = null; | ||
// try { | ||
namespec = new NamespecParser( | ||
this.fs.readFileSync(namespecPath).toString() | ||
).parse(); | ||
// } catch (e) { | ||
// logStyle(FAIL, `Error parsing ${namespecPath}: ${e}`); | ||
// } | ||
// Set the namespace. | ||
renamer = renamer.namespace(Renamer.pathSpecToParts(namespec.namespace)); | ||
if (namespec != null) { | ||
// Set the namespace. | ||
renamer = renamer.namespace(Renamer.pathSpecToParts(namespec.namespace)); | ||
// Set imports. | ||
for (const [importName, importMap] of namespec.imports.entries()) { | ||
for (const [type, names] of importMap.entries()) { | ||
for (const name of names) { | ||
renamer.import(importName, type, name); | ||
// Set imports. | ||
for (const [importName, importMap] of Array.from(namespec.imports.entries())) { | ||
for (const [type, names] of Array.from(importMap.entries())) { | ||
for (const name of names) { | ||
renamer.import(importName, type, name); | ||
} | ||
} | ||
} | ||
} | ||
// Set reserves. | ||
for (const [type, reserves] of namespec.reserves.entries()) { | ||
for (const reserveName of reserves.values()) { | ||
renamer.reserve(type, reserveName); | ||
// Set reserves. | ||
for (const [type, reserves] of Array.from(namespec.reserves.entries())) { | ||
for (const [nameValue] of Array.from(reserves.values())) { | ||
renamer.reserve(type, nameValue); | ||
} | ||
} | ||
// Set declares. | ||
for (const [type, declares] of Array.from(namespec.declares.entries())) { | ||
for (const [nameValue, varValue] of Array.from(declares.entries())) { | ||
renamer.declare(type, nameValue, varValue); | ||
} | ||
} | ||
} | ||
@@ -148,8 +162,12 @@ } | ||
); | ||
for (let i = matches.length - 1; i >= 0; i--) { | ||
// Iterate in reverse order to safely overwrite. | ||
let offset = 0; | ||
for (let i = 0; i < matches.length; i++) { | ||
// Iterate in correct order and keep track of offset. | ||
hadMatches = true; // there was at least a match somewhere | ||
const [fullMatch, typeMatch, name] = matches[i]; | ||
const {index} = matches[i]; | ||
let {index} = matches[i]; | ||
index -= offset; | ||
const renamed = renamer.addName(typeMatch, name); | ||
offset += fullMatch.length - renamed.length; | ||
contents = | ||
@@ -156,0 +174,0 @@ contents.substr(0, index) + |
@@ -37,4 +37,10 @@ /** | ||
reserves: Map<string, Set<string>>; | ||
declares: Map<string, Map<string, string>>; | ||
} | ||
function extractVarValue(nameVar: string): [string, string] { | ||
const index = nameVar.indexOf('='); | ||
return [nameVar.substr(0, index), nameVar.substr(index + 1)]; | ||
} | ||
export class NamespecParser { | ||
@@ -102,6 +108,9 @@ constructor(protected specContents: string) {} | ||
protected consumeImportOrReserve(): Contents { | ||
protected consumeMethod(): Contents { | ||
let result = this.consumeLine(/^from ([^ ]+) import$/, 'import'); | ||
if (result.contents == null) { | ||
result = this.consumeLine(/^(reserve)$/, 'reserve'); | ||
if (result.contents == null) { | ||
result = this.consumeLine(/^(declare)$/, 'declare'); | ||
} | ||
} | ||
@@ -112,9 +121,14 @@ return result; | ||
protected consumeIndented( | ||
expectedWhitespace: string | RegExp | null | ||
expectedWhitespace: string | RegExp | null, | ||
equalsOk: boolean = false | ||
): IndentedVar | null { | ||
let type; | ||
if (expectedWhitespace == null) { | ||
type = this.consumeLine(/^([ \t]+)([a-zA-Z0-9_-]+)$/); | ||
type = this.consumeLine( | ||
new RegExp(`^([ \\t]+)([a-zA-Z0-9_-]+${equalsOk ? '=.*' : ''})$`) | ||
); | ||
} else { | ||
type = this.consumeLine(new RegExp(`^(${expectedWhitespace})([a-zA-Z0-9_-]+)$`)); | ||
type = this.consumeLine( | ||
new RegExp(`^(${expectedWhitespace})([a-zA-Z0-9_-]+${equalsOk ? '=.*' : ''})$`) | ||
); | ||
} | ||
@@ -136,8 +150,9 @@ if (type.allMatches == null) return null; | ||
const reserves = new Map(); | ||
const declares = new Map(); | ||
const result: Namespec = {namespace, imports, reserves}; | ||
const result: Namespec = {namespace, imports, reserves, declares}; | ||
while (true) { | ||
// Iterate through remaining file consuming import statements. | ||
const entryResult = this.consumeImportOrReserve(); | ||
const entryResult = this.consumeMethod(); | ||
if (entryResult.contents == null) { | ||
@@ -158,2 +173,3 @@ // If at end-of-file, successful parse! | ||
let reservedMap: Map<string, Set<string>> | null = null; | ||
let declaredMap: Map<string, Map<string, string>> | null = null; | ||
if (entryResult.flag == 'import') { | ||
@@ -168,3 +184,3 @@ const importNamespace = entryResult.contents; | ||
} | ||
} else if (entryResult.flag != 'reserve') { | ||
} else if (entryResult.flag != 'reserve' && entryResult.flag != 'declare') { | ||
throw new Error(`Unexpected flag: ${entryResult.flag}`); | ||
@@ -185,9 +201,15 @@ } | ||
// If name indent level is unknown, search for more indented than type. | ||
name = this.consumeIndented(expectedTypeWhitespace + '[ \t]+'); | ||
name = this.consumeIndented( | ||
expectedTypeWhitespace + '[ \t]+', | ||
entryResult.flag == 'declare' | ||
); | ||
} else { | ||
name = this.consumeIndented(expectedNameWhitespace); | ||
name = this.consumeIndented( | ||
expectedNameWhitespace, | ||
entryResult.flag == 'declare' | ||
); | ||
} | ||
if (name == null) break; | ||
const nameValue = name.value; | ||
let nameValue = name.value; | ||
expectedNameWhitespace = name.whitespace; | ||
@@ -205,8 +227,20 @@ | ||
} else if (reserves != null) { | ||
// Add reserved. | ||
if (reserves.has(typeValue)) { | ||
const reservedSet = reserves.get(typeValue) as Set<string>; | ||
reservedSet.add(nameValue); | ||
// Add reserved or declared. | ||
let varValue; | ||
if (entryResult.flag == 'declare') { | ||
// Parse out declare value | ||
[nameValue, varValue] = extractVarValue(nameValue); | ||
if (declares.has(typeValue)) { | ||
const declaredMap = declares.get(typeValue) as Map<string, string>; | ||
declaredMap.set(nameValue, varValue); | ||
} else { | ||
declares.set(typeValue, new Map([[nameValue, varValue]])); | ||
} | ||
} else { | ||
reserves.set(typeValue, new Set([nameValue])); | ||
if (reserves.has(typeValue)) { | ||
const reservedSet = reserves.get(typeValue) as Set<string>; | ||
reservedSet.add(nameValue); | ||
} else { | ||
reserves.set(typeValue, new Set([nameValue])); | ||
} | ||
} | ||
@@ -213,0 +247,0 @@ } else { |
@@ -158,8 +158,14 @@ import {Incrementer} from './incrementer'; | ||
declare(type: string, name: string, value: string) { | ||
const typeMap = this.namingMaps.get(type); | ||
if (typeMap == null) throw new Error(`Cannot declare: invalid type ${type}`); | ||
typeMap.set(name, value); | ||
} | ||
danglingImports(): DanglingImport[] { | ||
let danglers = []; | ||
for (const [type, importMap] of this.imports.entries()) { | ||
for (const [type, importMap] of Array.from(this.imports.entries())) { | ||
// Go through each type-to-import entry. | ||
for (const [name, renamer] of importMap.entries()) { | ||
for (const [name, renamer] of Array.from(importMap.entries())) { | ||
// Grab the import renamer instance, and use that to extract the typemap. | ||
@@ -166,0 +172,0 @@ const typeMap = renamer.ownNamingMaps.get(type); |
172
src/tests.ts
@@ -592,2 +592,174 @@ import {Renamer} from './renamer'; | ||
t.test('distinguisherNamespecDeclareBasic', () => { | ||
const fs = new VirtualFs(); | ||
fs.writeFileSync( | ||
'/src/.namespec', | ||
`namespace main | ||
declare | ||
var | ||
blue=#697f98` | ||
); | ||
fs.writeFileSync( | ||
'/src/style.css', | ||
`._cls-foreground { | ||
color: _var-blue; | ||
} | ||
._cls-background { | ||
background: _var-blue; | ||
}` | ||
); | ||
fs.writeFileSync('/src/index.html', '<svg><rect fill="_var-blue"></rect></svg>'); | ||
const config: DistinguishConfig = { | ||
inputDir: '/src/', | ||
outputDir: '/out/', | ||
incrementer: 'minimal', | ||
types: ['cls', 'id', 'var'], | ||
exclude: [], | ||
}; | ||
const d = new Distinguisher(config, fs, fs.dirname, false); | ||
d.run(); | ||
t.assertEquals( | ||
fs.readFileSync('/out/style.css').toString(), | ||
`.a { | ||
color: #697f98; | ||
} | ||
.b { | ||
background: #697f98; | ||
}` | ||
); | ||
t.assertEquals( | ||
fs.readFileSync('/out/index.html').toString(), | ||
'<svg><rect fill="#697f98"></rect></svg>' | ||
); | ||
}); | ||
t.test('distinguisherNamespecDeclareModuleNoSpec', () => { | ||
const fs = new VirtualFs(); | ||
fs.writeFileSync( | ||
'/src/.namespec', | ||
`namespace main | ||
declare | ||
var | ||
blue=#697f98` | ||
); | ||
fs.writeFileSync('/src/index.html', '<svg><rect fill="_var-blue"></rect></svg>'); | ||
fs.writeFileSync('/src/toggle/toggle.html', '_var-blue'); | ||
const config: DistinguishConfig = { | ||
inputDir: '/src/', | ||
outputDir: '/out/', | ||
incrementer: 'minimal', | ||
types: ['cls', 'id', 'var'], | ||
exclude: [], | ||
}; | ||
const d = new Distinguisher(config, fs, fs.dirname, false); | ||
d.run(); | ||
t.assertEquals(fs.readFileSync('/out/toggle/toggle.html').toString(), '#697f98'); | ||
}); | ||
t.test('distinguisherNamespecDeclareModuleSpec', () => { | ||
const fs = new VirtualFs(); | ||
fs.writeFileSync( | ||
'/src/.namespec', | ||
`namespace main | ||
declare | ||
var | ||
blue=#697f98` | ||
); | ||
fs.writeFileSync('/src/index.html', '<svg><rect fill="_var-blue"></rect></svg>'); | ||
fs.writeFileSync('/src/toggle/.namespec', 'namespace toggle'); | ||
fs.writeFileSync('/src/toggle/toggle.html', '_var-blue'); | ||
const config: DistinguishConfig = { | ||
inputDir: '/src/', | ||
outputDir: '/out/', | ||
incrementer: 'minimal', | ||
types: ['cls', 'id', 'var'], | ||
exclude: [], | ||
}; | ||
const d = new Distinguisher(config, fs, fs.dirname, false); | ||
d.run(); | ||
t.assertEquals(fs.readFileSync('/out/toggle/toggle.html').toString(), 'a'); | ||
}); | ||
t.test('distinguisherNamespecDeclareModuleSpecImportParent', () => { | ||
const fs = new VirtualFs(); | ||
fs.writeFileSync( | ||
'/src/.namespec', | ||
`namespace main | ||
declare | ||
var | ||
blue=#697f98` | ||
); | ||
fs.writeFileSync('/src/index.html', '<svg><rect fill="_var-blue"></rect></svg>'); | ||
fs.writeFileSync( | ||
'/src/toggle/.namespec', | ||
`namespace toggle | ||
from .. import | ||
var | ||
blue` | ||
); | ||
fs.writeFileSync('/src/toggle/toggle.html', '_var-blue'); | ||
const config: DistinguishConfig = { | ||
inputDir: '/src/', | ||
outputDir: '/out/', | ||
incrementer: 'minimal', | ||
types: ['cls', 'id', 'var'], | ||
exclude: [], | ||
}; | ||
const d = new Distinguisher(config, fs, fs.dirname, false); | ||
d.run(); | ||
t.assertEquals(fs.readFileSync('/out/toggle/toggle.html').toString(), '#697f98'); | ||
}); | ||
t.test('distinguisherNamespecDeclareModuleSpecImportChild', () => { | ||
// Cannot import going the other way. | ||
const fs = new VirtualFs(); | ||
fs.writeFileSync( | ||
'/src/.namespec', | ||
`namespace main | ||
declare | ||
var | ||
blue=#697f98 | ||
from toggle import | ||
var | ||
blue` | ||
); | ||
fs.writeFileSync('/src/index.html', '<svg><rect fill="_var-blue"></rect></svg>'); | ||
fs.writeFileSync('/src/toggle/toggle.html', '_var-blue'); | ||
fs.writeFileSync('/src/toggle/.namespec', 'namespace toggle'); | ||
const config: DistinguishConfig = { | ||
inputDir: '/src/', | ||
outputDir: '/out/', | ||
incrementer: 'minimal', | ||
types: ['cls', 'id', 'var'], | ||
exclude: [], | ||
}; | ||
const d = new Distinguisher(config, fs, fs.dirname, false); | ||
d.run(); | ||
t.assertEquals(fs.readFileSync('/out/toggle/toggle.html').toString(), 'a'); | ||
}); | ||
function cli(argsString: string, fsInit?: (fs: VirtualFs) => void): CLIResult { | ||
@@ -594,0 +766,0 @@ const fs = new VirtualFs(); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
181863
4423
5