o
    $}                     @   sV  d Z ddlmZ ddlmZ ddlm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 ddlmZ ddlmZ ddlmZ ddlmZ ejejejejejejdZdd Zdd Zdd ZG dd de
jZG dd deZ G dd deZ		d%ddZ!G d d! d!eZ"d"d# Z#e$d$kre#e	%  dS dS )&a  Cloud SDK markdown document renderer.

This module marshals markdown renderers to convert Cloud SDK markdown to text,
HTML and manpage documents. The renderers are self-contained, allowing the
Cloud SDK runtime to generate documents on the fly for all target architectures.

The MarkdownRenderer class parses markdown from an input stream and renders it
using the Renderer class. The Renderer member functions provide an abstract
document model that matches markdown entities to the output document, e.g., font
embellishment, section headings, lists, hanging indents, text margins, tables.
There is a Renderer derived class for each output style that writes the result
on an output stream returns Rendere.Finish().
    )absolute_import)division)unicode_literalsN)
argv_utils)
exceptions)devsite_renderer)html_renderer)linter_renderer)man_renderer)markdown_renderer)renderer)text_renderer)devsitehtmlmanmarkdowntextlinterc                 C   sn   | | |krdS d}|t | k r5| | |kr|d7 }n| | |kr+|d8 }|dkr+|S |d7 }|t | k sdS )aE  Returns the index in buf of the end of the nested beg...end group.

  Args:
    buf: Input buffer.
    i: The buf[] index of the first beg character.
    beg: The group begin character.
    end: The group end character.

  Returns:
    The index in buf of the end of the nested beg...end group, 0 if there is
    no group.
  r      )len)bufibegendnesting r   S/tmp/google-cloud-sdk/lib/googlecloudsdk/core/document_renderers/render_document.py_GetNestedGroup;   s   
r   c                    s   t  fdddD  S )z5Returns True if target is a valid anchor/link target.c                 3   s    | ]}| v V  qd S Nr   ).0ctargetr   r   	<genexpr>X   s    z!_IsValidTarget.<locals>.<genexpr>z ,()[])anyr!   r   r!   r   _IsValidTargetV   s   r%   c                 C   s   t d| d| S )z1Return True if the link is set as the flag value.z--.*=https?$N)research)r   r   r   r   r   _IsFlagValueLink[   s   r(   c                       s    e Zd ZdZ fddZ  ZS )DocumentStyleErrorz)An exception for unknown document styles.c                    s0   dj |dtt d}tt| | d S )NzFUnknown markdown document style [{style}] -- must be one of: {styles}.z, )stylestyles)formatjoinsortedSTYLESkeyssuperr)   __init__)selfr*   message	__class__r   r   r2   c   s
   zDocumentStyleError.__init__)__name__
__module____qualname____doc__r2   __classcell__r   r   r5   r   r)   `   s    r)   c                   @   s   e Zd ZdZdd ZdS )_ListElementStatea  List element state.

  Attributes:
    bullet: True if the current element is a bullet.
    ignore_line: The number of blank line requests to ignore.
    level: List element nesting level counting from 0.
    line_break_seen: True if line break has been seen for bulleted lists.
  c                 C   s   d| _ d| _d| _d| _d S )NFr   )bulletignore_linelevelline_break_seenr3   r   r   r   r2   t   s   
z_ListElementState.__init__Nr7   r8   r9   r:   r2   r   r   r   r   r<   j   s    	r<   c                   @   s   e Zd ZdZejejejdZe	j
dddfddZdd Zdd	 Zd2d
dZdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Z d0d1 Z!dS )3MarkdownRenderera  Reads markdown and renders to a document.

  Attributes:
    _EMPHASIS: The font emphasis attribute dict indexed by markdown character.
    _buf: The current output line.
    _code_block_indent: ```...``` code block indent if >= 0.
    _depth: List nesting depth counting from 0.
    _edit: True if NOTES edits are required.
    _example: The current example indentation space count.
    _fin: The markdown input stream.
    _line: The current input line.
    _lists: _ListElementState list element state stack indexed by _depth.
    _next_example: The next example indentation space count.
    _notes: Additional text for the NOTES section.
    _paragraph: True if the last line was ``+'' paragraph at current indent.
    _next_paragraph: The next line starts a new paragraph at same indentation.
    _renderer: The document_renderer.Renderer subclass.
    command_metadata: Optional metadata of command.
    command_node: The command object that the document is being rendered for.
  )*_`Nc                 C   s|   || _ d| _|| _|| _| j| _t g| _d| _d| _d| _	d| _
