Giter Site home page Giter Site logo

json-schema-for-humans's Introduction

PyPI version

JSON Schema for Humans

Quickly generate a beautiful static HTML or Markdown page documenting a JSON schema

Documentation (with visual examples)

Features

  • Support for JSON Schema Draft-07
  • Since the result is static, it is easier to host and faster to load
  • HTML and Markdown output support
  • Different templates to choose from. More details: HTML version - Markdown version
  • Anchor links, allow to send a user to a specific section of the documentation
  • Support for references (even circular!)

Installation

pip install json-schema-for-humans

Usage

Options for generation of the doc are documented using the library itself: HTML version - Markdown version

They can be supplied in various ways:

  • Using a JSON or YAML configuration file with the CLI option --config-file
  • Using the CLI option --config
  • Using the ConfigurationOption object from code

More details are available in the appropriate sections below.

From CLI

generate-schema-doc [OPTIONS] SCHEMA_FILES_OR_DIR [RESULT_FILE_OR_DIR]

SCHEMA_FILES_OR_DIR can be:

  • a path to a single schema file;
  • a path to a directory, in this case all files with extensions json, yaml, or yml will be used;
  • a glob pattern (starts from the current working directory); or
  • a comma-separated list of the above

All schemas provided must be a valid JSON Schema (in JSON or YAML format)

