@@ -123,12 +123,13 @@ def __init__(
123123 relative_path = Path (self .document ["source" ]).relative_to (source_dir )
124124 self .current_document = str (relative_path .with_suffix ("" ))
125125 self .global_preface = global_preface
126+ self .file_preface = []
127+ self .prefaces = []
126128 self .transformers = BUILTIN_BLOCKS .copy ()
127129 self .transformers .update (custom_blocks )
128130 self .valid_blocks = self .transformers .keys ()
129131 self .title_stack = []
130132 self .current_refid = None
131- self .prefaces = []
132133 self .concat_global = concat_default
133134 self .concat_section = False
134135 self .concat_sources = []
@@ -153,7 +154,16 @@ def unknown_visit(self, node) -> None:
153154 self .concat_global = node .mode == "on"
154155 node .parent .remove (node )
155156 elif isinstance (node , PrefaceMarker ):
156- self .prefaces .extend (node .content .split ("\n " ))
157+ lines = node .content .split ("\n " ) or []
158+ if node .level == "next" :
159+ self .prefaces .extend (lines )
160+ elif node .level == "file" :
161+ self .file_preface = lines
162+ else :
163+ msg = f"Invalid preface argument: `{ node .level } `"
164+ logger .error (
165+ msg , type = warn_type , subtype = "invalid_argument" , location = node
166+ )
157167 node .parent .remove (node )
158168 elif isinstance (node , SkipMarker ):
159169 if node .level not in ("next" , "section" , "file" , "off" ):
@@ -243,31 +253,45 @@ def parse_source( # noqa: C901,PLR0912
243253 clean_source = source
244254 transform .source = source
245255
246- modified_source = "\n " .join (
247- self .global_preface + self .concat_sources + prefaces + [clean_source ]
256+ full_source = "\n " .join (
257+ self .global_preface
258+ + self .file_preface
259+ + self .concat_sources
260+ + prefaces
261+ + [clean_source ]
248262 )
249263 try :
250- names = parse_names (modified_source , node )
264+ names = parse_names (full_source , node )
251265 except SyntaxError as e :
252266 if language == "default" and not self .warn_default_parse_fail :
253267 return
254268
255269 show_source = self ._format_source_for_error (
256- self .global_preface , self .concat_sources , prefaces , transform .source
270+ self .global_preface ,
271+ self .file_preface ,
272+ self .concat_sources ,
273+ prefaces ,
274+ transform .source ,
257275 )
258276 msg = self ._parsing_error_msg (e , language , show_source )
259277 logger .warning (msg , type = warn_type , subtype = "parse_block" , location = node )
260278 return
261279 except Exception as e :
262280 show_source = self ._format_source_for_error (
263- self .global_preface , self .concat_sources , prefaces , transform .source
281+ self .global_preface ,
282+ self .file_preface ,
283+ self .concat_sources ,
284+ prefaces ,
285+ transform .source ,
264286 )
265287 msg = self ._parsing_error_msg (e , language , show_source )
266288 raise type (e )(msg ) from e
267289
268- if prefaces or self .concat_sources or self .global_preface :
290+ if prefaces or self .concat_sources or self .global_preface or self . file_preface :
269291 concat_lens = [s .count ("\n " ) + 1 for s in self .concat_sources ]
270- hidden_len = len (prefaces ) + sum (concat_lens ) + len (self .global_preface )
292+ hidden_len = len (prefaces + self .global_preface + self .file_preface ) + sum (
293+ concat_lens
294+ )
271295 for name in names :
272296 name .lineno -= hidden_len
273297 name .end_lineno -= hidden_len
@@ -281,16 +305,26 @@ def parse_source( # noqa: C901,PLR0912
281305 @staticmethod
282306 def _format_source_for_error (
283307 global_preface : list [str ],
308+ file_preface : list [str ],
284309 concat_sources : list [str ],
285310 prefaces : list [str ],
286311 source : str ,
287312 ) -> str :
288- lines = global_preface + concat_sources + prefaces + source .split ("\n " )
313+ lines = (
314+ global_preface
315+ + file_preface
316+ + concat_sources
317+ + prefaces
318+ + source .split ("\n " )
319+ )
289320 guides = ["" ] * len (lines )
290321 ix = 0
291322 if global_preface :
292- guides [0 ] = "global preface:"
323+ guides [ix ] = "global preface:"
293324 ix += len (global_preface )
325+ if file_preface :
326+ guides [ix ] = "file preface:"
327+ ix += len (concat_sources )
294328 if concat_sources :
295329 guides [ix ] = "concatenations:"
296330 ix += len (concat_sources )
0 commit comments