d| _d| _d| _d| _|| _d| _d| _d| _|| _dS )aK  Initializes the renderer.

    Args:
      style_renderer: The document_renderer.Renderer subclass.
      fin: The markdown input stream.
      notes: Optional sentences for the NOTES section.
      command_metadata: Optional metadata of command.
      command_node: The command object that the document is being rendered for.
     r   FNz$ gcloud)	_renderer_buf_fin_notes_editr<   _lists_code_block_indent_depth_example_next_example
_paragraph_peek_next_paragraph_linecommand_metadata_example_regex_last_list_level_in_example_sectioncommand_node)r3   style_rendererfinnotesrW   r[   r   r   r   r2      s&   

zMarkdownRenderer.__init__c                 C   s  |dkr||d | dkrd}|d }nV|dkr*||d | dkr*d}|d }nA|dkr?||d | dkr?d}|d }n,|dkrT||d | dkrTd}|d }n|d	kri||d	 | d
krid	}|d	 }ndS d}d}	 |t |ks|||  r||d  dkr|d8 }|}|}|d }n || dkr|}|d }t||dd}n|| dv rn|d7 }qp|sdS |d |||| ||| fS )a=  Checks for link:target[text] hyperlink anchor markdown.

    Hyperlink anchors are of the form:
      <link> ':' <target> [ '[' <text> ']' ]
    For example:
      http://www.google.com[Google Search]
    The underlying renderer determines how the parts are displayed.

    Args:
      buf: Input buffer.
      i: The buf[] index of ':'.

    Returns:
      (i, back, target, text)
        i: The buf[] index just past the link, 0 if no link.
        back: The number of characters to retain before buf[i].
        target: The link target.
        text: The link text.
       ftp   httplinkr      https   mailto)r   r   NNr   T.[]z
{}()<>'"`*)r   isspacer   )r3   r   r   back
target_begtext_begtext_end
target_endr   r   r   _AnchorStyle1   sP   





zMarkdownRenderer._AnchorStyle1c                 C   s   |d }t ||dd}|r|t|d ks||d  dkrdS |d }t ||d dd}|r2||kr4dS |d ||| ||| fS )a  Checks for [text](target) hyperlink anchor markdown.

    Hyperlink anchors are of the form:
      '[' <text> ']' '(' <target> ')'
    For example:
      [Google Search](http://www.google.com)
      [](http://www.show.the.link)
    The underlying renderer determines how the parts are displayed.

    Args:
      buf: Input buffer.
      i: The buf[] index of ':'.

    Returns:
      (i, target, text)
        i: The buf[] index just past the link, 0 if no link.
        target: The link target.
        text: The link text.
    r   ri   rj   ()r   NN   ))r   r   )r3   r   r   rn   ro   rm   rp   r   r   r   _AnchorStyle2   s   $zMarkdownRenderer._AnchorStyle2c                 C   s  | j dks| jr
dnd}d}|du r| j}d| _|rx| j|}d}d}|t|k rx|| }|dkr]| ||\}}}	}
|r[t|	r[t||s[|d|  }|d }| j	|	|
}n|dkr|| 
||\}}	}
|r{t|	r{|d }| j	|	|
}n||v rj|r||d  nd	}|t|d k r||d  nd	}|d
kr|d
kr|d
kr|t|d k r||d  nd	}|d
kr|d|d }|dkr|| jtj7 }|||d | 7 }|| jtj7 }|d }q%n|d|}|dkr|d7 }|||| 7 }|}q%|r|dkr|dkr|d7 }nR||kr&||7 }|d7 }nD|dkr5|dv r5|dv sD|d
krE|dv rE|dv rEn%| rP| rPn|rY|dkrYn|d
kra| }| j| j| }||7 }|d7 }|t|k s,| j|S )zConverts inline markdown attributes in self._buf.

    Args:
      buf: Convert markdown from this string instead of self._buf.

    Returns:
      A string with markdown attributes converted to render properly.
    r   rG   z*_`NF:r   ri    rF   rs   ```r_   z''rE   rD   z /z ./z .)rO   rQ   rJ   rI   Escaper   rq   r%   r(   Linkru   findFontr   CODEisalnum	_EMPHASISEntities)r3   r   emphasisretr   
is_literalr    index_after_anchorrl   r"   r   lrxindex_at_code_block_quoteindex_at_air_quoter   r   r   _Attributes  s   

  




@zMarkdownRenderer._Attributesc                 C   s^   | j |d r-|   | jr| j|kr|| _| j| _| j | jd | _| j|   dS dS )zRenders self._line[i:] as an example.

    This is a helper function for _ConvertCodeBlock() and _ConvertExample().

    Args:
      i: The current character index in self._line.
    N)rV   _FillrQ   rR   rJ   rI   Exampler   r3   r   r   r   r   _Exampled  s   zMarkdownRenderer._Examplec                 C   s   | j r| j|   dS dS )z5Sends self._buf to the renderer and clears self._buf.N)rJ   rI   Fillr   rA   r   r   r   r   t  s   zMarkdownRenderer._Fillc                 C   s$   | j dur| j }d| _ |S | j S )z}Reads and possibly preprocesses the next markdown line from self._fin.

    Returns:
      The next markdown input line.
    N)rT   rK   readliner3   liner   r   r   	_ReadLiney  s
   

zMarkdownRenderer._ReadLinec                 C   s
   || _ dS )zEPushes back one lookahead line. The next _ReadlLine will return line.N)rT   r   r   r   r   _PushBackLine  s   
zMarkdownRenderer._PushBackLinec                 C   s   | j s| j| j  dS 	 |  }|sn| j| | jr1|dkr1| jd| j d  d| _q| jrB| jd| j d  dS dS )z5Generates markdown with additonal NOTES if requested.NTz	## NOTES

rG   z

## NOTES

)rM   rI   WriterK   readr   rL   r   r   r   r   _ConvertMarkdownToMarkdown  s   z+MarkdownRenderer._ConvertMarkdownToMarkdownc                 C   s   | j r|S |   | j| j jr-| jj| jd dd | jr&|  jd8  _nd| j| j _| j| j jr?| j| j  jd8  _| j| j jsMd| j| j _| jr^| j| j jr^| j| j jrc| j	  dS )a?  Detects and converts a blank markdown line (length 0).

    Resets the indentation to the default and emits a blank line. Multiple
    blank lines are suppressed in the output.

    Args:
      i: The current character index in self._line.

    Returns:
      -1 if the input line is a blank markdown, i otherwise.
    r   Tr   FrH   )
rV   r   rN   rP   r=   rI   Listr>   r@   Liner   r   r   r   _ConvertBlankLine  s*   

z"MarkdownRenderer._ConvertBlankLinec                 C   s   t | jdks| jd dkr|S |   d| j| j _| j| j jr?| jj| jd dd | jr8|  jd8  _nd| j| j _| j	  d| _
dS )zDetects and converts + markdown line (length 1).

    Emits a blank line but retains the current indent.

    Args:
      i: The current character index in self._line.

    Returns:
      -1 if the input line is a '+' markdown, i otherwise.
    r   r   +Tr   FrH   )r   rV   r   rN   rP   r@   r=   rI   r   r   rU   r   r   r   r   _ConvertParagraph  s   
z"MarkdownRenderer._ConvertParagraphc                 C   s  |}| j | }|dvr|S |t| j k r-| j | |kr-|d7 }|t| j k r-| j | |ks|t| j ks;| j | dkr=|S | j d |kre| j | j || r[| j || d   dkr]|S || d  }nt| j }|   | j |d | | _|  }|dkr|dr| j|dd  	d | j
|| d	| _|d
v r|dkrd}nd}	 |  | _| jsn| j | _| jr| jj|  |d nqn| jr|dkr| j| _d| _|dk| _dS )a  Detects and converts a markdown heading line.

    = level-1 [=]
    # level-1 [#]
    == level-2 [==]
    ## level-2 [##]

    Args:
      i: The current character index in self._line.

    Returns:
      -1 if the input line is a heading markdown, i otherwise.
    )=#r   rw   rH   z(1)NrE   r   )NAMESYNOPSISr   TF)is_synopsisNOTESEXAMPLES)rV   r   endswithr   rJ   r   rI   
SetCommandlowersplitHeadingrP   r   rstripSynopsisrL   rZ   )r3   r   start_indexmarker	end_indexheadingis_synopsis_sectionr   r   r   _ConvertHeading  sV   


	
z MarkdownRenderer._ConvertHeadingc                 C   s   | j d dks| j d dksd| j vr|S |  }|s|S |ds)| | |S g }	 |  | _| js5n| j | _| jdrBn||  d q,d	| _t	
 }t|d
krm|d D ]}|j|d q^|d
d }|jry|ry| j|| dS )a  Detects and converts a sequence of markdown table lines.

    This method will consume multiple input lines if the current line is a
    table heading. The table markdown sequence is:

       [...format="csv"...]
       |====*
       col-1-data-item,col-2-data-item...
         ...
       <blank line ends table>

    Args:
      i: The current character index in self._line.

    Returns:
      -1 if the input lines are table markdown, i otherwise.
    r   ri   rH   rj   zformat="csv"z|====T,rG   r   )labelN)rV   r   
startswithr   rJ   r   appendr   r   r   TableAttributesr   	AddColumncolumnsrI   Table)r3   r   r   rowstabler   r   r   r   _ConvertOldTable  s8   




z!MarkdownRenderer._ConvertOldTablec                 C   s  d}d| j vr| |S d| j v rd}| j }nd}|  }|r#d|vr2|| j ur-| | | |S d}|rPtd| j  }|d sO|d sO|d	d }d}ng }td| }|d sj|d sj|d	d }d}|rt|t|kr|| j ur~| | | |S tj	|d
}t
t|D ]<}	d}
||	 }|dr|drd}
n|drd}
|	t|k r||	 nd}t||krt|nd}|j|
||d qg }	 |  }|dv r| | ntd| }|| q|r| j|| d| _dS )a  Detects and converts a sequence of markdown table lines.

    Markdown attributes are not supported in headings or column data.

    This method will consume multiple input lines if the current line is a
    table heading or separator line. The table markdown sequence is:

      heading line

        heading-1 | ... | heading-n
          OR for boxed table
        | heading-1 | ... | heading-n |

      separator line

        --- | ... | ---
          OR for boxed table
        | --- | ... | --- |
          WHERE
        :---  align left
        :---: align center
        ---:  align right
        ----* length >= fixed_width_length sets column fixed width

      row data lines

        col-1-data-item | ... | col-n-data-item
          ...

      blank line ends table

    Args:
      i: The current character index in self._line.

    Returns:
      -1 if the input lines are table markdown, i otherwise.
       z | z---FTz *\| *r   rH   r   )boxleftrv   centerrightN)alignr   width)NrG   r   z+
rG   )rV   r   r   r   r&   r   stripr   r   r   ranger   r   r   r   r   rI   r   rJ   )r3   r   fixed_width_lengthheadr   r   r   sepr   indexr   sr   r   r   rowr   r   r   _ConvertTable8  sl   &













zMarkdownRenderer._ConvertTablec                 C   sD   |t | jk r | j| dkr |d7 }|t | jk r | j| dks|S )zAdvances i past any indentation spaces.

    Args:
      i: The current character index in self._line.

    Returns:
      i after indentation spaces skipped.
    rw   r   )r   rV   r   r   r   r   _ConvertIndentation  s   	z$MarkdownRenderer._ConvertIndentationc                 C   s   | j |d drG| j |d d }|s3| jdkrd| _n|| _| j| jdkr.d dS d dS | jdk rG| rG| j| || _dS | jdk rN|S | | j dS )zDetects and converts a ```...``` code block markdown.

    Args:
      i: The current character index in self._line.

    Returns:
      -1 if the input line is part of a code block markdown, i otherwise.
    Nrx   r_   r   rH   rG   )rV   r   rO   rI   SetLangr~   r   )r3   r   langr   r   r   _ConvertCodeBlock  s$   	

z"MarkdownRenderer._ConvertCodeBlockc                 C   sR  |r|S | j d}|dk r|S d}d}|}|d }|t| j k r>| j | dkr>|d7 }|d7 }|t| j k r>| j | dks(|t| j k rN| j |  sN|S |t| j k rn| j |  rn|d7 }|t| j k rn| j |  s\|t| j kow| }|r~|d8 }| j dr|| _n| jr| j ds| jd }| j| j j	s| j| j j
|k r|  jd7  _| jt| jkr| jt  n| j| j j
|kr|  jd8  _| j| j j
|ks|   |rt| j }d}n!d| j| j _	d| j| j _|| j| j _
| j d| | _|  }|r
|}| jj|||d |t| j k r'|  j| j |d 7  _d	S )
aj  Detects and converts a definition list item markdown line.

         [item-level-1]:: [definition-line]
         [definition-lines]
         [item-level-2]::: [definition-line]
         [definition-lines]

    Args:
      i: The current character index in self._line.

    Returns:
      -1 if the input line is a definition list item markdown, i otherwise.
    z::r   r   Nrs   rv   F)
definitionr   rH   )rV   r{   r   rk   r   rY   r   rN   rP   r=   r?   r   r<   r   r>   rJ   r   rI   r   )r3   r   index_at_definition_markdownr?   
list_level
original_ir   r   r   r   r   _ConvertDefinitionList  sb   

z'MarkdownRenderer._ConvertDefinitionListc                 C   s  | j s
| j| dvr|S | j| }|d }|}|t| jk r;| j| |kr;|d7 }|d7 }|t| jk r;| j| |ks%|t| jksI| j| dkrK|S | j| j jru| j| j j|kru| j| j j|krt|  jd8  _| j| j j|ksdn|  jd7  _| jt| jkr| jt  d| j| j _d| j| j _	d| j| j _
|| j| j _|   | j| j |t| jk r| j| dkr|d7 }|t| jk r| j| dks|  j| j|d 7  _d	S )
a  Detects and converts a bullet list item markdown line.

    The list item indicator may be '-' or '*'. nesting by multiple indicators:

        - level-1
        -- level-2
        - level-1

    or nesting by indicator indentation:

        * level-1
          * level-2
        * level-1

    Args:
      i: The current character index in self._line.

    Returns:
      -1 if the input line is a bullet list item markdown, i otherwise.
    z-*rs   r   rw   Tr   FNrH   )rQ   rV   r   rN   rP   r=   r?   r   r<   r>   r@   r   rI   r   rJ   )r3   r   r=   r?   r   r   r   r   _ConvertBulletList  s>   
z#MarkdownRenderer._ConvertBulletListc                 C   sR   | j | j jr	dnd}| js|o| j  }|r |s"| js"| js"|S | | dS )a	  Detects and converts an example markdown line.

    Example lines are indented by one or more space characters.

    Args:
      i: The current character index in self._line.

    Returns:
      -1 if the input line is is an example line markdown, i otherwise.
    FTrH   )	rN   rP   r=   rZ   rJ   r   rQ   rS   r   )r3   r   example_allowedr   r   r   _ConvertExample=  s   