Examples:

  • my_schema.json
  • my_folder
  • my_folder/my_schema.yaml,another_schema.json
  • **/*.yaml.*

The default value for RESULT_FILE_OR_DIR depends on the context:

  • the current working directory if more than one schema as been provided as input
  • schema_doc.html if rendering a single schema as HTML
  • schema_doc.md if rendering a single schema as Markdown

In a case where more than one schema is provided as input, RESULT_FILE_OR_DIR must be a directory. The output documentation will have the same name as the input schema, but with a different extension (html or md).

Choosing a template

To choose a template on the CLI, use --config template_name=[TEMPLATE_NAME]. For example --config template_name=js (HTML) or --config template_name=md (Markdown). The list of available templates is documented here

CLI options

--config

Supply generation config parameters. The parameters are documented in the JSON schema config_schema.json at the root of the repo or see the generated doc: HTML version - Markdown version.

Each parameter is in the format --config parameter_name=parameter_value. Example: --config expand_buttons=true. The parameter value must be valid JSON.

For flags, you can also omit the value for true or prefix the parameter name with no_ for false. Example: --config expand_buttons or --config no_expand_buttons.

--config-file

Path to a JSON or YAML configuration file respecting the schema config_schema.json.

Example: --config-file jsfh-conf.yaml where jsfh-conf.yaml is in the current directory and contains the following:

description_is_markdown: false
expand_buttons: true
copy_js: false

From code

The following methods are available to import from json_schema_for_humans.generate

Method Name Schema input Output CSS and JS copied?
generate_from_schema schema_file as str or pathlib.Path Rendered doc as a str No
generate_from_filename schema_file_name as str or pathlib.Path Rendered doc written to the file at path result_file_name Yes
generate_from_file_object schema_file as an open file object (read mode) Rendered doc written to the file at result_file, which must be an open file object (in write mode) Yes

Notes:

  • When using file objects, it is assumed that files are opened with encoding "utf-8"
  • CSS and JS files are copied to the current working directory with names "schema_doc.css" and "schema_doc.min.js" respectively, if necessary
  • Other parameters of these methods are analogous to the CLI parameters documented above.

The GenerationConfiguration object

To reduce the number of parameters to pass from function to function in the code, there is a GenerationConfiguration object that should be used for providing options.

Example:

from json_schema_for_humans.generate import generate_from_filename
from json_schema_for_humans.generation_configuration import GenerationConfiguration

config = GenerationConfiguration(copy_css=False, expand_buttons=True)

generate_from_filename("my_schema.json", "schema_doc.html", config=config)

# Your doc is now in a file named "schema_doc.html". Next to it, "schema_doc.min.js" was copied, but not "schema_doc.css"
# Your doc will contain a "Expand all" and a "Collapse all" button at the top

Pre-load schemas

generate_from_schema has a loaded_schemas parameter that can be used to pre-load schemas. This must be a dict with the key being the real path of the schema file and the value being the result of loading the schema (with json.load or yaml.safe_load, for example).

This should not be necessary in normal scenarios.

What's supported

See the excellent Understanding JSON Schema to understand what are those checks

The following are supported:

  • Types
  • Regular expressions
  • String length
  • String format
  • Numeric types multiples and range
  • Constant and enumerated values
  • Required properties
  • Pattern properties
  • Default values
  • Array minItems, maxItems, uniqueItems, items, prefixItems, additionalItems, and contains
  • Combining schema with oneOf, allOf, anyOf, and not
  • Examples
  • Conditional subschemas

These are not supported at the moment (PRs welcome!):

  • Property names and size
  • Property dependencies
  • Media

References

References are supported:

  • To another part of the schema, e.g. { $ref: "#/definitions/something" }
  • To a local file, {"$ref": "references.json"}, {"$ref": "references.json#/definitions/something"}, {"$ref": "file:references.json"}, {"$ref": "file:references.json#/definitions/something}
  • To a URL, {"$ref": "http://example.com/schema.json"}, {"$ref": "http://example.com/schema.json#/definitions/something"}

You can have a description next to a $ref, it will be displayed in priority to the description from the referenced element.

If you have several attributes using the same definition, the definition will only be rendered once. All other usages of the same definition will be replaced with an anchor link to the first render of the definition. This can be turned off using --config no_link_to_reused_ref. See With references in the examples.

Templates

Templates control the style of the generated documentation.

js

This is the default template. It uses Bootstrap along with minimal Javascript to allow for the following:

  • Properties are in expandable dynamic sections. You can include a button to expand or collapse all. (See doc: HTML version - Markdown version)
  • Conditional subschemas (anyOf, oneOf, allOf) are in tabbed sections
  • Anchor links will scroll to, expand, and animate the target section
  • Long descriptions are collapsed by default

When using this template, you need to include the Javascript file (schema_doc.min.js) that is automatically copied next to the output HTML file (schema_doc.html by default).

js_offline

This schema is identical to the js template, but all CSS and JavaScript resources are bundled so that the generated documentation can be used in an offline setting.

flat

Note: This template is a work in progress

It is sometimes not possible or desirable to include custom Javascript in documentation. This template addresses this issue by removing interactive elements in favor of simpler HTML.

At the moment, this means the whole documentation is generated without any collapsible sections, which may make it hard to understand the schema structure. Contributions are welcomed to improve it!

MD (Markdown)

Note: This template is a work in progress

This template allows users to publish the generated documentation without hosting an HTTP server.

On GitHub, this format is rendered directly when browsing code.

A table of content is provided at the beginning of the file for easy navigation.

You can display some important information as badge using an option. See doc: HTML version - Markdown version

Contributions are welcomed to improve it!

Contributing

See CONTRIBUTING.md

json-schema-for-humans's People

Contributors

alexjurkiewicz avatar astro avatar azaroth42 avatar benedictst avatar bjw-s avatar calebhalvy avatar carlsmedstad avatar cduncan95 avatar chrono avatar dasch avatar dblanchette avatar dzordzu avatar fchastanet avatar fhalde avatar fpgmaas avatar fuji8 avatar homeworkprod avatar jnothman avatar jocgir avatar jonapich avatar khoumani avatar matthewpbryant avatar mbkranz avatar miarodri avatar mixxen avatar my-tien avatar semantic-release-bot avatar sw23 avatar thingsconnected avatar tobiasbora avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

json-schema-for-humans's Issues

Unhelpful error message when providing a non-existent output directory

In the process of porting a CI script to a new platform I mistakenly changed an output file so that it pointed to a non-existent directory. This results in an error message claiming that generate-schema-docs cannot find a CSS file, it would be better ifwe either either:

  1. Handle this case by creating the directory, like mkdir -p
  2. Correctly report up-front that the output directory does not exist

I would prefer the second option, but either would be better than the current behavior. I am happy to submit a PR once a decision has been made on what, if anything, to do.

Traceback (most recent call last):
  File "C:\git\project\packages\python.3.7.4\tools\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "C:\git\project\packages\python.3.7.4\tools\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\git\project\spdx-venv\Scripts\generate-schema-doc.exe\__main__.py", line 9, in <module>
  File "C:\git\project\spdx-venv\lib\site-packages\click\core.py", line 1137, in __call__
    return self.main(*args, **kwargs)
  File "C:\git\project\spdx-venv\lib\site-packages\click\core.py", line 1062, in main
    rv = self.invoke(ctx)
  File "C:\git\project\spdx-venv\lib\site-packages\click\core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "C:\git\project\spdx-venv\lib\site-packages\click\core.py", line 763, in invoke
    return __callback(*args, **kwargs)
  File "C:\git\project\spdx-venv\lib\site-packages\json_schema_for_humans\generate.py", line 258, in main
    generate_from_file_object(schema_file, result_file, config=config)
  File "C:\git\project\spdx-venv\lib\site-packages\json_schema_for_humans\generate.py", line 174, in generate_from_file_object
    copy_css_and_js_to_target(result_file.name, config)
  File "C:\git\project\spdx-venv\lib\site-packages\json_schema_for_humans\generate.py", line 199, in copy_css_and_js_to_target
    shutil.copy(source_file_path, os.path.join(target_directory, file_to_copy))
  File "C:\git\project\packages\python.3.7.4\tools\lib\shutil.py", line 248, in copy
    copyfile(src, dst, follow_symlinks=follow_symlinks)
  File "C:\git\project\packages\python.3.7.4\tools\lib\shutil.py", line 121, in copyfile
    with open(dst, 'wb') as fdst:
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\git\\project/doc/schema\\schema_doc.css'

Name tabbed sections after a property of an object

First of all, many thanks for this great tool!

I have the following schema and would like to use the properties.name.const value as the displayed name of the tabs, i.e. "name 1", "name 2", etc.:

{
	"oneOf": [{
		"type": "object",
		"properties": {
			"name": {
				"const": "name 1"
			},
			"value": {}
		}
	}, {
		"type": "object",
		"properties": {
			"name": {
				"const": "name 1"
			},
			"value": {}
		}
	}]
}

I changed every object to a reference, with the last part of it matching properties.name.const value, but I cannot use reference since the schema is then too complex. I tried to modify the intermediate representation and the SchemaNode along with the tabbed section template unsuccessfully. Please, could you tell me if there is a way to do it, or what should I modify in the code to do it?

Thank you very much for your support.

Broken generation for 0.5

Hi @dblanchette ,

I have run into the following issue with the new 0.5 version. To reproduce it I started with a fresh environment:

python -m venv env
source env/bin/activate
pip install json-schema-for-humans==0.5
generate-schema-doc document.json document.html

I get the following error:

Traceback (most recent call last):
  File "***/env/bin/generate-schema-doc", line 8, in <module>
    sys.exit(main())
  File "***/env/lib64/python3.6/site-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "***/env/lib64/python3.6/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "***/env/lib64/python3.6/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "***/env/lib64/python3.6/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "***/env/lib64/python3.6/site-packages/json_schema_for_humans/generate.py", line 400, in main
    schema_file, result_file, minify, deprecated_from_description, default_from_description, expand_buttons
  File "***/env/lib64/python3.6/site-packages/json_schema_for_humans/generate.py", line 361, in generate_from_file_object
    expand_buttons,
  File "***/env/lib64/python3.6/site-packages/json_schema_for_humans/generate.py", line 311, in generate_from_schema
    rendered = template.render(schema=schema, schema_path=schema_path, expand_buttons=expand_buttons)
  File "***/env/lib64/python3.6/site-packages/jinja2/environment.py", line 1090, in render
    self.environment.handle_exception()
  File "***/env/lib64/python3.6/site-packages/jinja2/environment.py", line 832, in handle_exception
    reraise(*rewrite_traceback_stack(source=source))
  File "***/env/lib64/python3.6/site-packages/jinja2/_compat.py", line 28, in reraise
    raise value.with_traceback(tb)
  File "<template>", line 224, in top-level template code
  File "***/env/lib64/python3.6/site-packages/jinja2/runtime.py", line 679, in _invoke
    rv = self._func(*arguments)
  File "<template>", line 138, in template
  File "***/env/lib64/python3.6/site-packages/jinja2/runtime.py", line 679, in _invoke
    rv = self._func(*arguments)
  File "<template>", line 69, in template
  File "***/env/lib64/python3.6/site-packages/jinja2/runtime.py", line 679, in _invoke
    rv = self._func(*arguments)
  File "<template>", line 156, in template
  File "***/env/lib64/python3.6/site-packages/json_schema_for_humans/generate.py", line 93, in resolve_ref
    target_path.append(ref_path_segment)

