Skip to content

Commit

Permalink
fixed formatters
Browse files Browse the repository at this point in the history
  • Loading branch information
yonamin committed May 4, 2023
1 parent 875b1e8 commit 5487451
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 155 deletions.
2 changes: 1 addition & 1 deletion __fixtures__/expected.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"name":"common","value":[{"name":"follow","stage":"added","value":false},{"name":"setting1","stage":"unchanged","value":"Value 1"},{"name":"setting2","stage":"removed","value":200},{"name":"setting3","stage":"updated","value":{"removed":true,"added":null}},{"name":"setting4","stage":"added","value":"blah blah"},{"name":"setting5","stage":"added","value":{"key5":"value5"}},{"name":"setting6","value":[{"name":"doge","value":[{"name":"wow","stage":"updated","value":{"removed":"","added":"so much"}}],"stage":"nested"},{"name":"key","stage":"unchanged","value":"value"},{"name":"ops","stage":"added","value":"vops"}],"stage":"nested"}],"stage":"nested"},{"name":"group1","value":[{"name":"baz","stage":"updated","value":{"removed":"bas","added":"bars"}},{"name":"foo","stage":"unchanged","value":"bar"},{"name":"nest","stage":"updated","value":{"removed":{"key":"value"},"added":"str"}}],"stage":"nested"},{"name":"group2","stage":"removed","value":{"abc":12345,"deep":{"id":45}}},{"name":"group3","stage":"added","value":{"deep":{"id":{"number":45}},"fee":100500}}]
[{"name":"common","children":[{"name":"follow","stage":"added","value":false},{"name":"setting1","stage":"unchanged","value":"Value 1"},{"name":"setting2","stage":"removed","value":200},{"name":"setting3","stage":"updated","value":{"removed":true,"added":null}},{"name":"setting4","stage":"added","value":"blah blah"},{"name":"setting5","stage":"added","value":{"key5":"value5"}},{"name":"setting6","children":[{"name":"doge","children":[{"name":"wow","stage":"updated","value":{"removed":"","added":"so much"}}],"stage":"nested"},{"name":"key","stage":"unchanged","value":"value"},{"name":"ops","stage":"added","value":"vops"}],"stage":"nested"}],"stage":"nested"},{"name":"group1","children":[{"name":"baz","stage":"updated","value":{"removed":"bas","added":"bars"}},{"name":"foo","stage":"unchanged","value":"bar"},{"name":"nest","stage":"updated","value":{"removed":{"key":"value"},"added":"str"}}],"stage":"nested"},{"name":"group2","stage":"removed","value":{"abc":12345,"deep":{"id":45}}},{"name":"group3","stage":"added","value":{"deep":{"id":{"number":45}},"fee":100500}}]
11 changes: 1 addition & 10 deletions bin/gendiff.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,7 @@ program
.option('-f, --format <type>', 'output format', 'stylish')
.action((filepath1, filepath2) => {
const { format } = program.opts();
switch (format) {
case ('stylish'):
console.log(compare(filepath1, filepath2, 'stylish'));
break;
case ('plain'):
console.log(compare(filepath1, filepath2, 'plain'));
break;
default:
console.log('Unknown format');
}
console.log(compare(filepath1, filepath2, format));
});

program.parse();
47 changes: 0 additions & 47 deletions formatters/plain.js

This file was deleted.

47 changes: 0 additions & 47 deletions formatters/stylish.js

