我正在尝试在 sphinxcontrib-httpexample 中添加一个新选项卡,例如
curl
、httpie
、python-request
。我已经进行了所需的更改,除了输出格式之外,一切都正常。
JSON 文件:
POST /plone/front-page/@aliases HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json
{
"items": [
{
"path": "/new-alias"
},
{
"path": "/old-alias"
},
{
"path": "/final-alias"
}
]
}
Python代码(我将其添加到这个文件中):
def build_plone_javascript_command(request):
javascript_code = 'createAliasesMutation'
redir_input2 = ''
# Request body
data = maybe_str(request.data())
if data:
if is_json(request.headers.get('Content-Type', '')):
redir_input2 = json.dumps(data, indent=2, sort_keys=True,
separators=(',', ': '))
else:
redir_input2 = data
# Output string
output_string = f"{javascript_code}\n|\nconst aliasesData = {redir_input2};"
return output_string
python 函数返回一个格式化字符串,然后将其放入 Sphinx CodeBlock 中。
修改后的Sphinx代码块:
from docutils import nodes
from docutils.parsers.rst import directives
from docutils.statemachine import StringList
from sphinx.directives.code import CodeBlock
from sphinxcontrib.httpexample import builders
from sphinxcontrib.httpexample import parsers
from sphinxcontrib.httpexample import utils
import os
import re
AVAILABLE_BUILDERS = {
'curl': (builders.build_curl_command, 'bash'),
'wget': (builders.build_wget_command, 'bash'),
'httpie': (builders.build_httpie_command, 'bash'),
'requests': (builders.build_requests_command, 'python'),
'python-requests': (builders.build_requests_command, 'python'),
'plone_javascript': (builders.build_plone_javascript_command, 'javascript'),
}
AVAILABLE_FIELDS = [
'query'
]
def choose_builders(arguments):
return [directives.choice(argument, AVAILABLE_BUILDERS)
for argument in (arguments or [])]
class HTTPExample(CodeBlock):
required_arguments = 0
optional_arguments = len(AVAILABLE_BUILDERS)
option_spec = utils.merge_dicts(CodeBlock.option_spec, {
'request': directives.unchanged,
'response': directives.unchanged,
})
def run(self):
config = self.state.document.settings.env.config
# Read enabled builders; Defaults to None
chosen_builders = choose_builders(self.arguments)
# Enable 'http' language for http part
self.arguments = ['http']
# process 'query' reST fields
if self.content:
raw = ('\r\n'.join(self.content)).encode('utf-8')
request = parsers.parse_request(raw)
params, _ = request.extract_fields('query')
params = [(p[1], p[2]) for p in params]
new_path = utils.add_url_params(request.path, params)
self.content[0] = ' '.join(
[request.command, new_path, request.request_version])
# split the request and optional response in the content.
# The separator is two empty lines followed by a line starting with
# 'HTTP/' or 'HTTP '
request_content = StringList()
request_content_no_fields = StringList()
response_content = None
emptylines_count = 0
in_response = False
is_field = r':({}) (.+): (.+)'.format('|'.join(AVAILABLE_FIELDS))
for i, line in enumerate(self.content):
source = self.content.source(i)
if in_response:
response_content.append(line, source)
else:
if emptylines_count >= 2 and \
(line.startswith('HTTP/') or line.startswith('HTTP ')):
in_response = True
response_content = StringList()
response_content.append(line, source)
elif line == '':
emptylines_count += 1
else:
request_content.extend(
StringList([''] * emptylines_count, source))
request_content.append(line, source)
if not re.match(is_field, line):
request_content_no_fields.extend(
StringList([''] * emptylines_count, source))
request_content_no_fields.append(line, source)
emptylines_count = 0
# Load optional external request
cwd = os.path.dirname(self.state.document.current_source)
if 'request' in self.options:
request = utils.resolve_path(self.options['request'], cwd)
with open(request) as fp:
request_content = request_content_no_fields = StringList(
list(map(str.rstrip, fp.readlines())), request)
# Load optional external response
if 'response' in self.options:
response = utils.resolve_path(self.options['response'], cwd)
with open(response) as fp:
response_content = StringList(
list(map(str.rstrip, fp.readlines())), response)
# reset the content to the request, stripped of the reST fields
self.content = request_content_no_fields
# Wrap and render main directive as 'http-example-http'
klass = 'http-example-http'
container = nodes.container('', classes=[klass])
container.append(nodes.caption('', 'http'))
container.extend(super(HTTPExample, self).run())
# Init result node list
result = [container]
# reset the content to just the request
self.content = request_content
# Append builder responses
if request_content_no_fields:
raw = ('\r\n'.join(request_content_no_fields)).encode('utf-8')
for name in chosen_builders:
request = parsers.parse_request(raw, config.httpexample_scheme)
builder_, language = AVAILABLE_BUILDERS[name]
name = 'JavaScript' if name == 'plone_javascript' else name
command = builder_(request)
content = StringList(
[command], request_content_no_fields.source(0))
options = self.options.copy()
options.pop('name', None)
options.pop('caption', None)
block = CodeBlock(
'code-block',
[language],
options,
content,
self.lineno,
self.content_offset,
self.block_text,
self.state,
self.state_machine
)
# Wrap and render main directive as 'http-example-{name}'
klass = 'http-example-{}'.format(name)
container = nodes.container('', classes=[klass])
container.append(nodes.caption('', name))
container.extend(block.run())
# Append to result nodes
result.append(container)
# Append optional response
if response_content:
options = self.options.copy()
options.pop('name', None)
options.pop('caption', None)
block = CodeBlock(
'code-block',
['http'],
options,
response_content,
self.lineno,
self.content_offset,
self.block_text,
self.state,
self.state_machine
)
# Wrap and render main directive as 'http-example-response'
klass = 'http-example-response'
container = nodes.container('', classes=[klass])
container.append(nodes.caption('', 'response'))
container.extend(block.run())
# Append to result nodes
result.append(container)
# Final wrap
container_node = nodes.container('', classes=['http-example'])
container_node.extend(result)
return [container_node]
输出:
createAliasesMutation | const aliasesData = { "items": [ { "datetime": "2022-05-05", "path": "/old-page", "redirect-to": "/front-page" }, { "datetime": "2022-05-05", "path": "/fizzbuzz", "redirect-to": "/front-page" } ] };
期望的输出(类似这样):
createAliasesMutation
|
const aliasesData =
{
"items": [
{
"path": "/new-alias"
},
{
"path": "/old-alias"
},
{
"path": "/final-alias"
}
]
}
HTML 文字:
<pre id="codecell19"><span></span><span class="nx">createAliasesMutation</span>
<span class="o">|</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">aliasesData</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s2">"items"</span><span class="o">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s2">"datetime"</span><span class="o">:</span><span class="w"> </span><span class="s2">"2022-05-05"</span><span class="p">,</span>
<span class="w"> </span><span class="s2">"path"</span><span class="o">:</span><span class="w"> </span><span class="s2">"/old-page"</span><span class="p">,</span>
<span class="w"> </span><span class="s2">"redirect-to"</span><span class="o">:</span><span class="w"> </span><span class="s2">"/front-page"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s2">"datetime"</span><span class="o">:</span><span class="w"> </span><span class="s2">"2022-05-05"</span><span class="p">,</span>
<span class="w"> </span><span class="s2">"path"</span><span class="o">:</span><span class="w"> </span><span class="s2">"/fizzbuzz"</span><span class="p">,</span>
<span class="w"> </span><span class="s2">"redirect-to"</span><span class="o">:</span><span class="w"> </span><span class="s2">"/front-page"</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">]</span>
<span class="p">};</span>
</pre>
我尝试使用此
stackoverflow问题中的
.replace('\\n','\n')
,但仍然不起作用。
编辑:我再次发布此问题,因为我没有在之前的帖子中添加所有详细信息。