I checked the same with using version 0.4.1 and that still works (as before).

Error running tox command

When I run 'tox' I get this error:

================================= ERRORS =================================
___________________ ERROR collecting tests/cli_test.py ___________________ 
ImportError while importing test module '...\repos\json-schema-for-humans\tests\cli_test.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests\cli_test.py:7: in <module>
    from json_schema_for_humans.generate import main
json_schema_for_humans\generate.py:8: in <module>
    from dataclasses import dataclass
E   ModuleNotFoundError: No module named 'dataclasses'

This is on python 3.6. Any thoughts?

ref key referencing a url invalid directory

I have schema files hosted in docs https://buildtesters.github.io/schemas/ i found your library interesting for autogenerating json schema docs.

It looks as if this library is validating the json schema before it generates the docs. I get this error

(schemas) siddiq90@DOE-7086392 schemas % generate-schema-doc script/script-v1.0.schema.json
Traceback (most recent call last):
  File "/Users/siddiq90/.local/share/virtualenvs/schemas-TS0lwyF1/bin/generate-schema-doc", line 8, in <module>
    sys.exit(main())
  File "/Users/siddiq90/.local/share/virtualenvs/schemas-TS0lwyF1/lib/python3.7/site-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/Users/siddiq90/.local/share/virtualenvs/schemas-TS0lwyF1/lib/python3.7/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/Users/siddiq90/.local/share/virtualenvs/schemas-TS0lwyF1/lib/python3.7/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/Users/siddiq90/.local/share/virtualenvs/schemas-TS0lwyF1/lib/python3.7/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/Users/siddiq90/.local/share/virtualenvs/schemas-TS0lwyF1/lib/python3.7/site-packages/json_schema_for_humans/generate.py", line 1071, in main
    generate_from_file_object(schema_file, result_file, config=config)
  File "/Users/siddiq90/.local/share/virtualenvs/schemas-TS0lwyF1/lib/python3.7/site-packages/json_schema_for_humans/generate.py", line 901, in generate_from_file_object
    result = generate_from_schema(schema_file, config=config)
  File "/Users/siddiq90/.local/share/virtualenvs/schemas-TS0lwyF1/lib/python3.7/site-packages/json_schema_for_humans/generate.py", line 822, in generate_from_schema
    intermediate_schema = build_intermediate_representation(schema_file, config, loaded_schemas)
  File "/Users/siddiq90/.local/share/virtualenvs/schemas-TS0lwyF1/lib/python3.7/site-packages/json_schema_for_humans/generate.py", line 495, in build_intermediate_representation
    intermediate_representation = _build_node(0, "", schema_path, [], _load_schema(schema_path, []))
  File "/Users/siddiq90/.local/share/virtualenvs/schemas-TS0lwyF1/lib/python3.7/site-packages/json_schema_for_humans/generate.py", line 474, in _build_node
    is_pattern_properties=schema_key == "patternProperties",
  File "/Users/siddiq90/.local/share/virtualenvs/schemas-TS0lwyF1/lib/python3.7/site-packages/json_schema_for_humans/generate.py", line 474, in _build_node
    is_pattern_properties=schema_key == "patternProperties",
  File "/Users/siddiq90/.local/share/virtualenvs/schemas-TS0lwyF1/lib/python3.7/site-packages/json_schema_for_humans/generate.py", line 491, in _build_node
    new_node.refers_to = _resolve_ref(new_node, schema)
  File "/Users/siddiq90/.local/share/virtualenvs/schemas-TS0lwyF1/lib/python3.7/site-packages/json_schema_for_humans/generate.py", line 369, in _resolve_ref
    _load_schema(referenced_schema_path, referenced_schema_path_to_element),
  File "/Users/siddiq90/.local/share/virtualenvs/schemas-TS0lwyF1/lib/python3.7/site-packages/json_schema_for_humans/generate.py", line 381, in _load_schema
    with open(schema_file_path, encoding="utf-8") as schema_fp:
FileNotFoundError: [Errno 2] No such file or directory: '/Users/siddiq90/Documents/schemas/script/https:/buildtesters.github.io/schemas/global/global.schema.json'

This schema file https://github.com/buildtesters/schemas/blob/master/script/script-v1.0.schema.json is referencing a public url https:/buildtesters.github.io/schemas/global/global.schema.json where my schema can be fetched. The issue is in your library when you are opening the schema file you assume schema file based on $ref is a local path. Any way to get around this.

I was able to generate schema docs for https://github.com/buildtesters/schemas/blob/master/global/global.schema.json which doesn't have any cross reference.

re-instate calling generate_doc() with provided data of schema

Thanks for the latest release.

I note that generate_from_schema() no longer uses its 'schema' parameter and instead passes schema_path to build_intermediate_representation().

This change removes the ability to call into generate_from_schema() with a pre-loaded data structure(s) of schemata.

That ability can be re-instated by optionally permitting callers to provide the loaded_schemas dict via generate_from_schema() into build_intermediate_representation().

I attached a patch on generate.py of version 0.13.0 which makes this change by adding loaded_schemas dict as an optional parameter of those two function calls:

adding-loaded-schemas-param-to-generate-py-patch.txt

Although this release does support direct load of a YAML filename, I believe this issue would add scope for permitting corner cases to be explored, especially when users already have their schemata in memory and would like to generate documentation from there.

Tabbed section doesn't show in markdown

When using anyof, allof, oneof, a tabbed section should show the objects that make up that array. Right now those do not show up. In the anyOf_option_names example the array table should be right above 1.1 Property:
image

Problem resolving $ref in some cases

I'm seeing an issue resolving references in the case where a schema node is created normally (i.e. not from a reference) and then a single property references that node. In _resolve_ref, the code that looks for existing references falls through to the else clause below even when 'other_user' is None (the reference wasn't created by another reference user but rather an explicit use).

else:
    # Both nodes are the same depth. The other having been seen first,
    # this node will be hidden and linked to the other node
    current_node.is_displayed = False
    return other_user

So this line:

