o k`x@sddlmZddlmZddlZddlZddlZddlZddlZddlTddl m Z m Z m Z m Z mZddlmZddlmZmZmZddlmZmZmZmZdd lmZdd lmZmZmZdd l m!Z!m"Z"m#Z#m$Z$dd l%m&Z&dd l'm(Z(m)Z)m*Z*ddl+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2ddl3m4Z4Gddde5Z6Gddde6Z7Gddde6Z8Gddde6Z9Gddde6Z:Gddde6Z;Gddde6Zd$d"d#Z?dS)% fnmatchcase)groupbyN)*)ResourceResourceNotFoundget_resource_nameget_resource_summaryget_resource_url)as_int) format_datefrom_utimestamp user_time)Markupescape find_elementtag) separated) unicode_quote to_unicodestripws)_dgettext cleandoc_tag_)chrome_resource_path)IWikiMacroProvider WikiSystem parse_args) MacroErrorOutlineFormatterProcessorError extract_linkformat_to_htmlformat_to_onelinersystem_message) InterWikiMapc@sJeZdZdZeedZdZdZdZ ddZ ddZ d d Z d d d Z dS) WikiMacroBaseaAbstract base class for wiki macros and processors. On usage error, the `MacroError` or `ProcessorError` exception should be raised, to ensure proper display of the error message in the rendered wiki content. The `_description` attribute contains the macro help. Set the `hide_from_macro_index` attribute to `True` to prevent displaying help in the macro index (`[[MacroList]]`). If the default value of `False` and the `_description` is empty, "No documentation found" will be displayed. TNFccs*|jj}|dr|dd}|VdS)z4Yield the name of the macro based on the class name.MacroN) __class____name__endswith)selfnamer/2/usr/lib/python3/dist-packages/trac/wiki/macros.py get_macrosIs    zWikiMacroBase.get_macroscCsB|jrdS|j|j}}|r|r||fS|S|jrt|jSdS)z:Return the subclass's gettext domain and macro descriptionN)hide_from_macro_index_domain _description__doc__inspectcleandoc)r-r.domain descriptionr/r/r0get_macro_descriptionPs z#WikiMacroBase.get_macro_descriptioncCstN)NotImplementedError)r-parserr.contentr/r/r0 parse_macro\szWikiMacroBase.parse_macrocCstd||jf)Nz9pre-0.11 Wiki macro %s by provider %s no longer supported)r=r*)r- formatterr.r?argsr/r/r0 expand_macro_s zWikiMacroBase.expand_macror<)r+ __module__ __qualname__r6 implementsrabstractr4r5r3r1r;r@rCr/r/r/r0r'.s r'c@s4eZdZdZedZedZedZ ddZ dS)TitleIndexMacromessagesa,Insert an alphabetic list of all wiki pages into the output. Accepts a prefix string as parameter: if provided, only pages with names that start with the prefix are included in the resulting list. If this parameter is omitted, all pages are listed. If the prefix is specified, a second argument of value `hideprefix` can be given as well, in order to remove that prefix from the output. The prefix string supports the standard relative-path notation ''when using the macro in a wiki page''. A prefix string starting with `./` will be relative to the current page, and parent pages can be specified using `../`. Several named parameters can be specified: - `format=compact`: The pages are displayed as comma-separated links. - `format=group`: The list of pages will be structured in groups according to common prefix. This format also supports a `min=n` argument, where `n` is the minimal number of pages for a group. - `format=hierarchy`: The list of pages will be structured according to the page name path hierarchy. This format also supports a `min=n` argument, where higher `n` flatten the display hierarchy - `depth=n`: limit the depth of the pages to list. If set to 0, only toplevel pages will be shown, if set to 1, only immediate children pages will be shown, etc. If not set, or set to -1, all pages in the hierarchy will be shown. - `include=page1:page*2`: include only pages that match an item in the colon-separated list of pages. If the list is empty, or if no `include` argument is given, include all pages. - `exclude=page1:page*2`: exclude pages that match an item in the colon- separated list of pages. The `include` and `exclude` lists accept shell-style patterns. z(/| )z ([0-9.]+)c st|\}|r|dnd|ot|dko|ddk}tdddddtdtdddddd d }fd d }|d pMdg|djj}rh|rh|jdkrh |j ro dnd|rzfddnddt fdd D} |dkrttfdd| DdS fdd fdd  fddfd d! fd"d#  fd$d% fd&d fd'dd(|} | r| | } ntfd)d| D} tj| d*d+S),Nr hideprefixminrLdepthformatr2csdd|ddDS)NcSsg|] }|r|qSr/strip.0incr/r/r0 szDTitleIndexMacro.expand_macro..parse_list..r2:)getsplitr.)kwr/r0 parse_listsz0TitleIndexMacro.expand_macro..parse_listincluderexcludewiki/cs|tdSr<lenpage)prefixr/r0z.TitleIndexMacro.expand_macro..cSs|Sr<r/rdr/r/r0rgc3sj|]0dksdkr2ddvrtfddDrtfddDsVqdS)rra WIKI_VIEWr`c3|]}t|VqdSr<rrTrdr/r0 z9TitleIndexMacro.expand_macro...c3rkr<r)rUexcrdr/r0rlrmN)countpermany)rU)rOexcludesrAincludesstartrdr0rlsz/TitleIndexMacro.expand_macro..compactc3s0|]}tj|j|dVqdShrefN)raformat_page_namerxr`)rUprA omitprefixr`r/r0rls  z, c sXg}|D]%}ddjjdj|ddD}|dd|D|fq|S)zReturn a list of (path elements, page_name) pairs, where path elements correspond to the page name (without prefix) splitted at Camel Case word boundaries, numbers and '/'. cSg|]}|qSr/rRrUeltr/r/r0rWzKTitleIndexMacro.expand_macro..split_pages_group..z \1 T)rZcSsg|]}|r|qSr/r/rr/r/r0rWr)SPLIT_RErZ NUM_SPLIT_REsubrzappend)pages page_pathsrepath)r}r-r`r/r0split_pages_groups z7TitleIndexMacro.expand_macro..split_pages_groupcsfdd|DS)zReturn a list of (path elements, page_name) pairs, where path elements correspond to the page name (without prefix) splitted according to the '/' hierarchy. cs$g|]}|d|fqS)ra)rzrZrUrer}r`r/r0rWszOTitleIndexMacro.expand_macro..split_pages_hierarchy..r/)rrr/r0split_pages_hierarchys z;TitleIndexMacro.expand_macro..split_pages_hierarchyc sdd}g}t||D]g\}}dd|D}|rft|krft|}t|dkr<|d\}}|||f}||q j|r\|D]} t| trU| \}}|||f} || qDq ||f}||q |D] \} } || qhq |S)aTransform a flat list of entries into a tree structure. `entries` is a list of `(path_elements, page_name)` pairs Return a list organized in a tree structure, in which: - a leaf is a page name - a node is a `(key, nodes)` pairs, where: - `key` is the leftmost of the path elements, common to the grouped (path element, page_name) entries - `nodes` is a list of nodes or leaves cS|\}}|r |dSdSNrr2r/rBeltsr.r/r/r0keyfnz?TitleIndexMacro.expand_macro..tree_group..keyfncS g|] \}}|dd|fqSrJNr/)rU path_elements page_namer/r/r0rWzDTitleIndexMacro.expand_macro..tree_group..rJr)rrcsortedrrmatch isinstancetuple) entriesrgroupskeygroupergrouped_entriessubnodessubkeynoderrr) minsize_groupr- tree_groupr/r0rs2             z0TitleIndexMacro.expand_macro..tree_groupc sdd}g}t||D]U\}}dd|D}dd|D}dd|D}|r*|dnd}|r2|d nd} |rTt|krTd d|D}t|} || | f} || q |r[||||q |S) aTransform a flat list of entries into a tree structure. `entries` is a list of `(path_elements, page_name)` pairs Return a list organized in a tree structure, in which: - a leaf is a `(rest, page)` pair, where: - `rest` is the rest of the path to be shown - `page` is a page name - a node is a `(key, nodes, page)` pair, where: - `key` is the leftmost of the path elements, common to the grouped (path element, page_name) entries - `page` is a page name (if one exists for that node) - `nodes` is a list of nodes or leaves cSrrr/rr/r/r0rrzCTitleIndexMacro.expand_macro..tree_hierarchy..keyfncSsg|]}|qSr/r/rUer/r/r0rWrhzHTitleIndexMacro.expand_macro..tree_hierarchy..cSs g|] }t|ddkr|qSrrJrbrr/r/r0rW cSs g|] }t|ddkr|qSrrbrr/r/r0rWrrNrJcSrrr/)rUrrer/r/r0rWr)rrcrrextend) rrrrrr sub_entries key_entries key_entrykey_pagerr)minsizetree_hierarchyr/r0rs&     z4TitleIndexMacro.expand_macro..tree_hierarchycstfdd|DS)Nc 3sb|],}tt|trtt|dd|dntj|j |dVqdS)rrarJrwN) rlirrstrongrSryrzrxr`rrAr} render_groupr`r/r0rl%s$  zETitleIndexMacro.expand_macro..render_group..rulgrouprr/r0r$sz2TitleIndexMacro.expand_macro..render_groupcstfdd|DS)Nc 3s|]>}tt|dkr,t|dr tj|dj|ddnt|d|dntjd|dj|ddVqdS)rJrrwrNraN)rrrcryrxr`joinrrArender_hierarchyr/r0rl-s     zITitleIndexMacro.expand_macro..render_hierarchy..rrrr/r0r,sz6TitleIndexMacro.expand_macro..render_hierarchyc|Sr<r/r{)rrrr/r0rg7rhcrr<r/r)rrrr/r0rg8s )r hierarchyc3s6|]}ttj|j|dVqdSrv)rrryrzrxr`rr|r/r0rl?s  titleindexclass_)rrSrc _arg_as_intrYmaxr`resourcerealmresolve_relative_nameidror get_pagesrrrdiv) r-rAr.r?rBrKrQr]rr transformrr/)rOrrrArsr\rrr}rfrrr-rrrtrrr`r0rCsX     $  ++  zTitleIndexMacro.expand_macroN) r+rDrEr4rr5recompilerrrCr/r/r/r0rHes #  rHc@ eZdZdZedZddZdS)RecentChangesMacrorIaList all pages that have recently been modified, ordered by the time they were last modified. This macro accepts two ordered arguments and a named argument. The named argument can be placed in any position within the argument list. The first parameter is a prefix string: if provided, only pages with names that start with the prefix are included in the resulting list. If this parameter is omitted, all pages are included in the list. The second parameter is the maximum number of pages to include in the list. The `group` parameter determines how the list is presented: `group=date` :: The pages are presented in bulleted lists that are grouped by date (default). `group=none` :: The pages are presented in a single bulleted list. Tip: if you only want to specify a maximum number of entries and don't want to filter by prefix, specify an empty first parameter, e.g. `[[RecentChanges(,10,group=none)]]`. cst|\}}|r|dnd}t|dkr t|dddnd}|dd}d} g}|rR|jj} | d| 7} || |Wdn1sMwY| d7} |ra| d 7} ||g} d} |j| |D]M\}} }d d || vr{qlj }t |t t|}|| kr|} | |gft| } d}| dkrjj|d | d }j|}| dd||| |fqlfdd| D}|dkrdd|D}n tdd|D}tj|ddS)NrrJrMrdatezaSELECT name, max(version) AS max_version, max(time) AS max_time FROM wikiz WHERE name %sz% GROUP BY name ORDER BY max_time DESCz LIMIT %srjr`diff)actionversionrPc3s*|]\}}|fdd|DfVqdS)c 3sX|]'\}}}}ttj|j|d|r$tdtjtd|ddnddVqdS)rwz (r)N )rrryrxr`smallr)rUrer.r diff_hrefrAr/r0rls  z..Nr/rUrrrr/r0rls  z2RecentChangesMacro.expand_macro..css,|]\}}tj|ddt|fVqdS)sectionrN)rh3rrr/r/r0rls css|]\}}|VqdSr<r/rr/r/r0rlswikipager)rrSrcrrYenvdb_query prefix_matchrprefix_match_valuerpreqrr r intrxr`rzrrr)r-rAr.r?rBr\rflimitrsqldbentries_per_dateprevdatertsrrrritems_per_dateoutr/rr0rCasX $      zRecentChangesMacro.expand_macroNr+rDrEr4rr5rCr/r/r/r0rG  rc@r)PageOutlineMacrorIa Display a structural outline of the current wiki page, each item in the outline being a link to the corresponding heading. This macro accepts four optional parameters: * The first is a number or range that allows configuring the minimum and maximum level of headings that should be included in the outline. For example, specifying "1" here will result in only the top-level headings being included in the outline. Specifying "2-3" will make the outline include all headings of level 2 and 3, as a nested list. The default is to include all heading levels. * The second parameter can be used to specify a custom title (the default is no title). * The third parameter selects the style of the outline. This can be either `inline` or `pullout` (the latter being the default). The `inline` style renders the outline as normal part of the content, while `pullout` causes the outline to be rendered in a box that is by default floated to the right side of the other content. * The fourth parameter specifies whether the outline is numbered or not. It can be either `numbered` or `unnumbered` (the former being the default). This parameter only has an effect in `inline` style. c sHd\d}d}d}|rfdd|dD}t|dkrf|d}d|vr5fd d|dd D\n t|d t|d krf|d }|d dD]} | } | d kr_d}qP| dkred}qPt} t|j|j } | j |j | | dt | } |rtj|dd| } |stj| dd} | S|stj| dd} | S)N)rJFTcSr~r/rRrUargr/r/r0rWrz1PageOutlineMacro.expand_macro..,r-csg|] }t|dqS)rLr)r)rUd max_depth min_depthr/r0rWrJrrNinline unnumberedshortenrrwiki-tocz wiki-toc-un)rZrcrrSlowerioStringIOr rcontextrQsourcergetvaluerh4r) r-rAr.r?titlernumberedargvrOrr oformatteroutliner/rr0rCsL        zPageOutlineMacro.expand_macroNrr/r/r/r0rrrc@sfeZdZdZedZddZdZe edZ e edZ e dZ e d Z e d Zd d Zd S) ImageMacrorIa Embed an image in wiki-formatted text. The first argument is the file specification. The file specification may reference attachments in three ways: * `module:id:file`, where module can be either '''wiki''' or '''ticket''', to refer to the attachment named ''file'' of the specified wiki page or ticket. * `id:file`: same as above, but id is either a ticket shorthand or a Wiki page name. * `file` to refer to a local attachment named 'file'. This only works from within that wiki page or a ticket. The file specification may also refer to: * repository files, using the `source:file` syntax (`source:file@rev` works also). * files, using direct URLs: `/file` for a project-relative, `//file` for a server-relative, or `http://server/file` for absolute location. An InterWiki prefix may be used. * embedded data using the [http://tools.ietf.org/html/rfc2397 rfc2397] `data` URL scheme, provided the URL is enclosed in quotes. The remaining arguments are optional and allow configuring the attributes and style of the rendered `` element: * digits and unit are interpreted as the size (ex. 120px, 25%) for the image * `right`, `left`, `center`, `top`, `bottom` and `middle` are interpreted as the alignment for the image (alternatively, the first three can be specified using `align=...` and the last three using `valign=...`) * `link=some TracLinks...` replaces the link to the image source by the one specified using a TracLinks. If no value is specified, the link is simply removed. * `inline` specifies that the content generated be an inline XHTML element. By default, inline content is not generated, therefore images won't be rendered in section headings and other one-line content. * `nolink` means without link to image source (deprecated, use `link=`) * `key=value` style are interpreted as HTML attributes or CSS style indications for the image. Valid keys are: * align, valign, border, width, height, alt, title, longdesc, class, margin, margin-(left,right,top,bottom), id and usemap * `border`, `margin`, and `margin-`* can only be a single number (units are pixels). * `margin` is superseded by `center` which uses auto margins Examples: {{{ [[Image(photo.jpg)]] # simplest [[Image(photo.jpg, 120px)]] # with image width size [[Image(photo.jpg, right)]] # aligned by keyword [[Image(photo.jpg, nolink)]] # without link to source [[Image(photo.jpg, align=right)]] # aligned by attribute }}} You can use an image from a wiki page, ticket or other module. {{{ [[Image(OtherPage:foo.bmp)]] # from a wiki page [[Image(base/sub:bar.bmp)]] # from hierarchical wiki page [[Image(#3:baz.bmp)]] # from another ticket [[Image(ticket:36:boo.jpg)]] # from another ticket (long form) [[Image(source:/img/bee.jpg)]] # from the repository [[Image(htdocs:foo/bar.png)]] # from project htdocs dir [[Image(shared:foo/bar.png)]] # from shared htdocs dir (since 1.0.2) }}} ''Adapted from the Image.py macro created by Shun-ichi Goto '' cCs,dd|j|p ddddD}d|vS)NcSg|]}t|qSr/rrr/r/r0rW"rz(ImageMacro.is_inline..r2rJrNr)_split_args_rerZ)r-r?rBr/r/r0 is_inline!szImageMacro.is_inlinez((?:[^%s"']|"[^"]*"|'[^']*')+)rrXz[0-9]+(%|px)?$zp(align|valign|border|width|height|alt|margin(?:-(?:left|right|top|bottom))?|title|longdesc|class|id|usemap)=(.+)z(?:["'])(.*)(?:["'])$c Cs6d}|rt|}dd|j|dddD}|sdS|d}i}i}d}ddlm} zdd| |jD} Wn tyFg} Ynw|r!|d} |j | rZ| |d <n| d krad}n| d r| d dd} t |j|j | } t| d } d}| dur| jd }n| dvr| |d<n| dkrd|d<|d<d|d<|ddnu| dvr| |d<nl|j | }|r|\}} |dkr| dvs|dkr| dvr|| nG|dvrdt| |dd||<n7|d vrd|vrdt| |dd||<n#|d!kr d"t| ||d!<n|j| }|r|d} | |t|<|sJ|j |r-|d#}d$d|j|dddD}|rD|dnd}d}}}d}t|j}|d%vre|}}|d&d}n!||vr}||d'|dd\}}|}n | d(r|dd}}|d&d}n| d)rd}d&|vr|d&d\}}||}|r|d&|7}||}}nt |d*kr|\}}}d+||f}|!||}|r|\}}|t"d,}nt#||$d-|}nt |dkrq|\}}|| vrd}d.|vr |d.d\}}|jj%||d/}|jj%||d0d1}|}ngd}|\}}|r8|dd2kr8d3}|dd}n,|d4krM|j&d5|}}t'j()|}n|d6krb|j&d6|}}t'j()|}nd7}|rpt#||$d-|}nt |dkr|j*$d-|}nt+t,d8S|rzt-|j|}Wn t.yd}t/|j j0d9}t,d:|j1t2|j|j3d;}Ynwd<|4|vrt5|j||j}t5|j||jd0d=}d>D]}|r||vr|||<q|rd?d@dA|6D|dB<t7|j8||j j0sdC|dD<t9j:dHdE|i|}|durt9j;||p|dFdG}|S)INcSr r/r rr/r/r0rW5rz+ImageMacro.expand_macro..rJrNr2r) BrowserModulecSsg|]}|dqS)rr/)rUresr/r/r0rWGrwidthnolinkzlink==rx)leftrightfloatcenterauto margin-left margin-rightblockdisplaymargin)topbottommiddlezvertical-alignalign)rrrvalign)rr r)z margin-topz margin-bottomz %dpxrM)rrrborderz %dpx solid'"cSsg|]}|dqS)r$rR)rUir/r/r0rWzs)httphttpsftpdata?rXz//rar%s:%sz ?format=raw attachment@)revraw)r.rQ#tickethtdocssitesharedr`zNo filespec givenzcommon/attachment.pngz(No image "%(id)s" attached to %(parent)s)rparentATTACHMENT_VIEW)rQ)raltz; css$|] \}}d|t|fVqdS)r+N)r)rUkvr/r/r0rlsz*ImageMacro.expand_macro..style anonymous crossoriginsrczpadding:0; border:none)rxr:r/).get_macro_descr..csg|] }||fqSr/)r;rfmacro_providerr/r0rWs zHMacroListMacro.expand_macro..get_macro_descr..z/Error: Can't get description for macro %(name)srr[cSs|dS)NrJr/rr/r/r0rgszFMacroListMacro.expand_macro..get_macro_descr..rrJr2rTrcSsg|]\}}|qSr/r/)rUr.descrr/r/r0rWr)r`macro_providerslistr1rqrAr%rrrrrrr$rrr#)namesname_descriptionsrrkpairsr?rArgr-rhr0get_macro_descrs^       z4MacroListMacro.expand_macro..get_macro_descrztrac-macrolistrc ss|];\}}tjtd|ddd|ddt|dkr1tttddd|dd Dp2d |p:ttd fVqd S) z[[r]]z%s-macrorrJzAliases:cSsg|] }td|dqS)z [[rs)rcode)rUaliasr/r/r0rWrz9MacroListMacro.expand_macro...NzNo documentation found)rrrurcr{rrem)rUr:rnr/r/r0rls"  z.MacroListMacro.expand_macro..cSs |ddS)NrJrr/)itemr/r/r0rgs z-MacroListMacro.expand_macro..rj)rSrrr)r-rAr.r?rrr/rqr0rCs #zMacroListMacro.expand_macroNrr/r/r/r0res  rec@r) TracIniMacrorIa"Produce documentation for the Trac configuration file. Typically, this will be used in the TracIni page. The macro accepts two ordered arguments and two named arguments. The ordered arguments are a configuration section filter, and a configuration option name filter: only the configuration options whose section and name start with the filters are output. The named arguments can be specified: section :: a glob-style filtering on the section names option :: a glob-style filtering on the option names csddlm}m}t|\}}i}dD]-\}} ||d} | r(t| ||<q| t|kr4|| nd} | r?t | ||<qd|v} dD]}||vrVt ||t j j ndd||<qF|d } |d}|j|j}i|D]\\}}}| |r||r||i|<qw| sD] }| |r|iqD]}tt|d dd |<qfd d tD}ddfddtjddfdd|DS)Nr) ConfigSectionOption))rr)optionrJr2r|)rr|cSsdS)NTr/)r9r/r/r0rg>riz+TracIniMacro.expand_macro..rcSs|jSr<r[)r|r/r/r0rgNsrjcs&g|]}||vr|jndfqS)r2)doc)rUr)section_registryr/r0rWOs z-TracIniMacro.expand_macro..cSsB|j}|dur|dkrtjt||ddStjtdddS)Nr2defaultrz (no default) nodefault)rrtdrudumpsr)r|rr/r/r0 default_cellSs z/TracIniMacro.expand_macro..default_cellcs6|rtjddtfddt|DSdS)Nr`rc 3sz|]8\}}tjttjt|jdd|jfdttjj|j |d|jf|dr5dnddVqdS) ztracini-optionz #%s-%s-option)rrxz %s-%s-optionrNoddeven)rrN) rtrrryrur.r#rrr})rUidxr|)rrArr-r/r0rl^s$   zCTracIniMacro.expand_macro..options_table..)rtabletbody enumerate)roptions)rrAr-)rr0 options_table[s  z0TracIniMacro.expand_macro..options_tabletracinirc3sN|]"\}}tjtd|d|dtjj|||fVqdS)z[%s]z %s-sectionrtN)rrrur#rrrY)rUr section_doc)rArrr-r/r0rlks z,TracIniMacro.expand_macro..) trac.configrzr{rrYrSfnmatch translatercrrr IGNORECASEr get_registrycompmgrrR setdefaultritervaluesrr)r-rAr.r?rzr{rBr\filtersindexpatternrfhas_option_filtersection_filter option_filteroption_registryrrr|sectionsr/)rrArrr~r-r0rC-sX      zTracIniMacro.expand_macroNrr/r/r/r0rys  ryc@r)KnownMimeTypesMacrorIzList all known mime-types which can be used as WikiProcessors. Can be given an optional argument which is interpreted as mime-type filter. c sddlm}||jj}d}t|\}}|r |dd}i|D]\} } |r1| |r>| | kr> | g | q&t j ddt jddt t t tdt t jd |jjd d t fd d tDS) Nr)Mimeviewr2r mimetypesrr`z MIME TypesWikiProcessorsrwc 3sF|]}ttjt|ddttdt|VqdS)ztext-align: left)r: N)rrthrurrr)rU mime_type mime_typesr/r0rls z3KnownMimeTypesMacro.expand_macro..)trac.mimeview.apirrmime_maprr>rSrstriprRrCrrrrrtheadrrrryrrxr`rr) r-rAr.r?rrmime_type_filterrBr\rrr/rr0rCzs:       z KnownMimeTypesMacro.expand_macroNrr/r/r/r0rrs  rc@s(eZdZdZedZgdZddZdS)TracGuideTocMacrorIacDisplay a table of content for the Trac guide. This macro shows a quick and dirty way to make a table-of-contents for the !Help/Guide. The table of contents will contain the Trac* and WikiFormatting pages, and can't be customized. See the [https://trac-hacks.org/wiki/TocMacro TocMacro] for a more customizable table of contents. )) TracGuideIndex) TracInstall Installation)TracInterfaceCustomization Customization) TracPluginsPlugins) TracUpgrade Upgrading)TracIni Configuration) TracAdminAdministration) TracBackupBackup) TracLoggingLogging)TracPermissions Permissions)TracWikizThe Wiki)WikiFormattingzWiki Formatting) TracTimelineTimeline) TracBrowserzRepository Browser)TracRevisionLogz Revision Log) TracChangeset Changesets) TracTicketsTickets) TracWorkflowWorkflow) TracRoadmapRoadmap) TracQueryzTicket Queries)TracBatchModifyz Batch Modify) TracReportsReports)TracRssz RSS Support)TracNotification Notificationcsnjjdd}|dkrd|dt|jtjttdt fdd|j Ddd S) Nr2rarrJzTable of Contentsc sRg|]%\}}tjtj|j|| odd|ko$ddqS)missing)rxractiver)rrryrxr`has_page)rUrefrcurpagerArfwsr/r0rWs z2TracGuideTocMacro.expand_macro..rr) rrfindrrrrrrrTOC)r-rAr.r?rr/rr0rCs   zTracGuideTocMacro.expand_macroN)r+rDrEr4rr5rrCr/r/r/r0rs rcCsNt|d||d}|dur%ttd|rtd||fdt|d|S)NrzInvalid macro argument %(expr)sz%s=%s)expr)r rrrru)rYrrLrint_valr/r/r0rsr)NNN)@rr itertoolsrr7rrPr trac.core trac.resourcerrrr r trac.utilr trac.util.datefmtr r rtrac.util.htmlrrrrtrac.util.presentationrtrac.util.textrrrtrac.util.translationrrrrtrac.web.chromer trac.wiki.apirrrtrac.wiki.formatterrr r!r"r#r$r%trac.wiki.interwikir& Componentr'rHrrr reryrrrr/r/r/r0s@     $ 7cOD>W%: