
    fgc                         d dl Z d dlZd dlZd dlZd dlmZ d dlmZ d dlm	Z	 d dl
mZ d dlmZ  G d dej                        Z G d	 d
ej                        Z G d dej                        Z G d d      Zy)    N)urlparse)models)slugify)reverse)ContentFilec                        e Zd Z ej                  d      Z ej                  dd      Z ej                         Z	 ej                  d      Z ej                         Zd Z fdZd Zd	 Zd
 Zd Zd Z xZS )Post   
max_lengthT)uniqueblankdefaultc                 2    t        d| j                  g      S )Npost_detail)args)r   slugselfs    #/var/www/rossjtaylor/blog/models.pyget_absolute_urlzPost.get_absolute_url   s    }DII;77    c                    | j                   st        | j                        | _         | j                  j	                         | _        t        |   |i | | j                  j                         j                          | j                  j                         j                          | j                          | j                          y N)r   r   titlebodystripsupersavesectionsalldeletepostreference_setparse_referencesparse_body_into_sections)r   r   kwargs	__class__s      r   r    z	Post.save   s    yy

+DIIIOO%	d%f%""$""$++-%%'r   c                 ,   t        j                  d      }|j                  | j                        D ]  }|j	                  d      j                         }|j	                  d      j                         }|j	                  d      r|j	                  d      j                         nd }|st        |      }d|j                   }t        j                  j                  | |      j                         rt        j                  j                  | |||        y )Nz$\[([^]]+)\]\((\S+)(?:\s"([^"]+)")?\)         zReference from )posturl)r-   r.   inline_textreference_title)recompilefinditerr   groupr   r   netlocPostReferenceobjectsfilterexistscreate)r   patternmatchr/   r.   	ref_titleparseds          r   r%   zPost.parse_references%   s     **DE%%dii0 	E++a...0K++a.&&(C27++a.A,,.dI!#-fmm_=	 !((//Ts/CJJL%%,, +$-	 - 	r   c           
      F   | j                   }d}t        j                  ||t        j                        }g }g }d}|D ]  }|j	                         |j                         }	}||kD  r|j                  d||| f       |j                  d      }
|j                  d      j                         }|j                  d|
|f       |j                  dt        |      dz
  f       |	} |t        |      k  r|j                  d||d  f       d}g }|D ]  }|d   dk(  r|d   }d}t        j                  ||t        j                        D ]c  }|j	                         |j                         }	}||kD  r|j                  d||| f       |j                  d      j                         }|j                  d	      }|r|d   j                         }d
