pax_global_header00006660000000000000000000000064143214514240014512gustar00rootroot0000000000000052 comment=d26197e6c6357c9f3deec052a97056359f0497ac jsonify-0.0.1/000077500000000000000000000000001432145142400131715ustar00rootroot00000000000000jsonify-0.0.1/.eslintrc000066400000000000000000000007731432145142400150240ustar00rootroot00000000000000{ "root": true, "extends": "@ljharb", "rules": { "complexity": 0, "consistent-return": 1, "func-style": [2, "declaration"], "max-depth": 1, "max-lines-per-function": 0, "max-statements": 0, "multiline-comment-style": 0, "no-control-regex": 1, "no-misleading-character-class": 1, "no-restricted-syntax": 1, "no-throw-literal": 0, "no-unmodified-loop-condition": 0, "sort-keys": 0, }, } jsonify-0.0.1/.github/000077500000000000000000000000001432145142400145315ustar00rootroot00000000000000jsonify-0.0.1/.github/FUNDING.yml000066400000000000000000000011021432145142400163400ustar00rootroot00000000000000# These are supported funding model platforms github: [ljharb] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: npm/jsonify community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] jsonify-0.0.1/.github/workflows/000077500000000000000000000000001432145142400165665ustar00rootroot00000000000000jsonify-0.0.1/.github/workflows/node-aught.yml000066400000000000000000000005161432145142400213460ustar00rootroot00000000000000name: 'Tests: node.js < 10' on: [pull_request, push] jobs: tests: uses: ljharb/actions/.github/workflows/node.yml@main with: range: '< 10' type: minors command: npm run tests-only node: name: 'node < 10' needs: [tests] runs-on: ubuntu-latest steps: - run: 'echo tests completed' jsonify-0.0.1/.github/workflows/node-pretest.yml000066400000000000000000000002061432145142400217200ustar00rootroot00000000000000name: 'Tests: pretest/posttest' on: [pull_request, push] jobs: tests: uses: ljharb/actions/.github/workflows/pretest.yml@main jsonify-0.0.1/.github/workflows/node-tens.yml000066400000000000000000000005211432145142400212030ustar00rootroot00000000000000name: 'Tests: node.js >= 10' on: [pull_request, push] jobs: tests: uses: ljharb/actions/.github/workflows/node.yml@main with: range: '>= 10' type: minors command: npm run tests-only node: name: 'node >= 10' needs: [tests] runs-on: ubuntu-latest steps: - run: 'echo tests completed' jsonify-0.0.1/.github/workflows/rebase.yml000066400000000000000000000004111432145142400205460ustar00rootroot00000000000000name: Automatic Rebase on: [pull_request_target] jobs: _: name: "Automatic Rebase" runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: ljharb/rebase@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} jsonify-0.0.1/.github/workflows/require-allow-edits.yml000066400000000000000000000003031432145142400232030ustar00rootroot00000000000000name: Require “Allow Edits” on: [pull_request_target] jobs: _: name: "Require “Allow Edits”" runs-on: ubuntu-latest steps: - uses: ljharb/require-allow-edits@main jsonify-0.0.1/.gitignore000066400000000000000000000001721432145142400151610ustar00rootroot00000000000000# gitignore node_modules/ # Only apps should have lockfiles npm-shrinkwrap.json package-lock.json yarn.lock .npmignore jsonify-0.0.1/.npmrc000066400000000000000000000000671432145142400143140ustar00rootroot00000000000000package-lock=false allow-same-version=true message=v%s jsonify-0.0.1/CHANGELOG.md000066400000000000000000000106531432145142400150070ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [v0.0.1](https://github.com/ljharb/jsonify/compare/v0.0.0...v0.0.1) - 2022-10-11 ### Commits - [eslint] fix indentation [`1c92797`](https://github.com/ljharb/jsonify/commit/1c92797745b21701242c14f53308d5edfef54025) - [eslint] add eslint [`6a05332`](https://github.com/ljharb/jsonify/commit/6a05332907827cdf79a515911aec6e12625f8c5c) - [readme] rename, add badges, soft-wrap [`cb1bd1a`](https://github.com/ljharb/jsonify/commit/cb1bd1a464733b27acd4e42062bb47f04e4e8064) - [actions] add reusable workflows [`49710ae`](https://github.com/ljharb/jsonify/commit/49710aef8d4a92178cab79015c487e83e2211a37) - [eslint] use function decls, but avoid relying on hoisting [`dcba2f4`](https://github.com/ljharb/jsonify/commit/dcba2f47667ca9c77fd3ce97f0c8cfa50d66a371) - [Tests] switch to `tape` [`d31aaa0`](https://github.com/ljharb/jsonify/commit/d31aaa075e57b13587d81d5c08dede3ec3cd8438) - [meta] add `auto-changelog` [`474188e`](https://github.com/ljharb/jsonify/commit/474188e42a5074cd43038e9f57c90e88708c3633) - using travis [`7064ab5`](https://github.com/ljharb/jsonify/commit/7064ab53e5f73fa31e2ce7aa47d210c539662f16) - [Refactor] `parse`: move fn comments outside of the fn body [`78f111a`](https://github.com/ljharb/jsonify/commit/78f111a8d8810d14a732a6395787b1ff5a2f899f) - [meta] create FUNDING.yml; add `funding` in package.json [`98db8e1`](https://github.com/ljharb/jsonify/commit/98db8e1d0793f57308fcda823c568f47e90702a1) - [meta] use `npmignore` to autogenerate an npmignore file [`1732b45`](https://github.com/ljharb/jsonify/commit/1732b4537dd952a04bee290310caed6b5fd3ade7) - [meta] update URLs [`26ded36`](https://github.com/ljharb/jsonify/commit/26ded3613780aeb41f802f4cf98e3337ac3e783d) - install notes [`57daaee`](https://github.com/ljharb/jsonify/commit/57daaeeb1c2d7a183cfc32727d5b447a3268c533) - Only apps should have lockfiles [`1f25819`](https://github.com/ljharb/jsonify/commit/1f2581918edc11f55fac1be574a695444eff0d58) - [meta] add `safe-publish-latest` [`8f3ef5e`](https://github.com/ljharb/jsonify/commit/8f3ef5e90262167420d71f08fe50a568499563d6) - [Tests] add `aud` in `posttest` [`4c64711`](https://github.com/ljharb/jsonify/commit/4c64711da1a2c3c20c0c27e4f6d18f61c94df223) - Update tap. [`8cf38a6`](https://github.com/ljharb/jsonify/commit/8cf38a62f34dd05c812829c6d0a9ee1a9486dc8a) - fix broken browserify link [`9dc7744`](https://github.com/ljharb/jsonify/commit/9dc77442cc375823640f13086d5737fdd918bccf) ## v0.0.0 - 2011-08-21 ### Commits - first commit [`11c7bdf`](https://github.com/ljharb/jsonify/commit/11c7bdf47c3f21b014b1e984be52211142d8d8b7) - the recursive descent parser is the fastest, going with it [`9210504`](https://github.com/ljharb/jsonify/commit/92105047b01811d216777d1b260373431b406f53) - took out unnecessary functions from json.js, only stringify-related stuff remain [`99a8b65`](https://github.com/ljharb/jsonify/commit/99a8b6580af5dedebb39db18127c671b405c26d3) - fix parse by removing another callback of indirection [`10e1b96`](https://github.com/ljharb/jsonify/commit/10e1b96b535cd66c0aee768aa6dbfc9778e87dbf) - Hygiene [`633fe5a`](https://github.com/ljharb/jsonify/commit/633fe5ae4bd69985254a68ae111505ec3d3e74ab) - a package.json [`5258ce2`](https://github.com/ljharb/jsonify/commit/5258ce240702c78f4affffdc3ea2e095ad04f49f) - pared down parse.js [`40d8617`](https://github.com/ljharb/jsonify/commit/40d86179553cc972b465c2446f58a7ecda1f24ce) - Style conformance. [`ad6079c`](https://github.com/ljharb/jsonify/commit/ad6079cbd8dc362a3cc42e1f97c01aa5ccd48bfe) - forgot the readme and index.js [`69d3062`](https://github.com/ljharb/jsonify/commit/69d306269813548103c027df972d960d1b439eef) - stringify test using garbage passes [`29db45f`](https://github.com/ljharb/jsonify/commit/29db45f4cd72dca91052baf744656d9561716f55) - parse test passes too hooray [`d58c20e`](https://github.com/ljharb/jsonify/commit/d58c20ee3e2550490bfb5380ad1b0c085ee12e02) - Create a JSON object only if one does not already exist. [`8d11dc6`](https://github.com/ljharb/jsonify/commit/8d11dc6950eafc7d01f141ce91d4f585caa29f3b) - !isFinite [`8e0b15c`](https://github.com/ljharb/jsonify/commit/8e0b15cb492f63067a88ad786e4d5fc0fa89a241) - move into lib [`006d2aa`](https://github.com/ljharb/jsonify/commit/006d2aaf373382b95801964d5b6505d9b79b3a16) jsonify-0.0.1/README.md000066400000000000000000000046261432145142400144600ustar00rootroot00000000000000# jsonify [![Version Badge][npm-version-svg]][package-url] [![github actions][actions-image]][actions-url] [![coverage][codecov-image]][codecov-url] [![License][license-image]][license-url] [![Downloads][downloads-image]][downloads-url] [![npm badge][npm-badge-png]][package-url] This module provides Douglas Crockford's JSON implementation without modifying any globals. `stringify` and `parse` are merely exported without respect to whether or not a global `JSON` object exists. [![build status](https://secure.travis-ci.org/ljharb/jsonify.png)](https://travis-ci.org/ljharb/jsonify) # methods ``` js var json = require('jsonify'); ``` ## json.parse(source, reviver) Return a new javascript object from a parse of the `source` string. If a `reviver` function is specified, walk the structure passing each name/value pair to `reviver.call(parent, key, value)` to transform the `value` before parsing it. ## json.stringify(value, replacer, space) Return a string representation for `value`. If `replacer` is specified, walk the structure passing each name/value pair to `replacer.call(parent, key, value)` to transform the `value` before stringifying it. If `space` is a number, indent the result by that many spaces. If `space` is a string, use `space` as the indentation. # install With [npm](https://npmjs.org) do: ``` npm install jsonify ``` To use this module in the browser, check out [browserify](https://github.com/browserify/browserify). # license public domain [package-url]: https://npmjs.org/package/jsonify [npm-version-svg]: https://versionbadg.es/ljharb/jsonify.svg [deps-svg]: https://david-dm.org/ljharb/jsonify.svg [deps-url]: https://david-dm.org/ljharb/jsonify [dev-deps-svg]: https://david-dm.org/ljharb/jsonify/dev-status.svg [dev-deps-url]: https://david-dm.org/ljharb/jsonify#info=devDependencies [npm-badge-png]: https://nodei.co/npm/jsonify.png?downloads=true&stars=true [license-image]: https://img.shields.io/npm/l/jsonify.svg [license-url]: LICENSE [downloads-image]: https://img.shields.io/npm/dm/jsonify.svg [downloads-url]: https://npm-stat.com/charts.html?package=jsonify [codecov-image]: https://codecov.io/gh/ljharb/jsonify/branch/main/graphs/badge.svg [codecov-url]: https://app.codecov.io/gh/ljharb/jsonify/ [actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/jsonify [actions-url]: https://github.com/ljharb/jsonify/actions jsonify-0.0.1/index.js000066400000000000000000000001471432145142400146400ustar00rootroot00000000000000'use strict'; exports.parse = require('./lib/parse'); exports.stringify = require('./lib/stringify'); jsonify-0.0.1/lib/000077500000000000000000000000001432145142400137375ustar00rootroot00000000000000jsonify-0.0.1/lib/parse.js000066400000000000000000000110471432145142400154120ustar00rootroot00000000000000'use strict'; var at; // The index of the current character var ch; // The current character var escapee = { '"': '"', '\\': '\\', '/': '/', b: '\b', f: '\f', n: '\n', r: '\r', t: '\t' }; var text; // Call error when something is wrong. function error(m) { throw { name: 'SyntaxError', message: m, at: at, text: text }; } function next(c) { // If a c parameter is provided, verify that it matches the current character. if (c && c !== ch) { error("Expected '" + c + "' instead of '" + ch + "'"); } // Get the next character. When there are no more characters, return the empty string. ch = text.charAt(at); at += 1; return ch; } function number() { // Parse a number value. var num; var str = ''; if (ch === '-') { str = '-'; next('-'); } while (ch >= '0' && ch <= '9') { str += ch; next(); } if (ch === '.') { str += '.'; while (next() && ch >= '0' && ch <= '9') { str += ch; } } if (ch === 'e' || ch === 'E') { str += ch; next(); if (ch === '-' || ch === '+') { str += ch; next(); } while (ch >= '0' && ch <= '9') { str += ch; next(); } } num = Number(str); if (!isFinite(num)) { error('Bad number'); } return num; } function string() { // Parse a string value. var hex; var i; var str = ''; var uffff; // When parsing for string values, we must look for " and \ characters. if (ch === '"') { while (next()) { if (ch === '"') { next(); return str; } else if (ch === '\\') { next(); if (ch === 'u') { uffff = 0; for (i = 0; i < 4; i += 1) { hex = parseInt(next(), 16); if (!isFinite(hex)) { break; } uffff = (uffff * 16) + hex; } str += String.fromCharCode(uffff); } else if (typeof escapee[ch] === 'string') { str += escapee[ch]; } else { break; } } else { str += ch; } } } error('Bad string'); } // Skip whitespace. function white() { while (ch && ch <= ' ') { next(); } } // true, false, or null. function word() { switch (ch) { case 't': next('t'); next('r'); next('u'); next('e'); return true; case 'f': next('f'); next('a'); next('l'); next('s'); next('e'); return false; case 'n': next('n'); next('u'); next('l'); next('l'); return null; default: error("Unexpected '" + ch + "'"); } } // Parse an array value. function array() { var arr = []; if (ch === '[') { next('['); white(); if (ch === ']') { next(']'); return arr; // empty array } while (ch) { arr.push(value()); // eslint-disable-line no-use-before-define white(); if (ch === ']') { next(']'); return arr; } next(','); white(); } } error('Bad array'); } // Parse an object value. function object() { var key; var obj = {}; if (ch === '{') { next('{'); white(); if (ch === '}') { next('}'); return obj; // empty object } while (ch) { key = string(); white(); next(':'); if (Object.prototype.hasOwnProperty.call(obj, key)) { error('Duplicate key "' + key + '"'); } obj[key] = value(); // eslint-disable-line no-use-before-define white(); if (ch === '}') { next('}'); return obj; } next(','); white(); } } error('Bad object'); } // Parse a JSON value. It could be an object, an array, a string, a number, or a word. function value() { white(); switch (ch) { case '{': return object(); case '[': return array(); case '"': return string(); case '-': return number(); default: return ch >= '0' && ch <= '9' ? number() : word(); } } // Return the json_parse function. It will have access to all of the above functions and variables. module.exports = function (source, reviver) { var result; text = source; at = 0; ch = ' '; result = value(); white(); if (ch) { error('Syntax error'); } // If there is a reviver function, we recursively walk the new structure, // passing each name/value pair to the reviver function for possible // transformation, starting with a temporary root object that holds the result // in an empty key. If there is not a reviver function, we simply return the // result. return typeof reviver === 'function' ? (function walk(holder, key) { var k; var v; var val = holder[key]; if (val && typeof val === 'object') { for (k in value) { if (Object.prototype.hasOwnProperty.call(val, k)) { v = walk(val, k); if (typeof v === 'undefined') { delete val[k]; } else { val[k] = v; } } } } return reviver.call(holder, key, val); }({ '': result }, '')) : result; }; jsonify-0.0.1/lib/stringify.js000066400000000000000000000103221432145142400163110ustar00rootroot00000000000000'use strict'; var escapable = /[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; var gap; var indent; var meta = { // table of character substitutions '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"': '\\"', '\\': '\\\\' }; var rep; function quote(string) { // If the string contains no control characters, no quote characters, and no // backslash characters, then we can safely slap some quotes around it. // Otherwise we must also replace the offending characters with safe escape sequences. escapable.lastIndex = 0; return escapable.test(string) ? '"' + string.replace(escapable, function (a) { var c = meta[a]; return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }) + '"' : '"' + string + '"'; } function str(key, holder) { // Produce a string from holder[key]. var i; // The loop counter. var k; // The member key. var v; // The member value. var length; var mind = gap; var partial; var value = holder[key]; // If the value has a toJSON method, call it to obtain a replacement value. if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } // If we were called with a replacer function, then call the replacer to obtain a replacement value. if (typeof rep === 'function') { value = rep.call(holder, key, value); } // What happens next depends on the value's type. switch (typeof value) { case 'string': return quote(value); case 'number': // JSON numbers must be finite. Encode non-finite numbers as null. return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': // If the value is a boolean or null, convert it to a string. Note: // typeof null does not produce 'null'. The case is included here in // the remote chance that this gets fixed someday. return String(value); case 'object': if (!value) { return 'null'; } gap += indent; partial = []; // Array.isArray if (Object.prototype.toString.apply(value) === '[object Array]') { length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; } // Join all of the elements together, separated with commas, and wrap them in brackets. v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v; } // If the replacer is an array, use it to select the members to be stringified. if (rep && typeof rep === 'object') { length = rep.length; for (i = 0; i < length; i += 1) { k = rep[i]; if (typeof k === 'string') { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } else { // Otherwise, iterate through all of the keys in the object. for (k in value) { if (Object.prototype.hasOwnProperty.call(value, k)) { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } // Join all of the member texts together, separated with commas, and wrap them in braces. v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v; default: } } module.exports = function (value, replacer, space) { var i; gap = ''; indent = ''; // If the space parameter is a number, make an indent string containing that many spaces. if (typeof space === 'number') { for (i = 0; i < space; i += 1) { indent += ' '; } } else if (typeof space === 'string') { // If the space parameter is a string, it will be used as the indent string. indent = space; } // If there is a replacer, it must be a function or an array. Otherwise, throw an error. rep = replacer; if ( replacer && typeof replacer !== 'function' && (typeof replacer !== 'object' || typeof replacer.length !== 'number') ) { throw new Error('JSON.stringify'); } // Make a fake root object containing our value under the key of ''. // Return the result of stringifying the value. return str('', { '': value }); }; jsonify-0.0.1/package.json000066400000000000000000000030261432145142400154600ustar00rootroot00000000000000{ "name": "jsonify", "version": "0.0.1", "description": "JSON without touching any globals", "main": "index.js", "directories": { "lib": ".", "test": "test" }, "devDependencies": { "@ljharb/eslint-config": "^21.0.0", "aud": "^2.0.1", "auto-changelog": "^2.4.0", "eslint": "=8.8.0", "garbage": "0.0.x", "in-publish": "^2.0.1", "npmignore": "^0.3.0", "safe-publish-latest": "^2.0.0", "tape": "^5.6.1" }, "scripts": { "prepack": "npmignore --auto --commentLines=autogenerated", "prepublishOnly": "safe-publish-latest", "prepublish": "not-in-publish || npm run prepublishOnly", "lint": "eslint --ext=js,mjs .", "pretest": "npm run lint", "tests-only": "tape 'test/**/*.js'", "test": "npm run tests-only", "posttest": "aud --production", "version": "auto-changelog && git add CHANGELOG.md", "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" }, "repository": { "type": "git", "url": "https://github.com/ljharb/jsonify.git" }, "keywords": [ "json", "browser" ], "author": { "name": "Douglas Crockford", "url": "https://crockford.com/" }, "funding": { "url": "https://github.com/sponsors/ljharb" }, "license": "Public Domain", "auto-changelog": { "output": "CHANGELOG.md", "template": "keepachangelog", "unreleased": false, "commitLimit": false, "backfillLimit": false, "hideCredit": true }, "publishConfig": { "ignore": [ ".github/workflows" ] } } jsonify-0.0.1/test/000077500000000000000000000000001432145142400141505ustar00rootroot00000000000000jsonify-0.0.1/test/parse.js000066400000000000000000000005241432145142400156210ustar00rootroot00000000000000'use strict'; var test = require('tape'); var json = require('../'); var garbage = require('garbage'); test('parse', function (t) { for (var i = 0; i < 50; i++) { var s = JSON.stringify(garbage(50)); t.deepEqual( json.parse(s), JSON.parse(s), 'comparing JSON.parse to jsonify.parse: run ' + (i + 1) ); } t.end(); }); jsonify-0.0.1/test/stringify.js000066400000000000000000000005301432145142400165220ustar00rootroot00000000000000'use strict'; var test = require('tape'); var json = require('../'); var garbage = require('garbage'); test('stringify', function (t) { for (var i = 0; i < 50; i++) { var obj = garbage(50); t.equal( json.stringify(obj), JSON.stringify(obj), 'comparing JSON.stringify to jsonify.stringify: run ' + (i + 1) ); } t.end(); });