├── .github └── workflows │ └── main.yml ├── .gitignore ├── .nlint.json ├── LICENSE ├── README.md ├── build ├── lint.js └── test.js ├── demo ├── .nlint.json ├── index.html ├── jquery-1.4.2.js ├── jquery-linedtextarea.css ├── jquery-linedtextarea.js ├── js.js └── styles.css ├── jsonlint.js ├── package-lock.json ├── package.json └── test ├── .nlint.json ├── files ├── json │ ├── .nlint.json │ ├── .nodelint.json │ ├── Numeric.json │ ├── comments.json │ ├── empty.json │ ├── endofarray.json │ ├── multi-comment.json │ ├── multi-object.json │ ├── nested.json │ ├── nocomments.json │ ├── nomulticomment.json │ ├── pit.json │ ├── string.json │ └── strings.json └── test-files.js ├── munit.js ├── test-clean.js └── test-invalid.js /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | node-version: [16.x, 18.x, 19.x] 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Node.js ${{ matrix.node-version }} 18 | uses: actions/setup-node@v3 19 | with: 20 | node-version: ${{ matrix.node-version }} 21 | - run: yarn install 22 | - run: yarn test 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/results/ 3 | -------------------------------------------------------------------------------- /.nlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": [ 3 | ".git/", 4 | "node_modules/", 5 | "bin/", 6 | "demo/jquery-linedtextarea.js", 7 | "demo/jquery-1.4.2.js" 8 | ], 9 | "linters": { 10 | "jshint": { 11 | "boss": true, 12 | "node": true, 13 | "undef": true 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2011-present Corey Hart 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![NPM version](https://badge.fury.io/js/jsonlint.png)](http://badge.fury.io/js/jsonlint) ![Test Runner](https://github.com/codenothing/jsonlint/actions/workflows/main.yml/badge.svg) [![Code Climate](https://codeclimate.com/github/codenothing/jsonlint.png)](https://codeclimate.com/github/codenothing/jsonlint) 2 | 3 | # JSONLint 4 | 5 | JSONLint is a JSON Linter that allows for comments in your JSON Files. 6 | 7 | ## Installation 8 | 9 | For use with NodeJS, use NPM 10 | 11 | ```bash 12 | $ npm install -g json-lint 13 | ``` 14 | 15 | For use in browser environments, include the script tag 16 | 17 | ```html 18 | 19 | ``` 20 | 21 | ## Usage 22 | 23 | ```js 24 | // Require it for NodeJS environment 25 | var JSONLint = require("json-lint"); 26 | 27 | // Run the JSON string through the linter 28 | var lint = JSONLint(json, options); 29 | 30 | // Do something with the error 31 | if (lint.error) { 32 | lint.error; // Error Message 33 | lint.line; // Line number in json file where error was found 34 | lint.character; // Character of line in json file where error was found 35 | } 36 | ``` 37 | 38 | JSONLint takes two arguments, and throws an error if found. 39 | 40 | - _string_ **json**: JSON String to be linted 41 | 42 | - _object_ **options**: Object of options. 43 | 44 | ## Options 45 | 46 | There is currently only 1 option that is handled: **comments**, which defaults to true if not set. 47 | -------------------------------------------------------------------------------- /build/lint.js: -------------------------------------------------------------------------------- 1 | require( 'nlint' ).render( __dirname + '/../' ); 2 | -------------------------------------------------------------------------------- /build/test.js: -------------------------------------------------------------------------------- 1 | var munit = global.munit = require( 'munit' ); 2 | 3 | // Only stop test suite when running make test 4 | if ( ! process.env.NODE_TEST_NO_SKIP ) { 5 | munit.defaults.settings.stopOnFail = true; 6 | } 7 | 8 | munit.render( __dirname + '/../test/', { 9 | results: __dirname + '/results/' 10 | }); 11 | -------------------------------------------------------------------------------- /demo/.nlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "linters": { 3 | "jshint": { 4 | "node": false, 5 | "browser": true, 6 | "predef": { 7 | "jQuery": false 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JSONLint 0.1.0: JSON Lint with comments 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |

JSONLint 0.1.0