|v r|dd  }d|v rY|j                  d      }d	j                  |d |       j                         }d	j                  ||dz   d        j                         }n!d	j                  |      j                         }d}|j                  d||f       nB|j                  dd	j                  |      j                         f       n|j                  d       |	}f |t        |      k  s|j                  d||d  f       |d   dk(  s|j                  |        d}g }|D ]  }|d   }|dk(  r|d   j                         }|s%|j                  d	      }g }|D ]F  }|j                         }|s|j                  d       (t        j                  ||      } | r|rEd	j                  |      j                         }!|!r"| j                  |!      }"|j                  |"       g }| j                  d      }#d }$d }%d|#v sd|#v rz|#j                  d      j                         }&|&d   }'|&dd  D ]1  }(|(j!                  d      st#        |(j                  d      d         }$3 d|v r|j                  d      d   d d }%|'}#|j                  dd|#|$|%f       6|j                  |       I |sd	j                  |      j                         }!|!s| j                  |!      }"|j                  |"       |dk(  r|d   })|j                  d|)f       |dk(  r |d   }|d   }|j                  d||f       |dk(  s|d   }*||*   \  }+},}|j                  d	      }|D -cg c]#  }-|-j                         s|-j                         % }}-|r|d   nd}.|.rt        j                  ||.      nd } d }#d }$d }%| r| j                  d      }#d|#v sd|#v rz|#j                  d      j                         }&|&d   }'|&dd  D ]1  }(|(j!                  d      st#        |(j                  d      d         }$3 dv r|j                  d      d   d d }%|'}#d	j                  |dd        }/nd	j                  |      }/|/j                         rZ| j                  |/j                               }"d	j                  |"D 0cg c]  }0|0d   dk(  st        |0      dk  s|0d   ! c}0      }1nd}1|j                  d|,|1|#|$|%f        d}2|D ]  }|d   }|dk(  rdt        |      dk(  r-|d   dk(  r%|d   }3| j$                  j'                  d|2|3d        n#|d   }4| j$                  j'                  d|2|4       |2dz  }2r|dk(  r-|d   })| j$                  j'                  d|2d|) d       |2dz  }2|dk(  r/|d   }|d   }| j$                  j'                  d|2||      }5|2dz  }2|dk(  ra|d   }#|d   }$|d   }%| j$                  j'                  d|2d      }5|$r|$|5_        |#|5_         |%r|%|5_        |5j-                  g d        |2dz  }2>|dk(  sE|d   },|d   }1|d   }#|d   }$t        |      d!kD  r|d!   nd }%| j$                  j'                  d|2|,d"k(  rd"nd#|#rd$|# d	|1 n|1%      }5|$r|$|5_        |%r|%|5_        |5j-                  g d        |2dz  }2 y c c}-w c c}0w )&Nz":::image_text_(left|right)(.*?):::r   textr*   r+   
image_textimage_text_placeholderz```(.*?)```
executedz--- executed_codecode)rG   rE   z!\[(.*?)\]\((.*?)\)zwidth=zdesc="=imager,   heading)section_typeorderrL   r   )rM   rN   r   z<pre><code>z</code></pre>)rM   rN   r   code_output   )r   image_widthimage_description)update_fields   leftrightIMAGE:)rM   rN   image_positionr   )r   r1   r3   DOTALLstartendappendr4   r   lensplitindexjoinr<   split_text_into_subsectionsextend
startswithintr!   r:   rQ   rR   r    )6r   contentimage_text_patternimage_text_blockstmp_contentplaceholderslast_endr<   rZ   r[   
block_side
block_textcode_fence_patternfinal_sectionsitemsegmentpos
code_matchcode_block_content
code_lines
first_line	sep_index	code_partoutput_partimage_pattern	new_finalsectionstypeseglinestext_lines_accline	img_matchbig_text_blocksub_secs	image_urlwidth
image_descpartsmain_urlpcode_contentr_   it_typesidel
image_line	text_partseccombined_bodyrN   heading_textr   ss6                                                         r   r&   zPost.parse_body_into_sectionsA   sS	   ))BKK(:GRYYO& 	E		3Ex""FGHU,C#DEQJQ--/Jz: FG 8#l:KA:MNOH	 c'l"	(:;<+ "	,DAw& q'"$++.@'299"U J!+!1!1!3Z^^5E3Es{&--vws57I.JK)3)9)9!)<)B)B)D&!3!9!9$!?J!%/]%8%8%:
%3)3ABJ&*4,6,<,<W,E	,0IIj)6L,M,S,S,U	.2ii
9Q;<8P.Q.W.W.Y,0IIj,A,G,G,I	.0*11?I{2[\ +116499Z;P;V;V;X2YZ&--l;C56 W%"))6734=*ABa44%%d+E"	,H /	% a	dGAJEaj&&(		$!#! "4D::<D&--b1  " =I )-1YY~-F-L-L-NN-+/+K+KN+[ ) 0 0 :-/N$-OOA$6	 $%)
#y0Gy4H$-OOC$8$>$>$@E',QxH%*12Y A#$<<#9,/Q,@EA  '$-1ZZ-@-DSb-I
(0I!(('2y%)TU&--d3E"4J "%)YY~%>%D%D%FN%#'#C#CN#S!((2&&qz  &,!78/)#AJ	%aj  /9k!JK22
,8,?)z"((.,1?qQWWY??).U1XB
CMBHH]J?SW	 	!
 ) 2I9,90D ) 4 : : <#(8!&qr =A ||H5(+AGGCLO(<= #d?*.**W*=b*A#2*FJ$,	 $		%) 4I $		% 0I??$#??	@QRH$(II.o#SQRVW]M]befibjmnbns1v.o$pM %'M  ,mYPUWa!bcCa	dH   N	GAJE w<1$y)@#*1:LMM((%+# ,!	 )  #1:DMM((%+#! ) 
 
&&qz$$!'&|nMB % 
 
/)#AJ	%ajMM((!0" +	 )  
'!#AJ	
$QZ
MM((!( ) 
 $)AM"*4A'%QR
,&qz '
#AJ	
+.w<!+;WQZ
MM((!--1V^6BK6)B}o>Q^	 )  $)AM*4A'%QR
]N	I @4 /ps   4b
b b
b
b
c                    |j                  d      }g }d}|D ]  }|j                         j                  d      rL|j                         dd  j                         }|s|j                  d       d}|j                  d| d       n|r|j                  d	       d}|j                  |        |r|j                  d	       dj	                  |      S 
NrC   Fz- r+   zV<ul class="list-disc text-gray-700 leading-relaxed list-inside text-xl p-2 pb-4 pt-4">Tz<li>z</li>z</ul>r^   r   rc   r\   r`   r   r@   r~   final_linesin_listr   re   s          r   handle_bulletszPost.handle_bullets3  s    

4  	)Dzz|&&t,**,qr*002&&'  A"G""T'%#89&&w/#G""4(	) w'yy%%r   c                     t        j                  dd|t         j                        }t        j                  dd|t         j                        }|S Nz\*\*(.*?)\*\*z<strong>\1</strong>)flagsz	\*(.*?)\*z<em>\1</em>r1   subrY   r   r@   s     r   handle_inline_formattingzPost.handle_inline_formattingG  9    vv&(>BIIVvvlND		Jr   c                    | j                  |      }| j                  |      }t        j                  d|j	                               }g }t        j
                  d      }|D ]  }|j                  d      }g }|D ]  }|j	                         }|s|j                  |      }	|	r^|r6dj                  |      j	                         }
|
r|j                  d|
f       g }|	j                  d      }|j                  d|df       |j                  |        |sdj                  |      j	                         }
|
r|j                  d|
f       g } |S )aQ  
        Splits a large text block into subsections:
        - Handles bullets and inline formatting
        - Separates by blank lines into paragraphs
        - Detects headings at start of lines (#, ##, etc.)
        Returns a list of tuples like:
        ('text', 'paragraph text')
        ('text', 'heading text', 'heading')
        z\n\s*\nz^(#{1,6})\s+(.*)rC   r@   r+   rL   )
r   r   r1   r^   r   r2   r<   r`   r\   r4   )r   
text_block
paragraphssubsectionsheading_patternparap_linestemp_para_linesr   heading_matchsubsection_textr   s               r   ra   z Post.split_text_into_subsectionsN  sM    ((4
22:>
XXj**:*:*<=
**%89 	%Djj&G O 1zz| / 5 5d ; &*.))O*D*J*J*L*'../HI*,#0#6#6q#9L&&i'HI#**40!1$ "&))O"<"B"B"D"&&'@A"$3	%4 r   )__name__
__module____qualname__r   	CharFieldr   	SlugFieldr   	DateFielddateBooleanField	is_public	TextFieldr   r   r    r%   r&   r   r   ra   __classcell__r(   s   @r   r	   r	      s    F,E64t4D6D###D1I6D8(8pd&(+r   r	   c                       e Zd Zg dZ ej
                  eej                  d      Z ej                  de      Z
 ej                  d      Z ej                  dd	d	
      Z ej                  d	d	      Z ej                   dd	d	      Z ej                  dddgd	d	      Z ej&                  d	d	      Z ej                  d	d	      Z ej                  d	d	      Z G d d      Zd Z fdZd Zd Zd Z xZS )PostSection))r@   Text)rG   Code)rK   Image)rA   zImage + Textr!   )	on_deleterelated_name   )r   choicesr*   r   r
   T)r   r   null)r   r   zpost_images/)	upload_tor   r   rT   )rU   Left)rV   Right)r   r   r   r   c                       e Zd ZdgZy)PostSection.MetarN   N)r   r   r   ordering r   r   Metar     s	    9r   r   c                 f    | j                   j                   d| j                   d| j                   S )Nz - z
 section #)r-   r   rM   rN   r   s    r   __str__zPostSection.__str__  s-    ))//"#d&7&7%8
