U
    \>eD                     @  s   d Z ddlmZ ddlZddlm  mZ ddlmZm	Z	 ddl
mZ ddl
mZ erbddlmZ d	d
ddddZdddddZG dd dejZG dd deZG dd deZG dd deZdS )z
Tree processors manipulate the tree created by block processors. They can even create an entirely
new `ElementTree` object. This is an excellent place for creating summaries, adding collected
references, or last minute adjustments.

    )annotationsN)TYPE_CHECKINGAny   )util)inlinepatterns)Markdownr   r   zutil.Registry[Treeprocessor])mdkwargsreturnc                 K  sB   t  }|t| dd |t| dd |t| dd |S )z3 Build the default  `treeprocessors` for Markdown. inline   Zprettify
   unescaper   )r   ZRegistryregisterInlineProcessorPrettifyTreeprocessorUnescapeTreeprocessor)r	   r
   Ztreeprocessors r   ;/tmp/pip-unpacked-wheel-wj0og6ym/markdown/treeprocessors.pybuild_treeprocessors'   s
    r   objectbool)sr   c                 C  s   t | tjst | tS dS )z_ Return `True` if object is a string but not an  [`AtomicString`][markdown.util.AtomicString]. F)
isinstancer   AtomicStringstr)r   r   r   r   isString0   s    
r   c                   @  s    e Zd ZdZdddddZdS )Treeprocessora  
    `Treeprocessor`s are run on the `ElementTree` object before serialization.

    Each `Treeprocessor` implements a `run` method that takes a pointer to an
    `Element` and modifies it as necessary.

    `Treeprocessors` must extend `markdown.Treeprocessor`.

    etree.Elementetree.Element | Nonerootr   c                 C  s   dS )a  
        Subclasses of `Treeprocessor` should implement a `run` method, which
        takes a root `Element`. This method can return another `Element`
        object, and the existing root `Element` will be replaced, or it can
        modify the current tree and return `None`.
        Nr   )selfr"   r   r   r   runA   s    zTreeprocessor.runN)__name__
__module____qualname____doc__r$   r   r   r   r   r   7   s   	r   c                   @  s   e Zd ZdZddddZdddd	d
ZddddddZddddddZd3ddddddZd4dddddddZ	d5dddd d!d"d#Z
d6d$dddd%d&d'd(Zd)d*dd+d,d-Zd7dd/dd0d1d2Zd.S )8r   zL
    A `Treeprocessor` that traverses a tree, applying inline patterns.
    r   )r	   c                 C  sJ   t j| _t j| _dt| j t| j | _t j| _|| _	|j
| _
g | _d S )N   )r   ZINLINE_PLACEHOLDER_PREFIX$_InlineProcessor__placeholder_prefixETXZ$_InlineProcessor__placeholder_suffixlenZ$_InlineProcessor__placeholder_lengthZINLINE_PLACEHOLDER_RE _InlineProcessor__placeholder_rer	   inlinePatterns	ancestors)r#   r	   r   r   r   __init__P   s    zInlineProcessor.__init__r   ztuple[str, str])typer   c                 C  s    dt | j }tj| }||fS )z Generate a placeholder z%04d)r,   stashed_nodesr   ZINLINE_PLACEHOLDER)r#   r1   idhashr   r   r   Z__makePlaceholderZ   s    
z!InlineProcessor.__makePlaceholderintztuple[str | None, int])dataindexr   c                 C  s4   | j ||}|r$|d| fS d|d fS dS )a  
        Extract id from data string, start from index.

        Arguments:
            data: String.
            index: Index, from which we start search.

        Returns:
            Placeholder id and string index, after the found placeholder.

        r   N)r-   searchgroupend)r#   r6   r7   mr   r   r   Z__findPlaceholder`   s    z!InlineProcessor.__findPlaceholderzetree.Element | str)noder1   r   c                 C  s   |  |\}}|| j|< |S )z Add node to stash. )!_InlineProcessor__makePlaceholderr2   )r#   r<   r1   placeholderr3   r   r   r   Z__stashNoder   s    
zInlineProcessor.__stashNoder   )r6   patternIndexr   c                 C  sP   t |tjsLd}t| j}||k rL| | j| |||\}}}|s|d7 }q|S )a  
        Process string with inline patterns and replace it with placeholders.

        Arguments:
            data: A line of Markdown text.
            patternIndex: The index of the `inlinePattern` to start with.

        Returns:
            String with placeholders.

        r   r   )r   r   r   r,   r.   _InlineProcessor__applyPattern)r#   r6   r?   