Returns None however it should return found_reference in this case (I think). Replacing return other_user with return found_reference fixed it for me but seems like it would break what the else clause was intended to handle.

To recreate:

generate-schema-doc --expand-buttons ./tests/cases/references.json
  • Go to references.html#anchor_nested_reference
  • You will see type: object instead of type: string (because the reference points to a string definition)

I'm not super confident in my fix but can attempt a PR if that'd be helpful. Thanks!

Markdown template producing error

I'm attempting to use the markdown template and seeing an error about calling name_for_breadcrumbs on a list on line 311 of json_schema_for_humans/md_template.py.

Version: 0.32.0

Here is the command I'm running as well as the stacktrace

generate-schema-doc --config template_name=md report.json
Traceback (most recent call last):
  File "/usr/local/bin/generate-schema-doc", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.9/site-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.9/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.9/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/json_schema_for_humans/generate.py", line 262, in main
    generate_from_file_object(schema_file, result_file, config=config)
  File "/usr/local/lib/python3.9/site-packages/json_schema_for_humans/generate.py", line 176, in generate_from_file_object
    result = generate_from_schema(schema_file, config=config)
  File "/usr/local/lib/python3.9/site-packages/json_schema_for_humans/generate.py", line 95, in generate_from_schema
    rendered = template.render(schema=intermediate_schema, config=config)
  File "/usr/local/lib/python3.9/site-packages/jinja2/environment.py", line 1090, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.9/site-packages/jinja2/environment.py", line 832, in handle_exception
    reraise(*rewrite_traceback_stack(source=source))
  File "/usr/local/lib/python3.9/site-packages/jinja2/_compat.py", line 28, in reraise
    raise value.with_traceback(tb)
  File "<template>", line 5, in top-level template code
  File "/usr/local/lib/python3.9/site-packages/json_schema_for_humans/templates/md/content.html", line 92, in top-level template code
    {% include "section_properties_details.html" %}
  File "/usr/local/lib/python3.9/site-packages/json_schema_for_humans/templates/md/section_properties_details.html", line 29, in top-level template code
    {% include "content.html" %}
  File "/usr/local/lib/python3.9/site-packages/json_schema_for_humans/templates/md/content.html", line 81, in top-level template code
    {% include "section_array.html" %}
  File "/usr/local/lib/python3.9/site-packages/json_schema_for_humans/templates/md/section_array.html", line 4, in top-level template code
    {{ schema | md_array_items_restrictions | md_generate_table }}
  File "/usr/local/lib/python3.9/site-packages/json_schema_for_humans/md_template.py", line 311, in array_items_restrictions
    item_label = item.name_for_breadcrumbs or f"Array Item {i}"
AttributeError: 'list' object has no attribute 'name_for_breadcrumbs'

Recursive element details location

