--- /dev/null
+var Flatted = (function (Primitive, primitive) {
+
+ /*!
+ * ISC License
+ *
+ * Copyright (c) 2018, Andrea Giammarchi, @WebReflection
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+ var Flatted = {
+
+ parse: function parse(text, reviver) {
+ var input = JSON.parse(text, Primitives).map(primitives);
+ var value = input[0];
+ var $ = reviver || noop;
+ var tmp = typeof value === 'object' && value ?
+ revive(input, new Set, value, $) :
+ value;
+ return $.call({'': tmp}, '', tmp);
+ },
+
+ stringify: function stringify(value, replacer, space) {
+ for (var
+ firstRun,
+ known = new Map,
+ input = [],
+ output = [],
+ $ = replacer && typeof replacer === typeof input ?
+ function (k, v) {
+ if (k === '' || -1 < replacer.indexOf(k)) return v;
+ } :
+ (replacer || noop),
+ i = +set(known, input, $.call({'': value}, '', value)),
+ replace = function (key, value) {
+ if (firstRun) {
+ firstRun = !firstRun;
+ return value;
+ }
+ var after = $.call(this, key, value);
+ switch (typeof after) {
+ case 'object':
+ if (after === null) return after;
+ case primitive:
+ return known.get(after) || set(known, input, after);
+ }
+ return after;
+ };
+ i < input.length; i++
+ ) {
+ firstRun = true;
+ output[i] = JSON.stringify(input[i], replace, space);
+ }
+ return '[' + output.join(',') + ']';
+ }
+
+ };
+
+ return Flatted;
+
+ function noop(key, value) {
+ return value;
+ }
+
+ function revive(input, parsed, output, $) {
+ return Object.keys(output).reduce(
+ function (output, key) {
+ var value = output[key];
+ if (value instanceof Primitive) {
+ var tmp = input[value];
+ if (typeof tmp === 'object' && !parsed.has(tmp)) {
+ parsed.add(tmp);
+ output[key] = $.call(output, key, revive(input, parsed, tmp, $));
+ } else {
+ output[key] = $.call(output, key, tmp);
+ }
+ } else
+ output[key] = $.call(output, key, value);
+ return output;
+ },
+ output
+ );
+ }
+
+ function set(known, input, value) {
+ var index = Primitive(input.push(value) - 1);
+ known.set(value, index);
+ return index;
+ }
+
+ // the two kinds of primitives
+ // 1. the real one
+ // 2. the wrapped one
+
+ function primitives(value) {
+ return value instanceof Primitive ? Primitive(value) : value;
+ }
+
+ function Primitives(key, value) {
+ return typeof value === primitive ? new Primitive(value) : value;
+ }
+
+}(String, 'string'));