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**',