@ashnazg/literalizer
v0.0.1
Published
creates literals for code-gen of JS use cases
Downloads
3
Readme
title: "@ashnazg/literalizer" sidebar_label: "literalizer"
Much like the carpal-tunnel silly oneliners in utils, this liblet was born because I like the literal notation in javascript more than the simpler rules of JSON.
There's plenty of relaxed JSON parsers, but no serializers to those variants that I could find, and I want this for code-generation and config-writing templating tools.
(In other words, I want to dynamically create plain-old-javascript things and then export them as a config file like ".eslintrc.js" in the same style that would result if I did it by hand.)
Usage
At it's core, it's just an equivalent to JSON.stringify($, null, '\t')
that avoids quoting keys:
var literalizer = require('@ashnazg/literalizer'); // ~/projects/ashnazg-npm/literalizer/literalizer.js
var map = {foo: 'bar'};
console.log(literalizer(map)); // => {foo: "bar"}
It doesn't (yet) take a replacer, but it does take an optional 2nd param that's a config:
var example_predefined_js_variable = ...;
var map = {foo: 'bar'};
literalizer(map, {
name: 'variable_name_in_output',
exports: !!caller_wants_a_node_module_file,
fold_width: 80, // simple non-scalars who's final line is shorter than this are compacted
local_scope: {example_predefined_js_variable} // the final output will NOT express the values of any variable mentioned here.
});
Compacting some fields based on final width
The compactor will pretty-print a map or list in one-line form if and only if:
- fold_width is set
- The final line is shorter than fold_width (including unpacked tabs at 4-space, key names, and the comma at the end.)
- no child element is a non-empty map or list
var literalizer = require('./literalizer.js');
var this_folds = {
smartcode: false,
'much foldy': 'so much fold.',
};
var this_does_not = {
smartcode: false,
'much foldy': 'too much to fold.',
ribbit: 'ribbit ribbit ribbit.', // because this line pushes it above the width limit given below
};
var these_are_all_fine = ['but this is fine', 42, [], {}, null, undefined];
var but_this_array_has_a_nontrivial_child = [{f:1}];
console.log(literalizer({
this_folds,
this_does_not,
these_are_all_fine,
but_this_array_has_a_nontrivial_child
}, {
fold_width: 80
}));
results
{
this_folds: {smartcode: false, "much foldy": "so much fold."},
this_does_not: {
smartcode: false,
"much foldy": "too much to fold.",
ribbit: "ribbit ribbit ribbit."
},
these_are_all_fine: ["but this is fine", 42, [], {}, null, undefined],
but_this_array_has_a_nontrivial_child: [
{f: 1}
]
}
instant module pattern
There's some trivial syntactic sugar to wrap the final output in one of a few common file patterns:
var literalizer = require('./literalizer.js');
function genConf() {
return {
prop1: 'val1',
subsettings: {
thing:'1'
}
};
}
console.log(literalizer(genConf(), {exports: true}));
results
module.exports = {
prop1: "val1",
subsettings: {
thing: "1"
}
};
named module level vars
console.log(literalizer(genConf(), {name: 'new_conf'}));
results
var new_conf = {
prop1: "val1",
subsettings: {
thing: "1"
}
};
named exports
console.log(literalizer(genConf(), {name: 'subconfig', exports: true}));
results
exports.subconfig = {
prop1: "val1",
subsettings: {
thing: "1"
}
};
depend on existing local scope vars
If you're already writing js vars in the file's preamble before the part generated using this library, you can have the output re-use those instead of blindly serializing the value redundantly:
var existing_map = {foo:'bar'};
function existingFunc() {};
console.log(`
var existing_map = {foo:'bar'};
function existingFunc() {};
`);
console.log(literalizer({
top: 'level prop',
works_in_maps: {
mixed: 'data',
existingFunc,
existing_map
},
works_in_lists: [
"because we look up these by value, we can tell when to just use the var name in list mode",
existingFunc,
existing_map
]
}, {
name: 'external',
exports: true,
local_scope: { existing_map, existingFunc }
}));
results
var existing_map = {foo:'bar'};
function existingFunc() {};
exports.external = {
top: "level prop",
works_in_maps: {
mixed: "data",
existingFunc,
existing_map
},
works_in_lists: [
"because we look up these by value, we can tell when to just use the var name in list mode",
existingFunc,
existing_map
]
};
TODO
- support renaming in local_scope.
this_doesnt_work: { newname: existingFunc },
- regexs
- generators
- inline fat arrows
Release 0.0.1
Happy with it for the plain old json-like work I'm on right now; annoyed at how much work it takes to reflect details about a JS-function like "are you a fat arrow?" that you'd need to isomorphically print the source code in all contexts.
(Since I don't need function literals in my current projects, I'm stopping here, as playing with functions has consumed 90% of the time put in so far for imperfect results.)