UNPKG

finepack

Version:

Organizes and maintains your JSON files readable

90 lines (71 loc) 3.32 kB
'use strict' Report = require './Report' KEYWORDS = require './Keywords' normalize = require './Normalize' JSONisEqual = require 'json-is-equal' sort = require 'sort-keys-recursive' DEFAULT = color: true validate: true filename: '' ### @description Sort the keys of an object by the order they appear in 'keyList'. @note Any key that is defined in 'obj' but not in 'keyList' will be ignored. * @param {obj} object An object literal. ### sortObjectKeysBy = (obj, keyList) -> keyList.reduce (acc, key) -> # Function, first argument of reduce(). acc[key] = obj[key] acc , {} # Object, second argument of reduce(), initial value of 'acc'. ### @description Organize the keys of a JSON file. * @param {string} data * @param {opts} object * @param [boolean] opts.color Activates the colorization of the messages. * @param [boolean] opts.validate Activates keyword validation. * @param [string] opts.filename Customizes the output messages. * @param [object] opts.sortOptions Customizes the sort options. ### module.exports = (data, opts = {}, cb) -> return cb new TypeError("Need to provide 'data' parameter") unless data opts = Object.assign({}, DEFAULT, opts) report = new Report opts.filename, opts.color, opts.validate # We only handle well formed data. try report.lint data catch err return report.errorMessage cb, err rawData = if typeof data is 'string' then JSON.parse data else data input = Object.assign({}, rawData) # We try to normalize the metadata; if it fails no problem, it will be detected # in the validation step. try input = normalize input catch err output = {} validation = report.validate input return report.requiredMessage(cb, input) if validation.required # Default sort order is alphabetical but not equivalent to sort((a,b) => a > b) # in various cases i.e when numbers, booleans ... are involved. This is how it # works: "Elements are sorted by converting them to strings and comparing # strings in Unicode code point order". SEE: https://mzl.la/1jBtmgE input = sort input, opts.sortOptions # After sorting, we move some fields in new positions for esthetic effect. # First, we get all 'KEYWORDS.sort' that are in 'input'; no need to sort them, # they are already in the correct order defined in './lib/Keywords.coffee'. specialKeys = KEYWORDS.sort.filter (k) -> Object.prototype.hasOwnProperty.call(input, k) # We get all the "non-special" keys in 'input'. We don't sort them, they # were alphabetically sorted (or maybe sorted in a custom order, if the user # passed a 'compareFunction') by 'sort-keys-recursive' (see above). otherKeys = Object.keys(input).filter (e) -> KEYWORDS.sort.indexOf(e) == -1 # We add the "special" keys before the rest of the keys. orderedInputKeys = [specialKeys..., otherKeys...] # We sort the keys in 'input' by the order they appear in 'orderedInputKeys'. output = sortObjectKeysBy input, orderedInputKeys # Restore special key sensitive to sorting output[key] = rawData[key] for key in KEYWORDS.inmutable when output[key]? return report.missingMessage(cb, output) if validation.missing return report.alreadyMessage(cb, output) if JSONisEqual data, output report.successMessage(cb, output)