16 | 17 | 18 | Allow Comments 19 |
20 |
21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /demo/jquery-linedtextarea.css: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Lined Textarea Plugin 3 | * http://alan.blog-city.com/jquerylinedtextarea.htm 4 | * 5 | * Copyright (c) 2010 Alan Williamson 6 | * 7 | * Released under the MIT License: 8 | * http://www.opensource.org/licenses/mit-license.php 9 | * 10 | * Usage: 11 | * Displays a line number count column to the left of the textarea 12 | * 13 | * Class up your textarea with a given class, or target it directly 14 | * with JQuery Selectors 15 | * 16 | * $(".lined").linedtextarea({ 17 | * selectedLine: 10, 18 | * selectedClass: 'lineselect' 19 | * }); 20 | * 21 | */ 22 | 23 | .linedwrap { 24 | border: 1px solid #c0c0c0; 25 | padding: 3px; 26 | } 27 | 28 | .linedtextarea { 29 | padding: 0px; 30 | margin: 0px; 31 | } 32 | 33 | .linedtextarea textarea, .linedwrap .codelines .lineno { 34 | font-size: 9pt; 35 | font-family: monospace; 36 | line-height: normal !important; 37 | } 38 | 39 | .linedtextarea textarea { 40 | padding-right:0.3em; 41 | padding-top:0.3em; 42 | border: 0; 43 | } 44 | 45 | .linedwrap .lines { 46 | margin-top: 0px; 47 | width: 50px; 48 | float: left; 49 | overflow: hidden; 50 | border-right: 1px solid #c0c0c0; 51 | margin-right: 10px; 52 | } 53 | 54 | .linedwrap .codelines { 55 | padding-top: 5px; 56 | } 57 | 58 | .linedwrap .codelines .lineno { 59 | color:#AAAAAA; 60 | padding-right: 0.5em; 61 | padding-top: 0.0em; 62 | text-align: right; 63 | white-space: nowrap; 64 | } 65 | 66 | .linedwrap .codelines .lineselect { 67 | color: red; 68 | } 69 | -------------------------------------------------------------------------------- /demo/jquery-linedtextarea.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Lined Textarea Plugin 3 | * http://alan.blog-city.com/jquerylinedtextarea.htm 4 | * 5 | * Copyright (c) 2010 Alan Williamson 6 | * 7 | * Version: 8 | * $Id: jquery-linedtextarea.js 464 2010-01-08 10:36:33Z alan $ 9 | * 10 | * Released under the MIT License: 11 | * http://www.opensource.org/licenses/mit-license.php 12 | * 13 | * Usage: 14 | * Displays a line number count column to the left of the textarea 15 | * 16 | * Class up your textarea with a given class, or target it directly 17 | * with JQuery Selectors 18 | * 19 | * $(".lined").linedtextarea({ 20 | * selectedLine: 10, 21 | * selectedClass: 'lineselect' 22 | * }); 23 | * 24 | * History: 25 | * - 2010.01.08: Fixed a Google Chrome layout problem 26 | * - 2010.01.07: Refactored code for speed/readability; Fixed horizontal sizing 27 | * - 2010.01.06: Initial Release 28 | * 29 | */ 30 | (function($) { 31 | 32 | $.fn.linedtextarea = function(options) { 33 | 34 | // Get the Options 35 | var opts = $.extend({}, $.fn.linedtextarea.defaults, options); 36 | 37 | 38 | /* 39 | * Helper function to make sure the line numbers are always 40 | * kept up to the current system 41 | */ 42 | var fillOutLines = function(codeLines, h, lineNo){ 43 | while ( (codeLines.height() - h ) <= 0 ){ 44 | if ( lineNo == opts.selectedLine ) 45 | codeLines.append("
" + lineNo + "
"); 46 | else 47 | codeLines.append("
" + lineNo + "
"); 48 | 49 | lineNo++; 50 | } 51 | return lineNo; 52 | }; 53 | 54 | 55 | /* 56 | * Iterate through each of the elements are to be applied to 57 | */ 58 | return this.each(function() { 59 | var lineNo = 1; 60 | var textarea = $(this); 61 | 62 | /* Turn off the wrapping of as we don't want to screw up the line numbers */ 63 | textarea.attr("wrap", "off"); 64 | textarea.css({resize:'none'}); 65 | var originalTextAreaWidth = textarea.outerWidth(); 66 | 67 | /* Wrap the text area in the elements we need */ 68 | textarea.wrap("
"); 69 | var linedTextAreaDiv = textarea.parent().wrap("
"); 70 | var linedWrapDiv = linedTextAreaDiv.parent(); 71 | 72 | linedWrapDiv.prepend("
"); 73 | 74 | var linesDiv = linedWrapDiv.find(".lines"); 75 | linesDiv.height( textarea.height() + 6 ); 76 | 77 | 78 | /* Draw the number bar; filling it out where necessary */ 79 | linesDiv.append( "
" ); 80 | var codeLinesDiv = linesDiv.find(".codelines"); 81 | lineNo = fillOutLines( codeLinesDiv, linesDiv.height(), 1 ); 82 | 83 | /* Move the textarea to the selected line */ 84 | if ( opts.selectedLine != -1 && !isNaN(opts.selectedLine) ){ 85 | var fontSize = parseInt( textarea.height() / (lineNo-2) ); 86 | var position = parseInt( fontSize * opts.selectedLine ) - (textarea.height()/2); 87 | textarea[0].scrollTop = position; 88 | } 89 | 90 | 91 | /* Set the width */ 92 | var sidebarWidth = linesDiv.outerWidth(); 93 | var paddingHorizontal = parseInt( linedWrapDiv.css("border-left-width"), 10 ) + 94 | parseInt( linedWrapDiv.css("border-right-width"), 10 ) + 95 | parseInt( linedWrapDiv.css("padding-left"), 10 ) + 96 | parseInt( linedWrapDiv.css("padding-right"), 10 ); 97 | var linedWrapDivNewWidth = originalTextAreaWidth - paddingHorizontal; 98 | var textareaNewWidth = originalTextAreaWidth - sidebarWidth - paddingHorizontal - 20; 99 | 100 | textarea.width( textareaNewWidth ); 101 | linedWrapDiv.width( linedWrapDivNewWidth ); 102 | 103 | 104 | 105 | /* React to the scroll event */ 106 | textarea.scroll( function(tn){ 107 | var domTextArea = $(this)[0]; 108 | var scrollTop = domTextArea.scrollTop; 109 | var clientHeight = domTextArea.clientHeight; 110 | codeLinesDiv.css( {'margin-top': (-1*scrollTop) + "px"} ); 111 | lineNo = fillOutLines( codeLinesDiv, scrollTop + clientHeight, lineNo ); 112 | }); 113 | 114 | 115 | /* Should the textarea get resized outside of our control */ 116 | textarea.resize( function(tn){ 117 | var domTextArea = $(this)[0]; 118 | linesDiv.height( domTextArea.clientHeight + 6 ); 119 | }); 120 | }); 121 | }; 122 | 123 | // default options 124 | $.fn.linedtextarea.defaults = { 125 | selectedLine: -1, 126 | selectedClass: 'lineselect' 127 | }; 128 | })(jQuery); 129 | -------------------------------------------------------------------------------- /demo/js.js: -------------------------------------------------------------------------------- 1 | jQuery(function(){ 2 | var textarea = jQuery('textarea').linedtextarea(), 3 | wrapper = jQuery('.linedwrap'), 4 | results = jQuery('#results'), 5 | comments = jQuery('input[type=checkbox]')[ 0 ], 6 | lint; 7 | 8 | jQuery('button').click(function(){ 9 | wrapper.removeClass('error').removeClass('success'); 10 | results.removeClass('error').removeClass('success'); 11 | lint = window.JSONLint( textarea.val(), { comments: comments.checked } ); 12 | 13 | if ( ! lint.error ) { 14 | wrapper.addClass('success'); 15 | results.addClass('success').html( 'Valid JSON.' ); 16 | } 17 | else { 18 | wrapper.addClass('error'); 19 | results.addClass('error').html([ 20 | lint.error + "
" + 21 | "Evidence: " + lint.evidence + "
" + 22 | "Line: " + lint.line + "
" + 23 | "Character: " + lint.character 24 | ].join('')); 25 | } 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /demo/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 12pt; 3 | } 4 | 5 | #content { 6 | width: 950px; 7 | margin: 20px auto; 8 | } 9 | 10 | .linedwrap.success { 11 | border: 2px solid green; 12 | } 13 | 14 | .linedwrap.error { 15 | border: 2px solid red; 16 | } 17 | 18 | textarea { 19 | width: 950px; 20 | height: 400px; 21 | font-size: 10pt; 22 | } 23 | 24 | button { 25 | padding: 5px 9px; 26 | margin: 5px 0; 27 | border: 1px solid #e1e1e1; 28 | background: #f5f5f5; 29 | } 30 | 31 | #results { 32 | padding: 10px; 33 | margin: 10px 0; 34 | } 35 | 36 | #results.success { 37 | background: #c9ffc7; 38 | } 39 | 40 | #results.error { 41 | background: #ffc7c7; 42 | } 43 | -------------------------------------------------------------------------------- /jsonlint.js: -------------------------------------------------------------------------------- 1 | (function( glob, undefined ) { 2 | 3 | var rnumber = /[0-9]/, 4 | rnewline = /(\r\n|\r|\n)/, 5 | revidence = /\r\n|\r|\n/, 6 | rwhitespace = /(\s|\t)/, 7 | rvalidsolidus = /\\("|\\|\/|b|f|n|r|t|u[0-9]{4})/, 8 | rE = /^(\-|\+)?[0-9]/; 9 | 10 | 11 | // Leeeeeeerrrrroooyy Jennkkkiiinnnss 12 | function JSONLint( json, options ) { 13 | var self = this; 14 | 15 | if ( ! ( self instanceof JSONLint ) ) { 16 | return new JSONLint( json, options ); 17 | } 18 | 19 | // Argument handling 20 | self.json = json || ''; 21 | self.options = options || {}; 22 | self.lower = self.json.toLowerCase(); 23 | 24 | // Allow comments by default 25 | if ( ! self.options.hasOwnProperty( 'comments' ) ) { 26 | self.options.comments = true; 27 | } 28 | 29 | // Internals 30 | self.c = ''; 31 | self.i = -1; 32 | self.length = self.json.length; 33 | self.line = 1; 34 | self.character = 0; 35 | self._evidence = self.json.split( revidence ); 36 | self.endblock = ''; 37 | self.commabreak = false; 38 | 39 | try { 40 | self.render(); 41 | } catch ( e ) { 42 | if ( typeof e != 'string' ) { 43 | throw e; 44 | } 45 | self.error = e; 46 | self.setEvidence(); 47 | } 48 | } 49 | 50 | 51 | // Meta (Please change contact info for republishing with changes) 52 | JSONLint.contact = "Corey Hart (corey@codenothing.com)"; 53 | JSONLint.version = '0.1.1'; 54 | 55 | 56 | // Methods 57 | JSONLint.prototype = { 58 | 59 | // Rendering Start 60 | render: function(){ 61 | var self = this, peek = '', content = false; 62 | 63 | for ( ; ++self.i < self.length; ) { 64 | self.c = self.json[ self.i ]; 65 | self.character++; 66 | 67 | if ( self.options.comments && self.c == '/' ) { 68 | peek = self.json[ self.i + 1 ]; 69 | if ( peek == '*' ) { 70 | self.multicomment(); 71 | } 72 | else if ( peek == '/' ) { 73 | self.comment(); 74 | } 75 | else { 76 | throw "Unknown character '/', maybe a comment?"; 77 | } 78 | } 79 | else if ( rnewline.exec( self.c ) ) { 80 | self.line++; 81 | self.character = 0; 82 | } 83 | else if ( rwhitespace.exec( self.c ) ) { 84 | continue; 85 | } 86 | else if ( content ) { 87 | throw "Unknown character '" + self.c + "', expecting end of file."; 88 | } 89 | else if ( self.c == '[' ) { 90 | content = true; 91 | self.array(); 92 | } 93 | else if ( self.c == '{' ) { 94 | content = true; 95 | self.object(); 96 | } 97 | else { 98 | throw "Unknown character '" + self.c + "', expecting opening block '{' or '[', or maybe a comment"; 99 | } 100 | } 101 | 102 | // Check for pure whitespace 103 | if ( ! content ) { 104 | throw "Invalid JSON, no content."; 105 | } 106 | }, 107 | 108 | // Multi line comment 109 | multicomment: function(){ 110 | var self = this; 111 | 112 | for ( ; ++self.i < self.length; ) { 113 | self.c = self.json[ self.i ]; 114 | self.character++; 115 | 116 | if ( self.c == "*" && self.json[ self.i + 1 ] == "/" ) { 117 | self.i++; 118 | self.character++; 119 | break; 120 | } 121 | else if ( rnewline.exec( self.c ) ) { 122 | self.line++; 123 | self.character = 0; 124 | } 125 | } 126 | }, 127 | 128 | // Single line comment 129 | comment: function(){ 130 | var self = this; 131 | 132 | for ( ; ++self.i < self.length; ) { 133 | self.c = self.json[ self.i ]; 134 | self.character++; 135 | 136 | if ( rnewline.exec( self.c ) ) { 137 | self.line++; 138 | self.character = 0; 139 | break; 140 | } 141 | } 142 | }, 143 | 144 | // Array Block 145 | array: function(){ 146 | // Keep reference of current endblock 147 | var self = this, 148 | _endblock = self.endblock, 149 | _commabreak = self.commabreak, 150 | ended = false; 151 | 152 | self.endblock = ']'; 153 | self.commabreak = false; 154 | while ( ( ended = self.value() ) !== true && self.i < self.length ) { 155 | // Do nothing, just wait for array values to finish 156 | } 157 | 158 | if ( ! ended ) { 159 | throw "EOF Error. Expecting closing ']'"; 160 | } 161 | 162 | // Reset previous endblock 163 | self.endblock = _endblock; 164 | self.commabreak = _commabreak; 165 | }, 166 | 167 | // Object Block 168 | object: function(){ 169 | // Keep reference of current endblock 170 | var self = this, 171 | _endblock = self.endblock, 172 | _commabreak = self.commabreak, 173 | found = false, peek = '', empty = true; 174 | 175 | self.endblock = '}'; 176 | self.commabreak = false; 177 | for ( ; ++self.i < self.length; ) { 178 | self.c = self.json[ self.i ]; 179 | self.character++; 180 | 181 | if ( self.options.comments && self.c == '/' ) { 182 | peek = self.json[ self.i + 1 ]; 183 | if ( peek == '*' ) { 184 | self.multicomment(); 185 | } 186 | else if ( peek == '/' ) { 187 | self.comment(); 188 | } 189 | else { 190 | throw "Unknown character '/', maybe a comment?"; 191 | } 192 | } 193 | else if ( rnewline.exec( self.c ) ) { 194 | self.line++; 195 | self.character = 0; 196 | } 197 | else if ( rwhitespace.exec( self.c ) ) { 198 | continue; 199 | } 200 | else if ( self.c == '"' ) { 201 | empty = false; 202 | if ( self.key() === true ) { 203 | // Reset old endblock 204 | self.endblock = _endblock; 205 | self.commabreak = _commabreak; 206 | found = true; 207 | break; 208 | } 209 | } 210 | else if ( empty && self.c == '}' ) { 211 | self.endblock = _endblock; 212 | self.commabreak = _commabreak; 213 | found = true; 214 | break; 215 | } 216 | else { 217 | throw "Unknown Character '" + self.c + "', expecting a string for key statement."; 218 | } 219 | } 220 | 221 | if ( ! found ) { 222 | throw "EOF Error, expecting closing '}'."; 223 | } 224 | }, 225 | 226 | // Key Statement 227 | key: function(){ 228 | var self = this; 229 | self.string(); 230 | 231 | for ( var peek = ''; ++self.i < self.length; ) { 232 | self.c = self.json[ self.i ]; 233 | self.character++; 234 | 235 | if ( self.options.comments && self.c == '/' ) { 236 | peek = self.json[ self.i + 1 ]; 237 | if ( peek == '*' ) { 238 | self.multicomment(); 239 | } 240 | else if ( peek == '/' ) { 241 | self.comment(); 242 | } 243 | else { 244 | throw "Unknown character '/', maybe a comment?"; 245 | } 246 | } 247 | else if ( rnewline.exec( self.c ) ) { 248 | self.line++; 249 | self.character = 0; 250 | } 251 | else if ( rwhitespace.exec( self.c ) ) { 252 | continue; 253 | } 254 | else if ( self.c == ":" ) { 255 | return self.value(); 256 | } 257 | else { 258 | throw "Unknown Character '" + self.c + "', expecting a semicolon."; 259 | } 260 | } 261 | }, 262 | 263 | // Value statement 264 | value: function(){ 265 | var self = this, peek = ''; 266 | 267 | for ( ; ++self.i < self.length; ) { 268 | self.c = self.json[ self.i ]; 269 | self.character++; 270 | 271 | if ( self.options.comments && self.c == '/' ) { 272 | peek = self.json[ self.i + 1 ]; 273 | if ( peek == '*' ) { 274 | self.multicomment(); 275 | } 276 | else if ( peek == '/' ) { 277 | self.comment(); 278 | } 279 | else { 280 | throw "Unknown character '/', maybe a comment?"; 281 | } 282 | } 283 | else if ( rnewline.exec( self.c ) ) { 284 | self.line++; 285 | self.character = 0; 286 | } 287 | else if ( rwhitespace.exec( self.c ) ) { 288 | continue; 289 | } 290 | else if ( self.c == '{' ) { 291 | self.object(); 292 | return self.endval(); 293 | } 294 | else if ( self.c == '[' ) { 295 | self.array(); 296 | return self.endval(); 297 | } 298 | else if ( self.c == '"' ) { 299 | self.string(); 300 | return self.endval(); 301 | } 302 | else if ( self.json.indexOf( 'true', self.i ) === self.i ) { 303 | self.i += 3; 304 | self.character += 3; 305 | return self.endval(); 306 | } 307 | else if ( self.json.indexOf( 'false', self.i ) === self.i ) { 308 | self.i += 4; 309 | self.character += 4; 310 | return self.endval(); 311 | } 312 | else if ( self.json.indexOf( 'null', self.i ) === self.i ) { 313 | self.i += 3; 314 | self.character += 3; 315 | return self.endval(); 316 | } 317 | else if ( self.c == '-' || rnumber.exec( self.c ) ) { 318 | return self.numeric(); 319 | } 320 | else if ( self.c == ']' && self.endblock == ']' ) { 321 | if ( self.commabreak ) { 322 | throw "Unexpected End Of Array Error. Expecting a value statement."; 323 | } 324 | return true; 325 | } 326 | else { 327 | throw "Unknown Character '" + self.c + "', expecting a value."; 328 | } 329 | } 330 | }, 331 | 332 | // String statement 333 | string: function(){ 334 | var self = this, found = false, m; 335 | 336 | for ( ; ++self.i < self.length; ) { 337 | self.c = self.json[ self.i ]; 338 | self.character++; 339 | 340 | if ( self.c == "\\" ) { 341 | if ( ( m = rvalidsolidus.exec( self.json.substr( self.i ) ) ) && m.index === 0 ) { 342 | self.i += m[ 1 ].length; 343 | self.character += m[ 1 ].length; 344 | } 345 | else { 346 | throw "Invalid Reverse Solidus '\\' declaration."; 347 | } 348 | } 349 | else if ( rnewline.exec( self.c ) ) { 350 | self.line++; 351 | self.character = 0; 352 | } 353 | else if ( self.c == '"' ) { 354 | found = true; 355 | break; 356 | } 357 | } 358 | 359 | // Make sure close string is found 360 | if ( ! found ) { 361 | throw "EOF: No close string '\"' found."; 362 | } 363 | }, 364 | 365 | // Numeric Value 366 | numeric: function(){ 367 | var self = this, 368 | negative = true, 369 | decimal = null, 370 | e = null, 371 | peek = ''; 372 | 373 | // We need to jump back a character to catch the whole number 374 | self.i--; 375 | self.character--; 376 | for ( ; ++self.i < self.length; ) { 377 | self.c = self.json[ self.i ]; 378 | self.character++; 379 | 380 | // Handle initial negative sign 381 | if ( negative ) { 382 | negative = false; 383 | if ( self.c == '-' ) { 384 | if ( ! rnumber.exec( self.json[ self.i + 1 ] ) ) { 385 | throw "Unknown Character '" + self.c + "' following a negative, expecting a numeric value."; 386 | } 387 | continue; 388 | } 389 | } 390 | 391 | // Only a single decimal is allowed in a numeric value 392 | if ( decimal && self.c == '.' ) { 393 | decimal = false; 394 | e = true; 395 | continue; 396 | } 397 | // Only a single e notation is allowed in a numeric value 398 | else if ( e && self.c.toLowerCase() == 'e' ) { 399 | e = false; 400 | negative = true; 401 | if ( rE.exec( self.json.substr( self.i + 1, 2 ) ) ) { 402 | self.character++; 403 | self.i++; 404 | } 405 | else { 406 | self.character++; 407 | throw "Unknown Character '" + self.json[ self.i + 1 ] + "' following e notation, expecting a numeric value."; 408 | } 409 | } 410 | // Normal Digit 411 | else if ( rnumber.exec( self.c ) ) { 412 | if ( decimal === null ) { 413 | decimal = true; 414 | } 415 | } 416 | // Assume end of number, and allow endval to handle it 417 | else { 418 | // Jump back a character to include the current one 419 | self.i--; 420 | self.character--; 421 | return self.endval(); 422 | } 423 | } 424 | }, 425 | 426 | // Ending a value statement 427 | endval: function(){ 428 | var self = this, peek = ''; 429 | self.commabreak = false; 430 | 431 | for ( ; ++self.i < self.length; ) { 432 | self.c = self.json[ self.i ]; 433 | self.character++; 434 | 435 | if ( self.options.comments && self.c == '/' ) { 436 | peek = self.json[ self.i + 1 ]; 437 | if ( peek == '*' ) { 438 | self.multicomment(); 439 | } 440 | else if ( peek == '/' ) { 441 | self.comment(); 442 | } 443 | else { 444 | throw "Unknown character '/', maybe a comment?"; 445 | } 446 | } 447 | else if ( rnewline.exec( self.c ) ) { 448 | self.line++; 449 | self.character = 0; 450 | } 451 | else if ( rwhitespace.exec( self.c ) ) { 452 | continue; 453 | } 454 | else if ( self.c == ',' ) { 455 | self.commabreak = true; 456 | break; 457 | } 458 | else if ( self.c == self.endblock ) { 459 | return true; 460 | } 461 | else { 462 | throw "Unknown Character '" + self.c + "', expecting a comma or a closing '" + self.endblock + "'"; 463 | } 464 | } 465 | }, 466 | 467 | // Expose line of the error 468 | setEvidence: function(){ 469 | var self = this, start = self.line - 5, end = start + 8, evidence = ''; 470 | 471 | // Min start 472 | if ( start < 0 ) { 473 | start = 0; 474 | end = 8; 475 | } 476 | 477 | // Max end 478 | if ( end >= self._evidence.length ) { 479 | end = self._evidence.length; 480 | } 481 | 482 | // Evidence display 483 | for ( ; start < end; start++ ) { 484 | evidence += ( start === ( self.line - 1 ) ? "-> " : " " ) + 485 | ( start + 1 ) + '| ' + 486 | self._evidence[ start ] + "\n"; 487 | } 488 | 489 | // Set the evidence display 490 | self.evidence = evidence; 491 | } 492 | }; 493 | 494 | 495 | // Check for nodejs module system 496 | if ( typeof exports == 'object' && typeof module == 'object' ) { 497 | module.exports = JSONLint; 498 | } 499 | // In a browser 500 | else { 501 | glob.JSONLint = JSONLint; 502 | } 503 | 504 | })( this ); 505 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "json-lint", 3 | "version": "0.1.1", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "json-lint", 9 | "version": "0.1.1", 10 | "devDependencies": { 11 | "munit": "0.0.8", 12 | "nlint": "0.0.7" 13 | }, 14 | "engines": { 15 | "node": ">=0.5" 16 | } 17 | }, 18 | "node_modules/argv": { 19 | "version": "0.0.2", 20 | "resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz", 21 | "integrity": "sha512-dEamhpPEwRUBpLNHeuCm/v+g0anFByHahxodVO/BbAarHVBBg2MccCwf9K+o1Pof+2btdnkJelYVUWjW/VrATw==", 22 | "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", 23 | "dev": true, 24 | "engines": { 25 | "node": ">=0.6.10" 26 | } 27 | }, 28 | "node_modules/async": { 29 | "version": "0.2.9", 30 | "resolved": "https://registry.npmjs.org/async/-/async-0.2.9.tgz", 31 | "integrity": "sha512-OAtM6mexGteNKdU29wcUfRW+VuBr94A3hx9h9yzBnPaQAbKoW1ORd68XM4CCAOpdL5wlNFgO29hsY1TKv2vAKw==", 32 | "dev": true 33 | }, 34 | "node_modules/cli": { 35 | "version": "0.4.5", 36 | "resolved": "https://registry.npmjs.org/cli/-/cli-0.4.5.tgz", 37 | "integrity": "sha512-dbn5HyeJWSOU58RwOEiF1VWrl7HRvDsKLpu0uiI/vExH6iNoyUzjB5Mr3IJY5DVUfnbpe9793xw4DFJVzC9nWQ==", 38 | "dev": true, 39 | "dependencies": { 40 | "glob": ">= 3.1.4" 41 | }, 42 | "engines": { 43 | "node": ">=0.2.5" 44 | } 45 | }, 46 | "node_modules/colors": { 47 | "version": "0.6.0-1", 48 | "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.0-1.tgz", 49 | "integrity": "sha512-ZaQtySU44lmZRP6M+CovFWnu7QnxLTsr/3wURb7BCOV1/gKjUb/3uu3NsLR+fvA2Jfs6sNfwcVq0Tp2mWYbuxg==", 50 | "dev": true, 51 | "engines": { 52 | "node": ">=0.1.90" 53 | } 54 | }, 55 | "node_modules/commander": { 56 | "version": "1.2.0", 57 | "resolved": "https://registry.npmjs.org/commander/-/commander-1.2.0.tgz", 58 | "integrity": "sha512-4AzfHvT/zLkvp+LVOHxZ02sHTuNrtoTnu8qEoJbpcL3nTnFhoNmAml1UV+96k9y5Tgz7jIjsom546WIi2iif0g==", 59 | "dev": true, 60 | "dependencies": { 61 | "keypress": "0.1.x" 62 | }, 63 | "engines": { 64 | "node": ">= 0.6.x" 65 | } 66 | }, 67 | "node_modules/console-browserify": { 68 | "version": "0.1.6", 69 | "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-0.1.6.tgz", 70 | "integrity": "sha512-FJahZyF+dLKrC7h4DOq5JsHA+f0cLJD3TR1+0CK3n6phtdrVAPsZZKq+PZRmo2RYSOHvvs8kNhU4uRiSZUbSbA==", 71 | "dev": true 72 | }, 73 | "node_modules/core-util-is": { 74 | "version": "1.0.3", 75 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", 76 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", 77 | "dev": true 78 | }, 79 | "node_modules/csslint": { 80 | "version": "0.10.0", 81 | "resolved": "https://registry.npmjs.org/csslint/-/csslint-0.10.0.tgz", 82 | "integrity": "sha512-mlD1oDw0juzD4dOthyAytPC4NsXqVZeIYAScIbgoYGY+Q7vcrhOQrH7js4JVZXcrOyKxi8ytC42ENMwO9CdnMQ==", 83 | "dev": true, 84 | "dependencies": { 85 | "parserlib": "~0.2.2" 86 | }, 87 | "bin": { 88 | "csslint": "cli.js" 89 | }, 90 | "engines": { 91 | "node": ">=0.8.0" 92 | } 93 | }, 94 | "node_modules/domelementtype": { 95 | "version": "1.3.1", 96 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", 97 | "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", 98 | "dev": true 99 | }, 100 | "node_modules/domhandler": { 101 | "version": "2.1.0", 102 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", 103 | "integrity": "sha512-4Qr6GTzdsnKVGdYferZT3na5zkswztvfsoyprP/j2bLf1l3pUTamwYvNVldkEYFG6Ll+3eV5mVk0zgRr6iI+SA==", 104 | "dev": true, 105 | "dependencies": { 106 | "domelementtype": "1" 107 | } 108 | }, 109 | "node_modules/domutils": { 110 | "version": "1.1.6", 111 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", 112 | "integrity": "sha512-ZeagMzMKyk9GSFMqV3x3uHgRN36hLpSOF6LIRXmftce0UUqFsAx/azJAJ4Jc+9DYKmwROH5HLOcOu1OPARWwNg==", 113 | "dev": true, 114 | "dependencies": { 115 | "domelementtype": "1" 116 | } 117 | }, 118 | "node_modules/esprima": { 119 | "version": "1.0.3", 120 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.3.tgz", 121 | "integrity": "sha512-Cc9SOu665lwATZT2tzVgeiZlqpnN6wKs2BvWrJ5nQSzGaivjL1MBYxyy951anmdsgMZNTssPXBRJq8W5vgRNcQ==", 122 | "dev": true, 123 | "bin": { 124 | "esparse": "bin/esparse.js", 125 | "esvalidate": "bin/esvalidate.js" 126 | }, 127 | "engines": { 128 | "node": ">=0.4.0" 129 | } 130 | }, 131 | "node_modules/glob": { 132 | "version": "3.2.7", 133 | "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.7.tgz", 134 | "integrity": "sha512-DaADhstzS42quruVnBdaZUrbSv3I+8K+7QQ5WrKQ1oFcBYJR9iuDNoz4MVxJlOhL4b8ETTAFZA6x755SiaUx2A==", 135 | "dev": true, 136 | "dependencies": { 137 | "inherits": "2", 138 | "minimatch": "~0.2.11" 139 | }, 140 | "engines": { 141 | "node": "*" 142 | } 143 | }, 144 | "node_modules/graceful-fs": { 145 | "version": "2.0.3", 146 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", 147 | "integrity": "sha512-hcj/NTUWv+C3MbqrVb9F+aH6lvTwEHJdx2foBxlrVq5h6zE8Bfu4pv4CAAqbDcZrw/9Ak5lsRXlY9Ao8/F0Tuw==", 148 | "deprecated": "please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js", 149 | "dev": true, 150 | "engines": { 151 | "node": ">=0.4.0" 152 | } 153 | }, 154 | "node_modules/htmlparser2": { 155 | "version": "3.3.0", 156 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", 157 | "integrity": "sha512-Z8i63n7seuPvRe1PQyrjmoVStv7bjMa0skrOl/k6tnT/5WpPNrzWLB1Hg/dJxBXH/M6KZvm25JQGVCiQGxURLQ==", 158 | "dev": true, 159 | "dependencies": { 160 | "domelementtype": "1", 161 | "domhandler": "2.1", 162 | "domutils": "1.1", 163 | "readable-stream": "1.0" 164 | } 165 | }, 166 | "node_modules/inherits": { 167 | "version": "2.0.4", 168 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 169 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 170 | "dev": true 171 | }, 172 | "node_modules/isarray": { 173 | "version": "0.0.1", 174 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 175 | "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", 176 | "dev": true 177 | }, 178 | "node_modules/jscs": { 179 | "version": "1.2.4", 180 | "resolved": "https://registry.npmjs.org/jscs/-/jscs-1.2.4.tgz", 181 | "integrity": "sha512-9UqO78RWOajGBICUV8/FdCL/883uYrkioJ7fBR6rs4W0Uiu0m2EAhQO9ByPh/4Qvx/atRVWHmwHreOiuFFeMgg==", 182 | "deprecated": "JSCS has merged with ESLint! See - https://medium.com/@markelog/jscs-end-of-the-line-bc9bf0b3fdb2", 183 | "dev": true, 184 | "dependencies": { 185 | "colors": "0.6.0-1", 186 | "commander": "1.2.0", 187 | "esprima": "1.0.3", 188 | "glob": "3.2.7", 189 | "minimatch": "0.2.12", 190 | "vow": "0.3.9", 191 | "vow-fs": "0.2.3", 192 | "xmlbuilder": "1.1.2" 193 | }, 194 | "bin": { 195 | "jscs": "bin/jscs" 196 | }, 197 | "engines": { 198 | "node": ">= 0.8.0" 199 | } 200 | }, 201 | "node_modules/jshint": { 202 | "version": "2.4.3", 203 | "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.4.3.tgz", 204 | "integrity": "sha512-bmwlrJCItW3tFoN70MivI2I0DCnIAp0xNrHtPq5bJ6aHu3dVVR51aVDP76LjmiS12SPRRGS0eVSbELT5zjtOPA==", 205 | "dev": true, 206 | "dependencies": { 207 | "cli": "0.4.x", 208 | "console-browserify": "0.1.x", 209 | "htmlparser2": "3.3.x", 210 | "minimatch": "0.x.x", 211 | "shelljs": "0.1.x", 212 | "underscore": "1.4.x" 213 | }, 214 | "bin": { 215 | "jshint": "bin/jshint" 216 | } 217 | }, 218 | "node_modules/json-lint": { 219 | "version": "0.1.0", 220 | "resolved": "https://registry.npmjs.org/json-lint/-/json-lint-0.1.0.tgz", 221 | "integrity": "sha512-QoBMCAo3sFnAl2nvCcrt5NmjqMRejlghhMvZ0ykhgfNpp7ukp1te7dP6q2o4fkvl03t08t75njni+y6S7jiHLg==", 222 | "dev": true, 223 | "engines": { 224 | "node": ">=0.5" 225 | } 226 | }, 227 | "node_modules/json5": { 228 | "version": "0.2.0", 229 | "resolved": "https://registry.npmjs.org/json5/-/json5-0.2.0.tgz", 230 | "integrity": "sha512-jzu3hxGhztAzldgKTbsW240mtPIgR6foddu9HqQgpv0ML2RcjE0mjyLro0XE92YAQYpTpcByY80vVzlKOM64xA==", 231 | "dev": true, 232 | "bin": { 233 | "json5": "lib/cli.js" 234 | }, 235 | "engines": { 236 | "node": "*" 237 | } 238 | }, 239 | "node_modules/keypress": { 240 | "version": "0.1.0", 241 | "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz", 242 | "integrity": "sha512-x0yf9PL/nx9Nw9oLL8ZVErFAk85/lslwEP7Vz7s5SI1ODXZIgit3C5qyWjw4DxOuO/3Hb4866SQh28a1V1d+WA==", 243 | "dev": true 244 | }, 245 | "node_modules/lru-cache": { 246 | "version": "2.7.3", 247 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", 248 | "integrity": "sha512-WpibWJ60c3AgAz8a2iYErDrcT2C7OmKnsWhIcHOjkUHFjkXncJhtLxNSqUmxRxRunpb5I8Vprd7aNSd2NtksJQ==", 249 | "dev": true 250 | }, 251 | "node_modules/minimatch": { 252 | "version": "0.2.12", 253 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.12.tgz", 254 | "integrity": "sha512-jeVdfKmlomLerf8ecetSr6gLS0OXnLRluhnv9Rf2yj70NsD8uVGqrpwTqJGKpIF8VTRR9fQAl62CZ1eNIEMk3A==", 255 | "deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue", 256 | "dev": true, 257 | "dependencies": { 258 | "lru-cache": "2", 259 | "sigmund": "~1.0.0" 260 | }, 261 | "engines": { 262 | "node": "*" 263 | } 264 | }, 265 | "node_modules/munit": { 266 | "version": "0.0.8", 267 | "resolved": "https://registry.npmjs.org/munit/-/munit-0.0.8.tgz", 268 | "integrity": "sha512-V95XdHT6lPE03Av2rz6S0r4WuPsUjXhHfqB7Q6nMO3WDtCw8YPB2TvY1HX2urG0/a4tiUNUgLywne+HaIS7Z8g==", 269 | "dev": true, 270 | "dependencies": { 271 | "argv": "0.0.2", 272 | "async": "0.2.9", 273 | "graceful-fs": "2.0.3" 274 | }, 275 | "bin": { 276 | "munit": "bin/munit" 277 | }, 278 | "engines": { 279 | "node": ">=0.8" 280 | } 281 | }, 282 | "node_modules/nlint": { 283 | "version": "0.0.7", 284 | "resolved": "https://registry.npmjs.org/nlint/-/nlint-0.0.7.tgz", 285 | "integrity": "sha512-XvhJkl4nBbYLJGmiDv5Ga3A9TsvF/HZawXXfrMKp1GZg+j+WKabWT7NePY2ohW1fUASfSl+iIENuodFvCVb1LA==", 286 | "dev": true, 287 | "dependencies": { 288 | "argv": "0.0.2", 289 | "async": "0.2.10", 290 | "csslint": "0.10.0", 291 | "jscs": "1.2.4", 292 | "jshint": "2.4.3", 293 | "json-lint": "0.1.0", 294 | "json5": "0.2.0" 295 | }, 296 | "bin": { 297 | "nlint": "bin/nlint" 298 | }, 299 | "engines": { 300 | "node": ">=0.6.10" 301 | } 302 | }, 303 | "node_modules/nlint/node_modules/async": { 304 | "version": "0.2.10", 305 | "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", 306 | "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==", 307 | "dev": true 308 | }, 309 | "node_modules/node-uuid": { 310 | "version": "1.4.0", 311 | "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.0.tgz", 312 | "integrity": "sha512-Vns3Mj1WBYNwPchf2T/pt9q2GUpM97JvLekAkAwWYX1H2kIxYQ+jUb3GWmaNRboP5XoS3p3nxptIv00I+cOtLg==", 313 | "deprecated": "Use uuid module instead", 314 | "dev": true 315 | }, 316 | "node_modules/parserlib": { 317 | "version": "0.2.5", 318 | "resolved": "https://registry.npmjs.org/parserlib/-/parserlib-0.2.5.tgz", 319 | "integrity": "sha512-SNu7MNq2Lp5aHXM1HZLyXEHpSAVpHU1y3pvPpxnq6jVK/5WIpKv9aA11PyMeiW9Y+EORem2J7XhiEIaOKizUHA==", 320 | "dev": true 321 | }, 322 | "node_modules/readable-stream": { 323 | "version": "1.0.34", 324 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", 325 | "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", 326 | "dev": true, 327 | "dependencies": { 328 | "core-util-is": "~1.0.0", 329 | "inherits": "~2.0.1", 330 | "isarray": "0.0.1", 331 | "string_decoder": "~0.10.x" 332 | } 333 | }, 334 | "node_modules/shelljs": { 335 | "version": "0.1.4", 336 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.1.4.tgz", 337 | "integrity": "sha512-UkXLBuUzAJwkal/0eYnQs8LpXQ4grKL5kPtA0RkUzhj1khUvw5Z2d717GRTRclDWQ+Y14yWkiM9cJX2CwSHxpw==", 338 | "dev": true, 339 | "bin": { 340 | "shjs": "bin/shjs" 341 | }, 342 | "engines": { 343 | "node": "*" 344 | } 345 | }, 346 | "node_modules/sigmund": { 347 | "version": "1.0.1", 348 | "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", 349 | "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==", 350 | "dev": true 351 | }, 352 | "node_modules/string_decoder": { 353 | "version": "0.10.31", 354 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 355 | "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", 356 | "dev": true 357 | }, 358 | "node_modules/underscore": { 359 | "version": "1.4.4", 360 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", 361 | "integrity": "sha512-ZqGrAgaqqZM7LGRzNjLnw5elevWb5M8LEoDMadxIW3OWbcv72wMMgKdwOKpd5Fqxe8choLD8HN3iSj3TUh/giQ==", 362 | "dev": true 363 | }, 364 | "node_modules/vow": { 365 | "version": "0.3.9", 366 | "resolved": "https://registry.npmjs.org/vow/-/vow-0.3.9.tgz", 367 | "integrity": "sha512-fc9eU77ORvSDGa4qAcs9WLZkvH3TrAlGwhEGDPiPeGzRjrZ9BU5BlkrKAvyZUdCNOezG5BkZ8m30h/XvWuDYXQ==", 368 | "dev": true, 369 | "engines": { 370 | "node": ">= 0.4.0" 371 | } 372 | }, 373 | "node_modules/vow-fs": { 374 | "version": "0.2.3", 375 | "resolved": "https://registry.npmjs.org/vow-fs/-/vow-fs-0.2.3.tgz", 376 | "integrity": "sha512-v4nH+/0tzAFxZzPJJv/0IvoNkAVlzs9DSy1kYMRgyGHaPwvvpFgFbg2uHmX80Kyuq493+jEhx9eHX4pcVLeB+g==", 377 | "dev": true, 378 | "dependencies": { 379 | "node-uuid": "1.4.0", 380 | "vow-queue": "0.0.2" 381 | }, 382 | "engines": { 383 | "node": ">= 0.6.0" 384 | }, 385 | "peerDependencies": { 386 | "vow": ">= 0.3.9" 387 | } 388 | }, 389 | "node_modules/vow-queue": { 390 | "version": "0.0.2", 391 | "resolved": "https://registry.npmjs.org/vow-queue/-/vow-queue-0.0.2.tgz", 392 | "integrity": "sha512-k5FUzXd0fZGThIzkMCpgunxOEzZZu9V08Bomrgfu37qlHJAjF7G4Qa5ATcd1Kl0fiuDAltAFyQK0kescFUDz4w==", 393 | "dev": true, 394 | "engines": { 395 | "node": ">= 0.8.0" 396 | }, 397 | "peerDependencies": { 398 | "vow": "~0.3.9" 399 | } 400 | }, 401 | "node_modules/xmlbuilder": { 402 | "version": "1.1.2", 403 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-1.1.2.tgz", 404 | "integrity": "sha512-gspXU5NGrWif4BFbSGHuojHkGzzFABcODPZfOogi5twMIVNNxDpxkzem7B/vlzIyCT49I1xa2apzsGttVMaT9g==", 405 | "dev": true, 406 | "dependencies": { 407 | "underscore": ">=1.5.x" 408 | }, 409 | "engines": { 410 | "node": ">=0.2.0" 411 | } 412 | }, 413 | "node_modules/xmlbuilder/node_modules/underscore": { 414 | "version": "1.13.6", 415 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", 416 | "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", 417 | "dev": true 418 | } 419 | }, 420 | "dependencies": { 421 | "argv": { 422 | "version": "0.0.2", 423 | "resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz", 424 | "integrity": "sha512-dEamhpPEwRUBpLNHeuCm/v+g0anFByHahxodVO/BbAarHVBBg2MccCwf9K+o1Pof+2btdnkJelYVUWjW/VrATw==", 425 | "dev": true 426 | }, 427 | "async": { 428 | "version": "0.2.9", 429 | "resolved": "https://registry.npmjs.org/async/-/async-0.2.9.tgz", 430 | "integrity": "sha512-OAtM6mexGteNKdU29wcUfRW+VuBr94A3hx9h9yzBnPaQAbKoW1ORd68XM4CCAOpdL5wlNFgO29hsY1TKv2vAKw==", 431 | "dev": true 432 | }, 433 | "cli": { 434 | "version": "0.4.5", 435 | "resolved": "https://registry.npmjs.org/cli/-/cli-0.4.5.tgz", 436 | "integrity": "sha512-dbn5HyeJWSOU58RwOEiF1VWrl7HRvDsKLpu0uiI/vExH6iNoyUzjB5Mr3IJY5DVUfnbpe9793xw4DFJVzC9nWQ==", 437 | "dev": true, 438 | "requires": { 439 | "glob": ">= 3.1.4" 440 | } 441 | }, 442 | "colors": { 443 | "version": "0.6.0-1", 444 | "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.0-1.tgz", 445 | "integrity": "sha512-ZaQtySU44lmZRP6M+CovFWnu7QnxLTsr/3wURb7BCOV1/gKjUb/3uu3NsLR+fvA2Jfs6sNfwcVq0Tp2mWYbuxg==", 446 | "dev": true 447 | }, 448 | "commander": { 449 | "version": "1.2.0", 450 | "resolved": "https://registry.npmjs.org/commander/-/commander-1.2.0.tgz", 451 | "integrity": "sha512-4AzfHvT/zLkvp+LVOHxZ02sHTuNrtoTnu8qEoJbpcL3nTnFhoNmAml1UV+96k9y5Tgz7jIjsom546WIi2iif0g==", 452 | "dev": true, 453 | "requires": { 454 | "keypress": "0.1.x" 455 | } 456 | }, 457 | "console-browserify": { 458 | "version": "0.1.6", 459 | "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-0.1.6.tgz", 460 | "integrity": "sha512-FJahZyF+dLKrC7h4DOq5JsHA+f0cLJD3TR1+0CK3n6phtdrVAPsZZKq+PZRmo2RYSOHvvs8kNhU4uRiSZUbSbA==", 461 | "dev": true 462 | }, 463 | "core-util-is": { 464 | "version": "1.0.3", 465 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", 466 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", 467 | "dev": true 468 | }, 469 | "csslint": { 470 | "version": "0.10.0", 471 | "resolved": "https://registry.npmjs.org/csslint/-/csslint-0.10.0.tgz", 472 | "integrity": "sha512-mlD1oDw0juzD4dOthyAytPC4NsXqVZeIYAScIbgoYGY+Q7vcrhOQrH7js4JVZXcrOyKxi8ytC42ENMwO9CdnMQ==", 473 | "dev": true, 474 | "requires": { 475 | "parserlib": "~0.2.2" 476 | } 477 | }, 478 | "domelementtype": { 479 | "version": "1.3.1", 480 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", 481 | "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", 482 | "dev": true 483 | }, 484 | "domhandler": { 485 | "version": "2.1.0", 486 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", 487 | "integrity": "sha512-4Qr6GTzdsnKVGdYferZT3na5zkswztvfsoyprP/j2bLf1l3pUTamwYvNVldkEYFG6Ll+3eV5mVk0zgRr6iI+SA==", 488 | "dev": true, 489 | "requires": { 490 | "domelementtype": "1" 491 | } 492 | }, 493 | "domutils": { 494 | "version": "1.1.6", 495 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", 496 | "integrity": "sha512-ZeagMzMKyk9GSFMqV3x3uHgRN36hLpSOF6LIRXmftce0UUqFsAx/azJAJ4Jc+9DYKmwROH5HLOcOu1OPARWwNg==", 497 | "dev": true, 498 | "requires": { 499 | "domelementtype": "1" 500 | } 501 | }, 502 | "esprima": { 503 | "version": "1.0.3", 504 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.3.tgz", 505 | "integrity": "sha512-Cc9SOu665lwATZT2tzVgeiZlqpnN6wKs2BvWrJ5nQSzGaivjL1MBYxyy951anmdsgMZNTssPXBRJq8W5vgRNcQ==", 506 | "dev": true 507 | }, 508 | "glob": { 509 | "version": "3.2.7", 510 | "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.7.tgz", 511 | "integrity": "sha512-DaADhstzS42quruVnBdaZUrbSv3I+8K+7QQ5WrKQ1oFcBYJR9iuDNoz4MVxJlOhL4b8ETTAFZA6x755SiaUx2A==", 512 | "dev": true, 513 | "requires": { 514 | "inherits": "2", 515 | "minimatch": "~0.2.11" 516 | } 517 | }, 518 | "graceful-fs": { 519 | "version": "2.0.3", 520 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", 521 | "integrity": "sha512-hcj/NTUWv+C3MbqrVb9F+aH6lvTwEHJdx2foBxlrVq5h6zE8Bfu4pv4CAAqbDcZrw/9Ak5lsRXlY9Ao8/F0Tuw==", 522 | "dev": true 523 | }, 524 | "htmlparser2": { 525 | "version": "3.3.0", 526 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", 527 | "integrity": "sha512-Z8i63n7seuPvRe1PQyrjmoVStv7bjMa0skrOl/k6tnT/5WpPNrzWLB1Hg/dJxBXH/M6KZvm25JQGVCiQGxURLQ==", 528 | "dev": true, 529 | "requires": { 530 | "domelementtype": "1", 531 | "domhandler": "2.1", 532 | "domutils": "1.1", 533 | "readable-stream": "1.0" 534 | } 535 | }, 536 | "inherits": { 537 | "version": "2.0.4", 538 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 539 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 540 | "dev": true 541 | }, 542 | "isarray": { 543 | "version": "0.0.1", 544 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 545 | "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", 546 | "dev": true 547 | }, 548 | "jscs": { 549 | "version": "1.2.4", 550 | "resolved": "https://registry.npmjs.org/jscs/-/jscs-1.2.4.tgz", 551 | "integrity": "sha512-9UqO78RWOajGBICUV8/FdCL/883uYrkioJ7fBR6rs4W0Uiu0m2EAhQO9ByPh/4Qvx/atRVWHmwHreOiuFFeMgg==", 552 | "dev": true, 553 | "requires": { 554 | "colors": "0.6.0-1", 555 | "commander": "1.2.0", 556 | "esprima": "1.0.3", 557 | "glob": "3.2.7", 558 | "minimatch": "0.2.12", 559 | "vow": "0.3.9", 560 | "vow-fs": "0.2.3", 561 | "xmlbuilder": "1.1.2" 562 | } 563 | }, 564 | "jshint": { 565 | "version": "2.4.3", 566 | "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.4.3.tgz", 567 | "integrity": "sha512-bmwlrJCItW3tFoN70MivI2I0DCnIAp0xNrHtPq5bJ6aHu3dVVR51aVDP76LjmiS12SPRRGS0eVSbELT5zjtOPA==", 568 | "dev": true, 569 | "requires": { 570 | "cli": "0.4.x", 571 | "console-browserify": "0.1.x", 572 | "htmlparser2": "3.3.x", 573 | "minimatch": "0.x.x", 574 | "shelljs": "0.1.x", 575 | "underscore": "1.4.x" 576 | } 577 | }, 578 | "json-lint": { 579 | "version": "0.1.0", 580 | "resolved": "https://registry.npmjs.org/json-lint/-/json-lint-0.1.0.tgz", 581 | "integrity": "sha512-QoBMCAo3sFnAl2nvCcrt5NmjqMRejlghhMvZ0ykhgfNpp7ukp1te7dP6q2o4fkvl03t08t75njni+y6S7jiHLg==", 582 | "dev": true 583 | }, 584 | "json5": { 585 | "version": "0.2.0", 586 | "resolved": "https://registry.npmjs.org/json5/-/json5-0.2.0.tgz", 587 | "integrity": "sha512-jzu3hxGhztAzldgKTbsW240mtPIgR6foddu9HqQgpv0ML2RcjE0mjyLro0XE92YAQYpTpcByY80vVzlKOM64xA==", 588 | "dev": true 589 | }, 590 | "keypress": { 591 | "version": "0.1.0", 592 | "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz", 593 | "integrity": "sha512-x0yf9PL/nx9Nw9oLL8ZVErFAk85/lslwEP7Vz7s5SI1ODXZIgit3C5qyWjw4DxOuO/3Hb4866SQh28a1V1d+WA==", 594 | "dev": true 595 | }, 596 | "lru-cache": { 597 | "version": "2.7.3", 598 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", 599 | "integrity": "sha512-WpibWJ60c3AgAz8a2iYErDrcT2C7OmKnsWhIcHOjkUHFjkXncJhtLxNSqUmxRxRunpb5I8Vprd7aNSd2NtksJQ==", 600 | "dev": true 601 | }, 602 | "minimatch": { 603 | "version": "0.2.12", 604 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.12.tgz", 605 | "integrity": "sha512-jeVdfKmlomLerf8ecetSr6gLS0OXnLRluhnv9Rf2yj70NsD8uVGqrpwTqJGKpIF8VTRR9fQAl62CZ1eNIEMk3A==", 606 | "dev": true, 607 | "requires": { 608 | "lru-cache": "2", 609 | "sigmund": "~1.0.0" 610 | } 611 | }, 612 | "munit": { 613 | "version": "0.0.8", 614 | "resolved": "https://registry.npmjs.org/munit/-/munit-0.0.8.tgz", 615 | "integrity": "sha512-V95XdHT6lPE03Av2rz6S0r4WuPsUjXhHfqB7Q6nMO3WDtCw8YPB2TvY1HX2urG0/a4tiUNUgLywne+HaIS7Z8g==", 616 | "dev": true, 617 | "requires": { 618 | "argv": "0.0.2", 619 | "async": "0.2.9", 620 | "graceful-fs": "2.0.3" 621 | } 622 | }, 623 | "nlint": { 624 | "version": "0.0.7", 625 | "resolved": "https://registry.npmjs.org/nlint/-/nlint-0.0.7.tgz", 626 | "integrity": "sha512-XvhJkl4nBbYLJGmiDv5Ga3A9TsvF/HZawXXfrMKp1GZg+j+WKabWT7NePY2ohW1fUASfSl+iIENuodFvCVb1LA==", 627 | "dev": true, 628 | "requires": { 629 | "argv": "0.0.2", 630 | "async": "0.2.10", 631 | "csslint": "0.10.0", 632 | "jscs": "1.2.4", 633 | "jshint": "2.4.3", 634 | "json-lint": "0.1.0", 635 | "json5": "0.2.0" 636 | }, 637 | "dependencies": { 638 | "async": { 639 | "version": "0.2.10", 640 | "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", 641 | "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==", 642 | "dev": true 643 | } 644 | } 645 | }, 646 | "node-uuid": { 647 | "version": "1.4.0", 648 | "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.0.tgz", 649 | "integrity": "sha512-Vns3Mj1WBYNwPchf2T/pt9q2GUpM97JvLekAkAwWYX1H2kIxYQ+jUb3GWmaNRboP5XoS3p3nxptIv00I+cOtLg==", 650 | "dev": true 651 | }, 652 | "parserlib": { 653 | "version": "0.2.5", 654 | "resolved": "https://registry.npmjs.org/parserlib/-/parserlib-0.2.5.tgz", 655 | "integrity": "sha512-SNu7MNq2Lp5aHXM1HZLyXEHpSAVpHU1y3pvPpxnq6jVK/5WIpKv9aA11PyMeiW9Y+EORem2J7XhiEIaOKizUHA==", 656 | "dev": true 657 | }, 658 | "readable-stream": { 659 | "version": "1.0.34", 660 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", 661 | "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", 662 | "dev": true, 663 | "requires": { 664 | "core-util-is": "~1.0.0", 665 | "inherits": "~2.0.1", 666 | "isarray": "0.0.1", 667 | "string_decoder": "~0.10.x" 668 | } 669 | }, 670 | "shelljs": { 671 | "version": "0.1.4", 672 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.1.4.tgz", 673 | "integrity": "sha512-UkXLBuUzAJwkal/0eYnQs8LpXQ4grKL5kPtA0RkUzhj1khUvw5Z2d717GRTRclDWQ+Y14yWkiM9cJX2CwSHxpw==", 674 | "dev": true 675 | }, 676 | "sigmund": { 677 | "version": "1.0.1", 678 | "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", 679 | "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==", 680 | "dev": true 681 | }, 682 | "string_decoder": { 683 | "version": "0.10.31", 684 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 685 | "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", 686 | "dev": true 687 | }, 688 | "underscore": { 689 | "version": "1.4.4", 690 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", 691 | "integrity": "sha512-ZqGrAgaqqZM7LGRzNjLnw5elevWb5M8LEoDMadxIW3OWbcv72wMMgKdwOKpd5Fqxe8choLD8HN3iSj3TUh/giQ==", 692 | "dev": true 693 | }, 694 | "vow": { 695 | "version": "0.3.9", 696 | "resolved": "https://registry.npmjs.org/vow/-/vow-0.3.9.tgz", 697 | "integrity": "sha512-fc9eU77ORvSDGa4qAcs9WLZkvH3TrAlGwhEGDPiPeGzRjrZ9BU5BlkrKAvyZUdCNOezG5BkZ8m30h/XvWuDYXQ==", 698 | "dev": true 699 | }, 700 | "vow-fs": { 701 | "version": "0.2.3", 702 | "resolved": "https://registry.npmjs.org/vow-fs/-/vow-fs-0.2.3.tgz", 703 | "integrity": "sha512-v4nH+/0tzAFxZzPJJv/0IvoNkAVlzs9DSy1kYMRgyGHaPwvvpFgFbg2uHmX80Kyuq493+jEhx9eHX4pcVLeB+g==", 704 | "dev": true, 705 | "requires": { 706 | "node-uuid": "1.4.0", 707 | "vow-queue": "0.0.2" 708 | } 709 | }, 710 | "vow-queue": { 711 | "version": "0.0.2", 712 | "resolved": "https://registry.npmjs.org/vow-queue/-/vow-queue-0.0.2.tgz", 713 | "integrity": "sha512-k5FUzXd0fZGThIzkMCpgunxOEzZZu9V08Bomrgfu37qlHJAjF7G4Qa5ATcd1Kl0fiuDAltAFyQK0kescFUDz4w==", 714 | "dev": true, 715 | "requires": {} 716 | }, 717 | "xmlbuilder": { 718 | "version": "1.1.2", 719 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-1.1.2.tgz", 720 | "integrity": "sha512-gspXU5NGrWif4BFbSGHuojHkGzzFABcODPZfOogi5twMIVNNxDpxkzem7B/vlzIyCT49I1xa2apzsGttVMaT9g==", 721 | "dev": true, 722 | "requires": { 723 | "underscore": ">=1.5.x" 724 | }, 725 | "dependencies": { 726 | "underscore": { 727 | "version": "1.13.6", 728 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", 729 | "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", 730 | "dev": true 731 | } 732 | } 733 | } 734 | } 735 | } 736 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "json-lint", 3 | "description": "JSON Lint with comments", 4 | "url": "https://github.com/codenothing/jsonlint", 5 | "author": "Corey Hart ", 6 | "version": "0.1.1", 7 | "main": "./jsonlint.js", 8 | "homepage": "https://github.com/codenothing/jsonlint", 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/codenothing/jsonlint.git" 12 | }, 13 | "keywords": [ 14 | "json", 15 | "lint", 16 | "comments" 17 | ], 18 | "files": [ 19 | "jsonlint.js", 20 | "package.json", 21 | "README.md", 22 | "LICENSE" 23 | ], 24 | "engines": { 25 | "node": ">=0.5" 26 | }, 27 | "bugs": { 28 | "url": "https://github.com/codenothing/jsonlint/issues" 29 | }, 30 | "scripts": { 31 | "clean": "rm -rf build/results/", 32 | "lint": "node build/lint.js", 33 | "test": "npm run clean && npm run lint && node build/test.js" 34 | }, 35 | "devDependencies": { 36 | "nlint": "0.0.7", 37 | "munit": "0.0.8" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/.nlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "linters": { 3 | "jshint": { 4 | "predef": { 5 | "JSONLint": false, 6 | "munit": false 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/files/json/.nlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": [ 3 | "string.json", 4 | "multi-object.json", 5 | "endofarray.json" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /test/files/json/.nodelint.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": [ 3 | "string.json", 4 | "multi-object.json", 5 | "endofarray.json" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /test/files/json/Numeric.json: -------------------------------------------------------------------------------- 1 | /** 2 | * This JSON file provided by CSSCompression(http://www.codenothing.com/css-compressor/) 3 | * Real world example to test length 4 | */ 5 | { 6 | // Decimal removal 7 | "decimal": { 8 | "remove": { 9 | "params": [ "1.0em" ], 10 | "expect": "1em" 11 | }, 12 | "negative remove": { 13 | "params": [ "-1.0em" ], 14 | "expect": "-1em" 15 | }, 16 | "positive remove": { 17 | "params": [ "+1.0em" ], 18 | "expect": "1em" 19 | }, 20 | "long decimal int": { 21 | "params": [ "1.00000em" ], 22 | "expect": "1em" 23 | }, 24 | "negative long decimal int": { 25 | "params": [ "-1.00000em" ], 26 | "expect": "-1em" 27 | }, 28 | /* 29 | Adding nested Multi line comments 30 | Just for fun 31 | */ 32 | "positive long decimal int": { 33 | "params": [ "+1.00000em" ], 34 | "expect": "1em" 35 | }, 36 | "long decimal": { 37 | "params": [ "1.10000em" ], 38 | "expect": "1.1em" 39 | }, 40 | "negative long decimal": { 41 | "params": [ "-1.10000em" ], 42 | "expect": "-1.1em" 43 | }, 44 | "keep": { 45 | "params": [ "1.059em" ], 46 | "expect": "1.059em" 47 | }, 48 | "negative keep": { 49 | "params": [ "-1.059em" ], 50 | "expect": "-1.059em" 51 | } 52 | }, 53 | 54 | // Unit removal 55 | "units": { 56 | "remove": { 57 | /* 58 | Adding nested Multi line comments 59 | Just for fun 60 | */ 61 | "params": [ "0px" ], 62 | "expect": "0" 63 | }, 64 | "percentage": { 65 | "params": [ "0%" ], 66 | "expect": "0" 67 | }, 68 | "non-zero": { 69 | "params": [ "50px" ], 70 | "expect": "50px" 71 | }, 72 | "non-zero decimal": { 73 | "params": [ "50.0px" ], 74 | "expect": "50.0px" 75 | }, 76 | "keep": { 77 | "params": [ "1pt" ], 78 | "expect": "1pt" 79 | } 80 | }, 81 | 82 | // Zero Removal 83 | "zeroes": { 84 | "0.8px": { 85 | "params": [ "0.8px" ], 86 | /* 87 | Adding nested Multi line comments 88 | Just for fun 89 | */ 90 | "expect": ".8px" 91 | }, 92 | "-0.5px": { 93 | "params": [ "-0.5px" ], 94 | "expect": "-.5px" 95 | }, 96 | "+0.5px": { 97 | "params": [ "+0.5px" ], 98 | "expect": ".5px" 99 | }, 100 | "0.2983%": { 101 | "params": [ "0.2983%" ], 102 | "expect": ".2983%" 103 | }, 104 | "-10.5px": { 105 | "params": [ "-10.5px" ], 106 | "expect": "-10.5px" 107 | }, 108 | "10.2983%": { 109 | "params": [ "10.2983%" ], 110 | "expect": "10.2983%" 111 | } 112 | }, 113 | 114 | // Main numeric handler, just checking that it handles 115 | // all of the above scenarios 116 | "numeric": { 117 | "0.8px": { 118 | "params": [ "0.8px" ], 119 | "expect": ".8px" 120 | }, 121 | "0 pixel": { 122 | "params": [ "0px" ], 123 | /* 124 | Adding nested Multi line comments 125 | Just for fun 126 | */ 127 | "expect": "0" 128 | }, 129 | "decimal removal": { 130 | "params": [ "1.0em" ], 131 | "expect": "1em" 132 | }, 133 | "Nothing": { 134 | "params": [ "1pt" ], 135 | "expect": "1pt" 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /test/files/json/comments.json: -------------------------------------------------------------------------------- 1 | // Single Line Comment 2 | [ 3 | // Blah 4 | true, 5 | // false, 6 | null, 7 | "string" // Nothing 8 | // Empty 9 | ] 10 | -------------------------------------------------------------------------------- /test/files/json/empty.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codenothing/jsonlint/a83b6f8b5dd37447c30c1baeb8cb287bbd2ec6c3/test/files/json/empty.json -------------------------------------------------------------------------------- /test/files/json/endofarray.json: -------------------------------------------------------------------------------- 1 | [ null, ] 2 | -------------------------------------------------------------------------------- /test/files/json/multi-comment.json: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Multi Line Comment 4 | 5 | */ 6 | { 7 | /* Start Comment */ 8 | "key": /* 9 | Inner Multi Line Comment 10 | */ 11 | "value", 12 | /* 13 | Key Break 14 | */ 15 | "key2": /* Same Line */ true 16 | /* End COmment */ 17 | } 18 | -------------------------------------------------------------------------------- /test/files/json/multi-object.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": true, 3 | "next": false 4 | } 5 | [ 6 | null 7 | ] 8 | -------------------------------------------------------------------------------- /test/files/json/nested.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": [ 3 | { 4 | "b": [ 5 | { 6 | "c": [ 7 | true, 8 | false, 9 | null, 10 | 1001 11 | ] 12 | } 13 | ] 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /test/files/json/nocomments.json: -------------------------------------------------------------------------------- 1 | [ 2 | // This will throw errr 3 | false 4 | ] 5 | -------------------------------------------------------------------------------- /test/files/json/nomulticomment.json: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This will throw error on first character 4 | 5 | */ 6 | { 7 | "test": null 8 | } 9 | -------------------------------------------------------------------------------- /test/files/json/pit.json: -------------------------------------------------------------------------------- 1 | /* 2 | this file contains as many different types of data as possible 3 | */ 4 | [ 5 | true, 6 | false, 7 | // false, 8 | null, 9 | 10, 10 | 10.0, 11 | 10.2E1, 12 | 10.2e-1, 13 | -10.5e192, 14 | -10.5e+192, 15 | [ 16 | true, 17 | false, 18 | // false, 19 | null, 20 | 10, 21 | 10.0, 22 | 10.2E1, 23 | 10.2e-1, 24 | -10.5e192, 25 | -10.5e+192 26 | ], 27 | { 28 | "test": true, 29 | "a": false, 30 | "b": null 31 | } 32 | ] 33 | -------------------------------------------------------------------------------- /test/files/json/string.json: -------------------------------------------------------------------------------- 1 | [ 2 | "\s" 3 | ] 4 | -------------------------------------------------------------------------------- /test/files/json/strings.json: -------------------------------------------------------------------------------- 1 | // Valid escaped strings 2 | [ 3 | "\"", 4 | "\\", 5 | "\/", 6 | "\b", 7 | "\f", 8 | "\n", 9 | "\r", 10 | "\t", 11 | "\u1234" 12 | ] 13 | -------------------------------------------------------------------------------- /test/files/test-files.js: -------------------------------------------------------------------------------- 1 | var fs = require( 'fs' ), 2 | expect = 0, 3 | tests = [ 4 | 5 | { 6 | file: 'Numeric.json' 7 | }, 8 | 9 | { 10 | file: 'comments.json' 11 | }, 12 | 13 | { 14 | file: 'multi-comment.json' 15 | }, 16 | 17 | { 18 | file: 'nested.json' 19 | }, 20 | 21 | { 22 | file: 'pit.json' 23 | }, 24 | 25 | { 26 | file: 'strings.json' 27 | }, 28 | 29 | 30 | { 31 | file: 'endofarray.json', 32 | error: true, 33 | line: 1, 34 | character: 9 35 | }, 36 | 37 | { 38 | file: 'nocomments.json', 39 | error: true, 40 | line: 2, 41 | character: 2, 42 | options: { 43 | comments: false 44 | } 45 | }, 46 | 47 | { 48 | file: 'nomulticomment.json', 49 | error: true, 50 | line: 1, 51 | character: 1, 52 | options: { 53 | comments: false 54 | } 55 | }, 56 | 57 | { 58 | file: 'string.json', 59 | error: true, 60 | line: 2, 61 | character: 3 62 | }, 63 | 64 | { 65 | file: 'empty.json', 66 | error: true, 67 | line: 1, 68 | character: 0 69 | }, 70 | 71 | { 72 | file: 'multi-object.json', 73 | error: true, 74 | line: 5, 75 | character: 1 76 | } 77 | 78 | ]; 79 | 80 | 81 | tests.forEach(function( test ) { 82 | expect += test.error ? 2 : 1; 83 | }); 84 | 85 | munit( 'Files', { expect: expect, timeout: 3000 }, function( assert ) { 86 | tests.forEach(function( test ) { 87 | fs.readFile( __dirname + '/json/' + test.file, 'utf-8', function( e, contents ) { 88 | if ( e ) { 89 | return assert.fail( test.file ); 90 | } 91 | 92 | var lint = JSONLint( contents, test.options ); 93 | if ( ! lint.error ) { 94 | assert.ok( test.file, ! test.error ); 95 | } 96 | else if ( ! test.error ) { 97 | assert.fail( test.file ); 98 | } 99 | else { 100 | assert.equal( test.file + '-line', lint.line, test.line ); 101 | assert.equal( test.file + '-character', lint.character, test.character ); 102 | } 103 | }); 104 | }); 105 | }); 106 | -------------------------------------------------------------------------------- /test/munit.js: -------------------------------------------------------------------------------- 1 | global.JSONLint = require( '../jsonlint.js' ); 2 | -------------------------------------------------------------------------------- /test/test-clean.js: -------------------------------------------------------------------------------- 1 | var tests = [ 2 | // Empties 3 | "[]", 4 | "{}", 5 | "[{}]", 6 | "[[]]", 7 | "{\"test\":[]}", 8 | "{\"test\":{}}", 9 | "{\"test\": [ ], \"test2\": [ ] }", 10 | 11 | // Null Value 12 | "{\"test\":null}", 13 | 14 | // Boolean Values 15 | "{\"test\":true}", 16 | "{\"test\":false}", 17 | 18 | // Numeric Values 19 | "{\"test\":1}", 20 | "{\"test\":-101}", 21 | "{\"test\":101.101}", 22 | "{\"test\":-101.101e1}", 23 | "{\"test\":101.101e-101}", 24 | "{\"test\":-101.101E1}", 25 | "{\"test\":101.101E-101}", 26 | "{\"test\":101.101e+101}", 27 | "{\"test\":101.101E+101}", 28 | 29 | // String Values 30 | "[\"\"]", 31 | "{\"test\":\"good\"}", 32 | "{\"test\":\"s p a c i n g \"}", 33 | "{\"test\":\"'single quote'\"}", 34 | "{\"test\":\"\\\"double quote\\\"\"}", 35 | 36 | // Valid Reverse solidus in strings 37 | "[\"\\\"\"]", 38 | "[\"\\\\\"]", 39 | "[\"\\/\"]", 40 | "[\"\\b\"]", 41 | "[\"\\f\"]", 42 | "[\"\\n\"]", 43 | "[\"\\r\"]", 44 | "[\"\\t\"]", 45 | "[\"\\u1234\"]", 46 | 47 | // Array Value 48 | "{\"test\": [ true ] }", 49 | 50 | // Array 51 | "[null]", 52 | "[true]", 53 | "[false]", 54 | "[1]", 55 | "[-101]", 56 | "[101.101E-101]", 57 | "[\"stringval\"]", 58 | 59 | // Multi Array 60 | "[ null, true, false, 1, -101, 101.101E-101, \"stringval\" ]", 61 | 62 | // Multi Object 63 | "{ \"test\": null, \"ing\": true, \"a\": false, \"b\": -101.101e-101 }" 64 | ]; 65 | 66 | munit( 'Clean', tests.length, function( assert ) { 67 | tests.forEach(function( test, index ) { 68 | var lint = JSONLint( test ); 69 | 70 | assert.ok( index + '', ! lint.error ); 71 | }); 72 | }); 73 | -------------------------------------------------------------------------------- /test/test-invalid.js: -------------------------------------------------------------------------------- 1 | var tests = { 2 | // JSON cannot be empty 3 | "Empty Test": { 4 | json: "", 5 | character: 0, 6 | line: 1 7 | }, 8 | 9 | // There can only be one object/array in a json string 10 | "Multi Object": { 11 | json: "{}[]", 12 | character: 3, 13 | line: 1 14 | }, 15 | 16 | // Invalid Null Value 17 | "Capital NULL": { 18 | json: "{\"test\":NULL}", 19 | character: 9, 20 | line: 1 21 | }, 22 | 23 | // Invalid Boolean Value 24 | "Capital TRUE": { 25 | json: "{\"test\":TRUE}", 26 | character: 9, 27 | line: 1 28 | }, 29 | "Capital FALSE": { 30 | json: "{\"test\":FALSE}", 31 | character: 9, 32 | line: 1 33 | }, 34 | 35 | // Invalid Numeric Values 36 | "+1": { 37 | json: "{\"test\":+1}", 38 | character: 9, 39 | line: 1 40 | }, 41 | "Double Decimal": { 42 | json: "{\"test\":-101.1.23}", 43 | character: 15, 44 | line: 1 45 | }, 46 | "Non Decimal E": { 47 | json: "{\"test\":1e}", 48 | character: 10, 49 | line: 1 50 | }, 51 | "Bad E": { 52 | json: "{\"test\":1.0e}", 53 | character: 13, 54 | line: 1 55 | }, 56 | "Double E": { 57 | json: "{\"test\":-101.101e1e12}", 58 | character: 19, 59 | line: 1 60 | }, 61 | "Double E negative": { 62 | json: "{\"test\":101.101e-101e-12}", 63 | character: 21, 64 | line: 1 65 | }, 66 | "E decimal": { 67 | json: "{\"test\":-101.101E1.102}", 68 | character: 19, 69 | line: 1 70 | }, 71 | 72 | // String Values (more complex in file sheets) 73 | "Bad Close Quote": { 74 | json: "{\"test\":\"go\"od\"}", 75 | character: 13, 76 | line: 1 77 | }, 78 | "Bad Close Quote with spacing": { 79 | json: "{\"test\":\"s p a c \ni \r\nn \"g \"}", 80 | character: 4, 81 | line: 4 82 | }, 83 | "No Close Quote": { 84 | json: "{\"test\":\"good}", 85 | character: 14, 86 | line: 1 87 | }, 88 | "Invalid Reverse Solidus": { 89 | json: "[ \"\\s\" ]", 90 | character: 4, 91 | line: 1 92 | }, 93 | "Invalid Reverse Solidus \\u short": { 94 | json: "[ \"\\u123\" ]", 95 | character: 4, 96 | line: 1 97 | }, 98 | "Invalid Reverse Solidus \\u 1": { 99 | json: "[ \"\\ua234\" ]", 100 | character: 4, 101 | line: 1 102 | }, 103 | "Invalid Reverse Solidus \\u 2": { 104 | json: "[ \"\\u1b34\" ]", 105 | character: 4, 106 | line: 1 107 | }, 108 | "Invalid Reverse Solidus \\u 3": { 109 | json: "[ \"\\u12c4\" ]", 110 | character: 4, 111 | line: 1 112 | }, 113 | "Invalid Reverse Solidus \\u 4": { 114 | json: "[ \"\\u123d\" ]", 115 | character: 4, 116 | line: 1 117 | }, 118 | 119 | // Invalid Brace Notations 120 | "Bad Closing Array": { 121 | json: "[null}", 122 | character: 6, 123 | line: 1 124 | }, 125 | "Bad Closing Object": { 126 | json: "{\"test\":null]", 127 | character: 13, 128 | line: 1 129 | }, 130 | 131 | // Multiple Array Values 132 | "No Comma Array": { 133 | json: "[ null, true, false, 1, -101,\n101.101E-101 \"stringval\" ]", 134 | character: 14, 135 | line: 2 136 | }, 137 | "No Comma Object": { 138 | json: "{\n\"test\": null,\n\"ing\": true,\n\"a\": false\n\"b\": -101.101e-101 }", 139 | character: 1, 140 | line: 5 141 | }, 142 | 143 | // End of array errors 144 | "End of Array Error": { 145 | json: "[ null, ]", 146 | character: 9, 147 | line: 1 148 | }, 149 | 150 | // End of object errors 151 | "End of Object Error": { 152 | json: "{\"test\": null, }", 153 | character: 16, 154 | line: 1 155 | }, 156 | 157 | // End of file Object errors 158 | "EOF Object Nothing": { 159 | json: "{\"test\": null", 160 | character: 13, 161 | line: 1 162 | }, 163 | "EOF Object Comma": { 164 | json: "{\"test\": null,", 165 | character: 14, 166 | line: 1 167 | }, 168 | "EOF Object Space": { 169 | json: "{\"test\": null ", 170 | character: 14, 171 | line: 1 172 | }, 173 | "EOF Object Array": { 174 | json: "{\"test\": [ null ]", 175 | character: 17, 176 | line: 1 177 | }, 178 | 179 | // End of file Array errors 180 | "EOF Array Nothing": { 181 | json: "[ null", 182 | character: 6, 183 | line: 1 184 | }, 185 | "EOF Array Space": { 186 | json: "[ null ", 187 | character: 7, 188 | line: 1 189 | }, 190 | "EOF Array Comma": { 191 | json: "[ null,", 192 | character: 7, 193 | line: 1 194 | }, 195 | "EOF Array object": { 196 | json: "[ null, { \"test\": null } ", 197 | character: 25, 198 | line: 1 199 | } 200 | }; 201 | 202 | munit( 'Inavlid', Object.keys( tests ).count * 2, function( assert ) { 203 | munit.each( tests, function( object, name ) { 204 | var lint = JSONLint( object.json, object.options ); 205 | 206 | if ( ! lint.error ) { 207 | assert.fail( name ); 208 | } 209 | else { 210 | assert.equal( name + '-line', lint.line, object.line ); 211 | assert.equal( name + '-character', lint.character, object.character ); 212 | } 213 | }); 214 | }); 215 | --------------------------------------------------------------------------------