U
    d7                     @   s   d Z ddlmZ ddlmZ ddlmZmZmZm	Z	m
Z
 ddlmZ ddlZddlZddlZddlm  mZ d d
dZdd ZedZdd Zdd Zd!ddZdd Zdd ZG dd deZG dd deZdd ZdS )"an  
Table of Contents Extension for Python-Markdown
===============================================

See <https://Python-Markdown.github.io/extensions/toc>
for documentation.

Oringinal code Copyright 2008 [Jack Miller](https://codezen.org/)

All changes Copyright 2008-2014 The Python Markdown Project

License: [BSD](https://opensource.org/licenses/bsd-license.php)

   )	Extension   )Treeprocessor)code_escapeparseBoolValueAMP_SUBSTITUTEHTML_PLACEHOLDER_REAtomicString)UnescapeTreeprocessor    NFc                 C   sL   |s"t d| } | ddd} tdd|   } td||| S )z, Slugify a string, to make it URL friendly. ZNFKDasciiignorez[^\w\s-] z[{}\s]+)	unicodedata	normalizeencodedecoderesubstriplowerformat)value	separatorunicode r   ;/tmp/pip-unpacked-wheel-muih9_xp/markdown/extensions/toc.pyslugify   s
    r   c                 C   s   t | |ddS )zP Slugify a string, to make it URL friendly while preserving Unicode characters. T)r   )r   )r   r   r   r   r   slugify_unicode$   s    r   z^(.*)_([0-9]+)$c                 C   sX   | |ks| sJt | }|r<d|dt|dd f } q d| df } q ||  | S )z@ Ensure id is unique in set of ids. Append '_1', '_2'... if not z%s_%dr   r   )
IDCOUNT_REmatchgroupintadd)ididsmr   r   r   unique,   s    
"
r'   c                 C   sF   g }|   D ]*}t|tr,|t| q|| qd| S )zGet title name.r   )itertext
isinstancer	   appendhtmlunescapejoinr   )eltextcr   r   r   get_name8   s    
r1   Tc                    s    fdd}t || S )zN Extract raw HTML from stash, reduce to plain text and swap with placeholder. c              	      sb   z j jt| d }W n" ttfk
r<   | d Y S X tdd|}r^tdd|}|S )z& Substitute raw html with plain text. r   r   z	(<[^>]+>)r   z(&[\#a-zA-Z0-9]+;))Z	htmlStashZrawHtmlBlocksr"   r!   
IndexError	TypeErrorr   r   )r&   rawresmdstrip_entitiesr   r   	_html_subF   s    z#stashedHTML2text.<locals>._html_sub)r   r   )r/   r7   r8   r9   r   r6   r   stashedHTML2textD   s    r:   c                 C   s   t  }|| S )z Unescape escaped text. )r
   r,   )r/   r0   r   r   r   r,   U   s    r,   c           	      C   s  g }t | r| d}g |d< |d g}|| g }| r| d}|d }g |d< ||d k r|  d}t|D ]}||d kr|d7 }qx qqx|r|d|  }|d|  }|| ||d kr|r|d d n|| n"|d | || || |}q8|S )a<  Given an unsorted list with errors and skips, return a nested one.
    [{'level': 1}, {'level': 2}]
    =>
    [{'level': 1, 'children': [{'level': 2, 'children': []}]}]

    A wrong list is also converted:
    [{'level': 2}, {'level': 1}]
    =>
    [{'level': 2, 'children': []}, {'level': 1, 'children': []}]
    r   childrenlevelr   N)lenpopr*   reversed)	toc_listZordered_listlastlevelsparentstZcurrent_levelZto_poppr   r   r   nest_toc_tokens[   sB    








rG   c                       sT   e Zd Z fddZdd Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
  ZS )TocTreeprocessorc                    s   t  | |d | _|d | _t|d d | _|d | _|d | _|d | _t	|d | _
|d	 | _t	|d
 d| _| jd kr|d
 | _|d | _|d | _td| _t|d trd|d krdd |d dD \| _| _nd| _t|d | _d S )Nmarkertitle	baselevelr   r   r   	toc_class
anchorlinkanchorlink_class	permalinkFpermalink_classpermalink_titlez[Hh][123456]	toc_depth-c                 S   s   g | ]}t |qS r   )r"   ).0xr   r   r   
<listcomp>   s     z-TocTreeprocessor.__init__.<locals>.<listcomp>)super__init__rI   rJ   r"   
base_levelr   seprL   r   use_anchorsrN   use_permalinksrP   rQ   r   compile
header_rgxr)   strsplittoc_top
toc_bottom)selfr7   config	__class__r   r   rX      s&    









