• Replacement routine for parseLists to allow for ordered/unordered multi-level lists

    By Gerry Riddell 1 decade ago

    Here is a replacement routine that I wrote. I am sure that it can be improved, so I would love to hear some feedback. It is pretty easy to implement, just replace old routine with the contents of the code listed below.

    Thanks to Ben for doing this! And thanks to Ralph for the table replacement routine, it was the starting point of my routine :-)

    I hope you enjoy it!

    • gerry.

      p.s. - I thought you could upload files, but I guess not, sorry for the long message!



      ' Gerry Riddell 15-Aug-2007: Multi-level List Support wrapper

      ' Supported formats are:

      ' UnOrdered Lists: -** <line item text>

      ' Ordered Lists: %-%%% <line item text>


      Public Function parseLists (txt As String) As String
      '** lines beginning with &quot;*&quot; are unordered bullet line items<br/>
      parseLists = parseMultiLists (txt, &quot;ul&quot;, &quot;*&quot;)<br/>
      '** lines beginning with &quot;%&quot; are ordered bullet line items<br/>
      parseLists = parseMultiLists (parseLists, &quot;ol&quot;, &quot;%&quot;)<br/>
      End Function

      ' Gerry Riddell 15-Aug-2007: Multi-level List Support main routine

      ' NOTE:

      ' 1) currently this is limited to three levels of lists

      ' 2) DO NOT mix and match ordered and unordered lists or you WILL get varying results

      ' with some twiddling you can get things to sometimes work, but use with caution



      ' 1) Allow unordered and ordered lists to interact nicely together

      ' 2) Allow unlimited levels of lists

      ' 3) Fix any efficiencies (like maybe the linebreak routine)


      Private Function parseMultiLists (txt As String, sTag As String, sBullet As String) As String
      Dim vInput As Variant<br/>
      Dim sValue As String<br/>
      Dim iLevel As Integer<br/>
      Dim i As Integer<br/>
      iLevel = 0<br/>
      ' Loop through input text line by line<br/>
      vInput = Split(txt, Chr(10))<br/>
      For i = Lbound(vInput) To Ubound(vInput)            <br/>
          If Left(vInput(i), 3) = Ustring(3, sBullet) Then<br/>
              vInput(i) = parseListItem (vInput(i), 3, iLevel, sTag)<br/>
              ' set the current level<br/>
              iLevel = 3<br/>
          Elseif Left(vInput(i), 2) = Ustring(2, sBullet) Then<br/>
              vInput(i) = parseListItem (vInput(i), 2, iLevel, sTag)<br/>
               ' set the current level<br/>
              iLevel = 2<br/>
          Elseif Left(vInput(i), 1) = sBullet Then<br/>
              vInput(i) = parseListItem (vInput(i), 1, iLevel, sTag)<br/>
                 ' set the current level<br/>
              iLevel = 1<br/>
                  ' No longer in list so close all levels, if needed<br/>
              If iLevel &gt; 0 Then<br/>
                  vInput(i) = vInput(i) &amp; parseListItem (&quot;&quot;, 0, iLevel, sTag)               <br/>
                     ' set the current level<br/>
                  iLevel = 0<br/>
              End If<br/>
          End If<br/>
      ' set up the various end of line conbinations so we can remove line breaks      <br/>
      Dim array1(5) As String<br/>
      Dim array2(5) As String<br/>
      array1(0) = &quot;&lt;/&quot; &amp; sTag &amp; &quot;&gt;&quot; &amp; Chr(10) &amp; &quot;&lt;&quot; &amp; sTag &amp; &quot;&gt;&quot;<br/>
      array1(1) = &quot;&lt;/li&gt;&quot; &amp; Chr(10) &amp; &quot;&lt;&quot; &amp; sTag &amp; &quot;&gt;&quot;<br/>
      array1(2) = &quot;&lt;/&quot; &amp; sTag &amp; &quot;&gt;&quot; &amp; Chr(10) &amp; &quot;&lt;li&gt;&quot;<br/>
      array1(3) = &quot;&lt;/li&gt;&quot; &amp; Chr(10) &amp; &quot;&lt;/&quot; &amp; sTag &amp; &quot;&gt;&quot;<br/>
      array1(4) = &quot;&lt;/&quot; &amp; sTag &amp; &quot;&gt;&quot; &amp; Chr(10) &amp; &quot;&lt;/li&gt;&quot;<br/>
      array1(5) = &quot;&lt;/li&gt;&quot; &amp; Chr(10) &amp; &quot;&lt;li&gt;&quot;<br/>
      array2(0) = &quot;&lt;/&quot; &amp; sTag &amp; &quot;&gt;&lt;&quot; &amp; sTag &amp; &quot;&gt;&quot;<br/>
      array2(1) = &quot;&lt;/li&gt;&lt;&quot; &amp; sTag &amp; &quot;&gt;&quot;<br/>
      array2(2) = &quot;&lt;/&quot; &amp; sTag &amp; &quot;&gt;&lt;li&gt;&quot;<br/>
      array2(3) = &quot;&lt;/li&gt;&lt;/&quot; &amp; sTag &amp; &quot;&gt;&quot; <br/>
      array2(4) = &quot;&lt;/&quot; &amp; sTag &amp; &quot;&gt;&lt;/li&gt;&quot;<br/>
      array2(5) = &quot;&lt;/li&gt;&lt;li&gt;&quot;<br/>
      ' Return string -- close list, if needed<br/>
      parseMultiLists = Implode(vInput, Chr(10))<br/>
      parseMultiLists = Replace(parseMultiLists, array1, array2)<br/>
      If iLevel &gt; 0 Then<br/>
          ' close the necessary list containers<br/>
          parseMultiLists = parseMultiLists &amp; parseListItem (&quot;&quot;, 0, iLevel, sTag)       <br/>
      End If<br/>
      End Function

      ' Gerry Riddell 15-Aug-2007: Multi-level List Support line item routine

      Private Function parseListItem (txt As String, newLevel As Integer, currLevel As Integer, tag As String) As String
      Dim i As Integer<br/>
      If newLevel &gt; currLevel Then<br/>
          ' create the necessary list containers<br/>
          For i = 1 To (newLevel-currLevel)<br/>
              parseListItem = parseListItem &amp; &quot;&lt;&quot; &amp; tag &amp; &quot;&gt;&quot;<br/>
      Elseif newLevel &lt; currLevel Then<br/>
          For i = 1 To (currLevel-newLevel)<br/>
              parseListItem = parseListItem &amp; &quot;&lt;/&quot; &amp; tag &amp; &quot;&gt;&quot;<br/>
      End If<br/>
      ' form the actual line entry <br/>
      If Len(txt) &gt; 0 Then<br/>
          parseListItem = parseListItem &amp; &quot;&lt;li&gt;&quot; &amp; Right(txt, Len(txt)-newLevel) &amp; &quot;&lt;/li&gt;&quot;<br/>
      End If<br/>
      End Function


    • An simplistic alternative ...

      By Dave Parillo 1 decade ago

      I honestly haven't had a chance to try out your solution, but here's the one I implemented. I didn't bother with numbered lists because given how infrequently we seem to use them, it just seemed easier to add <ol> to the safeHTML list.

      Replacement parse lists uses multiple *'s to indicate indenting level:

      Up to 10 levels are supported

      Private Function parseLists (txt As String) As String<br/>
          '** lines beginning with a * should be bullet lists - more *'s results in more indenting<br/>
          Dim i As Integer<br/>
          parseLists = doList (txt, 10)<br/>
          For i = 9 To 1 Step -1<br/>
              parseLists = doList (parseLists, i) <br/>
      End Function<br/>
        ' Create list items for each * found at the beginning of a line<br/>
         ' param txt           - the whole wiki page text<br/>
         ' param amount  - the number of bullets to search for<br/>
      Private Function doList (txt As String, amount As Integer) As String<br/>
          doList = ReplaceRangeEnds(txt, Chr(10) &amp; Ustring(amount, &quot;*&quot;), Chr(10), _<br/>
          Chr(10) &amp; &quot;&lt;li class='level&quot; &amp; amount &amp; &quot;'&gt;&quot; , &quot; &lt;/li&gt;&quot; &amp; Chr(10),  &quot;*&quot; , True) <br/>
          doList = ReplaceRangeEnds(doList, Chr(10) &amp; Ustring(amount, &quot;*&quot;), Chr(10), _<br/>
          &quot;&lt;li class='level&quot; &amp; amount &amp; &quot;'&gt;&quot; , &quot; &lt;/li&gt;&quot;,  Chr(10) , False)  <br/>
      End Function<br/>

      To style your lists add entries to your style sheet - you'll mostly want to set the margin-left and the list-style. For example:

      li {

      padding: 0;<br/>
      margin-bottom: 0;<br/>
      margin-left: 2em;<br/>
      list-style: square url(&quot;../webfiles/skin-monobook/$file/bullet.gif&quot;) outside;<br/>


      ul li.level1, li.level5, li.level9 {

      margin-left: 0em;<br/>
      list-style: square url(&quot;../webfiles/skin-monobook/$file/bullet.gif&quot;) outside;<br/>


      li.level2, li.level6, li.level10 {

      margin-left: 3em;<br/>
      list-style: circle none outside;<br/>


      li.level3, li.level7 {

      margin-left: 4em;<br/>
      list-style: disc none outside;<br/>


      li.level4, li.level8 {

      margin-left: 5em;<br/>
      list-style: square none outside;<br/>


      li.level5 { margin-left: 6em;}

      li.level6 { margin-left: 7em;}

      li.level7 { margin-left: 8em;}

      li.level8 { margin-left: 9em;}

      li.level9 { margin-left: 10em;}

      li.level10{ margin-left: 11em;}