title: $:/core/macros/toc
tags: $:/tags/Macro

\define toc-open-icon() $:/core/images/down-arrow
\define toc-closed-icon() $:/core/images/right-arrow

\define toc-caption()
\whitespace trim
<span class="tc-toc-caption tc-tiny-gap-left">
<$set name="tv-wikilinks" value="no">
  <$transclude field="caption">
    <$view field="title"/>
  </$transclude>
</$set>
</span>
\end

\define toc-level-indicator()
\whitespace trim
<%if [<__level__>compare:number:gt[0]]%>
  <%if [<currentTiddler>tagging[]] %>
    <span class="tc-tiny-gap-left">{{$:/core/images/new-button}}</span>
  <%else%>
    <span class="tc-tiny-gap-left">{{$:/core/images/blank}}</span>
  <%endif%>
<% endif %>
\end

\define toc-body(tag,sort:"",itemClassFilter,exclude,path,level)
\whitespace trim
<ol class="tc-toc">
  <$list filter="""[all[shadows+tiddlers]tag<__tag__>!has[draft.of]$sort$] -[<__tag__>] -[subfilter<__exclude__>]""">
    <$let item=<<currentTiddler>> path={{{ [<__path__>addsuffix[/]addsuffix<__tag__>] }}}>
      <$set name="excluded" filter="[subfilter<__exclude__>] [<__tag__>]">
        <$set name="toc-item-class" filter=<<__itemClassFilter__>> emptyValue="toc-item-selected" value="toc-item">
          <li class=<<toc-item-class>>>
            <$list filter="[all[current]toc-link[no]]" >
              <$list-empty>
                <!-- link to target-field or currentTiddler -->
                <$link to={{{ [<currentTiddler>get[target]else<currentTiddler>] }}}>
                  <<toc-level-indicator>>
                  <<toc-caption>>
                </$link>
              </$list-empty>
              <!-- toc-link = no -->
              <<toc-level-indicator>>
              <<toc-caption>>
            </$list>
            <$let _level={{{ [<__level__>subtract[1]] }}}>
              <%if [<_level>compare:number:gt[0]]%>
                <$macrocall $name="toc-body" tag=<<item>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<excluded>> path=<<path>> level=<<_level>>/>
              <%elseif [<_level>match[-1]]%>
                <!-- show full toc, no level defined -->
                <$macrocall $name="toc-body" tag=<<item>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<excluded>> path=<<path>>/>
              <%endif%>
            </$let>
          </li>
        </$set>
      </$set>
    </$let>
  </$list>
</ol>
\end

\define toc(tag,sort:"",itemClassFilter:"",exclude,level)
\whitespace trim
<$let __tag__={{{ [<__tag__>is[blank]then<currentTiddler>else<__tag__>] }}} >
  <$macrocall $name="toc-body"  tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<__exclude__>> level=<<__level__>>/>
</$let>
\end

\define toc-linked-expandable-body(tag,sort:"",itemClassFilter,exclude,path)
\whitespace trim
<!-- helper function -->
<$qualify name="toc-state" title={{{ [[$:/state/toc]addsuffix<__path__>addsuffix[-]addsuffix<currentTiddler>] }}}>
  <$set name="toc-item-class" filter=<<__itemClassFilter__>> emptyValue="toc-item-selected" value="toc-item">
    <li class=<<toc-item-class>>>
    <$link to={{{ [<currentTiddler>get[target]else<currentTiddler>] }}}>
      <$reveal type="nomatch" stateTitle=<<toc-state>> text="open">
        <$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep">
          <$transclude tiddler=<<toc-closed-icon>> />
        </$button>
      </$reveal>
      <$reveal type="match" stateTitle=<<toc-state>> text="open">
        <$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep">
          <$transclude tiddler=<<toc-open-icon>> />
        </$button>
      </$reveal>
      <<toc-caption>>
    </$link>
    <$reveal type="match" stateTitle=<<toc-state>> text="open">
      <$macrocall $name="toc-expandable" tag=<<currentTiddler>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<__exclude__>> path=<<__path__>>/>
    </$reveal>
    </li>
  </$set>
</$qualify>
\end