4::,OOr   c                     |j                  dd      }t        |   |i | | j                  dv r.|s+| j                  s| j
                  r| j                          y y y y y )Ndownloading_imageF)rK   rA   )popr   r    rM   rK   r   download_and_replace_images)r   r   r'   is_downloadingr(   s       r   r    zPostSection.save  se    $7?d%f%  77W[WaWafjfofo,,. gpWa7r   c                    | j                   sy | j                   j                         }d|v rV|j                  d      d   j                  d      d   }d}dj                  | j                   j                  d      dd        }nd}d}t	        j
                  d      }|j                  | j                  j                         D ]p  }|j                  d      }|j                  d	      }|j                  d
      }|j                         |j                         k(  sX|r| j                  |      | _
         n |sy | j                  |      }	|	r!|| _        || _         | j                  d       y y )NrW   r*   rC   r   rA   rK   rE   z$!\[(.*?)\]\((\S+)(?:\s+"([^"]+)")?\)r+   r,   T)r   )r   r   r^   r`   r1   r2   r3   r-   r4   extract_width_from_titlerQ   download_imagerM   r    )
r   r   rM   r   r;   r<   alt_textr.   r   local_file_names
             r   r   z'PostSection.download_and_replace_images  sA   yyIIOO%	 y !1!4::4@CI'L99TYY__T21267D"LD**DE %%diinn5 
	E{{1~H++a.CKKNE yy{ioo//'+'D'DU'KD$
	 --i8 ,DDIIII- r   c                     t        j                  d      }|j                  |      }|rt        |j	                  d            S y )Nzwidth=(\d+)r*   )r1   r2   searchrd   r4   )r   	title_strwidth_patternwmatchs       r   r   z$PostSection.extract_width_from_title  s;     