"zTocTreeprocessor.__init__c                 c   s@   |D ]6}| j |js|jdkr||fV  | |E dH  qdS )z? Iterator wrapper to get allowed parent and child all at once. )precodeN)r^   r    tag
iterparent)rc   nodechildr   r   r   rj      s    
zTocTreeprocessor.iterparentc                 C   s|   |  |D ]l\}}d|  }|s*q
|jr
|j | jkr
t|dkr
tt|D ]}|| |krX|||<  q
qXq
dS )z Replace marker with elem. r   r   N)rj   r-   r(   r   r/   rI   r>   range)rc   rootelemrF   r0   r/   ir   r   r   replace_marker   s    
"zTocTreeprocessor.replace_markerc                 C   s.   t |jd | j }|dkr d}d| |_dS )z. Adjust header level according to base level. r=      zh%dN)r"   ri   rY   )rc   ro   r<   r   r   r   	set_level   s    zTocTreeprocessor.set_levelc                 C   sl   t d}|j|_d| |jd< | j|jd< d|_|D ]}|| q6t|r^||d  qF|| d S )Na#hrefclassr   r   )etreeElementr/   attribrN   r*   r>   remove)rc   r0   elem_idanchorro   r   r   r   
add_anchor   s    
zTocTreeprocessor.add_anchorc                 C   s^   t d}| jdkrdt n| j|_d| |jd< | j|jd< | jrP| j|jd< || d S )Nrt   Tz%spara;ru   rv   rw   rJ   )	rx   ry   r\   r   r/   rz   rP   rQ   r*   )rc   r0   r|   rO   r   r   r   add_permalink   s    

zTocTreeprocessor.add_permalinkc                    sr   t d}| j|jd< | jr:t |d}d|jd< | j|_ fdd  || d| jjkrn| jjd 	| |S )z' Return a string div given a toc list. divrw   spanZtoctitlec                    sl   t |d}| D ]V}t |d}t |d}|dd|_d|dd |jd< |d	 r |d	 | q|S )
Nullirt   namer   ru   r$   rv   r;   )rx   
SubElementgetr/   rz   )rA   parentr   itemr   linkbuild_etree_ulr   r   r      s    z6TocTreeprocessor.build_toc_div.<locals>.build_etree_ulZprettify)
rx   ry   rL   rz   rJ   r   r/   r7   treeprocessorsrun)rc   rA   r   headerr   r   r   build_toc_div   s    


zTocTreeprocessor.build_toc_divc           
      C   s  t  }| D ]}d|jkr||jd  qg }| D ]}t|jtr:| j|jr:| 	| t
|}d|jkrtt|| j}t| || j||jd< t|jd | jkrt|jd | jkr|t|jd |jd tt|jd|| jddd d|jkr|jd= | jr6| ||jd  | jdkr:| ||jd  q:t|}| |}| jrz| || | j|}| jj D ]}	|	!|}q|| j_"|| j_#d S )Nr$   r=   zdata-toc-labelF)r8   )r<   r$   r   )FN)$setiterrz   r#   r)   ri   r_   r^   r    rs   r1   r,   r:   r7   r'   r   rZ   r"   ra   rb   r*   r   r   r[   r~   r\   r   rG   r   rI   rq   
serializerZpostprocessorsr   
toc_tokenstoc)
rc   docZused_idsr.   r   r/   Z	innertextr   r   ppr   r   r   r     sJ    


, 


zTocTreeprocessor.run)__name__
__module____qualname__rX   rj   rq   rs   r~   r   r   r   __classcell__r   r   re   r   rH      s   rH   c                       s0   e Zd ZeZ fddZdd Zdd Z  ZS )TocExtensionc                    sb   ddgddgddgddgd	dgd
dgddgddgddgt dgddgddgd| _t jf | d S )Nz[TOC]zhText to find and replace with Table of Contents - Set to an empty string to disable. Defaults to "[TOC]"r   z<Title to insert into TOC <div> - Defaults to an empty stringr   z6CSS class(es) used for the link. Defaults to "toclink"Fz8True if header should be a self link - Defaults to FalseZtoclinkr   zQTrue or link text if a Sphinx-style permalink should be added - Defaults to FalseZ
headerlinkz9CSS class(es) used for the link. Defaults to "headerlink"zPermanent linkz?Title attribute of the permalink - Defaults to 'Permanent link'1zBase level for headers.zdFunction to generate anchors based on header text - Defaults to the headerid ext's slugify function.rS   z Word separator. Defaults to "-".rr   a%  Define the range of section levels to include inthe Table of Contents. A single integer (b) definesthe bottom section level (<h1>..<hb>) only.A string consisting of two digits separated by a hyphenin between ("2-5"), define the top (t) and thebottom (b) (<ht>..<hb>). Defaults to `6` (bottom).)rI   rJ   rL   rM   rN   rO   rP   rQ   rK   r   r   rR   )r   rd   rW   rX   )rc   kwargsre   r   r   rX   D  sD    'zTocExtension.__init__c                 C   s<   | |  || _|   | ||  }|j|dd d S )Nr      )ZregisterExtensionr7   resetTreeProcessorClassZ
getConfigsr   register)rc   r7   Ztocextr   r   r   extendMarkdownn  s
    
zTocExtension.extendMarkdownc                 C   s   d| j _g | j _d S )Nr   )r7   r   r   )rc   r   r   r   r   z  s    zTocExtension.reset)	r   r   r   rH   r   rX   r   r   r   r   r   re   r   r   @  s   *r   c                  K   s
   t f | S )N)r   )r   r   r   r   makeExtension  s    r   )F)T)__doc__r   r   r   r   utilr   r   r   r   r	   r
   r   r+   r   xml.etree.ElementTreerx   ElementTreer   r   r]   r   r'   r1   r:   r,   rG   rH   r   r   r   r   r   r   <module>   s(   



? '?