Skip to content

Instantly share code, notes, and snippets.

@tk0miya
Created January 29, 2023 06:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tk0miya/d864e6dfe6bf5f1c4d3629638a6aa3e4 to your computer and use it in GitHub Desktop.
Save tk0miya/d864e6dfe6bf5f1c4d3629638a6aa3e4 to your computer and use it in GitHub Desktop.
# extension testbed
import re
from docutils import nodes
from docutils.nodes import Element, Node
from sphinx.util.docutils import SphinxDirective
from sphinx.writers.html5 import HTML5Translator
class CodeBlockCalloutsDirective(SphinxDirective):
has_content = True
def run(self) -> list[Node]:
node = nodes.container()
node.document = self.state.document
self.state.nested_parse(self.content, self.content_offset, node)
if len(node.children) != 1 or not isinstance(node.children[0], nodes.enumerated_list):
logger.warning(__('The content of code-block-callouts should be an enumerated list'),
location=(self.env.docname, self.lineno))
return []
node.children[0]['classes'].append('code-block-callouts')
return node.children
class CodeBlockCalloutsHTMLTranslator(HTML5Translator):
def visit_literal_block(self, node: Element) -> None:
if node.rawsource != node.astext():
# most probably a parsed-literal block -- don't highlight
return super().visit_literal_block(node)
lang = node.get('language', 'default')
linenos = node.get('linenos', False)
highlight_args = node.get('highlight_args', {})
highlight_args['force'] = node.get('force', False)
opts = self.config.highlight_options.get(lang, {})
if linenos and self.config.html_codeblock_linenos_style:
linenos = self.config.html_codeblock_linenos_style
highlighted = self.highlighter.highlight_block(
node.rawsource, lang, opts=opts, linenos=linenos,
location=node, **highlight_args
)
# additional line
highlighted = re.sub(r'<span class="c1"># (\d+)</span>', r'<span class="code-block-callouts"><span>\1</span></span>', highlighted)
starttag = self.starttag(node, 'div', suffix='',
CLASS='highlight-%s notranslate' % lang)
self.body.append(starttag + highlighted + '</div>\n')
raise nodes.SkipNode
def setup(app):
app.add_directive('code-block-callouts', CodeBlockCalloutsDirective)
app.set_translator('html', CodeBlockCalloutsHTMLTranslator)
return {
'version': 'builtin',
'parallel_read_safe': True,
'parallel_write_safe': True,
}

Welcome to project's documentation!

ol.code-block-callouts { counter-reset: my-counter; list-style: none; padding: 0; margin: 0; } ol.code-block-callouts > li { font-size: 16px; line-height: 1.5; padding-left: 30px; position: relative; } ol.code-block-callouts > li:before { content: counter(my-counter); counter-increment: my-counter; background-color: #333; border: 1px solid; border-radius: 50%; box-sizing: border-box; display: flex; justify-content: center; align-items: center; height: 22px; width: 22px; color: #ffffff; font-size: 85%; line-height: 1; position: absolute; top: 0; left: 0; } span.code-block-callouts { height: 22px; line-height: 22px; width: 22px; text-align: center; } span.code-block-callouts > span { background-color: #333; border: 1px solid; border-radius: 50%; box-sizing: border-box; display: inline-block; vertical-align: middle; height: 22px; width: 22px; color: #ffffff; font-size: 85%; }
def hello():  # 1
    return 'world'  # 2
  1. ハロー関数の定義
  2. ワールドを返す
@tk0miya
Copy link
Author

tk0miya commented Jan 29, 2023

Result:

screenshot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment