Skip to content

Commit e86fbde

Browse files
authored
feat: nodeHasChanged option + diff annotations (#204)
1 parent b41cd0c commit e86fbde

File tree

14 files changed

+532
-223
lines changed

14 files changed

+532
-223
lines changed

package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@
3939
},
4040
"peerDependencies": {
4141
"@stoplight/markdown-viewer": "^5",
42-
"@stoplight/mosaic": "^1",
43-
"@stoplight/mosaic-code-viewer": "^1",
42+
"@stoplight/mosaic": "^1.32",
43+
"@stoplight/mosaic-code-viewer": "^1.32",
4444
"react": ">=16.8",
4545
"react-dom": ">=16.8"
4646
},
@@ -50,6 +50,7 @@
5050
"@stoplight/react-error-boundary": "^2.0.0",
5151
"@types/json-schema": "^7.0.7",
5252
"classnames": "^2.2.6",
53+
"fnv-plus": "^1.3.1",
5354
"jotai": "^1.4.5",
5455
"lodash": "^4.17.19"
5556
},
@@ -58,10 +59,10 @@
5859
"@size-limit/preset-big-lib": "^4.11.0",
5960
"@stoplight/eslint-config": "3.0.0",
6061
"@stoplight/markdown-viewer": "^5.3.3",
61-
"@stoplight/mosaic": "^1.24.2",
62-
"@stoplight/mosaic-code-viewer": "^1.24.2",
62+
"@stoplight/mosaic": "^1.32.0",
63+
"@stoplight/mosaic-code-viewer": "^1.32.0",
6364
"@stoplight/scripts": "9.2.0",
64-
"@stoplight/types": "^12.3.0",
65+
"@stoplight/types": "^13.7.0",
6566
"@storybook/addon-essentials": "^6.4.14",
6667
"@storybook/builder-webpack5": "^6.4.14",
6768
"@storybook/core": "6.4.14",

src/__fixtures__/diff/root-ref.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"title": "User",
3+
"type": "object",
4+
"x-stoplight": { "id": "root-id" },
5+
"properties": {
6+
"billing_address": {
7+
"type": "string",
8+
"title": "Billing Address",
9+
"x-stoplight": { "id": "billing_address-id" },
10+
"$ref": "#/$defs/Address"
11+
}
12+
},
13+
"$defs": {
14+
"Address": {
15+
"type": "object",
16+
"title": "Address",
17+
"x-stoplight": { "id": "address-id" },
18+
"properties": {
19+
"street": {
20+
"type": "string",
21+
"x-stoplight": { "id": "address-street-id" }
22+
}
23+
}
24+
}
25+
}
26+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
{
2+
"title": "User",
3+
"type": "object",
4+
"x-stoplight": { "id": "root-id" },
5+
"properties": {
6+
"name": {
7+
"type": "string",
8+
"const": "Constant name",
9+
"examples": ["Example name", "Different name"],
10+
"x-stoplight": { "id": "name-id" }
11+
},
12+
"age": {
13+
"type": "number",
14+
"minimum": 10,
15+
"maximum": 40,
16+
"x-stoplight": { "id": "age-id" }
17+
},
18+
"completed_at": {
19+
"type": "string",
20+
"format": "date-time",
21+
"x-stoplight": { "id": "completed_at-id" }
22+
},
23+
"list": {
24+
"type": ["null", "array"],
25+
"items": {
26+
"type": ["string", "number"],
27+
"x-stoplight": { "id": "list-items-id" }
28+
},
29+
"minItems": 1,
30+
"maxItems": 4,
31+
"x-stoplight": { "id": "list-id" }
32+
},
33+
"email": {
34+
"type": "string",
35+
"format": "email",
36+
37+
"deprecated": true,
38+
"default": "[email protected]",
39+
"minLength": 2,
40+
"x-stoplight": { "id": "email-id" }
41+
},
42+
"list-of-objects": {
43+
"type": "array",
44+
"items": {
45+
"type": "object",
46+
"x-stoplight": { "id": "list-of-objects-items-id" },
47+
"properties": {
48+
"id": {
49+
"type": "string",
50+
"x-stoplight": { "id": "list-of-objects-items-id-id" }
51+
},
52+
"friend": {
53+
"type": "object",
54+
"x-stoplight": { "id": "list-of-objects-items-friend-id" },
55+
"properties": {
56+
"id": {
57+
"type": "string",
58+
"x-stoplight": { "id": "list-of-objects-items-friend-id-id" }
59+
},
60+
"name": {
61+
"type": "object",
62+
"x-stoplight": { "id": "list-of-objects-items-friend-name-id" },
63+
"properties": {
64+
"first": {
65+
"type": "string",
66+
"x-stoplight": { "id": "list-of-objects-items-friend-name-first-id" }
67+
},
68+
"last": {
69+
"type": "string",
70+
"x-stoplight": { "id": "list-of-objects-items-friend-name-last-id" }
71+
}
72+
}
73+
}
74+
}
75+
}
76+
}
77+
},
78+
"minItems": 1,
79+
"maxItems": 4,
80+
"x-stoplight": { "id": "list-of-objects-id" }
81+
},
82+
"friend": {
83+
"type": "object",
84+
"x-stoplight": { "id": "friend-id" },
85+
"properties": {
86+
"id": {
87+
"type": "string",
88+
"x-stoplight": { "id": "friend-id-id" }
89+
},
90+
"name": {
91+
"type": "string",
92+
"x-stoplight": { "id": "friend-name-id" }
93+
}
94+
}
95+
}
96+
}
97+
}

src/__stories__/Diff.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type { NodeHasChangedFn } from '@stoplight/types';
2+
import { Story } from '@storybook/react';
3+
import { JSONSchema4 } from 'json-schema';
4+
import React from 'react';
5+
6+
import { JsonSchemaProps, JsonSchemaViewer } from '../components/JsonSchemaViewer';
7+
8+
const defaultSchema = require('../__fixtures__/default-schema.json');
9+
const simpleExample = require('../__fixtures__/diff/simple-example.json');
10+
const rootRefExample = require('../__fixtures__/diff/root-ref.json');
11+
12+
export default {
13+
component: JsonSchemaViewer,
14+
argTypes: {},
15+
};
16+
17+
const changed: Record<string, ReturnType<NodeHasChangedFn>> = {
18+
'age-id': { type: 'removed' },
19+
'list-id': { type: 'modified', selfAffected: true },
20+
'list-of-objects-id': { type: 'modified', isBreaking: true },
21+
'list-of-objects-items-friend-id': { type: 'modified', isBreaking: true },
22+
'list-of-objects-items-friend-name-id': { type: 'modified', selfAffected: true, isBreaking: true },
23+
'list-of-objects-items-friend-name-last-id': { type: 'added', isBreaking: true },
24+
'friend-id': { type: 'added', isBreaking: true },
25+
'address-street-id': { type: 'added' },
26+
};
27+
const nodeHasChanged: NodeHasChangedFn = ({ nodeId }) => {
28+
const change = changed[nodeId!];
29+
return change || false;
30+
};
31+
32+
const Template: Story<JsonSchemaProps> = ({ schema = defaultSchema as JSONSchema4, ...args }) => (
33+
<JsonSchemaViewer schema={schema} {...args} nodeHasChanged={nodeHasChanged} />
34+
);
35+
36+
export const SimpleAllOf = Template.bind({});
37+
SimpleAllOf.args = { schema: simpleExample as JSONSchema4 };
38+
39+
export const RootRef = Template.bind({});
40+
RootRef.args = { schema: rootRefExample as JSONSchema4 };

0 commit comments

Comments
 (0)