Skip to content

Commit c4908bb

Browse files
bschlenkarmandabric
authored andcommitted
feat: allow filterProps to be a function (#417)
1 parent 7c92d58 commit c4908bb

6 files changed

+86
-4
lines changed

README.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,13 @@ console.log(reactElementToJSXString(<div a="1" b="2">Hello, world!</div>));
7070

7171
Just return the name you want for the provided ReactElement, as a string.
7272

73-
**options.filterProps: array, default []**
73+
**options.filterProps: string[] | (val: any, key: string) => boolean, default []**
7474

75-
Provide an array of props to filter for every component. For example ['key'] will suppress the key="" prop from being added.
75+
If an array of strings is passed, filter out any prop who's name is in
76+
the array. For example ['key'] will suppress the key="" prop from being added.
77+
78+
If a function is passed, it will be called for each prop with two arguments,
79+
the prop value and key, and will filter out any that return false.
7680

7781
**options.showDefaultProps: boolean, default true**
7882

src/formatter/createPropFilter.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/* @flow */
2+
3+
export default function createPropFilter(
4+
props: {},
5+
filter: string[] | ((any, string) => boolean)
6+
) {
7+
if (Array.isArray(filter)) {
8+
return (key: string) => filter.indexOf(key) === -1;
9+
} else {
10+
return (key: string) => filter(props[key], key);
11+
}
12+
}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* @flow */
2+
3+
import createPropFilter from './createPropFilter';
4+
5+
describe('createPropFilter', () => {
6+
it('should filter based on an array of keys', () => {
7+
const props = { a: 1, b: 2, c: 3 };
8+
const filter = createPropFilter(props, ['b']);
9+
10+
const filteredPropKeys = Object.keys(props).filter(filter);
11+
12+
expect(filteredPropKeys).toEqual(['a', 'c']);
13+
});
14+
15+
it('should filter based on a callback', () => {
16+
const props = { a: 1, b: 2, c: 3 };
17+
const filter = createPropFilter(
18+
props,
19+
(val, key) => key !== 'b' && val < 3
20+
);
21+
22+
const filteredPropKeys = Object.keys(props).filter(filter);
23+
24+
expect(filteredPropKeys).toEqual(['a']);
25+
});
26+
});

src/formatter/formatReactElementNode.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import formatTreeNode from './formatTreeNode';
55
import formatProp from './formatProp';
66
import mergeSiblingPlainStringChildrenReducer from './mergeSiblingPlainStringChildrenReducer';
77
import sortPropsByNames from './sortPropsByNames';
8+
import createPropFilter from './createPropFilter';
89
import type { Options } from './../options';
910
import type { ReactElementTreeNode } from './../tree';
1011

@@ -126,13 +127,15 @@ export default (
126127

127128
const visibleAttributeNames = [];
128129

130+
const propFilter = createPropFilter(props, filterProps);
131+
129132
Object.keys(props)
130-
.filter(propName => filterProps.indexOf(propName) === -1)
133+
.filter(propFilter)
131134
.filter(onlyPropsWithOriginalValue(defaultProps, props))
132135
.forEach(propName => visibleAttributeNames.push(propName));
133136

134137
Object.keys(defaultProps)
135-
.filter(defaultPropName => filterProps.indexOf(defaultPropName) === -1)
138+
.filter(propFilter)
136139
.filter(() => showDefaultProps)
137140
.filter(defaultPropName => !visibleAttributeNames.includes(defaultPropName))
138141
.forEach(defaultPropName => visibleAttributeNames.push(defaultPropName));

src/formatter/formatReactElementNode.spec.js

+26
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,30 @@ describe('formatReactElementNode', () => {
125125
</div>`
126126
);
127127
});
128+
129+
it('should allow filtering props by function', () => {
130+
const tree = {
131+
type: 'ReactElement',
132+
displayName: 'h1',
133+
defaultProps: {},
134+
props: { className: 'myClass', onClick: () => {} },
135+
childrens: [
136+
{
137+
value: 'Hello world',
138+
type: 'string',
139+
},
140+
],
141+
};
142+
143+
const options = {
144+
...defaultOptions,
145+
filterProps: (val, key) => !key.startsWith('on'),
146+
};
147+
148+
expect(formatReactElementNode(tree, false, 0, options)).toEqual(
149+
`<h1 className="myClass">
150+
Hello world
151+
</h1>`
152+
);
153+
});
128154
});

src/index.spec.js

+11
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,17 @@ describe('reactElementToJSXString(ReactElement)', () => {
794794
).toEqual('<TestComponent a="b" />');
795795
});
796796

797+
it("reactElementToJSXString(<TestComponent />, { filterProps: () => !key.startsWith('some')) })", () => {
798+
expect(
799+
reactElementToJSXString(
800+
<TestComponent a="b" someProp="foo" someOtherProp={false} />,
801+
{
802+
filterProps: (val, key) => !key.startsWith('some'),
803+
}
804+
)
805+
).toEqual('<TestComponent a="b" />');
806+
});
807+
797808
it('reactElementToJSXString(<TestComponent />, { useBooleanShorthandSyntax: false })', () => {
798809
expect(
799810
reactElementToJSXString(

0 commit comments

Comments
 (0)