@ashnazg/literalizer

0.0.1 • Public • Published

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:

  1. fold_width is set
  2. The final line is shorter than fold_width (including unpacked tabs at 4-space, key names, and the comma at the end.)
  3. 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

  1. support renaming in local_scope.
    this_doesnt_work: {
    	newname: existingFunc
    },
    
  2. regexs
  3. generators
  4. 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.)

Readme

Keywords

none

Package Sidebar

Install

npm i @ashnazg/literalizer

Weekly Downloads

2

Version

0.0.1

License

MIT

Unpacked Size

13.3 kB

Total Files

5

Last publish

Collaborators

  • xander