startIndexcountmatchedr   r   r   Z__handleInlinex   s    
   

zInlineProcessor.__handleInlineTr   r   None)r<   subnodeisTextr   c                 C  sv   |r|j }d|_ n|j}d|_| |||}|sL||k	rLt||d }nd}|  |D ]}|||d  q\dS )a'  
        Process placeholders in `Element.text` or `Element.tail`
        of Elements popped from `self.stashed_nodes`.

        Arguments:
            node: Parent node.
            subnode: Processing node.
            isText: Boolean variable, True - it's text, False - it's a tail.

        Nr   r   )texttail%_InlineProcessor__processPlaceholderslistr7   reverseinsert)r#   r<   rE   rF   rG   ZchildResultposnewChildr   r   r   Z__processElementText   s    z$InlineProcessor.__processElementText
str | Nonez%list[tuple[etree.Element, list[str]]])r6   parentrF   r   c                   sb  ddd fdd}g d}|r^| | j|}|dkr,| ||\}}|| jkr| j|}	|dkr||| }
||
 t|	ts|	gt|	 D ]>}|jr|j	 r| 
|	|d |jr|j	 r| 
|| qn||	 |}q |}|	| jd	d	 f n"|t| j }||||  |}q ||d	 }
t|tjrPt|
}
||
 d
}q S )a  
        Process string with placeholders and generate `ElementTree` tree.

        Arguments:
            data: String with placeholders instead of `ElementTree` elements.
            parent: Element, which contains processing inline data.
            isText: Boolean variable, True - it's text, False - it's a tail.

        Returns:
            List with `ElementTree` elements with applied inline patterns.

        rO   rD   rG   r   c                   s   | r|r>d d j r.d d  j | 7  _ q|| d d _ n> s`j rX j | 7  _ q|| _ njrv j| 7  _n| _d S )Nr   )rH   rG   )rG   rF   rP   resultr   r   linkText   s    z7InlineProcessor.__processPlaceholders.<locals>.linkTextr   rR   FN )findr*   !_InlineProcessor__findPlaceholderr2   getr   r   rJ   rH   strip$_InlineProcessor__processElementTextrG   appendr/   r,   r   r   )r#   r6   rP   rF   rU   ZstrartIndexr7   r3   Z
phEndIndexr<   rG   childr:   r   rS   r   Z__processPlaceholders   sL    


  

z%InlineProcessor.__processPlaceholderszinlinepatterns.Patternztuple[str, bool, int])patternr6   r?   rA   r   c                 C  s  t |tj}|jD ] }| | jkr|ddf  S q|rd}| ||D ]>}|||\}}	}
|	dksr|
dkr||	d7 }d}qL qqLn"| 
||d }|d| }|s|ddfS |s||}|d}	|	d}
|dkr|d|
fS t |ts~t |jtjs~|gt| D ]`}t|s|jrb| j|j  | |j|d |_| j  |jr| |j||_q| || }|rd|d|	 |||
d ddfS d||d|| d ddfS dS )	a  
        Check if the line fits the pattern, create the necessary
        elements, add it to `stashed_nodes`.

        Arguments:
            data: The text to be processed.
            pattern: The pattern to be checked.
            patternIndex: Index of current pattern.
            startIndex: String index, from which we start searching.

        Returns:
            String with placeholders instead of `ElementTree` elements.

        Fr   NTr   z{}{}{}z{}{}{}{}rR   )r   r   r   ZANCESTOR_EXCLUDESlowerr/   ZgetCompiledRegExpfinditerZhandleMatchr:   matchstartr   rG   r   r   rJ   r   r\   tag_InlineProcessor__handleInlinepoprH   _InlineProcessor__stashNoder1   formatr9   groups)r#   r^   r6   r?   rA   Z	new_styleexcludera   r<   rb   r:   ZleftDatar]   r>   r   r   r   Z__applyPattern   sp    






 
 
 
  
 zInlineProcessor.__applyPatternr    z	list[str])rP   parentsr   c                 C  sH   g }|dk	r2|dk	r$| |j  | j|}q|  || dS )zBuild the ancestor list.N)r\   rc   r_   