Regarding the new support for recursive definitions (#8) I have a proposal that I think could make things slightly more understandable. Currently the details of a recursive element are shown the first time it appears, and all others are links to this first instance. However, the first time a recursive element appears could be deeply nested. It could be better instead to show the details of the recursive element the first time it appears in the least depth.

An example is the following
Screenshot from 2020-05-21 19-25-31
The graph in the first level links to a definition which is deeply nested. Someone trying to understand this schema would first like to learn about the elements at the first level, so having this link to a deeper level just makes it a bit more confusing than what it would be if the details were at this first level.

Please use the description of a referenced schema

Please use the description of a referenced item, if the referring item does not have a description set.

Having a description on a ref adds vital readability to a rendered schema.

json-schema-for-humans already supports a description in a referring object, i.e.:
name: { "$ref": "#/definitions/filled_string", description: "render this" }

Documentation implies that description might be better inherited from the referenced object:

You will always use $ref as the only key in an object: any other keys you put there will be ignored by the validator.

While it ought still to be okay to use a description on the referencing object if one is present, it seems more desirable to detect and use the description from the referenced object, rather than to print no description.

Considering the schema:

definitions:
  filled_string:
    description: a filled string
    type: string
    minLength: 1
type: object
additionalProperties: false
properties:
  name: { "$ref": "#/definitions/filled_string" }
  alignment: { "$ref": "#/definitions/filled_string" }

A more ideal rendering of this schema would put the description "a filled string" next to a ref link, rather than leaving the description blank.

This change could be done by adjusting the action of this part of the template:

{# There can be a description next to $ref, so let's display it #}
{{ add_description(property, current_id) }}

Examples section spacing issue

There is a problem when generating elements with examples. The issue has to do with the fact that Bootstrap automatically adds a 1rem margin below any pre HTML tags. This results in example blocks appearing as though they have another line after the end.

The fix I have found is to add a class to the pre tags containing the examples that says m-0 or mb-0. This will override Bootstrap's default behavior and remove the spacing. I was going to open a PR myself, but couldn't find where to place this code. Any help is greatly appreciated.

Support using a JSON configuration file for options

The number of CLI parameters is growing and I think it would be easy going forward to use a configuration file instead.

Of course, that file would have a JSON Schema for its format and the documentation for which would be generated using the library itself.

It would also be nice to keep the CLI parameters. We would need a way to set values in the configuration from CLI parameters without each of them needing to be created manually. For example, if the configuration file has the minify attribute with type bool, the flag --minify/--no-minify should be generated automatically.

This would also help cleaning up the parameters on the 3 code entry points: generate_from_schema, generate_from_filename, and generate_from_file_object. They could accept a Configuration object that would be the result of loading the JSON configuration. That way there is only one single source for all parameters.

Add support for pattern properties

This is a very useful element of the JSON schema, it allows users to specify that any properties matching some regular expression be allowed.

The work needed to implement this feature is fairly minor, a second check on each element will need to be made, we will also need to add a new visual indicator for the pattern property, and we will need to decide on how to render the regular expression in the schema documentation.

I will be submitting a PR in the next couple of days for consideration.

Add table of content

For big schemas, it would be nice to have a table of content.

It would basically be a lightweight version of the schema without the description and definitions.

Each element would be a link to the actual definition in the schema below.

This feature needs to be optional, activated with a config option.

Parsing error for loaded schema

Hello,

I have the following error with version 0.33.1:

  File "XXX\venv\lib\site-packages\json_schema_for_humans\intermediate_representation.py", line 240, in _load_schema
    loaded_schema = loaded_schema[path_part]
TypeError: list indices must be integers or slices, not str
  if isinstance(path_part, str):
          loaded_schema = loaded_schema[path_part]

According to the test in the code 'path_part' is a string, hence the error. Do you have an idea of what has to be done in this case?
I can't provide you with a schema yet, since I'm still investigating on my side.

Thank you for your help.

Regards

Support YAML as source files

Looking at #32 , it seems some people are using yaml instead of JSON for their schemas.

Since YAML is a superset of JSON, loading using PyYaml all the time would allow this without impacting JSON versions.

Consider adding "break-on-newline" to markdown2 options or make configurable

We have a few schemas that contain "\n" characters in their descriptions for better formatting, so we've found it useful to pass the "break-on-newline" extra to the markdown2 call, such that
tags are used to preserve the newlines.

Is this something that'd be good to make a config option? Alternatively the config file could support passing any of the options, however I'm not sure many others are useful in this context:
https://github.com/trentm/python-markdown2/wiki/Extras

Complex regex structures in patternProperties lead to duplicate html IDs

Complex schema with pattern properties are likely to have duplicate html IDs since many regex tokens are replaced with underscores. This causes the generated documentation to be unusable in these cases.

I would suggest that using the pattern is not the best solution to this issue, we render the heading with the title, this would be a more sensible choice. Or indeed to use the parent element's name and an enumerator. Either way this is a regression to 0.9.0 as far as I can tell.

Add option to emit separate files for <head> and <body>

Thanks for your support so far, I appreciate the effort.

I am working on including the generated HTML files in a documentation generated by sphinx (using reST).

The problem is, sphinx generates a wrapper HTML which already contains <head>. Since I include the generated HTML as-is, it causes problems since the document now has two heads. However, it is possible to handle adding additional items into this original <head> section with sphinx, and it would be easier if separate files were generated for the <head> and <body> sections of the output.

Adding this might be a feature bloat, or too specific use-case. What do you think? I can also implement a post-processing script that does the separation.

Wrong specific value for constant tuples

Hello,

I have the following valid JSON schema:

{
"type": "array", 
"oneOf": [
    { "title": "1st constant", "const": [ 1, 2 ] },
    { "title": "2nd constant", "const": [ 3, 4 ] }
]
}

I am expecting to have an HTML page with "One Of" and two tabs: "1st constant" and "2nd constant", plus:

  • 1st tab:
Type: const
Specific value: [ 1, 2 ]
  • 2nd tab:
Type: const
Specific value: [ 3, 4 ]

But instead, "Specific value" is always set to "null".

Your help would be greatly appreciated. Thanks.

YAML does not support tabs for indentation

YAML spec explicitly rules out the use of tabs for indentation, while most JSON parsers will just ignore whitespace.
I would expect the latter behaviour, but because we use YAML as the parser this is not the current behavior.

As two options:

  1. We could strip the whitespace out, either ourselves or using a package like JSONminify.
  2. We could explicitly replace tabs with spaces.

Id be happy to take this and make a PR if you have an option you prefer.

Running into infinite loop with recursive schema

I'm running into infinite recursion with a schema that looks like this:

{
    "$id": "https://example.com/person.schema.json",
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "Person",
    "type": "object",
    "properties": {
        "relationships": {
            "$ref": "#/definitions/person/properties/relationships"
        }
    },
    "definitions": {
        "person": {
            "type": "object",
            "description": "A human being",
            "properties": {
                "relationships": {
                    "type": "object",
                    "description": "Relationships between this person and others",
                    "properties": {
                        "mother": {
                            "$ref": "#/definitions/person"
                        }
                    }
                }
            }
        }
    }
}

What I'd expect is for a document that looks something like this:

  • relationships
    • mother
      • relationships
        -> mother (link to existing mother section, because reference has been encountered before)

I've poked around the code a bit but haven't been able to get to the bottom of the issue yet

Hiding Fields

Is there any way to mark some fields in the schema as private so as to hide them from the generated html?

Recursive schema definitions result in infinite recursion

Currently if you have a schema with a recursive definition, the code will spin on the recursion until hitting the max recursion limit. Here's an example of a recursive schema definition:

"person": {
  "type": "object",
  "properties": {
    "children": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/person"
      }
    }
  }
}

I worked around this by hacking the code to stop resolving references after a certain depth, which is a fairly simple solution. I think a better solution would be to catch when schemas reference a parent element, and to create an anchor link to the parent. That would prevent duplicate content as well.

Any thoughts?

Problem resolving references across directory hierarchy