>2%%i0v||A''r   c                    	 t        j                  |d      }|j                          t	        |      }t
        j                  j                  |j                        }|sd}t        |j                        }| j                  j                  ||d       | j                  j                  S # t         j                  $ r Y y w xY w)N
   )timeoutz	image.jpgF)r    )requestsgetraise_for_statusRequestExceptionr   ospathbasenamer   re   rK   r    name)r   r.   response
parsed_urlfilenameimage_contents         r   r   zPostSection.download_image  s    	||C4H%%' c]
77##JOO4"H
 $H$4$45

-e<zz (( 		s   'B* *C ?C )r   r   r   SECTION_TYPESr   
ForeignKeyr	   CASCADEr-   r   rM   PositiveIntegerFieldrN   rL   r   r   
ImageFieldrK   rX   IntegerFieldrQ   rO   rR   r   r   r    r   r   r   r   r   s   @r   r   r   |  s   M 6TV^^*UD#6##r=IL'F''2Ef#TEG6$T2DFdNE%V%%!#56N
 &&%%Dt<K"&""D9K(((t$? P
/1.fr   r   c                       e Zd Z ej                  eej                        Z ej                         Z	 ej                  d      Z ej                  d      Zd Zy)r6   )r   r
   r   i  c                 :    | j                    d| j                   dS )Nz ())r0   r.   r   s    r   r   zPostReference.__str__  s     &&'r$((155r   N)r   r   r   r   r   r	   r   r-   URLFieldr.   r   r/   r0   r   r   r   r   r6   r6     sQ    6TV^^<D
