docusaurus-plugin-generate-schema-docs 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +28 -0
  2. package/__tests__/ExampleDataLayer.test.js +13 -0
  3. package/__tests__/__fixtures__/static/schemas/anchor/parent-event-anchor.json +29 -0
  4. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/add-to-cart-event.json +45 -0
  5. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/choice-event.json +78 -0
  6. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/complex-event.json +193 -0
  7. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/components/dataLayer.json +56 -0
  8. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/components/product.json +126 -0
  9. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/purchase-event.json +73 -0
  10. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/root-any-of-event.json +40 -0
  11. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/root-choice-event.json +54 -0
  12. package/__tests__/__snapshots__/generateEventDocs.anchor.test.js.snap +79 -0
  13. package/__tests__/__snapshots__/generateEventDocs.nested.test.js.snap +8 -2
  14. package/__tests__/__snapshots__/generateEventDocs.test.js.snap +20 -5
  15. package/__tests__/__snapshots__/generateEventDocs.versioned.test.js.snap +8 -2
  16. package/__tests__/components/PropertiesTable.test.js +34 -1
  17. package/__tests__/components/PropertyRow.test.js +5 -5
  18. package/__tests__/generateEventDocs.anchor.test.js +71 -0
  19. package/__tests__/helpers/example-helper.test.js +71 -0
  20. package/__tests__/helpers/getConstraints.test.js +72 -27
  21. package/__tests__/helpers/schemaToTableData.test.js +28 -33
  22. package/__tests__/helpers/validator.test.js +115 -0
  23. package/__tests__/validateSchemas-integration.test.js +29 -0
  24. package/__tests__/validateSchemas.test.js +18 -102
  25. package/components/ExampleDataLayer.js +14 -5
  26. package/components/PropertiesTable.js +22 -7
  27. package/components/PropertiesTable.module.css +27 -0
  28. package/components/PropertyRow.js +24 -25
  29. package/components/SchemaRows.css +6 -0
  30. package/components/SchemaViewer.js +2 -2
  31. package/components/WordWrapButton.js +31 -0
  32. package/components/wordWrapButton.module.css +8 -0
  33. package/generateEventDocs.js +2 -1
  34. package/helpers/buildExampleFromSchema.js +49 -52
  35. package/helpers/example-helper.js +41 -0
  36. package/helpers/file-system.js +1 -2
  37. package/helpers/getConstraints.js +1 -0
  38. package/helpers/schema-doc-template.js +8 -1
  39. package/helpers/schema-processing.js +2 -15
  40. package/helpers/schemaToExamples.js +46 -74
  41. package/helpers/schemaToTableData.js +4 -3
  42. package/helpers/validator.js +108 -0
  43. package/index.js +18 -9
  44. package/package.json +1 -2
  45. package/validateSchemas.js +70 -53
  46. package/__tests__/helpers/loadSchema.test.js +0 -20
  47. package/helpers/loadSchema.js +0 -11