This file was deleted.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@hexlet/code",
"version": "1.0.0",
"type": "module",
"description": "[![Actions Status](https://github.com/yonamin/frontend-project-46/workflows/hexlet-check/badge.svg)](https://github.com/yonamin/frontend-project-46/actions)",
"description": "gendiff can find the difference between two data structures",
"main": "src/index.js",
"bin": {
"gendiff": "bin/gendiff.js"
Expand Down
File renamed without changes.
File renamed without changes.
48 changes: 48 additions & 0 deletions src/formatters/plain.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import _ from 'lodash';

const normalizeValue = (item) => {
if (_.isObject(item)) {
return '[complex value]';
}
if (typeof item === 'string') {
return `'${item}'`;
}
return item;
};

const plain = (tree) => {
const iter = (item, ancestry) => {
const lines = item
.filter((node) => node.stage !== 'unchanged')
.flatMap((node) => {
const { stage } = node;
const { name } = node;
const newAncestry = `${ancestry}.${name}`;
if (stage === 'nested') {
return iter(node.children, newAncestry);
}
const getTail = (status) => {
const value = normalizeValue(node.value);
switch (status) {
case 'added':
return `added with value: ${value}`;
case 'removed':
return 'removed';
case 'updated': {
const removed = `${normalizeValue(node.value.removed)}`;
const added = `${normalizeValue(node.value.added)}`;
return `updated. From ${removed} to ${added}`;
}
default:
return `Unknown stage '${status}'`;
}
};

const tail = getTail(stage);
return `Property '${newAncestry.slice(1)}' was ${tail}`;
});
return lines.join('\n');
};
return iter(tree, '');
};
export default plain;
56 changes: 56 additions & 0 deletions src/formatters/stylish.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import _ from 'lodash';

const stylish = (tree, replacer = ' ', spacesCount = 4) => {
const stringify = (item, depth) => {
if (!_.isObject(item) || item === null) {
return String(item);
}

const indentSize = ((depth * spacesCount) - 2);
const currentIndent = replacer.repeat(indentSize);
const bracketIndent = replacer.repeat(indentSize - 2);

const currentVal = _.isPlainObject(item) ? Object.entries(item) : item;
const lines = currentVal.flatMap((node) => {
const { stage } = node;
if (!stage) {
const [key, value] = node;
return `${currentIndent} ${key}: ${stringify(value, depth + 1)}`;
}
const getSign = (status) => {
switch (status) {
case 'added':
return '+';
case 'removed':
return '-';
default:
return ' ';
}
};

const sign = getSign(stage);
const key = `${sign} ${node.name}`;
const value = stringify(node.value, depth + 1);

if (stage === 'nested') {
return `${currentIndent}${key}: ${stringify(node.children, depth + 1)}`;
}
if (stage === 'updated') {
const removed = stringify(node.value.removed, depth + 1);
const added = stringify(node.value.added, depth + 1);
return `${currentIndent}- ${node.name}: ${removed}\n${currentIndent}+ ${node.name}: ${added}`;
}

return `${currentIndent}${key}: ${value}`;
});

return [
'{',
...lines,
`${bracketIndent}}`,
].join('\n');
};

return stringify(tree, 1);
};
export default stylish;
79 changes: 38 additions & 41 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,49 @@ import path from 'path';
import { cwd } from 'process';
import _ from 'lodash';
import parse from './parsers.js';
import chooseFormat from '../formatters/index.js';
import chooseFormat from './formatters/index.js';

const gendiff = (file1, file2) => {
const diff = (data1, data2) => {
const keys = _.sortBy(_.union(Object.keys(data1), Object.keys(data2)));
const result = keys.map((key) => {
const value1 = _.cloneDeep(data1[key]);
const value2 = _.cloneDeep(data2[key]);
const node = {};
node.name = key;
const buildTree = (file1, file2) => {
const keys = _.sortBy(_.union(Object.keys(file1), Object.keys(file2)));
const result = keys.map((key) => {
const value1 = _.cloneDeep(file1[key]);
const value2 = _.cloneDeep(file2[key]);
const node = {};
node.name = key;

if (!Object.hasOwn(data1, key)) {
node.stage = 'added';
node.value = value2;
return node;
}
if (!Object.hasOwn(data2, key)) {
node.stage = 'removed';
node.value = value1;
return node;
}
if ((_.isPlainObject(value1)) && (_.isPlainObject(value2))) {
node.value = diff(value1, value2);
node.stage = 'nested';
return node;
}

if (value1 === value2) {
node.stage = 'unchanged';
node.value = value1;
return node;
}
if (!Object.hasOwn(file1, key)) {
node.stage = 'added';
node.value = value2;
return node;
}
if (!Object.hasOwn(file2, key)) {
node.stage = 'removed';
node.value = value1;
return node;
}
if ((_.isPlainObject(value1)) && (_.isPlainObject(value2))) {
node.children = buildTree(value1, value2);
node.stage = 'nested';
return node;
}

node.stage = 'updated';
node.value = { removed: value1, added: value2 };
if (value1 === value2) {
node.stage = 'unchanged';
node.value = value1;
return node;
});
return result;
};
return diff(file1, file2);
}

node.stage = 'updated';
node.value = { removed: value1, added: value2 };
return node;
});
return result;
};

export default (filepath1, filepath2, format = 'stylish') => {
const extname1 = path.extname(filepath1);
const extname2 = path.extname(filepath2);
const parsedFile1 = parse(readFileSync(path.resolve(cwd(), filepath1)), extname1);
const parsedFile2 = parse(readFileSync(path.resolve(cwd(), filepath2)), extname2);
return chooseFormat(gendiff(parsedFile1, parsedFile2), format);
const fileFormat1 = path.extname(filepath1).slice(1);
const fileFormat2 = path.extname(filepath2).slice(1);
const parsedFile1 = parse(readFileSync(path.resolve(cwd(), filepath1)), fileFormat1);
const parsedFile2 = parse(readFileSync(path.resolve(cwd(), filepath2)), fileFormat2);
return chooseFormat(buildTree(parsedFile1, parsedFile2), format);
};
17 changes: 9 additions & 8 deletions src/parsers.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import yaml from 'js-yaml';

const parse = (file, extname) => {
let parsed;
if (extname === '.json') {
parsed = JSON.parse(file);
const parse = (data, format) => {
switch (format) {
case 'json':
return JSON.parse(data);
case 'yaml':
case 'yml':
return yaml.load(data);
default:
throw new Error('Unknown format');
}
if (extname === '.yaml' || extname === '.yml') {
parsed = yaml.load(file);
}
return parsed;
};

export default parse;

0 comments on commit 5487451

Please sign in to comment.