z MarkdownRenderer._ConvertExamplec                 C   sx   |s| j s|S | j| j  js|S | j| j  jdkr$| j| j   jd8  _| j| j  js:|   | jj| j d dd |S )zDetects and converts an end of list markdown line.

    Args:
      i: The current character index in self._line.

    Returns:
      -1 if the input line is an end of list markdown, i otherwise.
    r   Tr   )rP   rN   r@   r>   r   rI   r   r   r   r   r   _ConvertEndOfListP  s   
	z"MarkdownRenderer._ConvertEndOfListc                 C   s.   d| j | j _|  jd| j|d  7  _dS )a  Detects and converts any remaining markdown text.

    The input line is always consumed by this method. It should be the last
    _Convert*() method called for each input line.

    Args:
      i: The current character index in self._line.

    Returns:
      -1
    Frw   NrH   )rN   rP   r@   rJ   rV   r   r   r   r   _ConvertRemainderd  s   z"MarkdownRenderer._ConvertRemainderc                 C   sH   |    | jr| j  | jdd |  j| j7  _|    | j S )zFlushes the fill buffer and checks for NOTES.

    A previous _ConvertHeading() will have cleared self._notes if a NOTES
    section has already been seen.

    Returns:
      The renderer Finish() value.
    rs   r   )r   rL   rI   r   r   rJ   FinishrA   r   r   r   _Finisht  s   	

zMarkdownRenderer._Finishc                 C   s   t | jtjr|   dS 	 | j| _d| _| j| _d| _| 	 | _
| j
s)	 |  S | j
| jr;d| j d | j
 | _
| j
 | _
d}| j| j| j| j| j| j| j| j| j| j| jfD ]}||}|dk rg nq[q)zCRenders the markdown from fin to out and returns renderer.Finish().NTr   Frw   z  )
isinstancerI   r   rC   r   rR   rQ   rU   rS   r   rV   r   rX   r   r   r   r   r   r   r   r   r   r   r   r   r   )r3   r   detect_and_convertr   r   r   Run  sB   
zMarkdownRenderer.Runr   )"r7   r8   r9   r:   r   BOLDITALICr}   r   sysstdinr2   rq   ru   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rC   {   s8    
@
U80jA2rC   r   P   c           	      C   sJ   | t vrt| t |  |ptj||||d}t||ptj||d  dS )aU  Renders markdown to a selected document style.

  Args:
    style: The rendered document style name, must be one of the STYLES keys.
    fin: The input stream containing the markdown.
    out: The output stream for the rendered document.
    width: The page width in characters.
    notes: Optional sentences inserted in the NOTES section.
    title: The document title.
    command_metadata: Optional metadata of command, including available flags.
    command_node: The command object that the document is being rendered for.

  Raises:
    DocumentStyleError: The markdown style was unknown.
  )outtitler   rW   r[   )r]   r^   rW   N)r/   r)   r   stdoutrC   r   r   )	r*   r]   r   r   r^   r   rW   r[   r\   r   r   r   RenderDocument  s   
r   c                   @   s   e Zd ZdZdddZdS )CommandMetaDatazHObject containing metadata of command to be passed into linter renderer.NTc                 C   s&   |r|ng | _ |r|ng | _|| _d S r   )flags
bool_flagsis_group)r3   r   r   r   r   r   r   r2     s   
zCommandMetaData.__init__)NNTrB   r   r   r   r   r     s    r   c                 C   st   t jdd}|jdddd |jddtt d	d
d |jdddd || dd }t|j|j	|j
dd dS )z&Standalone markdown document renderer.zNRenders markdown on the standard input into a document on the standard output.)descriptionz--notes	SENTENCESzDInserts SENTENCES into the NOTES section which is created if needed.)metavarhelpz--styleSTYLEr   zThe output style.)r   choicesdefaultr   z--titleTITLEzThe document title.r   N)r^   r   rW   )argparseArgumentParseradd_argumentr.   r/   r0   
parse_argsr   r*   r^   r   )argvparserargsr   r   r   main  s0   

r   __main__)r   NNr   NNNN)&r:   
__future__r   r   r   r   r&   r   googlecloudsdk.corer   r   &googlecloudsdk.core.document_renderersr   r   r	   r
   r   r   r   DevSiteRendererHTMLRendererManRendererrC   TextRendererLinterRendererr/   r   r%   r(   Errorr)   objectr<   r   r   r   r7   GetDecodedArgvr   r   r   r   <module>   sV   

      8
	