Skip to content

Commit 89fbc18

Browse files
committed
📝 Add initial sphinx ext for per-doc feedbacks
Resolves #8783
1 parent db86ae8 commit 89fbc18

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

docs/docs_feedback_sphinxext.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
"""A sphinx extension for collecting per doc feedback."""
2+
3+
from __future__ import annotations
4+
5+
from typing import TYPE_CHECKING
6+
7+
if TYPE_CHECKING:
8+
from typing import Dict, List, Union
9+
10+
from sphinx.application import Sphinx
11+
12+
13+
def _modify_rst_document_source_on_read(
14+
app: Sphinx,
15+
docname: str,
16+
source: List[str],
17+
) -> None:
18+
"""Add info block to top and bottom of each document source.
19+
20+
This function modifies RST source in-place by adding an admonition
21+
block at the top and the bottom of each document right after it's
22+
been read from disk preserving :orphan: at top, if present.
23+
"""
24+
admonition_type = 'important'
25+
valid_admonitions = {
26+
'attention', 'caution', 'danger', 'error', 'hint',
27+
'important', 'note', 'tip', 'warning', 'admonition',
28+
}
29+
30+
if admonition_type not in valid_admonitions:
31+
raise ValueError(
32+
'Expected admonition_type to be one of '
33+
f'{valid_admonitions} but got {admonition_type}.'
34+
)
35+
36+
questions_list = """
37+
1. What problem were you trying to solve when you came to this page?
38+
39+
2. What content was useful?
40+
41+
3. What content was not useful?
42+
"""
43+
questions_list_urlencoded = (
44+
f"""
45+
0. Document: {docname}. Page URL: https://
46+
{questions_list}
47+
""".
48+
rstrip('\r\n\t ').
49+
replace('\r', '%0D').
50+
replace('\n', '%0A').
51+
replace(' ', '%20')
52+
)
53+
54+
admonition_msg = rf"""
55+
**Did this article help?**
56+
57+
We are currently doing research to improve pip's documentation
58+
and would love your feedback.
59+
Please `email us`_ and let us know:
60+
61+
{questions_list}
62+
63+
.. _email us:
64+
mailto:Docs\ UX\ Team \
65+
<docs-feedback+ux/[email protected]>\
66+
?subject=[Doc:\ {docname}]\ Pip\ docs\ feedback\ \
67+
(URL\:\ https\://)\
68+
&body={questions_list_urlencoded}
69+
"""
70+
orphan_mark = ':orphan:'
71+
info_block = f'.. {admonition_type}::\n\t\t{admonition_msg}\n'
72+
73+
is_orphan = orphan_mark in source[0]
74+
if is_orphan:
75+
source[0].replace(orphan_mark, '')
76+
else:
77+
orphan_mark = ''
78+
79+
source[0] = '\n\n'.join((
80+
orphan_mark, info_block, source[0], info_block,
81+
))
82+
83+
84+
def setup(app: Sphinx) -> Dict[str, Union[bool, str]]:
85+
"""Initialize the Sphinx extension.
86+
87+
This function adds a callback for modifying the document sources
88+
in-place on read.
89+
"""
90+
app.connect('source-read', _modify_rst_document_source_on_read)
91+
92+
return {
93+
'parallel_read_safe': True,
94+
'parallel_write_safe': True,
95+
'version': 'builtin',
96+
}

docs/html/conf.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@
3030
# Add any Sphinx extension module names here, as strings. They can be
3131
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
3232
# extensions = ['sphinx.ext.autodoc']
33-
extensions = ['sphinx.ext.extlinks', 'pip_sphinxext', 'sphinx.ext.intersphinx']
33+
extensions = [
34+
'sphinx.ext.extlinks',
35+
'sphinx.ext.intersphinx',
36+
'docs_feedback_sphinxext',
37+
'pip_sphinxext',
38+
]
3439

3540
# intersphinx
3641
intersphinx_cache_limit = 0

0 commit comments

Comments
 (0)