o
    %e                     @   s   d Z ddlZddlZddlmZ ddlmZmZ ddlm	Z	 ddl
mZ dd	lmZ i d
ejdejdejdejdejdejdejdejdejdejdejdejdejdejdejdejZdd eddD Zeddd  ed!Zed"Z ed#Z!d$d% Z"d&d' Z#d(d) Z$	d^d*d+Z%d,d- Z&d.d/ Z'			d_d0d1Z(	d`d2d3Z)d4d5 Z*d6d7 Z+d8d9 Z,d:d; Z-ed<j.fd=d>Z/d^d?d@Z0dAdB Z1dCdD Z2dEdF Z3dGdH Z4dIdJ Z5dadLdMZ6dNdO Z7dPdQ Z8dRdS Z9dTdU Z:d^dVdWZ;dXdY Z<dZd[ Z=d\d] Z>dS )bzTurn an element tree with style into a "before layout" box tree.

This includes creating anonymous boxes and processing whitespace as necessary.

    N   )html)
propertiestargets)collapse_table_borders)LOGGER   )boxesblockflowinliner   )r   	flow-root)r   r   )r   table)r   r   )r   flex)r   r   )z	table-row)ztable-row-groupztable-header-groupztable-footer-group)ztable-column)ztable-column-group)z
table-cell)ztable-captionc                 C   s   i | ]	}|t |d  qS )i  )chr).0i r   X/var/www/html/venv/lib/python3.10/site-packages/weasyprint/formatting_structure/build.py
<dictcomp>)   s    r   !      u   　u   −)    -   z
?z[	 ]*
[	 ]*z[	 ]+c                 C   s$   t | } t| } t| } t| } | S )zDCreate anonymous boxes in box descendants according to layout rules.)anonymous_table_boxes
flex_boxesinline_in_blockblock_in_inlineboxr   r   r   create_anonymous_boxes1   s
   r$   c           
         sh   t  |||||}|r|\}nd fdd	}	t  |	|||||\}|  d|_t|}t|}|S )z=Build a formatting structure (box tree) from an element tree.Nc                    s2   | |}|d ur|  krd|d< |S d|d< |S )Nr
   displaynoner   )elementpseudo_typestyleelement_tree	style_forr   r   root_style_forE   s   
z2build_formatting_structure.<locals>.root_style_forTN)element_to_boxcheck_pending_targetsis_for_root_elementr$   set_viewport_overflow)
r,   r-   get_image_from_uribase_urltarget_collectorcounter_style	footnotesbox_listr#   r.   r   r+   r   build_formatting_structure:   s    r:   c                 C   s   t |d d d  | |||S )Nr%   r   )BOX_TYPE_FROM_DISPLAY)element_tagr*   contentr(   r   r   r   make_boxZ   s   r>   c              
   C   sh  t | jtsg S || }|d }	|	dkrg S |d dkr+|d dkr'd|d< nd|d< t| j|g | }
|d	u rBd
gdd
gidhgf}|\}}}t|| g }|t  || d|
_|| d|
_g }d|d v ryt	t
| ||||||}|| |t| d||||| |d r||d ||
 | j}|r|tj|
| | D ]u}t||||||||}|r|d
 jd dkr|d
 }d|jd< || || d}t| j d|g | }t||||||||_||_|g}|| |j}|rtj|
|}|rt |d tjr|d  j|j7  _q|| q|t| d||||| | D ]}||   || s=|| q+|d dkrH|ng |
_t|
 t| |
|||| t|
 |ryt|
jdkry|d dkry|
jtj|
d |d dkr|d d  d7  < || d}t| j d|g | }t||
||||||_|
jd
| t| |
||S )a!  Convert an element and its children into a box with children.

    Return a list of boxes. Most of the time the list will have one item but
    may have zero or more than one.

    Eg.::

        <p>Some <em>emphasised</em> text.</p>

    gives (not actual syntax)::

        BlockBox[
            TextBox['Some '],
            InlineBox[
                TextBox['emphasised'],
            ],
            TextBox[' text.'],
        ]

    ``TextBox``es are anonymous inline boxes:
    See https://www.w3.org/TR/CSS21/visuren.html#anonymous

    r%   r&   floatfootnotefootnote_displayr   r
   r   Nr   first-letterz
first-line	list-itembeforeanchorr'   zfootnote-callz::footnote-callafter
appearancer   list_style_positionoutsideu   ​zfootnote-markerz::footnote-marker) 
isinstancetagstrr>   update_countersappendsetfirst_letter_stylefirst_line_stylelistmarker_to_boxextendbefore_after_to_boxstore_targettextr	   TextBoxanonymous_fromr0   r*   content_to_boxeschildrenr@   tailpopprocess_whitespaceset_content_listsprocess_text_transformleninsertr   handle_element)r(   r-   r4   r5   r6   r7   r8   stater*   r%   r#   quote_depthcounter_valuescounter_scopesr\   marker_boxesrX   child_elementchild_boxesr@   
call_stylefootnote_calltext_boxnamemarker_stylemarkerr   r   r   r0   _   s   















r0   c              
   C   s   || |}|r|du rg S |d }|dkrg S |d }	|	dv r!g S t | j d| |g | }
|\}}}t|| g }d|v rOtt| ||||||}|| |t||
||||| ||
_|d d	kru|\}}}t| |
|d
 ||| |
gS )z8Return the boxes for ::before or ::after pseudo-element.Nr%   r&   r=   )normalinhibitr'   ::rC   bookmark_levelr'   bookmark_label)	r>   rL   rN   rS   rT   rU   r[   r\   compute_bookmark_label)r(   r)   re   r-   r4   r6   r7   r*   r%   r=   r#   rf   rg   _counter_scopesr\   ri   _quote_depthr   r   r   rV      s>   






rV   c              
   c   s   || d}g }|\}	}
}t | j d||| }|d dkr dS |d \}}|d dvr:|t|||	|
||| nH|d	krV|||d
 d}|durVtj||}|| |s|d dkr|
ddgd }|d }|	||}tj
||}d|jd< || |sdS |d dkrtj||}d|jd< |d dkrtdd}ntdd}tj}d||fff|jd< ntj||}|V  dS )zyYield the box for ::marker pseudo-element if there is one.

    https://drafts.csswg.org/css-lists-3/#marker-pseudo

    rq   ::markerr%   r&   Nlist_style_imager=   )rr   rs   urlimage_orientationr|   orientationlist_style_typer'   rC   r   rF   zpre-wrapwhite_spacerI   rJ   absoluteposition	directionltri%d   	translate	transform)r>   rL   rU   r[   r	   InlineReplacedBoxrZ   rO   getrender_markerrY   r*   BlockBoxr   	DimensionZERO_PIXELS	InlineBox)r(   re   parent_styler-   r4   r6   r7   r*   r\   rf   rg   rx   r#   
image_typeimagecounter_valuecounter_typemarker_text
marker_boxtranslate_xtranslate_yr   r   r   rT   .  sT   








rT   c           -         s  g  t   fdd}g }i }|
duo|du}|jo| }jdu r.dd | D _| D ]>\}}|dkr>|| q0|dkrg|durg|\}}|dkrOq0||jd	 d
}|durf tj| q0|dkrwt	|}||
  q0|dkr|stdd| q0||
j|g|R   q0|dv r|d |d }dkrq0|r|t|| vr|| |dkr||dgd }|}n|d }|fdd||dgD }|| q0|dv rt|dd |d \}}dkrq0||||}|jdkr ne|jj}|r,||vr,t|}||g }||vr,|| |j } | | |dkrK| |dgd }|}n$|d }|d dkrY n|d }!|!fdd| |dgD }|| q0|dkr|\}}"||||}|jdkr|j}#t	|"|#}||
  q0 n|dkrd||	fvrd|v }$|d }%|$std|d d |d< |%r|	\}&}'|$r|&n|'}(||(t|d t|(d   |$r|d  d7  < q0|d krA|std!d| q0|
j|g|R  })|)du r
q0|)  })d"|)jd#< t!|)tj"r;|)# D ]}*|*jd$ d%v r*qt$|*j|*|||||
|d&	|*_%q |) q0|d'kro|d sLq0tj&|d }+tj'|+f},d(|,jd)< d(|+jd)< d*|,_( |, q0sv r|)||||  S dS )+ae  Compute and return the boxes corresponding to the ``content_list``.

    ``parse_again`` is called to compute the ``content_list`` again when
    ``target_collector.lookup_target()`` detected a pending target.

    ``build_formatting_structure`` calls
    ``target_collector.check_pending_targets()`` after the first pass to do
    required reparsing.

    c                    sT    d | r( rt d tjr d  j| 7  _d S  tj|  d S d S )NTrF   )addrK   r	   rY   rX   rO   rZ   rX   )content_boxeshas_text
parent_boxr   r   add_text  s   
z&compute_content_list.<locals>.add_textNc                 S   s   i | ]	\}}||  qS r   )copy)r   keyvaluer   r   r   r     s    z(compute_content_list.<locals>.<dictcomp>stringr|   externalr}   r~   z	content()zstring()z,"string(%s)" is only allowed in page margins )	counter()z
counters()r   rF   r'   r   r   c                 3       | ]	}  |V  qd S r/   render_valuer   r   r7   r   r   r   	<genexpr>  
    

z'compute_content_list.<locals>.<genexpr>)target-counter()ztarget-counters()r   z
up-to-dater   c                 3   r   r/   r   r   r   r   r   r     r   ztarget-text()quoteopenzno-z	element()z-"element(%s)" is only allowed in page marginsstaticr   r=   )rr   r'   )contextpagezleader()prer   T)*rP   
collectingcached_counter_valuesitemsr*   rO   r	   r   rZ   extract_textstripr   warningjoinget_string_set_forrS   r   r   lookup_targetre   
target_boxr   anchor_name_from_token
setdefaultcached_page_counter_valuesr   update
startswithmaxminrb   get_running_element_fordeepcopyrK   	ParentBoxdescendantsr[   r\   rY   r   	is_leadercollect_missing_counters)-content_listr   rg   	css_tokenparse_againr6   r7   r4   rf   quote_styler   r   r(   r   missing_countersmissing_target_countersin_page_contextneed_collect_missingtype_r   originurir   
added_textcounter_namer   rX   	separatoranchor_tokenr   target_valuesanchor_namelocal_countersseparator_string
text_styler   is_openrc   open_quotesclose_quotesquotesnew_boxchildrn   
leader_boxr   )r   r7   r   r   r   r   compute_content_listq  s"  	
























r   c	                    sf   d fdd	}	d dkrg S |dd d}
t d ||
|	 |d ||}|p2g S )z:Take the value of a ``content`` property and return boxes.Nc              
      sz   | du ri }n|   }|j g }|t|  tjdkr8tjd tj	r8|jd _dS |_dS )z9Closure to parse the ``parent_boxes`` children all again.Nr   r   )
r   r   r   rU   r[   rb   r\   rK   r	   LineBox)mixin_pagebased_countersr   local_childrenr7   r4   orig_quote_depthr   r*   r6   r   r   r   .  s   
z%content_to_boxes.<locals>.parse_againr=   rs   r   r/   )r   )r*   r   rf   rg   r4   r6   r7   r   r   r   r   r9   r   r   r   r[   *  s   
r[   c              
      s   d
 fdd	}d }t  |||d}	|	durIddd |	D }
 jD ]}|d	 kr> j|  nq. j|
f dS dS )zCParse the content-list value of ``string_name`` for ``string-set``.Nc                    s:   | du ri }n|   }| j t | dS )z7Closure to parse the string-set string value all again.N)r   r   r   compute_string_setr   r   r#   r   r7   r(   string_namer6   r   r   r   W  s   
z'compute_string_set.<locals>.parse_againzstring-set::r(    c                 s   s"    | ]}t |tjr|jV  qd S r/   rK   r	   rY   rX   r   r#   r   r   r   r   k  s    
z%compute_string_set.<locals>.<genexpr>r   r/   )r   r   
string_setremoverO   )r(   r#   r   r   rg   r6   r7   r   r   r9   r   string_set_tupler   r   r   r   T  s"   



r   c           	   
      sV   i f fdd	}d}t  |||d}|r)ddd |D  _dS dS )	z5Parses the content-list value for ``bookmark-label``.c                    s@   | du ri }n|   }|   }| j t | dS )z.Closure to parse the bookmark-label all again.N)r   r   r   rw   r   r#   r   r7   r(   r6   r   r   r   y  s   
z+compute_bookmark_label.<locals>.parse_againzbookmark-labelr   r   c                 s   s    | ]}t |V  qd S r/   )box_textr   r   r   r   r     s    z)compute_bookmark_label.<locals>.<genexpr>N)r   r   rv   )	r(   r#   r   rg   r6   r7   r   r   r9   r   r   r   rw   v  s   
rw   c           	   	   C   sj   g |_ |d dkr t|d D ]\}\}}t| |||||| q|d dkr3t| ||d ||| dS dS )zSet the content-lists values.

    These content-lists are used in GCPM properties like ``string-set`` and
    ``bookmark-label``.

    r   r'   ru   rv   N)r   	enumerater   rw   )	r(   r#   r*   rg   r6   r7   r   r   string_valuesr   r   r   r`     s   
r`   c           
      C   s  | \}}}|d }|d D ]\}}||v r||    n|| ||g | q|d D ] \}}||g }|sK||vsAJ || |d ||d< q/|d }	|	dkrdd|d v rbd	g}	ng }	|	D ]$\}}||g }|s||vsxJ || |d |d  |7  < qfd
S )z$Handle the ``counter-*`` properties.rF   counter_resetcounter_setr   counter_incrementautorC   r%   )rC   r   N)r^   r   r   rO   )
re   r*   ry   rg   rh   sibling_scopesro   r   valuesr   r   r   r   rN     s6   






rN   z\Sc                 C   s   t | tjo|| j S )z9Return True if ``box`` is a TextBox with only whitespace.r   )r#   _has_non_whitespacer   r   r   is_whitespace  s   r  c                 #   s    |du r fdd}g }|D ]'}||r*|r& j | g d}t||V  g }|V  qt| tjr1q|| q|rH j | g d}t||V  dS dS )z
    Wrap consecutive children that do not pass ``test`` in a box of type
    ``wrapper_type``.

    ``test`` defaults to children being of the same type as ``wrapper_type``.

    Nc                    s
   t |  S r/   )rK   r   wrapper_typer   r   test  s   
zwrap_improper.<locals>.test)r\   )rZ   table_boxes_childrenrK   r	   FlexContainerBoxrO   )r#   r\   r  r  improperr   wrapperr   r  r   wrap_improper  s$   r  c                 C   s2   t | tjr
|  r| S dd | jD }t| |S )zRemove and add boxes according to the table model.

    Take and return a ``Box`` object.

    See https://www.w3.org/TR/CSS21/tables.html#anonymous-boxes

    c                 S      g | ]}t |qS r   )r   r   r   r   r   r   
<listcomp>      z)anonymous_table_boxes.<locals>.<listcomp>)rK   r	   r   
is_runningr\   r  r#   r\   r   r   r   r     s   
r   c                    s  t  tjr	g }n*t  tjr3dd |D }|s3 jdu s" jdk r%d}n j} fddt|D } jrit|dkri|dd \}}|jrOt	|rO|
  t|dkri|dd \}}|jrit	|ri|
d d	d tdg|dd
  ||dd dg D }t  tjrt |tjdd }nt  tjrt |tj}t  tjrt |tj}n
t |tjdd }t  tjrt |tjdd }nt t |tjfdd}t  tjrt |S t| _ S )z3Internal implementation of anonymous_table_boxes().c                 S   s   g | ]
}t |tjr|qS r   )rK   r	   TableColumnBoxr  r   r   r   r    s    
z(table_boxes_children.<locals>.<listcomp>Nr   c                    s   g | ]	}t j g qS r   )r	   r  rZ   )r   _r"   r   r   r    s    r   r   c                 S   s2   g | ]\}}}|r|j r|r|j rt|s|qS r   )internal_table_or_captionr  )r   
prev_childr   
next_childr   r   r   r  /  s    	

rF   c                 S   s   | j S r/   proper_table_childr  r   r   r   <lambda>B  s    z&table_boxes_children.<locals>.<lambda>c                 S   s   t | tj S r/   )rK   r	   TableCellBoxr  r   r   r   r  N  s    c                 S   s   | j  S r/   r  r  r   r   r   r  T      c                    s   | j  p | jv S r/   )r  proper_parentsr  )parent_typer   r   r  Y  s    
)rK   r	   r  TableColumnGroupBoxspanrangetabular_containerrb   r  r  r^   zipTableBoxr  TableRowBoxTableRowGroupBoxr  r   InlineTableBoxtype
wrap_tablerS   r\   )r#   r\   r!  internalrX   r   )r#   r  r   r    sn   




r  c           !   
   C   s  g }g }g }t j|t j|t j|t j|t j|i}|D ]}|t| | qg g d}|D ]}||jd  | q,t	t
| |t j}	d}
|	D ]}|
|_|jr\|jD ]	}|
|_|
d7 }
qQqF|
|j7 }
qF|
}t
| |t j}g }d}d}|D ](}|jd }|dkr|du rd|_|}qs|d	kr|du rd|_|}qs|| qs|dur|gng | |dur|gng  }d}|D ]v}d
d |jD }|jD ]a}|d}d}
|jD ]T}|
|v r|
d7 }
|
|v s|
|_|
|j }|jdkrt|d }|jdkr|}||_nt|j||_|d|jd  }t|
|}|D ]}|| q|}
t||
}qq|t|j7 }q| |}|j |_t|	|_|jd dkrJt||||_t| t jrUt j }nt j!}|"| |d |g |d  }|j |_d|_#t$j%D ]} |j|  |j| < t$j&|  |j| < qs|S )a  Take a table box and return it in its table wrapper box.

    Also re-order children and assign grid positions to each column and cell.

    Because of colspan/rowspan works, grid_y is implicitly the index of a row,
    but grid_x is an explicit attribute on cells, columns and column group.

    https://www.w3.org/TR/CSS21/tables.html#model
    https://www.w3.org/TR/CSS21/tables.html#table-layout

    )topbottomcaption_sider   r   Nr%   r   Tr   c                 S   s   g | ]}t  qS r   )rP   )r   rowr   r   r   r    s    zwrap_table.<locals>.<listcomp>border_collapsecollapser,  r-  )'r	   r  r   r&  r'  TableCaptionBoxr)  rO   r*   rS   r  grid_xr\   r!  	is_header	is_footerr^   colspanrowspanrb   r   r"  r   r   copy_with_childrenr   tuplecolumn_groupsr   collapsed_border_gridrK   r(  InlineBlockBoxr   rZ   is_table_wrapperr   TABLE_WRAPPER_BOX_PROPERTIESINITIAL_VALUES)!r#   r\   columnsrowsall_captionsby_typer   captionscaptionr:  r3  groupcolumn
grid_width
row_groupsbody_row_groupsheaderfooterr%   grid_heightoccupied_cells_by_rowr/  occupied_cells_in_this_rowcell
new_grid_xmax_rowspanspanned_rowsspanned_columnsoccupied_cellsr   r  r  ro   r   r   r   r*  c  s   












r*  c                 C   s8   t | tjr
|  r| S dd | jD }t| || _| S )zRemove and add boxes according to the flex model.

    Take and return a ``Box`` object.

    See https://www.w3.org/TR/css-flexbox-1/#flex-items

    c                 S   r  r   )r   r  r   r   r   r    r  zflex_boxes.<locals>.<listcomp>)rK   r	   r   r  r\   flex_childrenr  r   r   r   r     s
   r   c                 C   s   t | tjr?g }|D ]2}| sd|_t |tjr |jds q
t |tjr7tj	
| |g}d|_|| q
|| q
|S |S )NTr   )rK   r	   r	  is_absolutely_positionedis_flex_itemrY   rX   r   InlineLevelBoxr   rZ   rO   )r#   r\   rV  r   	anonymousr   r   r   rV    s   rV  Fc                 C   s  t | tjrW| j}|s|S td|}| jd dv }| jd dv }|r)td|}|r1|dd}|rQt	d| }}|rK|
drK|dd }d| _|d}nd	}|| _n%| jD ]!}t |tjtjfrut||}|  rt| rt|}qZ| r{d	}qZ|o|   S )
zFirst part of "The 'white-space' processing model".

    See https://www.w3.org/TR/CSS21/text.html#white-space-model
    https://drafts.csswg.org/css-text-3/#white-space-rules

    
r   )rr   nowraprr   r\  zpre-liner   r   NTF)rK   r	   rY   rX   LINE_FEED_REsubr*   TAB_REreplaceSPACE_REr   leading_collapsible_spaceendswithr\   r   r_   is_in_normal_flowr  )r#   following_collapsible_spacerX   new_line_collapsespace_collapseprevious_textr   child_collapsible_spacer   r   r   r_     s>   
r_   c                 C   s   t | tjr5| jd }|dkr"dd dd tdd d| | j| _| jd dkr3| jd	d
| _d S d S |  sL| jD ]}t |tjtj	frKt
| q<d S d S )Ntext_transformr'   c                 S      |   S r/   )upperr   r   r   r   r  H  r  z(process_text_transform.<locals>.<lambda>c                 S   rl  r/   )lowerr   r   r   r   r  I  r  c                 S   s
   |  tS r/   )r   ASCII_TO_WIDEr   r   r   r   r  K  s   
 )	uppercase	lowercase
capitalizez
full-widthhyphens   ­r   )rK   r	   rY   r*   rr  rX   ra  r  r\   r   ra   )r#   rk  r   r   r   r   ra   C  s,   

ra   c                 C   sR   d}d}| D ] }t |d }|s|dv rd}| }n|dkr"d}||7 }q|S )uC   Capitalize words according to CSS’s "text-transform: capitalize".Fr   r   )LNTZ)unicodedatacategoryrm  )rX   letter_foundoutputletterry  r   r   r   rr  V  s   

rr  c           
      C   s  | j r|  r	| S t| j }|r| jdu r|d j| _g }d}|D ]}|r(d|_t|tjr5|js5|j}q!d}|t	| q!| j
du rG|| _
t| tjsR|| _ | S g }g }|D ]Y}t|tjrbJ |rn| rn|| qXt|tjsz|r| s|st|tjr|jdkr|jd dv s|| qX|rtj| |}tj| |g}	||	 g }|| qX|rtj| |}|rtj| |g}	||	 n|| || _ | S )a  Build the structure of lines inside blocks and return a new box tree.

    Consecutive inline-level boxes in a block container box are wrapped into a
    line box, itself wrapped into an anonymous block box.

    This line box will be broken into multiple lines later.

    This is the first case in
    https://www.w3.org/TR/CSS21/visuren.html#anonymous-block-level

    Eg.::

        BlockBox[
            TextBox['Some '],
            InlineBox[TextBox['text']],
            BlockBox[
                TextBox['More text'],
            ]
        ]

    is turned into::

        BlockBox[
            AnonymousBlockBox[
                LineBox[
                    TextBox['Some '],
                    InlineBox[TextBox['text']],
                ]
            ]
            BlockBox[
                LineBox[
                    TextBox['More text'],
                ]
            ]
        ]

    Fr   Tr   r   r]  )r\   r  rS   rc  rK   r	   rY   rX   rO   r    trailing_collapsible_spaceBlockContainerBoxr   rW  rY  re  r*   rZ   r   )
r#   box_childrenr\   r}  r   new_line_childrennew_children	child_boxline_boxrZ  r   r   r   r    e  sh   &






r    c           	      C   s   | j r|  r	| S g }d}| j D ]Y}t|tjrZt| j dks&J d| j  d}	 t||d\}}}|du r7ntj| |g}|	| |	t
| q)|rWtj| |g}n|}nt
|}||urdd}|	| q|ro|| _ | S )a  Build the structure of blocks inside lines.

    Inline boxes containing block-level boxes will be broken in two
    boxes on each side on consecutive block-level boxes, each side wrapped
    in an anonymous block-level box.

    This is the second case in
    https://www.w3.org/TR/CSS21/visuren.html#anonymous-block-level

    Eg. if this is given::

        BlockBox[
            LineBox[
                InlineBox[
                    TextBox['Hello.'],
                ],
                InlineBox[
                    TextBox['Some '],
                    InlineBox[
                        TextBox['text']
                        BlockBox[LineBox[TextBox['More text']]],
                        BlockBox[LineBox[TextBox['More text again']]],
                    ],
                    BlockBox[LineBox[TextBox['And again.']]],
                ]
            ]
        ]

    this is returned::

        BlockBox[
            AnonymousBlockBox[
                LineBox[
                    InlineBox[
                        TextBox['Hello.'],
                    ],
                    InlineBox[
                        TextBox['Some '],
                        InlineBox[TextBox['text']],
                    ]
                ]
            ],
            BlockBox[LineBox[TextBox['More text']]],
            BlockBox[LineBox[TextBox['More text again']]],
            AnonymousBlockBox[
                LineBox[
                    InlineBox[
                    ]
                ]
            ],
            BlockBox[LineBox[TextBox['And again.']]],
            AnonymousBlockBox[
                LineBox[
                    InlineBox[
                    ]
                ]
            ],
        ]

    Fr   z9Line boxes should have no siblings at this stage, got %r.NT)
skip_stack)r\   r  rK   r	   r   rb   _inner_block_in_inliner   rZ   rO   r!   )	r#   r  changedr   stacknew_liner   anon	new_childr   r   r   r!     s@   =

	r!   c                 C   s  g }d}d}d}|du }|rd}n|  \\}}t| j|d D ]V\}}	|| }
t|	tjr@|	 r@|du s9J |	}|
d7 }
n(t|	tjrSt|	|}d}|\}}}n
|du sYJ t	|	}||	urcd}|
| |durw|
|i}| |}  n
q!|s||r| |} | ||fS )a  Find a block-level box in an inline formatting context.

    If one is found, return ``(new_box, block_level_box, resume_at)``.
    ``new_box`` contains all of ``box`` content before the block-level box.
    ``resume_at`` can be passed as ``skip_stack`` in a new call to
    this function to resume the search just after the block-level box.

    If no block-level box is found after the position marked by
    ``skip_stack``, return ``(new_box, None, None)``

    NFr   r   T)r   r   r\   rK   r	   BlockLevelBoxre  r   r  r!   rO   r8  )r#   r  r  block_level_box	resume_atr  is_startskipr   r   index	recursionr  r   r   r   r  ;  sB   





r  c                 C   s\   | }| j  dkr!| jd dkr!| jD ]}|j  dkr |} nq|jd | _d|jd< | S )z
    Set a ``viewport_overflow`` attribute on the box for the root element.

    Like backgrounds, ``overflow`` on the root element must be propagated
    to the viewport.

    See https://www.w3.org/TR/CSS21/visufx.html#overflow
    r   overflowvisiblebody)r<   rn  r*   r\   viewport_overflow)root_box
chosen_boxr   r   r   r   r3   p  s   	

r3   c                 C   s:   t | tjr	| jS t | tjrddd |  D S dS )Nr   c                 s   sF    | ]}|j d s|j ds|j dst|tjr|jV  qdS )z::beforez::afterrz   N)r<   rd  rK   r	   rY   rX   r  r   r   r   r     s    




zbox_text.<locals>.<genexpr>)rK   r	   rY   rX   r   r   r   r"   r   r   r   r     s   
r   c                    s    dv rt |S  dv r"t|tjr d fdd| D S dS  dkrId}d}t |}|D ]}t|}|dvrB|r@ |S d	}||7 }q0|S d S )
N)rX   r=   )rD   rG   r   c                 3   s6    | ]}|j d   rt|tjst|V  qdS )rt   N)r<   rd  rK   r	   r   r   r  	text_partr   r   r     s    

zextract_text.<locals>.<genexpr>rB   F)PsPePiPfPoT)r   rK   r	   r   r   r   rx  ry  )r  r#   character_foundfirst_letterrX   r|  ry  r   r  r   r     s,   

r   r/   )NNNNNN)NN)F)?__doc__rerx  r   r   cssr   r   layout.tabler   loggerr   r	   r   r   r<  r%  r(  FlexBoxInlineFlexBoxr&  r'  r  r   r  r2  r;   r"  ro  r   compiler^  r`  rb  r$   r:   r>   r0   rV   rT   r   r[   r   rw   r`   rN   searchr  r  r   r  r*  r   rV  r_   ra   rr  r    r!   r  r3   r   r   r   r   r   r   <module>   s    



	 
 ".E
 <
*"'
&^ 
6p
f5