@@ -0,0 +1,71 @@
1
+ import {
2
+ getExamples,
3
+ getSingleExampleValue,
4
+ } from '../../helpers/example-helper';
5
+
6
+ describe('example-helper', () => {
7
+ describe('getExamples', () => {
8
+ it('returns "const" as the only example when present', () => {
9
+ const schema = {
10
+ examples: ['example1'],
11
+ const: 'const-value',
12
+ };
13
+ expect(getExamples(schema)).toEqual(['const-value']);
14
+ });
15
+
16
+ it('aggregates "examples", "example", and "default"', () => {
17
+ const schema = {
18
+ examples: ['example1'],
19
+ example: 'example2',
20
+ default: 'default-value',
21
+ };
22
+ expect(getExamples(schema)).toEqual([
23
+ 'example1',
24
+ 'example2',
25
+ 'default-value',
26
+ ]);
27
+ });
28
+
29
+ it('handles duplicates', () => {
30
+ const schema = {
31
+ examples: ['example1'],
32
+ example: 'example1',
33
+ default: 'example1',
34
+ };
35
+ expect(getExamples(schema)).toEqual(['example1']);
36
+ });
37
+ });
38
+
39
+ describe('getSingleExampleValue', () => {
40
+ it('returns "const" when present', () => {
41
+ const schema = {
42
+ const: 'const-value',
43
+ examples: ['example1'],
44
+ };
45
+ expect(getSingleExampleValue(schema)).toBe('const-value');
46
+ });
47
+
48
+ it('returns the first "examples" when "const" is not present', () => {
49
+ const schema = {
50
+ examples: ['example1', 'example2'],
51
+ default: 'default-value',
52
+ };
53
+ expect(getSingleExampleValue(schema)).toBe('example1');
54
+ });
55
+
56
+ it('returns "example" when "const" and "examples" are not present', () => {
57
+ const schema = {
58
+ example: 'example',
59
+ default: 'default-value',
60
+ };
61
+ expect(getSingleExampleValue(schema)).toBe('example');
62
+ });
63
+
64
+ it('returns "default" as a fallback', () => {
65
+ const schema = {
66
+ default: 'default-value',
67
+ };
68
+ expect(getSingleExampleValue(schema)).toBe('default-value');
69
+ });
70
+ });
71
+ });
@@ -2,8 +2,11 @@ import { getConstraints } from '../../helpers/getConstraints';
2
2
 