\define toc-unlinked-expandable-body(tag,sort:"",itemClassFilter,exclude,path)
\whitespace trim
<!-- helper function -->
<$qualify name="toc-state" title={{{ [[$:/state/toc]addsuffix<__path__>addsuffix[-]addsuffix<currentTiddler>] }}}>
  <$set name="toc-item-class" filter=<<__itemClassFilter__>> emptyValue="toc-item-selected" value="toc-item">
    <li class=<<toc-item-class>>>
      <$reveal type="nomatch" stateTitle=<<toc-state>> text="open">
        <$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep">
        <$transclude tiddler=<<toc-closed-icon>> />
          <<toc-caption>>
        </$button>
      </$reveal>
      <$reveal type="match" stateTitle=<<toc-state>> text="open">
        <$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep">
          <$transclude tiddler=<<toc-open-icon>> />
          <<toc-caption>>
        </$button>
      </$reveal>
      <$reveal type="match" stateTitle=<<toc-state>> text="open">
        <$macrocall $name="toc-expandable" tag=<<currentTiddler>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<__exclude__>> path=<<__path__>>/>
      </$reveal>
    </li>
  </$set>
</$qualify>
\end

\define toc-expandable-empty-message()
<$macrocall $name="toc-linked-expandable-body" tag=<<tag>> sort=<<sort>> itemClassFilter=<<itemClassFilter>> exclude=<<excluded>> path=<<path>>/>
\end

\define toc-expandable(tag,sort:"",itemClassFilter:"",exclude,path)
\whitespace trim
<$let __tag__={{{ [<__tag__>is[blank]then<currentTiddler>else<__tag__>] }}} tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> path={{{ [<__path__>addsuffix[/]addsuffix<__tag__>] }}}>
  <$set name="excluded" filter="[subfilter<__exclude__>] [<__tag__>]">
    <ol class="tc-toc toc-expandable">
      <$list filter="""[all[shadows+tiddlers]tag<__tag__>!has[draft.of]$sort$] -[<__tag__>] -[subfilter<__exclude__>]""">
        <$list filter="[all[current]toc-link[no]]" emptyMessage=<<toc-expandable-empty-message>> >
          <$macrocall $name="toc-unlinked-expandable-body" tag=<<__tag__>> sort=<<__sort__>> itemClassFilter="""itemClassFilter""" exclude=<<excluded>> path=<<path>> />
        </$list>
      </$list>
    </ol>
  </$set>
</$let>
\end

\define toc-linked-selective-expandable-body(tag,sort:"",itemClassFilter,exclude,path)
\whitespace trim
<$qualify name="toc-state" title={{{ [[$:/state/toc]addsuffix<__path__>addsuffix[-]addsuffix<currentTiddler>] }}}>
  <$set name="toc-item-class" filter=<<__itemClassFilter__>> emptyValue="toc-item-selected" value="toc-item" >
    <li class=<<toc-item-class>>>
      <$link to={{{ [<currentTiddler>get[target]else<currentTiddler>] }}}>
          <$list filter="[all[current]tagging[]$sort$]  -[subfilter<__exclude__>] +[limit[1]]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button>">
          <$reveal type="nomatch" stateTitle=<<toc-state>> text="open">
            <$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep">
            <$transclude tiddler=<<toc-closed-icon>> />
            </$button>
          </$reveal>
          <$reveal type="match" stateTitle=<<toc-state>> text="open">
            <$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep">
              <$transclude tiddler=<<toc-open-icon>> />
            </$button>
          </$reveal>
        </$list>
        <<toc-caption>>
      </$link>
      <$reveal type="match" stateTitle=<<toc-state>> text="open">
        <$macrocall $name="toc-selective-expandable" tag=<<currentTiddler>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<__exclude__>> path=<<__path__>>/>
      </$reveal>
    </li>
  </$set>
</$qualify>
\end

