Skip to content

Commit

Permalink
Merge pull request #111 from Spy-Seth/fix/flow-errors
Browse files Browse the repository at this point in the history
Fix flow errors
  • Loading branch information
armandabric committed Jul 21, 2017
2 parents 90af0c5 + cf231a9 commit a97e5ea
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 74 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"prepublish": "npm run build",
"prebuild": "mkdir -p dist && rm -rf ./dist/*",
"prettier:fix": "prettier --write --single-quote --trailing-comma es5 \"{src/**/*.js,package.json}\"",
"test": "jest && npm run lint",
"test": "jest && npm run lint && yarn run flow",
"test:watch": "jest --watch",
"release": "./release.sh"
},
Expand Down
4 changes: 2 additions & 2 deletions src/formatter/formatComplexDataStructure.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { isValidElement } from 'react';
import stringify from 'stringify-object';
import sortobject from 'sortobject';
import parseReactElement from './../parser/parseReactElement';
import formatReactElementNode from './formatReactElementNode';
import formatTreeNode from './formatTreeNode';
import spacer from './spacer';
import type { Options } from './../options';

Expand All @@ -24,7 +24,7 @@ export default (
const currentValue = currentObj[prop];

if (currentValue && isValidElement(currentValue)) {
return formatReactElementNode(
return formatTreeNode(
parseReactElement(currentValue, options),
true,
lvl,
Expand Down
3 changes: 3 additions & 0 deletions src/formatter/formatPropValue.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ const formatPropValue = (
return `"${escape(propValue)}"`;
}

// > "Symbols (new in ECMAScript 2015, not yet supported in Flow)"
// @see: https://flow.org/en/docs/types/primitives/
// $FlowFixMe: Flow does not support Symbol
if (typeof propValue === 'symbol') {
return `{${String(propValue)}}`;
}
Expand Down
6 changes: 3 additions & 3 deletions src/formatter/formatReactElementNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import formatProp from './formatProp';
import mergeSiblingPlainStringChildrenReducer from './mergeSiblingPlainStringChildrenReducer';
import propNameSorter from './propNameSorter';
import type { Options } from './../options';
import type { TreeNode } from './../tree';
import type { ReactElementTreeNode } from './../tree';

const recurse = (lvl: number, inline: boolean, options: Options) => element =>
formatTreeNode(element, inline, lvl, options);
Expand Down Expand Up @@ -56,15 +56,15 @@ const shouldRenderMultilineAttr = (
!inline;

export default (
node: TreeNode,
node: ReactElementTreeNode,
inline: boolean,
lvl: number,
options: Options
): string => {
const {
type,
displayName = '',
childrens = [],
childrens,
props = {},
defaultProps = {},
} = node;
Expand Down
4 changes: 2 additions & 2 deletions src/formatter/formatTree.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* @flow */

import formatReactElementNode from './formatReactElementNode';
import formatTreeNode from './formatTreeNode';
import type { Options } from './../options';
import type { TreeNode } from './../tree';

export default (node: TreeNode, options: Options): string =>
formatReactElementNode(node, false, 0, options);
formatTreeNode(node, false, 0, options);
13 changes: 3 additions & 10 deletions src/formatter/formatTree.spec.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
/* @flow */

import formatTree from './formatTree';
import formatReactElementNode from './formatReactElementNode';
import formatTreeNode from './formatTreeNode';

jest.mock('./formatReactElementNode', () =>
jest.fn(() => '<MockedComponent />')
);
jest.mock('./formatTreeNode', () => jest.fn(() => '<MockedComponent />'));

describe('formatTree', () => {
it('should format the node as a root node', () => {
Expand All @@ -14,12 +12,7 @@ describe('formatTree', () => {

const result = formatTree(tree, options);

expect(formatReactElementNode).toHaveBeenCalledWith(
tree,
false,
0,
options
);
expect(formatTreeNode).toHaveBeenCalledWith(tree, false, 0, options);

expect(result).toBe('<MockedComponent />');
});
Expand Down
34 changes: 20 additions & 14 deletions src/formatter/mergeSiblingPlainStringChildrenReducer.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,35 @@
/* @flow */

import { createStringTreeNode } from './../tree';
import type { TreeNode } from './../tree';

export default (
previousNodes: TreeNode[],
currentNode: TreeNode
): TreeNode[] => {
const lastNode = previousNodes[previousNodes.length - 1];
const newNode = { ...currentNode };

if (newNode.type === 'number') {
newNode.type = 'string';
newNode.value = String(newNode.value);
}
const nodes = previousNodes.slice(
0,
previousNodes.length > 0 ? previousNodes.length - 1 : 0
);
const previousNode = previousNodes[previousNodes.length - 1];

if (
lastNode &&
lastNode.type === 'string' &&
typeof lastNode.value === 'string' &&
newNode.type === 'string'
previousNode &&
(currentNode.type === 'string' || currentNode.type === 'number') &&
(previousNode.type === 'string' || previousNode.type === 'number')
) {
lastNode.value += newNode.value || '';
nodes.push(
createStringTreeNode(
String(previousNode.value) + String(currentNode.value)
)
);
} else {
previousNodes.push(newNode);
if (previousNode) {
nodes.push(previousNode);
}

nodes.push(currentNode);
}

return previousNodes;
return nodes;
};
71 changes: 46 additions & 25 deletions src/formatter/mergeSiblingPlainStringChildrenReducer.spec.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
/* @flow */

import mergeSiblingPlainStringChildrenReducer from './mergeSiblingPlainStringChildrenReducer';
import {
createNumberTreeNode,
createStringTreeNode,
createReactElementTreeNode,
} from './../tree';
import type { TreeNode } from './../tree';

const createScalarTreeNode = (type, value) => ({ type, value });
const createReactElementTreeNode = childrens => ({
type: 'ReactElement',
childrens,
});

test('mergeSiblingPlainStringChildrenReducer should merge sibling string tree nodes', () => {
const childrens: TreeNode[] = [
createScalarTreeNode('string', 'a'),
createScalarTreeNode('string', 'b'),
createScalarTreeNode('string', 'c'),
createStringTreeNode('a'),
createStringTreeNode('b'),
createStringTreeNode('c'),
];

expect(childrens.reduce(mergeSiblingPlainStringChildrenReducer, [])).toEqual([
Expand All @@ -24,35 +23,51 @@ test('mergeSiblingPlainStringChildrenReducer should merge sibling string tree no
]);
});

test('mergeSiblingPlainStringChildrenReducer should merge consider number as string', () => {
const childrens: TreeNode[] = [
createScalarTreeNode('string', 'a'),
createScalarTreeNode('number', 51),
createScalarTreeNode('string', 'c'),
];

expect(childrens.reduce(mergeSiblingPlainStringChildrenReducer, [])).toEqual([
test('mergeSiblingPlainStringChildrenReducer should consider number as string', () => {
expect(
[
createStringTreeNode('a'),
createNumberTreeNode(51),
createStringTreeNode('c'),
].reduce(mergeSiblingPlainStringChildrenReducer, [])
).toEqual([
{
type: 'string',
value: 'a51c',
},
]);

expect(
[
createStringTreeNode(5),
createNumberTreeNode(1),
createStringTreeNode('a'),
].reduce(mergeSiblingPlainStringChildrenReducer, [])
).toEqual([
{
type: 'string',
value: '51a',
},
]);
});

test('mergeSiblingPlainStringChildrenReducer should merge detect non string node', () => {
test('mergeSiblingPlainStringChildrenReducer should detect non string node', () => {
const childrens: TreeNode[] = [
createReactElementTreeNode(['foo']),
createScalarTreeNode('string', 'a'),
createScalarTreeNode('number', 'b'),
createReactElementTreeNode(['bar']),
createScalarTreeNode('string', 'c'),
createScalarTreeNode('number', 42),
createReactElementTreeNode(['baz']),
createReactElementTreeNode('MyFoo', {}, {}, ['foo']),
createStringTreeNode('a'),
createNumberTreeNode('b'),
createReactElementTreeNode('MyBar', {}, {}, ['bar']),
createStringTreeNode('c'),
createNumberTreeNode(42),
createReactElementTreeNode('MyBaz', {}, {}, ['baz']),
];

expect(childrens.reduce(mergeSiblingPlainStringChildrenReducer, [])).toEqual([
{
type: 'ReactElement',
displayName: 'MyFoo',
props: {},
defaultProps: {},
childrens: ['foo'],
},
{
Expand All @@ -61,6 +76,9 @@ test('mergeSiblingPlainStringChildrenReducer should merge detect non string node
},
{
type: 'ReactElement',
displayName: 'MyBar',
props: {},
defaultProps: {},
childrens: ['bar'],
},
{
Expand All @@ -69,6 +87,9 @@ test('mergeSiblingPlainStringChildrenReducer should merge detect non string node
},
{
type: 'ReactElement',
displayName: 'MyBaz',
props: {},
defaultProps: {},
childrens: ['baz'],
},
]);
Expand Down
22 changes: 12 additions & 10 deletions src/parser/parseReactElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

import { Children, Element, isValidElement } from 'react';
import type { Options } from './../options';
import {
createStringTreeNode,
createNumberTreeNode,
createReactElementTreeNode,
} from './../tree';
import type { TreeNode } from './../tree';

const getReactElementDisplayName = (element: Element<*>): string =>
Expand Down Expand Up @@ -34,13 +39,11 @@ const parseReactElement = (
options: Options
): TreeNode => {
const { displayName: displayNameFn = getReactElementDisplayName } = options;
const type = typeof element;

if (type === 'string' || type === 'number') {
return {
type,
value: element,
};
if (typeof element === 'string') {
return createStringTreeNode(element);
} else if (typeof element === 'number') {
return createNumberTreeNode(element);
} else if (!isValidElement(element)) {
throw new Error(
`react-element-to-jsx-string: Expected a React.Element, got \`${typeof element}\``
Expand All @@ -65,13 +68,12 @@ const parseReactElement = (
.filter(onlyMeaningfulChildren)
.map(child => parseReactElement(child, options));

return {
type: 'ReactElement',
return createReactElementTreeNode(
displayName,
props,
defaultProps,
childrens,
};
childrens
);
};

export default parseReactElement;
50 changes: 43 additions & 7 deletions src/tree.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,48 @@
/* @flow */
/* eslint-disable no-use-before-define */

export type TreeNode = {|
type: 'ReactElement' | 'string' | 'number',
type PropsType = { [key: string]: any };
type DefaultPropsType = { [key: string]: any };

value?: string | number,
export type StringTreeNode = {|
type: 'string',
value: string,
|};

export type NumberTreeNode = {|
type: 'number',
value: number,
|};

displayName?: string,
props?: { [key: string]: TreeNode },
defaultProps?: { [key: string]: TreeNode },
childrens?: TreeNode[],
export type ReactElementTreeNode = {|
type: 'ReactElement',
displayName: string,
props: PropsType,
defaultProps: DefaultPropsType,
childrens: TreeNode[],
|};

export type TreeNode = StringTreeNode | NumberTreeNode | ReactElementTreeNode;

export const createStringTreeNode = (value: string): StringTreeNode => ({
type: 'string',
value,
});

export const createNumberTreeNode = (value: number): NumberTreeNode => ({
type: 'number',
value,
});

export const createReactElementTreeNode = (
displayName: string,
props: PropsType,
defaultProps: DefaultPropsType,
childrens: TreeNode[]
): ReactElementTreeNode => ({
type: 'ReactElement',
displayName,
props,
defaultProps,
childrens,
});
Loading

0 comments on commit a97e5ea

Please sign in to comment.