parent_maprY   rK   extend)r#   rP   rj   r/   r   r   r   Z__build_ancestorsM  s    z!InlineProcessor.__build_ancestorsNzlist[str] | None)treer/   r   c                 C  s  i | _ |dkrg n
|dd }dd | D | _||fg}|r| \}}|| _| || j g }|D ]0}|jrt|jtj	s| j
|j  |j}	d|_| | |	|}
|
D ]}|| j|d < q||
7 }|
||
f | j  |jrr| |j}td}d|_| ||d}|jr.|j|_t||d }|  |D ]$}|| j|d < |||d  qLt|rj|| j|< |
|| jdd f qj|D ]2\}}
t|
D ]\}}|d }||| qqq<|S )a  Apply inline patterns to a parsed Markdown tree.

        Iterate over `Element`, find elements with inline tag, apply inline
        patterns and append newly created Elements to tree.  To avoid further
        processing of string with inline patterns, instead of normal string,
        use subclass [`AtomicString`][markdown.util.AtomicString]:

            node.text = markdown.util.AtomicString("This will not be processed.")

        Arguments:
            tree: `Element` object, representing Markdown tree.
            ancestors: List of parent tag names that precede the tree node (if needed).

        Returns:
            An element tree object with applied inline patterns.

        Nc                 S  s   i | ]}|D ]
}||qqS r   r   ).0pcr   r   r   
<dictcomp>o  s
        z'InlineProcessor.run.<locals>.<dictcomp>r   dFr   )r2   iterrk   re   r/   !_InlineProcessor__build_ancestorsrG   r   r   r   r\   rc   r_   rI   rd   rH   etreeElementrJ   r7   rK   rL   r,   	enumerate)r#   rm   r/   Ztree_parentsstackZcurrElementrj   ZinsertQueuer]   rG   lstitemrH   ZdumbyZ
tailResultrM   rN   elementiobjr   r   r   r$   W  s\    

  


zInlineProcessor.run)r   )T)T)r   )N)r%   r&   r'   r(   r0   r=   rX   rf   rd   r[   rI   r@   rt   r$   r   r   r   r   r   K   s   
! V P
r   c                   @  s0   e Zd ZdZdddddZddddd	Zd
S )r   z' Add line breaks to the html document. r   rD   )elemr   c                 C  s   d}| j |jrn|jdkrn|jr,|j sLt|rL| j |d jrL||_|D ]}| j |jrP| | qP|jr~|j s||_dS )z8 Recursively add line breaks to `ElementTree` children. 
)codeprer   N)r	   Zis_block_levelrc   rG   rZ   r,   _prettifyETreerH   )r#   r~   r|   er   r   r   r     s    z$PrettifyTreeprocessor._prettifyETreer!   c                 C  s   |  | |d}|D ](}|jr,|j s4d|_qd|j |_q|d}|D ]J}t|rP|d jdkrP|d }t|sP|jdk	rPt|j	 d |_qPdS )z7 Add line breaks to `Element` object and its children. brr   z
%sr   r   r   N)
r   rs   rH   rZ   r,   rc   rG   r   r   rstrip)r#   r"   Zbrsr   Zpresr   r   r   r   r   r$     s    


zPrettifyTreeprocessor.runN)r%   r&   r'   r(   r   r$   r   r   r   r   r     s   r   c                   @  sV   e Zd ZdZedejej	Z
dddddZdddd	d
ZdddddZdS )r   z Restore escaped chars z	{}(\d+){}zre.Match[str]r   )r;   r   c                 C  s   t t|dS )Nr   )chrr5   r9   )r#   r;   r   r   r   	_unescape  s    zUnescapeTreeprocessor._unescaperQ   c                 C  s   | j | j|S )N)REsubr   )r#   rG   r   r   r   r     s    zUnescapeTreeprocessor.unescaper   rD   r!   c                 C  sh   |  D ]Z}|jr*|jdks*| |j|_|jr>| |j|_| D ]\}}||| | qFqdS )z/ Loop over all elements and unescape all text. r   N)rs   rG   rc   r   rH   itemsset)r#   r"   r~   keyvaluer   r   r   r$     s    zUnescapeTreeprocessor.runN)r%   r&   r'   r(   recompilerg   r   ZSTXr+   r   r   r   r$   r   r   r   r   r     s
   r   )r(   
__future__r   r   xml.etree.ElementTreeru   ElementTreetypingr   r   rV   r   r   Zmarkdownr   r   r   Z	Processorr   r   r   r   r   r   r   r   <module>   s    	  V'