\define toc-unlinked-selective-expandable-body(tag,sort:"",itemClassFilter,exclude,path)
\whitespace trim
<$qualify name="toc-state" title={{{ [[$:/state/toc]addsuffix<__path__>addsuffix[-]addsuffix<currentTiddler>] }}}>
  <$set name="toc-item-class" filter=<<__itemClassFilter__>> emptyValue="toc-item-selected" value="toc-item">
    <li class=<<toc-item-class>>>
      <$list filter="[all[current]tagging[]$sort$] -[subfilter<__exclude__>] +[limit[1]]" variable="ignore" emptyMessage="""<$button class="tc-btn-invisible">{{$:/core/images/blank}}</$button><span class="toc-item-muted"><<toc-caption>></span>""">
        <$reveal type="nomatch" stateTitle=<<toc-state>> text="open">
          <$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep">
            <$transclude tiddler=<<toc-closed-icon>> />
            <<toc-caption>>
          </$button>
        </$reveal>
        <$reveal type="match" stateTitle=<<toc-state>> text="open">
          <$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep">
            <$transclude tiddler=<<toc-open-icon>> />
            <<toc-caption>>
          </$button>
        </$reveal>
      </$list>
      <$reveal type="match" stateTitle=<<toc-state>> text="open">
        <$macrocall $name="toc-selective-expandable" tag=<<currentTiddler>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<__exclude__>> path=<<__path__>>/>
      </$reveal>
    </li>
  </$set>
</$qualify>
\end

\define toc-selective-expandable-empty-message()
<$macrocall $name="toc-linked-selective-expandable-body" tag=<<tag>> sort=<<sort>> itemClassFilter=<<itemClassFilter>> exclude=<<excluded>> path=<<path>>/>
\end

\define toc-selective-expandable(tag,sort:"",itemClassFilter,exclude,path)
\whitespace trim
<$let __tag__={{{ [<__tag__>is[blank]then<currentTiddler>else<__tag__>] }}} tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> path={{{ [<__path__>addsuffix[/]addsuffix<__tag__>] }}}>
  <$set name="excluded" filter="[subfilter<__exclude__>] [<__tag__>]">
    <ol class="tc-toc toc-selective-expandable">
      <$list filter="""[all[shadows+tiddlers]tag<__tag__>!has[draft.of]$sort$] -[<__tag__>] -[subfilter<__exclude__>]""">
        <$list filter="[all[current]toc-link[no]]" variable="ignore" emptyMessage=<<toc-selective-expandable-empty-message>> >
          <$macrocall $name="toc-unlinked-selective-expandable-body" tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<excluded>> path=<<path>>/>
        </$list>
      </$list>
    </ol>
  </$set>
</$let>
\end

\define toc-tabbed-external-nav(tag,sort:"",selectedTiddler:"$:/temp/toc/selectedTiddler",unselectedText,missingText,template:"",exclude)
\whitespace trim
<$let __tag__={{{ [<__tag__>is[blank]then<currentTiddler>else<__tag__>] }}}>
  <$tiddler tiddler={{{ [<__selectedTiddler__>get[text]] }}}>
    <div class="tc-tabbed-table-of-contents">
      <$linkcatcher to=<<__selectedTiddler__>>>
        <div class="tc-table-of-contents">
          <$macrocall $name="toc-selective-expandable" tag=<<__tag__>> sort=<<__sort__>> itemClassFilter="[all[current]] -[<__selectedTiddler__>get[text]]" exclude=<<__exclude__>>/>
        </div>
      </$linkcatcher>
      <div class="tc-tabbed-table-of-contents-content">
        <$reveal stateTitle=<<__selectedTiddler__>> type="nomatch" text="">
          <$transclude mode="block" tiddler=<<__template__>>>
            <h1><<toc-caption>></h1>
            <$transclude mode="block">$missingText$</$transclude>
          </$transclude>
        </$reveal>
        <$reveal stateTitle=<<__selectedTiddler__>> type="match" text="">
          $unselectedText$
        </$reveal>
      </div>
    </div>
  </$tiddler>
</$let>
\end

\define toc-tabbed-internal-nav(tag,sort:"",selectedTiddler:"$:/temp/toc/selectedTiddler",unselectedText,missingText,template:"",exclude)
\whitespace trim
<$let __tag__={{{ [<__tag__>is[blank]then<currentTiddler>else<__tag__>] }}}>
  <$linkcatcher to=<<__selectedTiddler__>>>
    <$macrocall $name="toc-tabbed-external-nav" tag=<<__tag__>> sort=<<__sort__>> selectedTiddler=<<__selectedTiddler__>> unselectedText=<<__unselectedText__>> missingText=<<__missingText__>> template=<<__template__>> exclude=<<__exclude__>> />
  </$linkcatcher>
</$let>
\end
