docusaurus-plugin-generate-schema-docs 1.1.0 → 1.2.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.
- package/README.md +97 -0
- package/__tests__/ExampleDataLayer.test.js +169 -0
- package/__tests__/__fixtures__/static/schemas/add-to-cart-event.json +55 -0
- package/__tests__/__fixtures__/static/schemas/components/dataLayer.json +58 -0
- package/__tests__/__fixtures__/static/schemas/components/product.json +211 -0
- package/__tests__/__fixtures__/validateSchemas/circular-schema.json +8 -0
- package/__tests__/__fixtures__/validateSchemas/components/referenced.json +8 -0
- package/__tests__/__fixtures__/validateSchemas/invalid-example-schema.json +8 -0
- package/__tests__/__fixtures__/validateSchemas/main-schema-with-missing-ref.json +8 -0
- package/__tests__/__fixtures__/validateSchemas/main-schema-with-ref.json +8 -0
- package/__tests__/__fixtures__/validateSchemas/no-example-schema.json +12 -0
- package/__tests__/__fixtures__/validateSchemas/schema-A.json +7 -0
- package/__tests__/__fixtures__/validateSchemas/schema-B.json +7 -0
- package/__tests__/__fixtures__/validateSchemas/valid-schema.json +8 -0
- package/__tests__/__snapshots__/generateEventDocs.test.js.snap +53 -0
- package/__tests__/components/PropertiesTable.test.js +24 -0
- package/__tests__/components/PropertyRow.test.js +67 -0
- package/__tests__/components/SchemaJsonViewer.test.js +32 -0
- package/__tests__/components/SchemaRows.test.js +80 -0
- package/__tests__/components/SchemaViewer.test.js +27 -0
- package/__tests__/components/TableHeader.test.js +20 -0
- package/__tests__/generateEventDocs.test.js +84 -0
- package/__tests__/helpers/buildExampleFromSchema.test.js +188 -0
- package/__tests__/helpers/getConstraints.test.js +58 -0
- package/__tests__/helpers/loadSchema.test.js +14 -0
- package/__tests__/helpers/processSchema.test.js +36 -0
- package/__tests__/validateSchemas.test.js +100 -0
- package/components/ExampleDataLayer.js +7 -5
- package/components/PropertiesTable.js +5 -10
- package/components/PropertyRow.js +74 -0
- package/components/SchemaJsonViewer.js +3 -2
- package/components/SchemaRows.css +28 -0
- package/components/SchemaRows.js +19 -47
- package/components/SchemaViewer.js +4 -2
- package/components/TableHeader.js +15 -0
- package/generateEventDocs.js +37 -36
- package/helpers/buildExampleFromSchema.js +3 -3
- package/helpers/getConstraints.js +53 -0
- package/helpers/loadSchema.js +11 -0
- package/helpers/mdx-template.js +36 -0
- package/helpers/processSchema.js +32 -0
- package/index.js +21 -11
- package/package.json +13 -2
- package/validateSchemas.js +6 -3
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// A list of JSON Schema keywords that have simple key-value constraints.
|
|
2
|
+
const constraintHandlers = {
|
|
3
|
+
// Simple key-value constraints
|
|
4
|
+
minLength: (val) => `minLength: ${val}`,
|
|
5
|
+
maxLength: (val) => `maxLength: ${val}`,
|
|
6
|
+
minimum: (val) => `minimum: ${val}`,
|
|
7
|
+
maximum: (val) => `maximum: ${val}`,
|
|
8
|
+
exclusiveMinimum: (val) => `exclusiveMinimum: ${val}`,
|
|
9
|
+
exclusiveMaximum: (val) => `exclusiveMaximum: ${val}`,
|
|
10
|
+
minItems: (val) => `minItems: ${val}`,
|
|
11
|
+
maxItems: (val) => `maxItems: ${val}`,
|
|
12
|
+
minProperties: (val) => `minProperties: ${val}`,
|
|
13
|
+
maxProperties: (val) => `maxProperties: ${val}`,
|
|
14
|
+
multipleOf: (val) => `multipleOf: ${val}`,
|
|
15
|
+
format: (val) => `format: ${val}`,
|
|
16
|
+
minContains: (val) => `minContains: ${val}`,
|
|
17
|
+
maxContains: (val) => `maxContains: ${val}`,
|
|
18
|
+
|
|
19
|
+
// Special-cased constraints
|
|
20
|
+
pattern: (val) => `pattern: /${val}/`,
|
|
21
|
+
uniqueItems: (val) => (val ? 'uniqueItems: true' : null),
|
|
22
|
+
additionalProperties: (val) => (val === false ? 'additionalProperties: false' : null),
|
|
23
|
+
propertyNames: (val) => `propertyNames: ${JSON.stringify(val)}`,
|
|
24
|
+
dependentRequired: (val) => {
|
|
25
|
+
const deps = Object.entries(val).map(([key, depVal]) => `${key} -> [${depVal.join(', ')}]`).join('; ');
|
|
26
|
+
return `dependentRequired: ${deps}`;
|
|
27
|
+
},
|
|
28
|
+
contains: (val) => `contains: ${JSON.stringify(val)}`,
|
|
29
|
+
enum: (val) => `enum: [${val.join(', ')}]`,
|
|
30
|
+
const: (val) => `const: ${JSON.stringify(val)}`,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const getConstraints = (prop, isReq) => {
|
|
34
|
+
const constraints = [];
|
|
35
|
+
if (isReq)
|
|
36
|
+
{
|
|
37
|
+
constraints.push('required');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
for (const keyword in constraintHandlers)
|
|
41
|
+
{
|
|
42
|
+
if (prop[keyword] !== undefined)
|
|
43
|
+
{
|
|
44
|
+
const handler = constraintHandlers[keyword];
|
|
45
|
+
const result = handler(prop[keyword]);
|
|
46
|
+
if (result)
|
|
47
|
+
{
|
|
48
|
+
constraints.push(result);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return constraints;
|
|
53
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Loads a JSON schema file and returns its content as a JSON object.
|
|
5
|
+
* @param {string} filePath Path to the JSON schema file.
|
|
6
|
+
* @returns {object} The parsed JSON schema.
|
|
7
|
+
*/
|
|
8
|
+
export default function loadSchema(filePath) {
|
|
9
|
+
const rawContent = fs.readFileSync(filePath, 'utf-8');
|
|
10
|
+
return JSON.parse(rawContent);
|
|
11
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export default function MdxTemplate(data) {
|
|
2
|
+
const {
|
|
3
|
+
schema,
|
|
4
|
+
mergedSchema,
|
|
5
|
+
baseEditUrl,
|
|
6
|
+
file,
|
|
7
|
+
topPartialImport,
|
|
8
|
+
bottomPartialImport,
|
|
9
|
+
topPartialComponent,
|
|
10
|
+
bottomPartialComponent
|
|
11
|
+
} = data;
|
|
12
|
+
|
|
13
|
+
return `---
|
|
14
|
+
title: ${schema.title}
|
|
15
|
+
description: ${JSON.stringify(schema.description)}
|
|
16
|
+
sidebar_label: ${schema.title}
|
|
17
|
+
custom_edit_url: ${baseEditUrl}/demo/static/schemas/${file}
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
import SchemaViewer from '@theme/SchemaViewer';
|
|
21
|
+
import SchemaJsonViewer from '@theme/SchemaJsonViewer';
|
|
22
|
+
${topPartialImport}
|
|
23
|
+
${bottomPartialImport}
|
|
24
|
+
|
|
25
|
+
# ${schema.title}
|
|
26
|
+
|
|
27
|
+
${schema.description}
|
|
28
|
+
|
|
29
|
+
${topPartialComponent}
|
|
30
|
+
|
|
31
|
+
<SchemaViewer schema={${JSON.stringify(mergedSchema)}} />
|
|
32
|
+
<SchemaJsonViewer schema={${JSON.stringify(schema)}} />
|
|
33
|
+
|
|
34
|
+
${bottomPartialComponent}
|
|
35
|
+
`;
|
|
36
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import $RefParser from "@apidevtools/json-schema-ref-parser";
|
|
2
|
+
import mergeJsonSchema from "json-schema-merge-allof";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Processes a JSON schema file by bundling external references,
|
|
6
|
+
* dereferencing internal references, and merging allOf properties.
|
|
7
|
+
*
|
|
8
|
+
* @param {string} filePath Path to the JSON schema file.
|
|
9
|
+
* @returns {Promise<object>} The processed (merged) schema.
|
|
10
|
+
*/
|
|
11
|
+
export default async function processSchema(filePath) {
|
|
12
|
+
// 1. Bundle all external references into a single, self-contained schema
|
|
13
|
+
const bundledSchema = await $RefParser.bundle(filePath, {
|
|
14
|
+
mutateInputSchema: false,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// 2. Dereference the bundled schema to resolve internal refs for allOf merging
|
|
18
|
+
const dereferencedSchema = await $RefParser.dereference(bundledSchema, {
|
|
19
|
+
dereference: {
|
|
20
|
+
circular: 'ignore', // Keep recursive parts as $refs
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Then merge allOf properties
|
|
25
|
+
const mergedSchema = mergeJsonSchema(dereferencedSchema, {
|
|
26
|
+
resolvers: {
|
|
27
|
+
defaultResolver: mergeJsonSchema.options.resolvers.title
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
return mergedSchema;
|
|
32
|
+
}
|
package/index.js
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
import validateSchemas from './validateSchemas.js';
|
|
2
2
|
import generateEventDocs from './generateEventDocs.js';
|
|
3
3
|
import path from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
const
|
|
5
|
+
export default async function (context) {
|
|
6
|
+
const { siteDir } = context;
|
|
7
|
+
const { organizationName, projectName } = context.siteConfig;
|
|
8
|
+
const options = { organizationName, projectName, siteDir };
|
|
9
|
+
const schemasPath = path.join(siteDir, 'static/schemas');
|
|
10
|
+
|
|
11
|
+
// Generate docs on startup
|
|
12
|
+
await generateEventDocs(options);
|
|
8
13
|
|
|
9
|
-
export default function (context, options) {
|
|
10
14
|
return {
|
|
11
15
|
name: 'docusaurus-plugin-generate-schema-docs',
|
|
12
16
|
|
|
17
|
+
getPathsToWatch() {
|
|
18
|
+
// Watch the schemas directory for changes
|
|
19
|
+
return [schemasPath];
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
async loadContent() {
|
|
23
|
+
// Generate event documentation when watched files change
|
|
24
|
+
await generateEventDocs(options);
|
|
25
|
+
},
|
|
26
|
+
|
|
13
27
|
getThemePath() {
|
|
14
|
-
return
|
|
28
|
+
return './components';
|
|
15
29
|
},
|
|
16
30
|
|
|
17
31
|
extendCli(cli) {
|
|
@@ -21,7 +35,7 @@ export default function (context, options) {
|
|
|
21
35
|
.action(async () => {
|
|
22
36
|
console.log('Validating GTM Schemas...');
|
|
23
37
|
// You might get the path from 'options' or assume a default
|
|
24
|
-
const schemaPath = options?.path || path.join(context.siteDir, 'schemas');
|
|
38
|
+
const schemaPath = options?.path || path.join(context.siteDir, 'static/schemas');
|
|
25
39
|
|
|
26
40
|
const success = await validateSchemas(schemaPath);
|
|
27
41
|
|
|
@@ -42,9 +56,5 @@ export default function (context, options) {
|
|
|
42
56
|
await generateEventDocs();
|
|
43
57
|
});
|
|
44
58
|
},
|
|
45
|
-
|
|
46
|
-
async loadContent() {
|
|
47
|
-
await generateEventDocs();
|
|
48
|
-
},
|
|
49
59
|
};
|
|
50
|
-
}
|
|
60
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docusaurus-plugin-generate-schema-docs",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Docusaurus plugin to generate documentation from JSON schemas.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/benedikt-buchert/tracking_docs.git"
|
|
10
|
+
},
|
|
7
11
|
"dependencies": {
|
|
8
12
|
"@apidevtools/json-schema-ref-parser": "^15.1.3",
|
|
9
|
-
"fs-extra": "^11.
|
|
13
|
+
"fs-extra": "^11.3.3",
|
|
10
14
|
"json-schema-merge-allof": "^0.8.1"
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public",
|
|
18
|
+
"provenance": true
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"jest": "^30.2.0"
|
|
11
22
|
}
|
|
12
23
|
}
|
package/validateSchemas.js
CHANGED
|
@@ -2,11 +2,13 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import buildExampleFromSchema from './helpers/buildExampleFromSchema';
|
|
4
4
|
import Ajv2020 from 'ajv/dist/2020.js';
|
|
5
|
+
import addFormats from 'ajv-formats';
|
|
5
6
|
import $RefParser from "@apidevtools/json-schema-ref-parser";
|
|
6
7
|
import mergeJsonSchema from "json-schema-merge-allof";
|
|
7
8
|
|
|
8
9
|
const validateSchemas = async (schemaPath) => {
|
|
9
10
|
const ajv = new Ajv2020();
|
|
11
|
+
addFormats(ajv);
|
|
10
12
|
ajv.addKeyword('x-gtm-clear');
|
|
11
13
|
|
|
12
14
|
const getAllFiles = (dir, allFiles = []) => {
|
|
@@ -28,7 +30,7 @@ const validateSchemas = async (schemaPath) => {
|
|
|
28
30
|
return allFiles;
|
|
29
31
|
};
|
|
30
32
|
|
|
31
|
-
const allSchemaFiles = getAllFiles(
|
|
33
|
+
const allSchemaFiles = getAllFiles(schemaPath);
|
|
32
34
|
for (const file of allSchemaFiles)
|
|
33
35
|
{
|
|
34
36
|
const schemaContent = fs.readFileSync(file, 'utf-8');
|
|
@@ -41,7 +43,7 @@ const validateSchemas = async (schemaPath) => {
|
|
|
41
43
|
for (const file of schemaFiles)
|
|
42
44
|
{
|
|
43
45
|
const filePath = path.join(schemaPath, file);
|
|
44
|
-
|
|
46
|
+
|
|
45
47
|
// Dereference and merge, same as in generateEventDocs.js
|
|
46
48
|
const clonedSchema = await $RefParser.dereference(filePath, {
|
|
47
49
|
mutateInputSchema: false, dereference: {
|
|
@@ -64,7 +66,8 @@ const validateSchemas = async (schemaPath) => {
|
|
|
64
66
|
{
|
|
65
67
|
const originalSchema = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
66
68
|
const validate = ajv.getSchema(originalSchema.$id);
|
|
67
|
-
if (!validate)
|
|
69
|
+
if (!validate)
|
|
70
|
+
{
|
|
68
71
|
console.error(`❌ Could not find compiled schema for ${originalSchema.$id}`);
|
|
69
72
|
allValid = false;
|
|
70
73
|
continue;
|