Skip to content

Make tab width configurable #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ When a domain-specific language that compiles to JavaScript uses JSON as a forma

#### Editing forms/JSON

When a form also allows to edit JSON representation of data on the same screen, this module can be used to sinchronise navigation in JSON and in the form.
When a form also allows to edit JSON representation of data on the same screen, this module can be used to synchronise navigation in JSON and in the form.


## Usage
Expand Down Expand Up @@ -107,11 +107,12 @@ Location object has properties (zero-based numbers):

Options:
- _bigint_: parse large integers as [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).
- _tabWidth_: tab width for column calculation

Whitespace:
- the only character that increases line number in mappings is line feed ('\n'), so if your JSON string has '\r\n' sequence, it will still be counted as one line,
- both '\r' and '\n' are counted as a character when determining `pos` (it is possible to slice sections of JSON string using `pos` property), but `column` counter is reset when `r` or `n` is encountered,
- tabs ('\t') are counted as four spaces when determining `column` but as a single character for `pos`.
- tabs ('\t') are by default counted as four spaces (configurable through the `tabWidth` option) when determining `column` but as a single character for `pos`.

Comparison with the standard `JSON.parse`:
- when it is not possible to parse JSON, a SyntaxError exception with exactly the same message is thrown,
Expand All @@ -132,6 +133,7 @@ Comparison with the standard `JSON.stringify`:
Options:
- _space_: same as `space` parameter.
- _es6_: stringify ES6 Maps, Sets and Typed arrays (as JSON arrays).
- _tabWidth_: need to be the same as for `parse` to get identical result


## License
Expand Down
9 changes: 7 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ exports.parse = function (source, _, options) {
var column = 0;
var pos = 0;
var bigint = options && options.bigint && typeof BigInt != 'undefined';
var tabWidth = (options && options.tabWidth && typeof options.tabWidth === 'number') ? options.tabWidth : 4;
Copy link
Author

@mischnic mischnic Nov 1, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change produces a lint error. Not sure how this should be resolved

json-source-map/index.js
  240:21  error  Function has a complexity of 17. Maximum allowed is 15  complexity

return {
data: _parse('', true),
pointers: pointers
Expand Down Expand Up @@ -55,7 +56,7 @@ exports.parse = function (source, _, options) {
while (pos < source.length) {
switch (source[pos]) {
case ' ': column++; break;
case '\t': column += 4; break;
case '\t': column += tabWidth; break;
case '\r': column = 0; break;
case '\n': column = 0; line++; break;
default: break loop;
Expand Down Expand Up @@ -243,6 +244,10 @@ exports.stringify = function (data, _, options) {
var whitespace = typeof options == 'object'
? options.space
: options;
var tabWidth = (typeof options == 'object' &&
typeof options.tabWidth === 'number')
? options.tabWidth
: 4;
switch (typeof whitespace) {
case 'number':
var len = whitespace > 10
Expand All @@ -262,7 +267,7 @@ exports.stringify = function (data, _, options) {
var char = whitespace[j];
switch (char) {
case ' ': wsColumn++; break;
case '\t': wsColumn += 4; break;
case '\t': wsColumn += tabWidth; break;
case '\r': wsColumn = 0; break;
case '\n': wsColumn = 0; wsLine++; break;
default: throw new Error('whitespace characters not allowed in JSON');
Expand Down
42 changes: 39 additions & 3 deletions spec/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,40 @@ describe('parse', function() {
});
});

it.only('should support whitespace with tabs and custom tabWidth', function () {
var json = '{\n\
\t"foo": [\n\
\t\t{\n\
\t\t\t"bar": true\n\
\t\t}\n\
\t]\n\
}';

var pointers = testParse(json, JSON.parse(json), null, '\t', {tabWidth: 1});
assert.deepStrictEqual(pointers, {
'': {
value: { line: 0, column: 0, pos: 0 },
valueEnd: { line: 6, column: 1, pos: 39 }
},
'/foo': {
key: { line: 1, column: 1, pos: 3 },
keyEnd: { line: 1, column: 6, pos: 8 },
value: { line: 1, column: 8, pos: 10 },
valueEnd: { line: 5, column: 2, pos: 37 }
},
'/foo/0': {
value: { line: 2, column: 2, pos: 14 },
valueEnd: { line: 4, column: 3, pos: 34 }
},
'/foo/0/bar': {
key: { line: 3, column: 3, pos: 19 },
keyEnd: { line: 3, column: 8, pos: 24 },
value: { line: 3, column: 10, pos: 26 },
valueEnd: { line: 3, column: 14, pos: 30 }
}
});
});

it('should support whitespace with CRs', function () {
var json = '{\r\n\
"foo": [\r\n\
Expand Down Expand Up @@ -293,15 +327,17 @@ describe('parse', function() {
});


function testParse(json, expectedData, skipReverseCheck, whitespace) {
var result = jsonMap.parse(json);
function testParse(json, expectedData, skipReverseCheck, whitespace, options) {
var result = jsonMap.parse(json, null, options);
var data = result.data;
var pointers = result.pointers;
assert.deepStrictEqual(data, expectedData);
testResult(json, pointers, data);

if (!skipReverseCheck) {
var reverseResult = jsonMap.stringify(expectedData, null, whitespace);
var reverseResult = jsonMap.stringify(expectedData, null, {
space: whitespace, tabWidth: options && options.tabWidth
});
assert.strictEqual(json, reverseResult.json);
assert.deepStrictEqual(pointers, reverseResult.pointers);
}
Expand Down