diff --git a/botocore/docs/client.py b/botocore/docs/client.py index ba2366a846..9559594697 100644 --- a/botocore/docs/client.py +++ b/botocore/docs/client.py @@ -335,6 +335,7 @@ def _add_top_level_documentation(self, section, shape): def _add_exception_catch_example(self, section, shape): section.style.new_line() section.style.bold('Example') + section.style.new_paragraph() section.style.start_codeblock() section.write('try:') section.style.indent() diff --git a/botocore/docs/translator.py b/botocore/docs/translator.py new file mode 100644 index 0000000000..aabf36be9a --- /dev/null +++ b/botocore/docs/translator.py @@ -0,0 +1,62 @@ +# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +from sphinx.locale import admonitionlabels +from sphinx.writers.html5 import HTML5Translator as SphinxHTML5Translator + + +class BotoHTML5Translator(SphinxHTML5Translator): + """Extension of Sphinx's ``HTML5Translator`` for Botocore documentation.""" + + STRONG_TO_H3_HEADINGS = [ + "Example", + "Examples", + "Exceptions", + "Request Syntax", + "Response Structure", + "Response Syntax", + "Structure", + "Syntax", + ] + + def visit_admonition(self, node, name=""): + """Uses the h3 tag for admonition titles instead of the p tag.""" + self.body.append( + self.starttag(node, "div", CLASS=("admonition " + name)) + ) + if name: + title = ( + f"

{admonitionlabels[name]}

" + ) + self.body.append(title) + + def visit_strong(self, node): + """Visit a strong HTML element. + + Opens the h3 tag for a specific set of words/phrases and opens the + strong tag for all others. + """ + if len(node) > 0 and node[0] in self.STRONG_TO_H3_HEADINGS: + self.body.append(self.starttag(node, "h3", "")) + else: + self.body.append(self.starttag(node, "strong", "")) + + def depart_strong(self, node): + """Depart a strong HTML element. + + Closes the h3 tag for a specific set of words/phrases and closes the + strong tag for all others. + """ + if node[0] in self.STRONG_TO_H3_HEADINGS: + self.body.append("") + else: + self.body.append("") diff --git a/docs/source/_static/css/custom.css b/docs/source/_static/css/custom.css index a559c5da5f..357d1ec0d4 100644 --- a/docs/source/_static/css/custom.css +++ b/docs/source/_static/css/custom.css @@ -31,3 +31,29 @@ h1, code, li { .sidebar-logo{ padding: 20% 15%; } + +/* Apply furo styled admonition titles for

. */ +h3.admonition-title { + position: relative; + margin: 0 -0.5rem 0.5rem; + padding-left: 2.5rem; + padding-right: .5rem; + padding-top: .4rem; + padding-bottom: .4rem; + font-weight: 700; + font-size: 1.5em; + line-height: 1.25; + border-radius: unset; + background-color: var(--color-admonition-title-background); +} +/* Apply furo styled admonition icons before

. */ +h3.admonition-title::before { + content: ""; + position: absolute; + left: 0.5rem; + width: 1.5rem; + height: 1.5rem; + background-color: var(--color-admonition-title); + mask-image: var(--icon-admonition-default); + mask-repeat: no-repeat; +} diff --git a/docs/source/_static/js/custom.js b/docs/source/_static/js/custom.js index 6596a718e1..7d876350c2 100644 --- a/docs/source/_static/js/custom.js +++ b/docs/source/_static/js/custom.js @@ -82,18 +82,6 @@ function makeServiceLinkCurrent(serviceName) { } const currentPagePath = window.location.pathname.split('/'); const codeBlockSelector = 'div.highlight pre'; -const boldTextSelector = 'strong'; -const boldElements = document.querySelectorAll(boldTextSelector); -const headings = [ - 'Example', - 'Examples', - 'Exceptions', - 'Request Syntax', - 'Response Structure', - 'Response Syntax', - 'Structure', - 'Syntax' -]; // Expands the "Available Services" sub-menu in the side-bar when viewing // nested doc pages and highlights the corresponding service list item. function expandSubMenu() { @@ -112,18 +100,9 @@ function makeCodeBlocksScrollable() { codeCell.tabIndex = 0; }); } -// Converts implicit bold headings into actual headings with h3 tags. -function convertImplicitHeadings() { - boldElements.forEach(boldElement => { - if (headings.includes(boldElement.innerHTML)) { - boldElement.parentElement.outerHTML = `

${ boldElement.innerHTML }

`; - } - }); -} // Functions to run after the DOM loads. function runAfterDOMLoads() { expandSubMenu(); - convertImplicitHeadings(); makeCodeBlocksScrollable(); } // Run a function after the DOM loads. diff --git a/docs/source/conf.py b/docs/source/conf.py index b2cb4eaa3f..ca7b6edf8f 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -14,6 +14,7 @@ import datetime, sys, os from botocore.session import get_session from botocore.docs import generate_docs +from botocore.docs.translator import BotoHTML5Translator generate_docs(os.path.dirname(os.path.abspath(__file__)), get_session()) @@ -283,3 +284,8 @@ # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' + + +def setup(app): + # Register our custom HTML translator. + app.set_translator("html", BotoHTML5Translator) diff --git a/tests/unit/docs/test_client.py b/tests/unit/docs/test_client.py index c80cebc6e6..a0ec02a386 100644 --- a/tests/unit/docs/test_client.py +++ b/tests/unit/docs/test_client.py @@ -144,7 +144,8 @@ def test_modeled_exceptions(self): self.assert_contains_lines_in_order( [ '.. py:class:: MyService.Client.exceptions.SomeException', - '**Example**::', + '**Example**', + '::', 'except client.exceptions.SomeException as e:', '.. py:attribute:: response', '**Syntax**',