Skip to content

Commit

Permalink
{feature} support indentation parameter in stringify
Browse files Browse the repository at this point in the history
  • Loading branch information
bgotink committed Sep 14, 2022
1 parent aae8043 commit 2aa0a56
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 14 deletions.
16 changes: 15 additions & 1 deletion src/json.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,15 @@ interface FromJsonOptions {
* The default value of this option is the value of `allowEntriesInArrays` or `allowEntriesInObjects`, depending on the type of the value.
*/
allowEntriesInRoot?: boolean;

/**
* The indentation to give each nested level of node
*
* If a string is passed, that string is used as indentation.
* If a number higher than zero is passed, the indentation is set to the whitespace character repeated for that number of times.
* If zero is passed or no indentation is given, no newlines with indentation will be inserted into the output.
*/
indentation?: string | number;
}

/**
Expand Down Expand Up @@ -306,6 +315,11 @@ export function parse(text: string, reviver: JiKReviver<unknown>): unknown;
* Stringify the given JSON value into JiK text
*
* @param value The JSON value to encode
* @param indentation The indentation to give each nested level of node, either the actual indentation string or the number of spaces
* @throws If the given JSON value contains cycles.
*/
export function stringify(value: unknown): string;
export function stringify(
value: unknown,
replacer?: null,
indentation?: string | number,
): string;
53 changes: 47 additions & 6 deletions src/json.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export function toJson(nodeOrDocument, options) {
* @param {boolean} [options.allowEntriesInArrays]
* @param {boolean} [options.allowEntriesInObjects]
* @param {boolean} [options.allowEntriesInRoot]
* @param {string | number} [options.indentation]
*/
export function fromJson(
value,
Expand All @@ -182,18 +183,35 @@ export function fromJson(
allowEntriesInArrays = allowEntries,
allowEntriesInObjects = allowEntries,
allowEntriesInRoot,
indentation: indentationStep,
} = {},
) {
return fromJsonValue(
if (typeof indentationStep === 'string') {
indentationStep = indentationStep;
} else if (typeof indentationStep === 'number' && indentationStep > 0) {
indentationStep = ' '.repeat(indentationStep);
} else {
indentationStep = '';
}

const result = fromJsonValue(
value,
{
nodeName,
allowEntriesInArrays,
allowEntriesInObjects,
allowEntriesInCurrent: allowEntriesInRoot,
indentation: '',
indentationStep,
},
new Set(),
);

if (!indentationStep) {
result.trailing = '';
}

return result;
}

/**
Expand All @@ -218,6 +236,8 @@ function isLiteral(value) {
* @param {unknown} value
* @param {object} options
* @param {string} options.nodeName
* @param {string} options.indentation
* @param {string} options.indentationStep
* @param {boolean} options.allowEntriesInArrays
* @param {boolean} options.allowEntriesInObjects
* @param {boolean} [options.allowEntriesInCurrent]
Expand All @@ -228,6 +248,8 @@ function fromJsonValue(
value,
{
nodeName,
indentation,
indentationStep,
allowEntriesInArrays,
allowEntriesInObjects,
allowEntriesInCurrent,
Expand All @@ -242,8 +264,11 @@ function fromJsonValue(
value = /** @type {{toJSON: Function}} */ (value).toJSON();
}

const node = Node.create(nodeName);
node.leading = indentation;
node.trailing = indentationStep ? '\n' : ';';

if (isLiteral(value)) {
const node = Node.create(nodeName);
node.addArgument(value ?? null);
return node;
}
Expand All @@ -256,8 +281,6 @@ function fromJsonValue(

parents.add(value);
try {
const node = Node.create(nodeName);

if (Array.isArray(value)) {
let useChild = !(allowEntriesInCurrent ?? allowEntriesInArrays);

Expand All @@ -279,6 +302,8 @@ function fromJsonValue(
nodeName: arrayItemKey,
allowEntriesInArrays,
allowEntriesInObjects,
indentation: indentation + indentationStep,
indentationStep,
},
parents,
),
Expand Down Expand Up @@ -307,6 +332,8 @@ function fromJsonValue(
nodeName: arrayItemKey,
allowEntriesInArrays,
allowEntriesInObjects,
indentation: indentation + indentationStep,
indentationStep,
},
parents,
),
Expand All @@ -323,6 +350,8 @@ function fromJsonValue(
nodeName: name,
allowEntriesInArrays,
allowEntriesInObjects,
indentation: indentation + indentationStep,
indentationStep,
},
parents,
),
Expand All @@ -332,6 +361,16 @@ function fromJsonValue(
}
}