&//
C"&""c2K&f&&#6O6r   r6   c                   0    e Zd Zd Zd Zd Zd Zd Zd Zy)PostBodyParserc                     || _         y r   )r@   r   s     r   __init__zPostBodyParser.__init__  s	    	r   c                     g }| j                   j                  d      }|j                  | j                  |             |S )NrC   )r@   r^   rb   parse_blocks)r   r!   r~   s      r   parsezPostBodyParser.parse  s7     		%))%01r   c                    g }d}g }|t        |      k  r||   }|j                         j                  d      r|j                         j                  d      j                         }|j	                         }|r|d   nd}d|v }	g }
|dz  }|t        |      k  rl||   j                         j                  d      sJ|
j                  ||          |dz  }|t        |      k  r#||   j                         j                  d      sJ|dz  }|	rd|
v r|
j                  d      }|
d| }|
|dz   d }n|
}g }dj                  |      }dj                  |      }|r3| j                  dj                  |            }|j                  |       g }|j                  d	||d
       nqdj                  |
      }|r3| j                  dj                  |            }|j                  |       g }|j                  d|d       n|j                  |       |dz  }|t        |      k  r|r/|j                  | j                  dj                  |                   |S )ay  
        Parse the entire body into logical sections.
        We'll have:
        - Executed code blocks: ```python executed ...``` until ```
          with `---` line to separate code and output
        - Regular code blocks: ```python``` until ```
        - Bullet lists: lines starting with '- '
        - Bold/Italics inline: transform after building text sections
        r   z```rE   rD   r*   z---NrC   rF   )typer   rO   rG   r   r   )	r]   r   rc   lstripr^   r\   r_   r`   create_text_section)r   r~   r!   icurrent_textr   	lang_liner   langrD   rt   idxrw   rx   code_str
output_strtext_sections                    r   r   zPostBodyParser.parse_blocks  sG    #e*n8Dzz|&&u- JJL//6<<>	!)#(uQxb%.  
Q#e*nU1X^^-=-H-H-O%%eAh/FA #e*nU1X^^-=-H-H-O
 Q
*(..u5$.t$4	&0Q&8$.	&(#yy3H!%;!7J $'+'?'?		,@W'X 5')OO / ('1%   $yy4H#'+'?'?		,@W'X 5')OO & (%  ##D)Q{ #e*n@ OOD44TYY|5LMNr   c                 P    | j                  |      }| j                  |      }d|dS )Nr@   r   )r   r   r   s     r   r   z"PostBodyParser.create_text_sectionc  s-    ""4(,,T2--r   c                    |j                  d      }g }d}|D ]  }|j                         j                  d      rL|j                         dd  j                         }|s|j                  d       d}|j                  d| d       n|r|j                  d	       d}|j                  |        |r|j                  d	       dj	                  |      S r   r   r   s          r   r   zPostBodyParser.handle_bulletsj  s     

4  	)Dzz|&&t,**,qr*002&&'  A"G""T'%#89&&w/#G""4(	) w'yy%%r   c                     t        j                  dd|t         j                        }t        j                  dd|t         j                        }|S r   r   r   s     r   r   z'PostBodyParser.handle_inline_formatting  r   r   N)	r   r   r   r   r   r   r   r   r   r   r   r   r   r      s"    Pd.&,r   r   )r   uuidr1   r   urllib.parser   	django.dbr   django.utils.textr   django.urlsr   django.core.files.baser   Modelr	   r   r6   r   r   r   r   <module>r     sb    	  	  !  %  .k6<< k\w&,, wt6FLL 6E Er   