3
3
  describe('getConstraints', () => {
4
4
  it('should return "required" if isReq is true', () => {
5
- const constraints = getConstraints({}, true);
6
- expect(constraints).toContain('required');
5
+ expect(getConstraints({}, true)).toEqual(['required']);
6
+ });
7
+
8
+ it('should return an empty array if isReq is false and there are no other constraints', () => {
9
+ expect(getConstraints({}, false)).toEqual([]);
7
10
  });
8
11
 
9
12
  it('should handle simple key-value constraints', () => {
@@ -12,47 +15,89 @@ describe('getConstraints', () => {
12
15
  maxLength: 10,
13
16
  minimum: 0,
14
17
  maximum: 100,
18
+ exclusiveMinimum: 0,
19
+ exclusiveMaximum: 100,
15
20
  minItems: 1,
16
21
  maxItems: 5,
22
+ minProperties: 2,
23
+ maxProperties: 3,
24
+ multipleOf: 2,
25
+ format: 'email',
26
+ minContains: 1,
27
+ maxContains: 3,
17
28
  };
18
- const constraints = getConstraints(prop, false);
19
- expect(constraints).toEqual([
29
+ const expected = [
20
30
  'minLength: 1',
21
31
  'maxLength: 10',
22
32
  'minimum: 0',
23
33
  'maximum: 100',
34
+ 'exclusiveMinimum: 0',
35
+ 'exclusiveMaximum: 100',
24
36
  'minItems: 1',
25
37
  'maxItems: 5',
26
- ]);
27
- });
28
-
29
- it('should handle pattern constraint', () => {
30
- const prop = { pattern: '^[a-z]+$' };
31
- const constraints = getConstraints(prop, false);
32
- expect(constraints).toContain('pattern: /^[a-z]+$/');
38
+ 'minProperties: 2',
39
+ 'maxProperties: 3',
40
+ 'multipleOf: 2',
41
+ 'format: email',
42
+ 'minContains: 1',
43
+ 'maxContains: 3',
44
+ ];
45
+ expect(getConstraints(prop, false)).toEqual(
46
+ expect.arrayContaining(expected),
47
+ );
33
48
  });
34
49
 
35
- it('should handle uniqueItems constraint', () => {
36
- const prop = { uniqueItems: true };
37
- const constraints = getConstraints(prop, false);
38
- expect(constraints).toContain('uniqueItems: true');
50
+ it('should handle special-cased constraints', () => {
51
+ const prop = {
52
+ pattern: '^[a-z]+$',
53
+ uniqueItems: true,
54
+ additionalProperties: false,
55
+ propertyNames: { pattern: '^[A-Z][a-zA-Z0-9]*$' },
56
+ dependentRequired: {
57
+ prop1: ['prop2', 'prop3'],
58
+ },
59
+ contains: { type: 'string' },
60
+ enum: ['a', 'b', 'c'],
61
+ const: 'hello',
62
+ };
63
+ const expected = [
64
+ 'pattern: /^[a-z]+$/',
65
+ 'uniqueItems: true',
66
+ 'additionalProperties: false',
67
+ 'propertyNames: {"pattern":"^[A-Z][a-zA-Z0-9]*$"}',
68
+ 'dependentRequired: prop1 -> [prop2, prop3]',
69
+ 'contains: {"type":"string"}',
70
+ 'enum: [a, b, c]',
71
+ 'const: "hello"',
72
+ ];
73
+ expect(getConstraints(prop, false)).toEqual(
74
+ expect.arrayContaining(expected),
75
+ );
39
76
  });
40
77
 
41
- it('should handle additionalProperties constraint', () => {
42
- const prop = { additionalProperties: false };
43
- const constraints = getConstraints(prop, false);
44
- expect(constraints).toContain('additionalProperties: false');
78
+ it('should handle default constraint', () => {
79
+ const prop = {
80
+ default: 'default value',
81
+ };
82
+ const expected = ['default: "default value"'];
83
+ expect(getConstraints(prop, false)).toEqual(expected);
45
84
  });
46
85
 
47
- it('should handle enum constraint', () => {
48
- const prop = { enum: ['a', 'b', 'c'] };
49
- const constraints = getConstraints(prop, false);
50
- expect(constraints).toContain('enum: [a, b, c]');
86
+ it('should not include a constraint for a value of undefined', () => {
87
+ const prop = {
88
+ minLength: undefined,
89
+ };
90
+ expect(getConstraints(prop, false)).toEqual([]);
51
91
  });
52
92
 
53
- it('should handle const constraint', () => {
54
- const prop = { const: 'a' };
55
- const constraints = getConstraints(prop, false);
56
- expect(constraints).toContain('const: "a"');
93
+ it('should handle a mix of constraints', () => {
94
+ const prop = {
95
+ minLength: 5,
96
+ pattern: '^[a-zA-Z0-9]*$',
97
+ };
98
+ const expected = ['minLength: 5', 'pattern: /^[a-zA-Z0-9]*$/'];
99
+ expect(getConstraints(prop, true)).toEqual(
100
+ expect.arrayContaining(['required', ...expected]),
101
+ );
57
102
  });
58
103
  });
@@ -118,39 +118,6 @@ describe('schemaToTableData', () => {
118
118
  expect(choiceRow.choiceType).toBe('oneOf');
119
119
  });
120
120
 
121
- it('correctly processes the "examples" array', () => {
122
- const schema = {
123
- properties: {
124
- prop_with_examples: {
125
- type: 'string',
126
- examples: ['first-example', 'second-example'],
127
- },
128
- },
129
- };
130
-
131
- const tableData = schemaToTableData(schema);
132
-
133
- expect(tableData).toHaveLength(1);
134
- const propRow = tableData[0];
135
-
136
- expect(propRow.name).toBe('prop_with_examples');
137
- expect(propRow.example).toEqual(['first-example', 'second-example']);
138
- });
139
-
140
- it('handles singular "example" if "examples" is not present', () => {
141
- const schema = {
142
- properties: {
143
- prop_with_example: {
144
- type: 'string',
145
- example: 'singular-example',
146
- },
147
- },
148
- };
149
-
150
- const tableData = schemaToTableData(schema);
151
- expect(tableData[0].example).toBe('singular-example');
152
- });
153
-
154
121
  it('handles "oneOf" nested inside a property', () => {
155
122
  const schema = {
156
123
  properties: {
@@ -219,4 +186,32 @@ describe('schemaToTableData', () => {
219
186
  expect(paramD.name).toBe('param_d');
220
187
  expect(paramD.level).toBe(0); // This is the core of the test
221
188
  });
189
+
190
+ it('uses "const" as example if "examples" and "example" are not present', () => {
191
+ const schema = {
192
+ properties: {
193
+ prop_with_const: {
194
+ type: 'string',
195
+ const: 'const-value',
196
+ },
197
+ },
198
+ };
199
+
200
+ const tableData = schemaToTableData(schema);
201
+ expect(tableData[0].examples).toEqual(['const-value']);
202
+ });
203
+
204
+ it('uses "default" as example if "examples", "example", and "const" are not present', () => {
205
+ const schema = {
206
+ properties: {
207
+ prop_with_default: {
208
+ type: 'string',
209
+ default: 'default-value',
210
+ },
211
+ },
212
+ };
213
+
214
+ const tableData = schemaToTableData(schema);
215
+ expect(tableData[0].examples).toEqual(['default-value']);
216
+ });
222
217
  });
@@ -0,0 +1,115 @@
1
+ import { createValidator } from '../../helpers/validator';
2
+
3
+ describe('createValidator', () => {
4
+ it('creates a validator that returns true for valid data with no schema version (draft-07)', async () => {
5
+ const schema = {
6
+ type: 'object',
7
+ properties: {
8
+ name: {
9
+ type: 'string',
10
+ },
11
+ },
12
+ required: ['name'],
13
+ };
14
+
15
+ const validator = await createValidator(schema);
16
+ const result = validator({ name: 'test' });
17
+
18
+ expect(result.valid).toBe(true);
19
+ expect(result.errors).toEqual([]);
20
+ });
21
+
22
+ it('creates a validator that returns false for invalid data with no schema version (draft-07)', async () => {
23
+ const schema = {
24
+ type: 'object',
25
+ properties: {
26
+ name: {
27
+ type: 'string',
28
+ },
29
+ },
30
+ required: ['name'],
31
+ };
32
+
33
+ const validator = await createValidator(schema);
34
+ const result = validator({ name: 123 });
35
+
36
+ expect(result.valid).toBe(false);
37
+ expect(result.errors).not.toEqual([]);
38
+ });
39
+
40
+ it('creates a validator that can validate against a draft-04 schema', async () => {
41
+ const schema = {
42
+ $schema: 'http://json-schema.org/draft-04/schema#',
43
+ type: 'object',
44
+ properties: {
45
+ name: {
46
+ type: 'string',
47
+ },
48
+ },
49
+ required: ['name'],
50
+ };
51
+
52
+ const validator = await createValidator(schema);
53
+ const result = validator({ name: 'test' });
54
+
55
+ expect(result.valid).toBe(true);
56
+ expect(result.errors).toEqual([]);
57
+ });
58
+
59
+ it('creates a validator that can validate against a draft-07 schema', async () => {
60
+ const schema = {
61
+ $schema: 'http://json-schema.org/draft-07/schema#',
62
+ type: 'object',
63
+ properties: {
64
+ name: {
65
+ type: 'string',
66
+ },
67
+ },
68
+ required: ['name'],
69
+ };
70
+
71
+ const validator = await createValidator(schema);
72
+ const result = validator({ name: 'test' });
73
+
74
+ expect(result.valid).toBe(true);
75
+ expect(result.errors).toEqual([]);
76
+ });
77
+
78
+ it('creates a validator that can validate against a 2019-09 schema', async () => {
79
+ const schema = {
80
+ $schema: 'https://json-schema.org/draft/2019-09/schema',
81
+ type: 'object',
82
+ properties: {
83
+ name: {
84
+ type: 'string',
85
+ },
86
+ },
87
+ required: ['name'],
88
+ };
89
+
90
+ const validator = await createValidator(schema);
91
+ const result = validator({ name: 'test' });
92
+
93
+ expect(result.valid).toBe(true);
94
+ expect(result.errors).toEqual([]);
95
+ });
96
+
97
+ it('creates a validator that can validate against a 2020-12 schema', async () => {
98
+ const schema = {
99
+ $schema: 'https://json-schema.org/draft/2020-12/schema',
100
+ type: 'object',
101
+ properties: {
102
+ name: {
103
+ type: 'string',
104
+ },
105
+ },
106
+ required: ['name'],
107
+ };
108
+
109
+ const validator = await createValidator(schema);
110
+ const result = validator({ name: 'test' });
111
+
112
+ expect(result.valid).toBe(true);
113
+ expect(result.errors).toEqual([]);
114
+ });
115
+ });
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @jest-environment node
3
+ */
4
+
5
+ import path from 'path';
6
+ import validateSchemas from '../validateSchemas';
7
+ import { getPathsForVersion } from '../helpers/path-helpers';
8
+
9
+ describe('validateSchemas - Integration', () => {
10
+ let consoleErrorSpy;
11
+ let consoleLogSpy;
12
+
13
+ beforeEach(() => {
14
+ // Spy on console.error and console.log to keep test output clean
15
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
16
+ consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
17
+ });
18
+
19
+ afterEach(() => {
20
+ jest.restoreAllMocks();
21
+ });
22
+
23
+ it('should return true for the "next" version schemas', async () => {
24
+ const siteDir = path.resolve(__dirname, '../../../demo');
25
+ const { schemaDir } = getPathsForVersion('next', siteDir);
26
+ const result = await validateSchemas(schemaDir);
27
+ expect(result).toBe(true);
28
+ });
29
+ });
@@ -14,124 +14,40 @@ describe('validateSchemas', () => {
14
14
 
15
15
  beforeEach(() => {
16
16
  tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'schema-test-'));
17
- consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
18
- consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
19
17
  });
20
18
 
21
19
  afterEach(() => {
22
20
  fs.rmSync(tmpDir, { recursive: true, force: true });
23
- jest.restoreAllMocks();
24
21
  });
25
22
 
26
- const writeSchema = (dir, fileName, content) => {
27
- const filePath = path.join(dir, fileName);
28
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
29
- fs.writeFileSync(filePath, JSON.stringify(content, null, 2));
30
- };
31
-
32
- const loadFixture = (fixtureName) => {
33
- const fixturePath = path.resolve(
23
+ it('should return true for a complex set of valid schemas', async () => {
24
+ const fixtureDir = path.resolve(
34
25
  __dirname,
35
26
  '__fixtures__',
36
27
  'validateSchemas',
37
- fixtureName,
28
+ 'complex-validation',
38
29
  );
39
- const schemaContent = fs.readFileSync(fixturePath, 'utf8');
40
- return JSON.parse(schemaContent);
41
- };
42
-
43
- it('should return true when all schemas are valid', async () => {
44
- const validSchema = loadFixture('valid-schema.json');
45
- writeSchema(tmpDir, 'valid-schema.json', validSchema);
46
-
47
- const result = await validateSchemas(tmpDir);
30
+ const schemaDir = path.join(tmpDir, 'schemas');
31
+ fs.mkdirSync(schemaDir, { recursive: true });
32
+ fs.cpSync(fixtureDir, schemaDir, { recursive: true });
33
+ const result = await validateSchemas(schemaDir);
48
34
  expect(result).toBe(true);
49
- expect(consoleLogSpy).toHaveBeenCalledWith(
50
- 'OK Schema valid-schema.json produced a valid example.',
51
- );
52
35
  });
53
36
 
54
37
  it('should return false if an example fails validation', async () => {
55
- const invalidExampleSchema = loadFixture('invalid-example-schema.json');
56
- writeSchema(tmpDir, 'invalid-example-schema.json', invalidExampleSchema);
57
-
58
- const result = await validateSchemas(tmpDir);
59
- expect(result).toBe(false);
60
- expect(consoleErrorSpy).toHaveBeenCalledWith(
61
- 'x Schema invalid-example-schema.json example data failed validation:',
38
+ const fixturePath = path.resolve(
39
+ __dirname,
40
+ '__fixtures__',
41
+ 'validateSchemas',
42
+ 'invalid-example-schema.json',
62
43
  );
63
- expect(consoleErrorSpy).toHaveBeenCalledWith(
64
- expect.arrayContaining([
65
- expect.objectContaining({
66
- instancePath: '/age',
67
- keyword: 'type',
68
- message: 'must be number',
69
- }),
70
- ]),
44
+ const schemaDir = path.join(tmpDir, 'schemas');
45
+ fs.mkdirSync(schemaDir, { recursive: true });
46
+ fs.copyFileSync(
47
+ fixturePath,
48
+ path.join(schemaDir, 'invalid-example-schema.json'),
71
49
  );
72
- });
73
-
74
- it('should fail validation for missing required property', async () => {
75
- const noValidExampleSchema = loadFixture('no-example-schema.json');
76
- writeSchema(tmpDir, 'no-valid-example-schema.json', noValidExampleSchema);
77
-
78
- const result = await validateSchemas(tmpDir);
50
+ const result = await validateSchemas(schemaDir);
79
51
  expect(result).toBe(false);
80
- expect(consoleErrorSpy).toHaveBeenCalledWith(
81
- 'x Schema no-valid-example-schema.json does not produce a valid example.',
82
- );
83
- });
84
-
85
- it('should handle schemas with $refs correctly', async () => {
86
- const componentSchema = loadFixture(
87
- path.join('components', 'referenced.json'),
88
- );
89
- const mainSchema = loadFixture('main-schema-with-ref.json');
90
-
91
- writeSchema(
92
- path.join(tmpDir, 'components'),
93
- 'referenced.json',
94
- componentSchema,
95
- );
96
- writeSchema(tmpDir, 'main-schema-with-ref.json', mainSchema);
97
-
98
- const result = await validateSchemas(tmpDir);
99
- expect(result).toBe(true);
100
- expect(consoleLogSpy).toHaveBeenCalledWith(
101
- 'OK Schema main-schema-with-ref.json produced a valid example.',
102
- );
103
- });
104
-
105
- it('should reject if a referenced schema is missing', async () => {
106
- const mainSchema = loadFixture('main-schema-with-missing-ref.json');
107
- writeSchema(tmpDir, 'main-schema-with-missing-ref.json', mainSchema);
108
-
109
- const expectedErrorPath = path.join(tmpDir, 'non-existent-component.json');
110
- await expect(validateSchemas(tmpDir)).rejects.toThrow(
111
- expect.objectContaining({
112
- message: expect.stringContaining(
113
- `Error opening file ${expectedErrorPath}`,
114
- ),
115
- }),
116
- );
117
- });
118
-
119
- it('should throw an error if duplicate schema IDs are found', async () => {
120
- const schemaA = {
121
- $id: 'duplicate-id',
122
- type: 'object',
123
- properties: { a: { type: 'string' } },
124
- };
125
- const schemaB = {
126
- $id: 'duplicate-id',
127
- type: 'object',
128
- properties: { b: { type: 'string' } },
129
- };
130
- writeSchema(path.join(tmpDir, 'A'), 'schema-A.json', schemaA);
131
- writeSchema(path.join(tmpDir, 'B'), 'schema-B.json', schemaB);
132
-
133
- await expect(validateSchemas(tmpDir)).rejects.toThrow(
134
- 'schema with key or id "duplicate-id" already exists',
135
- );
136
52
  });
137
53
  });
@@ -5,7 +5,7 @@ import TabItem from '@theme/TabItem';
5
5
  import Heading from '@theme/Heading';
6
6
  import { schemaToExamples } from '../helpers/schemaToExamples';
7
7
 
8
- const generateCodeSnippet = (example, schema) => {
8
+ const generateCodeSnippet = (example, schema, dataLayerName = 'dataLayer') => {
9
9
  const clearableProperties = findClearableProperties(schema || {});
10
10
  let codeSnippet = '';
11
11
  const propertiesToClear = clearableProperties.filter(
@@ -17,14 +17,22 @@ const generateCodeSnippet = (example, schema) => {
17
17
  propertiesToClear.forEach((prop) => {
18
18
  resetObject[prop] = null;
19
19
  });
20
- codeSnippet += `window.dataLayer.push(${JSON.stringify(resetObject, null, 2)});\n`;
20
+ codeSnippet += `window.${dataLayerName}.push(${JSON.stringify(
21
+ resetObject,
22
+ null,
23
+ 2,
24
+ )});\n`;
21
25
  }
22
26
 
23
- codeSnippet += `window.dataLayer.push(${JSON.stringify(example, null, 2)});`;
27
+ codeSnippet += `window.${dataLayerName}.push(${JSON.stringify(
28
+ example,
29
+ null,
30
+ 2,
31
+ )});`;
24
32
  return codeSnippet;
25
33
  };
26
34
 
27
- export default function ExampleDataLayer({ schema }) {
35
+ export default function ExampleDataLayer({ schema, dataLayerName }) {
28
36
  const exampleGroups = schemaToExamples(schema);
29
37
 
30
38
  if (!exampleGroups || exampleGroups.length === 0) {
@@ -36,6 +44,7 @@ export default function ExampleDataLayer({ schema }) {
36
44
  const codeSnippet = generateCodeSnippet(
37
45
  exampleGroups[0].options[0].example,
38
46
  schema,
47
+ dataLayerName,
39
48
  );
40
49
  return <CodeBlock language="javascript">{codeSnippet}</CodeBlock>;
41
50
  }
@@ -51,7 +60,7 @@ export default function ExampleDataLayer({ schema }) {
51
60
  {group.options.map(({ title, example }, index) => (
52
61
  <TabItem value={index} label={title} key={index}>
53
62
  <CodeBlock language="javascript">
54
- {generateCodeSnippet(example, schema)}
63
+ {generateCodeSnippet(example, schema, dataLayerName)}
55
64
  </CodeBlock>
56
65
  </TabItem>
57
66
  ))}
@@ -1,17 +1,32 @@
1
- import React from 'react';
1
+ import React, { useState } from 'react';
2
2
  import SchemaRows from './SchemaRows';
3
3
  import TableHeader from './TableHeader';
4
+ import WordWrapButton from './WordWrapButton';
4
5
  import { schemaToTableData } from '../helpers/schemaToTableData';
6
+ import styles from './PropertiesTable.module.css';
5
7
 
6
8
  export default function PropertiesTable({ schema }) {
9
+ const [isWordWrapOn, setIsWordWrapOn] = useState(true);
7
10
  const tableData = schemaToTableData(schema);
8
11
 
9
12
  return (
10
- <table>
11
- <TableHeader />
12
- <tbody>
13
- <SchemaRows tableData={tableData} />
14
- </tbody>
15
- </table>
13
+ <div
14
+ className={`${styles.tableWrapper} ${
15
+ !isWordWrapOn ? styles.noWordWrap : ''
16
+ }`}
17
+ >
18
+ <div className={styles.buttonGroup}>
19
+ <WordWrapButton
20
+ onClick={() => setIsWordWrapOn((w) => !w)}
21
+ isEnabled={isWordWrapOn}
22
+ />
23
+ </div>
24
+ <table>
25
+ <TableHeader />
26
+ <tbody>
27
+ <SchemaRows tableData={tableData} />
28
+ </tbody>
29
+ </table>
30
+ </div>
16
31
  );
17
32
  }
@@ -0,0 +1,27 @@
1
+ .tableWrapper {
2
+ position: relative;
3
+ margin-top: 1rem;
4
+ }
5
+
6
+ .tableWrapper code {
7
+ white-space: pre-wrap;
8
+ word-break: break-word;
9
+ min-width: auto;
10
+ }
11
+
12
+ .tableWrapper td {
13
+ min-width: 5.3rem;
14
+ }
15
+
16
+ .noWordWrap code {
17
+ white-space: pre;
18
+ word-break: normal;
19
+ }
20
+
21
+ .buttonGroup {
22
+ position: absolute;
23
+ right: 0;
24
+ top: -2.7rem;
25
+ display: flex;
26
+ gap: 0.5rem;
27
+ }