I noticed an issue resolving reference, in cases where one schema has a reference to another in a different directory, and that schema then references a schema in the same (or other) directory. All relative references should be resolved based on the referring schema's path, not the root schema's path (which is currently what's happening).

display type aliases for mixed array items (e.g. anyOf)

JSON-schema allows the definition of arrays whose items may be of different types (which themself can be again defined in the same schema). Currently, the generated schema browser will merely call them "Option 1", "Option 2", ... and display their resolved schema.

However, it would be more expressive to display the names through which they were defined.

Consider for example (simplified, of course):

definitions:
  customer:
   type: object
   properties: ['customer-id']
  employee:
    type: object
    properties: ['employee-id']

type: object
properties:
  people:
    type: array
    items:
     anyOf:
      - $ref: '#/definitions/customer'
      - $ref: '#/definitions/employee'

In this example, it would be much more expressive to name the available "options" customer and employee.

Please note that this example is of course simplified, and does certainly in this form not make too much sense. I derived it from an actual (I think reasonable) use-case.

Cheers
Christian

string pattern interpreted as html tags

In some cases parts of string pattern get interpreted as html tags which results in not correctly displaying the original pattern. An example of this is the following:

{
  "type": "string",
  "pattern": "^(<<variable:([-+/*0-9A-Za-z_]+)>>|<<auto>>)$"
}

The generated html displays it as
Screenshot from 2020-05-21 19-01-48
which is due <variable... and <auto> becoming html tags

<code>^(&lt;<variable:([-+ *0-9a-za-z_]+)="">&gt;|&lt;<auto>&gt;)$</auto></variable:([-+></code>

recursive self referencing

in case of recursive self referencing like this definition:

	"tree": {
	  "type": "object",
	  "properties": {
		"value": { "type": "string" },
		"branches": {
		  "type": "array",
		  "items": { "$ref": "#/definitions/tree" },
		  "minItems": 1
		}
	  },
	  "required": ["value"]

generation fails with message: RecursionError: maximum recursion depth exceeded.
Maybe self referencing should be marked specially in output and not try to generate HTML tags endlessly.

generate_from_filename() does not need to load YAML

generate_from_filename() does a redundant YAML load of schema_file_name.

The result of the load operation, once passed into generate_from_schema() is discarded without use, due to later introduction of build_intermediate_representation().

The YAML load operation of generate_from_filename() should be factored out.

Markdown templates don't support if keyboards with more than 2 layers.

When I try to generate documentation with an if object 2-3 layers deep, it fails with Markdown and mc_nested mode and succeeds on js of flat.

"if": {
                "properties": {
                    "setting": {
                        "properties": {
                            "sampling": {
                                "properties": {
                                    "mode": {
                                        "const": "some_const"
                                    }
                                }                        
                            }
                        }
                    }
                }
            },

Output:

...
  File "/home/username/.local/lib/python3.8/site-packages/json_schema_for_humans/templates/md_nested/section_conditional_subschema.html", line 8, in top-level template code
    {{- first_property.kw_const.literal | python_to_json -}}
  File "/home/username/.local/lib/python3.8/site-packages/json_schema_for_humans/jinja_filters.py", line 83, in python_to_json
    return json.dumps(value, indent=4, separators=(",", ": "), ensure_ascii=False)
  File "/usr/lib/python3.8/json/__init__.py", line 234, in dumps
    return cls(
  File "/usr/lib/python3.8/json/encoder.py", line 201, in encode
    chunks = list(chunks)
  File "/usr/lib/python3.8/json/encoder.py", line 438, in _iterencode
    o = _default(o)
  File "/usr/lib/python3.8/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Undefined is not JSON serializabl

Add support for additionalProperties

As well as a boolean value, additionalProperties can take an entire schema, to which all additional properties must conform.

I plan to contribute this myself, and have some rough code working, taking inspiration from the PR which implemented the pattern properties support.

I don't intend on adding anything specific for the simple true/false cases, but maybe I should do that at the same time for completeness? What content should be displayed in this case?

Schema generation fails for top level array

First of all, thanks for this great tool! It generates really nice documentation.

One thing I could not get to work is generate the correct HTML for schemas with top level array definitions, e.g. see below:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "Example",
    "description": "Example for demonstration",
    "type": "array",
    "items": {
        "description": "A string",
        "type": "string"
    }
}

This should be valid json schema, but it generates the following output:

<!DOCTYPE html><html lang=en> <head><link rel=stylesheet type=text/css href="https://fonts.googleapis.com/css?family=Overpass:300,400,600,800"><script src=https://code.jquery.com/jquery-3.4.1.min.js integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin=anonymous></script><link href=https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css rel=stylesheet integrity=sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T crossorigin=anonymous><script src=https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js integrity=sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM crossorigin=anonymous></script><link rel=stylesheet type=text/css href=schema_doc.css><script src=https://use.fontawesome.com/facf9fa52c.js></script><title>Example</title><h1>Example</h1></head> <body></body> </html>

Which is just an empty template.

Is this case planned to be supported? If so, let me know if you need help implementing it.

Cheers!

Add path to element

When browsing a big schema, it would be useful to be able to see the path to the current element in the schema (i.e. where it should actually be when you write your JSON file that complies with the schema)

This should be optional and activated with a config option.

--no-link-to-reused-ref does not work

Hi, it seems that --no-link-to-reused-ref does not work - I still see the "Same definition as" links even though I enabled this.

I am using python 3.7.8 on Windows 10.

Elements next to $ref should be merged with the referenced element instead of thrown out

Currently, if an element has a $ref along with other attributes, only $ref and description are used to generates the documentation.

For example:

{
  "$id": "https://example.com/schema.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Test",
  "type": "object",
  "properties": {
    "aProperty": {
      "$ref": "#/definitions/aProperty",
      "default": "Default from property"
    }
  },
  "definitions": {
    "aProperty": {
      "default": "Default from definition",
      "type": "string"
    }
  }
}

Generates the following:
chrome_Xc2X32LQet

But it should generate this:
chrome_NLyIMZW4fo

Side note: The official spec does not define if default should have priority over the one in the referenced element, but JSON Schema for Humans already uses description from the referencing node, so it makes sense to do the same for default.

Trouble using tool

Hi I am having trouble using the tool. I am using it on the schema attached and it is giving me the output of a single page saying type: Object.

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "definitions": {
        "IArtifactData": {
            "properties": {
                "commitMap": {
                    "$ref": "#/definitions/Record<string,string>"
                },
                "tagMap": {
                    "$ref": "#/definitions/Record<string,string[]>"
                }
            },
            "type": "object"
        },
        "IArtifactPublishEvents": {
            "properties": {
                "artifactRepoKey": {
                    "type": "string"
                },
                "artifactType": {
                    "type": "string"
                },
                "event": {
                    "type": "string"
                },
                "eventRegex": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "IArtifactType": {
            "properties": {
                "artifactType": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "IArtifacts": {
            "properties": {
                "artifacts": {
                    "$ref": "#/definitions/Record<string,string[]>"
                }
            },
            "type": "object"
        },
        "IArtifactsResolver": {
            "allOf": [
                {
                    "$ref": "#/definitions/IArtifacts"
                },
                {
                    "$ref": "#/definitions/IEvent"
                },
                {
                    "$ref": "#/definitions/IEventFallback"
                },
                {
                    "$ref": "#/definitions/IArtifactsResolverOverrides"
                }
            ]
        },
        "IArtifactsResolverBase": {
            "allOf": [
                {
                    "$ref": "#/definitions/IArtifacts"
                },
                {
                    "$ref": "#/definitions/IEvent"
                },
                {
                    "$ref": "#/definitions/IEventFallback"
                }
            ]
        },
        "IArtifactsResolverOverrides": {
            "properties": {
                "overrides": {
                    "items": {
                        "allOf": [
                            {
                                "$ref": "#/definitions/IArtifacts"
                            },
                            {
                                "$ref": "#/definitions/IEvent"
                            },
                            {
                                "$ref": "#/definitions/IEventFallback"
                            }
                        ]
                    },
                    "type": "array"
                }
            },
            "type": "object"
        },
        "IBuild": {
            "properties": {
                "artifactPublishEvents": {
                    "items": {
                        "$ref": "#/definitions/IArtifactPublishEvents"
                    },
                    "type": "array"
                },
                "artifacts": {
                    "$ref": "#/definitions/Record<string,string[]>"
                },
                "dependencies": {
                    "allOf": [
                        {
                            "$ref": "#/definitions/IArtifacts"
                        },
                        {
                            "$ref": "#/definitions/IEvent"
                        },
                        {
                            "$ref": "#/definitions/IEventFallback"
                        },
                        {
                            "$ref": "#/definitions/IArtifactsResolverOverrides"
                        }
                    ]
                },
                "name": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "IBuildVersions": {
            "properties": {
                "artifacts": {
                    "$ref": "#/definitions/Record<string,IArtifactData>"
                },
                "repos": {
                    "$ref": "#/definitions/Record<string,IRepoData>"
                }
            },
            "type": "object"
        },
        "IBuildVersionsGitRepo": {
            "properties": {
                "gitRepo": {
                    "$ref": "#/definitions/IGitConnectionRepo"
                }
            },
            "type": "object"
        },
        "ICommitVersionMap": {
            "type": "object"
        },
        "ICommon": {
            "properties": {
                "artifactPublishEvents": {
                    "items": {
                        "$ref": "#/definitions/IArtifactPublishEvents"
                    },
                    "type": "array"
                },
                "artifacts": {
                    "$ref": "#/definitions/Record<string,string[]>"
                },
                "name": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "IDeploy": {
            "properties": {
                "artifactPublishEvents": {
                    "items": {
                        "$ref": "#/definitions/IArtifactPublishEvents"
                    },
                    "type": "array"
                },
                "artifacts": {
                    "$ref": "#/definitions/Record<string,string[]>"
                },
                "deploymentMap": {
                    "$ref": "#/definitions/Record<string,IDeployment>"
                },
                "name": {
                    "type": "string"
                },
                "overrides": {
                    "items": {
                        "allOf": [
                            {
                                "$ref": "#/definitions/IArtifacts"
                            },
                            {
                                "$ref": "#/definitions/IEvent"
                            },
                            {
                                "$ref": "#/definitions/IEventFallback"
                            }
                        ]
                    },
                    "type": "array"
                }
            },
            "type": "object"
        },
        "IDeployBase": {
            "allOf": [
                {
                    "$ref": "#/definitions/ICommon"
                },
                {
                    "$ref": "#/definitions/IArtifactsResolverOverrides"
                }
            ]
        },
        "IDeployment": {
            "properties": {
                "artifacts": {
                    "$ref": "#/definitions/Record<string,string[]>"
                },
                "environmentKey": {
                    "type": "string"
                },
                "event": {
                    "type": "string"
                },
                "eventFallback": {
                    "type": "string"
                },
                "eventRegex": {
                    "type": "string"
                },
                "group": {
                    "type": "string"
                },
                "overrides": {
                    "items": {
                        "allOf": [
                            {
                                "$ref": "#/definitions/IArtifacts"
                            },
                            {
                                "$ref": "#/definitions/IEvent"
                            },
                            {
                                "$ref": "#/definitions/IEventFallback"
                            }
                        ]
                    },
                    "type": "array"
                }
            },
            "type": "object"
        },
        "IDeploymentBase": {
            "allOf": [
                {
                    "$ref": "#/definitions/IArtifacts"
                },
                {
                    "$ref": "#/definitions/IEvent"
                },
                {
                    "$ref": "#/definitions/IEventFallback"
                },
                {
                    "$ref": "#/definitions/IArtifactsResolverOverrides"
                },
                {
                    "$ref": "#/definitions/IEventRegex"
                }
            ]
        },
        "IEvent": {
            "properties": {
                "event": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "IEventFallback": {
            "properties": {
                "eventFallback": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "IEventRegex": {
            "properties": {
                "eventRegex": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "IGitConnection": {
            "properties": {
                "authorEmail": {
                    "type": "string"
                },
                "authorName": {
                    "type": "string"
                },
                "pathPrefix": {
                    "type": "string"
                },
                "remoteHost": {
                    "type": "string"
                },
                "remotePasswordEnvVar": {
                    "type": "string"
                },
                "remoteProtocol": {
                    "type": "string"
                },
                "remoteUser": {
                    "type": "string"
                },
                "sshKeyFile": {
                    "type": "string"
                },
                "sshKeyFileEnvVar": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "IGitConnectionRepo": {
            "properties": {
                "gitConnectionKey": {
                    "type": "string"
                },
                "path": {
                    "type": "string"
                },
                "ref": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "IGlobalConfig": {
            "properties": {
                "artifactRepoMap": {
                    "$ref": "#/definitions/Record<string,any>"
                },
                "buildVersions": {
                    "$ref": "#/definitions/IBuildVersionsGitRepo"
                },
                "environmentMap": {
                    "$ref": "#/definitions/Record<string,any>"
                },
                "gitConnectionMap": {
                    "$ref": "#/definitions/Record<string,IGitConnection>"
                }
            },
            "type": "object"
        },
        "IPromote": {
            "properties": {
                "artifactPublishEvents": {
                    "items": {
                        "$ref": "#/definitions/IArtifactPublishEvents"
                    },
                    "type": "array"
                },
                "artifacts": {
                    "$ref": "#/definitions/Record<string,string[]>"
                },
                "baseVersion": {
                    "type": "string"
                },
                "gitTagDisable": {
                    "type": "boolean"
                },
                "name": {
                    "type": "string"
                },
                "promotionMap": {
                    "$ref": "#/definitions/Record<string,IPromotion>"
                },
                "tagPrefix": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "IPromotion": {
            "properties": {
                "artifacts": {
                    "$ref": "#/definitions/Record<string,string[]>"
                },
                "event": {
                    "type": "string"
                },
                "eventFallback": {
                    "type": "string"
                },
                "overrides": {
                    "items": {
                        "allOf": [
                            {
                                "$ref": "#/definitions/IArtifacts"
                            },
                            {
                                "$ref": "#/definitions/IEvent"
                            },
                            {
                                "$ref": "#/definitions/IEventFallback"
                            }
                        ]
                    },
                    "type": "array"
                },
                "promoteToEvent": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "IRepoConfig": {
            "properties": {
                "build": {
                    "$ref": "#/definitions/IBuild"
                },
                "common": {
                    "$ref": "#/definitions/ICommon"
                },
                "deploy": {
                    "$ref": "#/definitions/IDeploy"
                },
                "promote": {
                    "$ref": "#/definitions/IPromote"
                }
            },
            "type": "object"
        },
        "IRepoData": {
            "properties": {
                "tagPrefixMap": {
                    "$ref": "#/definitions/Record<string,Record<string,string[]>>"
                }
            },
            "type": "object"
        },
        "ITagPrefixMap": {
            "type": "object"
        },
        "ITagVersionMap": {
            "type": "object"
        },
        "Record<string,IArtifactData>": {
            "description": "Construct a type with a set of properties K of type T",
            "type": "object"
        },
        "Record<string,IDeployment>": {
            "type": "object"
        },
        "Record<string,IGitConnection>": {
            "type": "object"
        },
        "Record<string,IPromotion>": {
            "type": "object"
        },
        "Record<string,IRepoData>": {
            "description": "Construct a type with a set of properties K of type T",
            "type": "object"
        },
        "Record<string,Record<string,string[]>>": {
            "type": "object"
        },
        "Record<string,any>": {
            "type": "object"
        },
        "Record<string,string>": {
            "type": "object"
        },
        "Record<string,string[]>": {
            "type": "object"
        }
    }
}

Passing file path to template as template_name

Thank you for such a great tool!

Question: I am currently abusing the fact that os.path.join() will reset if given an absolute path to join, and hence line 1259 where generate calculates the template_folder can be tricked into reading from any arbitrary directory.

For example:

$ generate-schema-doc --config no_show_breadcrumbs --config description_is_markdown --config template_name=$PWD/template schema/object.json html/object.html

reads its template from the current directory/template rather than "js" or "flat".

Is this intentional, and can be relied on to not go away (and if so, could it be documented please?) or is this a not-so-clever hack and I should do something more sane? :)

Seeing a few issues with the latest updates

  1. Getting a JS error when I inspect via the developer tools console in the browser:
Uncaught Error: Syntax error, unrecognized expression: a[href^=#]
    at Function.se.error (jquery-3.4.1.min.js:2)
    at se.tokenize (jquery-3.4.1.min.js:2)
    at se.compile (jquery-3.4.1.min.js:2)
    at se.select (jquery-3.4.1.min.js:2)
    at se (jquery-3.4.1.min.js:2)
    at Function.se.matchesSelector (jquery-3.4.1.min.js:2)
    at Object.add (jquery-3.4.1.min.js:2)
    at HTMLDocument.<anonymous> (jquery-3.4.1.min.js:2)
    at Function.each (jquery-3.4.1.min.js:2)
    at k.fn.init.each (jquery-3.4.1.min.js:2)

It appears the JS needs to be $(document).on('click', 'a[href^="#"]', function(event) {

  1. Accordion expand/collapse broken for suffix with parent that starts with a number (i.e 0). In the code below, parent + property_name should be sent through the escape function:
    {%- set suffix = property_name | escape_property_name_for_id -%}
    {%- if parent != "" -%}
        {%- set suffix = parent ~ "__" ~ suffix -%}
    {%- endif -%}

Perhaps something like this:

    {%- set suffix = property_name -%}
    {%- if parent != "" -%}
        {%- set suffix = parent ~ "__" ~ suffix -%}
    {%- endif -%}
    {%- set suffix = suffix | escape_property_name_for_id -%}
  1. Missing expand all/collapse all buttons for some schemas. The buttons are missing for code that goes through the else path of this code:
<body onload="anchorOnLoad()">
    {%- if title -%}
        <h1>{{ title }}</h1>
    {%- endif -%}
    {%- set properties = schema.get("properties") -%}
    {%- if schema.get("type") == "object" and properties -%}
        {%- set description = schema.get("description") -%}
        {%- if description -%}
            <span class="description">{{ description | markdown }}</span>
        {%- endif -%}
        {%- if expand_buttons -%}
            <div class="text-right">
                <button class="btn btn-primary" type="button" data-toggle="collapse" data-target=".collapse:not(.show)" aria-expanded="false">Expand all</button>
                <button class="btn btn-primary" type="button" data-toggle="collapse" data-target=".collapse.show" aria-expanded="false">Collapse all</button>
            </div>
        {%- endif -%}

        {%- set required_properties = schema.get("required") or [] -%}
        {%- for property_name, property in properties.items() -%}
            {{ subsection(False, loop.index, "", property_name, property, required_properties, schema_path) }}
        {%- endfor -%}
    {% else %}
        {{ content(0, schema.get("title", "Main schema"), schema, schema_path) }}
    {%- endif -%}

</body>

Seems like the expand_buttons code is needed inside of content(...) as well

Error Artifact in Generated Docs

First, thanks a lot for maintaining this!

Now, the question. The following input produces an HTML document that seems to contain an error artifact ("0x7f233bf07ee0"):

image

{
    "type": "object",
    "properties": {
        "uniqueId": {
            "type": "string",
            "description": "Unique ID in source/master system",
            "maxLength": 255
        }
    }
}

The command used to generate is:

docker build --iidfile=/tmp/schemas.docker .

docker run \
        -v $PWD:/code \
        -w /code \
        --rm \
        `cat /tmp/schemas.docker` \
        generate-schema-doc \
            --config description_is_markdown=false \
            --config expand_buttons=true \
            "test.json"

And the environment is a fresh Docker container:

FROM python:3-buster

RUN pip install json-schema-for-humans

Any hints on how to get the full error message and/or how to fix it? :)

Add special text in case of a circular reference

As a solution to #50 , circular references are now detected and added as a link to the first seen element in the loop.

However, it might be clearer to indicate a different text than the one used for repeated definitions (Same definition as x).

The text could be something like This is a circular reference to x

Wrong default value used when several nodes references the same

Example:

{
  "properties": {
    "a": {
      "$ref": "#/definitions/common",
      "default": "Default from a"
     } ,
    "b": {
      "$ref": "#/definitions/common",
      "default": "Default from b"
     }
  },
  "definitions": {
    "common": {
      "description": "a description"
    }
  }
}

We get the following:
chrome_z9kKoM8PSK

The default from b is wrong

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.