@@ -38,15 +38,20 @@ class Snippet(object):
3838 # :rst:role:`doc`.
3939 docname : str
4040
41- #: Absolute path of the source file.
41+ #: Absolute path to the source file.
4242 file : str
4343
44- #: Line number range of snippet, in the source file which is left closed
45- #: and right opened.
44+ #: Line number range of source file (:attr:`Snippet.file`),
45+ #: left closed and right opened.
4646 lineno : tuple [int , int ]
4747
48- #: The original reStructuredText of snippet
49- rst : list [str ]
48+ #: The source text read from source file (:attr:`Snippet.file`),
49+ # in Markdown or reStructuredText.
50+ source : list [str ]
51+
52+ #: Text representation of the snippet, usually generated form
53+ # :meth:`nodes.Element.astext`.
54+ text : list [str ]
5055
5156 #: The possible identifier key of snippet, which is picked from nodes'
5257 #: (or nodes' parent's) `ids attr`_.
@@ -57,7 +62,7 @@ class Snippet(object):
5762 def __init__ (self , * nodes : nodes .Element ) -> None :
5863 assert len (nodes ) != 0
5964
60- env : BuildEnvironment = nodes [0 ].document .settings .env
65+ env : BuildEnvironment = nodes [0 ].document .settings .env # type: ignore
6166
6267 file , docname = None , None
6368 for node in nodes :
@@ -66,7 +71,7 @@ def __init__(self, *nodes: nodes.Element) -> None:
6671 docname = env .path2doc (file )
6772 break
6873 if not file or not docname :
69- raise ValueError ('Missing source file or docname' )
74+ raise ValueError (f'Nodes { nodes } lacks source file or docname' )
7075 self .file = file
7176 self .docname = docname
7277
@@ -78,13 +83,18 @@ def __init__(self, *nodes: nodes.Element) -> None:
7883 lineno [1 ] = max (lineno [1 ], _line_of_end (node ))
7984 self .lineno = (lineno [0 ], lineno [1 ])
8085
81- lines = []
86+ source = []
8287 with open (self .file , 'r' ) as f :
8388 start = self .lineno [0 ] - 1
8489 stop = self .lineno [1 ] - 1
8590 for line in itertools .islice (f , start , stop ):
86- lines .append (line .strip ('\n ' ))
87- self .rst = lines
91+ source .append (line .strip ('\n ' ))
92+ self .source = source
93+
94+ text = []
95+ for node in nodes :
96+ text .extend (node .astext ().split ('\n ' ))
97+ self .text = text
8898
8999 # Find exactly one ID attr in nodes
90100 self .refid = None
@@ -102,19 +112,21 @@ def __init__(self, *nodes: nodes.Element) -> None:
102112
103113
104114class Code (Snippet ):
115+ ALLOWED_LANGS = ['console' ]
105116 #: Language of code block
106117 lang : str
107118 #: Description of code block, usually the text of preceding paragraph
108119 desc : str
109- #: The code itself.
110- code : str
111120
112121 def __init__ (self , node : nodes .literal_block ) -> None :
113122 assert isinstance (node , nodes .literal_block )
114123 super ().__init__ (node )
115124
116125 self .lang = node ['language' ]
117- self .code = node .astext ()
126+ if self .lang not in self .ALLOWED_LANGS :
127+ raise ValueError (
128+ f'Language of node { node } { self .lang } not in allowed language list { self .ALLOWED_LANGS } ' ,
129+ )
118130
119131 self .desc = ''
120132 if isinstance (para := node .previous_sibling (), nodes .paragraph ):
@@ -131,7 +143,10 @@ def __init__(self, node: nodes.literal_block) -> None:
131143 # In this case, the preceding paragraph "Foo:" is the descritpion
132144 # of the code block. This convention also applies to the code,
133145 # code-block, sourcecode directive.
134- self .desc += para .astext ().replace ('\n ' , ' ' )
146+
147+ # For better display, the trailing colon is removed.
148+ # TODO: https://en.wikipedia.org/wiki/Colon_(punctuation)#Computing
149+ self .desc += para .astext ().replace ('\n ' , ' ' ).rstrip (':::︁︓﹕' )
135150 if caption := node .get ('caption' ):
136151 # Use caption as descritpion.
137152 # In sphinx, all of code-block, sourcecode and code have caption option.
@@ -147,10 +162,9 @@ class WithTitle(object):
147162 title : str
148163
149164 def __init__ (self , node : nodes .Element ) -> None :
150- if title := node .next_node (nodes .title ):
151- self .title = title .astext ()
152- else :
165+ if not (title := node .next_node (nodes .title )):
153166 raise ValueError (f'Node f{ node } lacks title' )
167+ self .title = title .astext ()
154168
155169
156170class Section (Snippet , WithTitle ):
0 commit comments