if (node.children) {
if (indentationStep) {
node.children.nodes[0].leading = `\n${
node.children.nodes[0].leading ?? ''
}`;
}

node.children.trailing = indentation;
}

return node;
} finally {
parents.delete(value);
Expand All @@ -348,7 +387,9 @@ export function parse(string, reviver) {

/**
* @param {unknown} value
* @param {unknown} [_]
* @param {string | number} [indentation]
*/
export function stringify(value) {
return formatKdl(fromJson(value));
export function stringify(value, _, indentation) {
return formatKdl(fromJson(value, {indentation}));
}
44 changes: 37 additions & 7 deletions test/jik.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ test('fromJson options', () => {
arrayProp: [0, 1, [2, 3], 4, 5],
};

expect(format(fromJson(value))).toEqual(
expect(format(clearFormat(fromJson(value)))).toEqual(
format(
clearFormat(
parseKdl(
Expand All @@ -104,7 +104,31 @@ test('fromJson options', () => {
),
);

expect(format(fromJson(value, {allowEntries: false}))).toEqual(
expect(format(fromJson(value))).toEqual(
format(
parseKdl(
`- prop1=false prop2=false {objectProp prop=true;arrayProp 0 1 {- 2 3;- 4;- 5;};}`,
),
),
);

expect(format(fromJson(value, {indentation: 1}))).toEqual(
format(
parseKdl(
`- prop1=false prop2=false {\n objectProp prop=true\n arrayProp 0 1 {\n - 2 3\n - 4\n - 5\n }\n}\n`,
),
),
);

expect(format(fromJson(value, {indentation: '\t'}))).toEqual(
format(
parseKdl(
`- prop1=false prop2=false {\n\tobjectProp prop=true\n\tarrayProp 0 1 {\n\t\t- 2 3\n\t\t- 4\n\t\t- 5\n\t}\n}\n`,
),
),
);

expect(format(clearFormat(fromJson(value, {allowEntries: false})))).toEqual(
format(
clearFormat(
parseKdl(
Expand Down Expand Up @@ -132,7 +156,9 @@ test('fromJson options', () => {
),
);

expect(format(fromJson(value, {allowEntriesInArrays: false}))).toEqual(
expect(
format(clearFormat(fromJson(value, {allowEntriesInArrays: false}))),
).toEqual(
format(
clearFormat(
parseKdl(
Expand All @@ -156,7 +182,9 @@ test('fromJson options', () => {
),
);

expect(format(fromJson(value, {allowEntriesInObjects: false}))).toEqual(
expect(
format(clearFormat(fromJson(value, {allowEntriesInObjects: false}))),
).toEqual(
format(
clearFormat(
parseKdl(
Expand All @@ -179,7 +207,9 @@ test('fromJson options', () => {
),
);

expect(format(fromJson(value, {allowEntriesInRoot: false}))).toEqual(
expect(
format(clearFormat(fromJson(value, {allowEntriesInRoot: false}))),
).toEqual(
format(
clearFormat(
parseKdl(
Expand Down Expand Up @@ -232,14 +262,14 @@ test('parse reviver', () => {

test('stringify supports toJSON methods', () => {
expect(stringify(new Date('2022-09-09T10:23:23.445Z'))).toBe(
'- "2022-09-09T10:23:23.445Z"\n',
'- "2022-09-09T10:23:23.445Z"',
);

expect(
stringify({
toJSON: () => ['an', 'array'],
}),
).toBe('- "an" "array"\n');
).toBe('- "an" "array"');
});

test.run();

0 comments on commit 2aa0a56

Please sign in to comment.