diff --git a/source/_static/jsonschema.css b/source/_static/jsonschema.css index 20f9f0ed..189af8fe 100644 --- a/source/_static/jsonschema.css +++ b/source/_static/jsonschema.css @@ -64,7 +64,15 @@ code, pre { font-family: Inconsolata,Monaco,Menlo,Consolas,"Courier New",monospace; } -.navbar, h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { +.navbar, h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6, .new { font-family: "Overlock","Helvetica Neue",Helvetica,Arial,sans-serif; font-weight: 900; } + +.new { + color: #3333ff; +} + +.new:before { + content: "★ "; +} diff --git a/source/conf.py b/source/conf.py index 27d04105..493ff9c2 100644 --- a/source/conf.py +++ b/source/conf.py @@ -22,6 +22,13 @@ # The standard of JSON Schema to test the examples against jsonschema_standard = 4 +rst_prolog = """ +.. role:: new + +.. |draft7| replace:: :new:`New in draft 7` +.. |draft6| replace:: :new:`New in draft 6` +""" + # -- General configuration ----------------------------------------------------- import sphinx_bootstrap_theme @@ -32,7 +39,7 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.mathjax', 'sphinx.ext.ifconfig', - 'sphinxext.jsonschemaext', 'sphinxext.language_specific'] + 'sphinxext.jsonschemaext', 'sphinxext.tab'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -193,7 +200,7 @@ # -- Options for LaTeX output -------------------------------------------------- from sphinxext import jsonschemaext -from sphinxext import language_specific +from sphinxext import tab latex_elements = { # The paper size ('letterpaper' or 'a4paper'). @@ -218,7 +225,7 @@ \def\marginparright{\@mparswitchfalse} \def\marginparoutside{\@mparswitchtrue} \makeatother - ''' + jsonschemaext.latex_preamble + language_specific.latex_preamble, + ''' + jsonschemaext.latex_preamble + tab.latex_preamble, 'fncychap': '\\usepackage[Conny]{fncychap}' } diff --git a/source/conventions.rst b/source/conventions.rst index 51f6c79d..d81b4e40 100644 --- a/source/conventions.rst +++ b/source/conventions.rst @@ -35,6 +35,26 @@ JSON in a few different languages: For C, you may want to consider using `Jansson `_ to read and write JSON. +Draft-specific notes +-------------------- + +The JSON Schema standard has been through a number of revisions or "drafts". The +most important are Draft 7, the most recent at the time of this writing, and +Draft 4, on which a lot of production software was built, and the draft for +which an earlier version of this book was written. + +The text is written to encourage the use of the latest Draft 7 and gives +priority to the latest conventions and features, but where it differs from Draft +4, those differences are highlighted in special call-outs. If you only wish to +target Draft 7, you can safely ignore those sections. + +|draft7| + +.. draft_specific:: + + --Draft 4 + This is where anything pertaining to an old draft would be mentioned. + Examples -------- diff --git a/source/sphinxext/language_specific.py b/source/sphinxext/tab.py similarity index 69% rename from source/sphinxext/language_specific.py rename to source/sphinxext/tab.py index 83bcd48d..03ee94ed 100644 --- a/source/sphinxext/language_specific.py +++ b/source/sphinxext/tab.py @@ -12,13 +12,13 @@ def __init__(self, *args, **kwargs): def split_content(l): parts = [] part = [] - language = None + label = None def add_part(): - if language is None: - raise ValueError("No language specified") + if label is None: + raise ValueError("No label specified") parts.append(AttrDict({ - 'language': language, + 'label': label, 'content': part})) for line in l: @@ -26,7 +26,7 @@ def add_part(): if len(part): add_part() part = [] - language = line[2:].strip() + label = line[2:].strip() else: part.append(line) @@ -35,7 +35,7 @@ def add_part(): return parts -class language_specific_pages(nodes.Element): +class pages(nodes.Element): local_attributes = ['parts'] def __init__(self, *args, **kwargs): @@ -43,18 +43,26 @@ def __init__(self, *args, **kwargs): nodes.Element.__init__(self, *args, **kwargs) +class language_specific_pages(pages): + header = 'Language-specific info:' + + +class draft_pages(pages): + header = 'Draft-specific info:' + + class section(nodes.Element): pass -def visit_language_specific_pages_node_html(self, node): +def visit_pages_node_html(self, node): node['classes'] = ['tabbable'] ul = nodes.bullet_list() ul['classes'] = ['nav', 'nav-tabs'] # set_source_info(self, ul) - href = tab('', 'Language-specific info:') + href = tab('', node.header) href['classes'] = ['disabled'] paragraph = nodes.paragraph('', '') li = nodes.list_item('') @@ -66,8 +74,8 @@ def visit_language_specific_pages_node_html(self, node): first = True for part in node.parts: - href = tab(part.language, part.language) - href['refuri'] = '#' + make_id(node, part.language) + href = tab(part.label, part.label) + href['refuri'] = '#' + make_id(node, part.label) paragraph = nodes.paragraph('') li = nodes.list_item('') if first: @@ -90,7 +98,7 @@ def visit_language_specific_pages_node_html(self, node): page['classes'] = ['tab-pane'] if first: page['classes'].append('active') - page['ids'] = [make_id(node, part.language)] + page['ids'] = [make_id(node, part.label)] page.append(part.paragraph) pages.append(page) @@ -102,19 +110,19 @@ def visit_language_specific_pages_node_html(self, node): self.body.append(self.starttag(node, 'div')) -def depart_language_specific_pages_node_html(self, node): +def depart_pages_node_html(self, node): self.body.append('') -def visit_language_specific_pages_node_latex(self, node): +def visit_pages_node_latex(self, node): for part in node.parts: t = tab('', '') - t.language = part.language + t.label = part.label t.append(part.paragraph) node.append(t) -def depart_language_specific_pages_node_latex(self, node): +def depart_pages_node_latex(self, node): pass @@ -135,23 +143,23 @@ def depart_tab_node_html(self, node): def visit_tab_node_latex(self, node): - self.body.append(r'\begin{jsonframe}{%s}{black}' % node.language) + self.body.append(r'\begin{jsonframe}{%s}{black}' % node.label) def depart_tab_node_latex(self, node): self.body.append(r'\end{jsonframe}') -def make_id(self, language): - return '{0}_{1}'.format(hex(id(self))[2:], language) +def make_id(self, label): + return '{0}_{1}'.format(hex(id(self))[2:], label) -class LanguageSpecificDirective(Directive): +class TabDirective(Directive): has_content = True def run(self): parts = split_content(self.content) - container = language_specific_pages(parts=parts) + container = self.make_container(parts) for part in parts: paragraph = nodes.paragraph('', '') @@ -163,17 +171,33 @@ def run(self): return [container] +class LanguageSpecificDirective(TabDirective): + def make_container(self, parts): + return language_specific_pages(parts=parts) + + +class DraftDirective(TabDirective): + def make_container(self, parts): + return draft_pages(parts=parts) + + def setup(app): app.add_node(tab, html=(visit_tab_node_html, depart_tab_node_html), latex=(visit_tab_node_latex, depart_tab_node_latex)) app.add_node(language_specific_pages, - html=(visit_language_specific_pages_node_html, - depart_language_specific_pages_node_html), - latex=(visit_language_specific_pages_node_latex, - depart_language_specific_pages_node_latex)) + html=(visit_pages_node_html, + depart_pages_node_html), + latex=(visit_pages_node_latex, + depart_pages_node_latex)) + app.add_node(draft_pages, + html=(visit_pages_node_html, + depart_pages_node_html), + latex=(visit_pages_node_latex, + depart_pages_node_latex)) app.add_directive('language_specific', LanguageSpecificDirective) + app.add_directive('draft_specific', DraftDirective) latex_preamble = r"""