From d6c4d0433bfbdab695da6af0f8a3435bd6f8554b Mon Sep 17 00:00:00 2001 From: Zshawn Syed Date: Thu, 25 Jun 2020 20:35:03 -0700 Subject: [PATCH] Add configuration to enable ordered list * Created new configuration option to enable ordered list through use_ordered_list input * Default behaviour is false so users will continue to have ul tags * Using existing class configuration, user can change styling on top ol tag and sub listing ol tags separately * No ability to update styling on sub-nested ol tags separately but code is open to this change * Added tests for new logic * Update README with example of usage and render --- README.md | 38 +++++++++++++ lib/table_of_contents/configuration.rb | 7 ++- lib/table_of_contents/parser.rb | 15 ++++- test/parser/test_ordered_list.rb | 76 ++++++++++++++++++++++++++ test/test_configuration.rb | 2 + test/test_helper.rb | 4 +- 6 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 test/parser/test_ordered_list.rb diff --git a/README.md b/README.md index e85fc30..a54e5de 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ - [Skip TOC Section](#skip-toc-section) - [CSS Styling](#css-styling) - [Custom CSS Class](#custom-css-class) + - [Using Unordered/Ordered lists](#using-unorderedordered-lists) ## Installation @@ -151,6 +152,7 @@ toc: sublist_class: '' item_class: toc-entry item_prefix: toc- + use_ordered_list: false ``` ## Customization @@ -245,3 +247,39 @@ toc: # Default is "toc-": item_prefix: item- ``` + +### Using Unordered/Ordered lists + +By default the table of contents will be generated as an unordered list via `` tags. This can be configured to use ordered lists instead `
    `. +This can be configured in `_config.yml`: + +```yml +toc: + use_ordered_list: true # default is false +``` + +In order to change the list type, use the [list-style-type](https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-type) css property. +Add a class to the `sublist_class` configuration to append it to the `ol` tags so that you can add the `list-style-type` property. + +Example + +```yml +toc: + use_ordered_list: true + list_class: my-list-class + sublist_class: my-sublist-class +``` + +```css +.my-list-class { + list-style-type: upper-alpha; +} + +.my-sublist-class: { + list-style-type: lower-alpha; +} +``` + +This will produce: + +![screenshot](https://user-images.githubusercontent.com/7675276/85813980-a0ea5a80-b719-11ea-9458-ccf9b86a778b.png) \ No newline at end of file diff --git a/lib/table_of_contents/configuration.rb b/lib/table_of_contents/configuration.rb index 7988402..298c02e 100644 --- a/lib/table_of_contents/configuration.rb +++ b/lib/table_of_contents/configuration.rb @@ -5,7 +5,8 @@ module TableOfContents # jekyll-toc configuration class class Configuration attr_reader :toc_levels, :no_toc_class, :no_toc_section_class, - :list_class, :sublist_class, :item_class, :item_prefix + :list_class, :sublist_class, :item_class, :item_prefix, + :use_ordered_list DEFAULT_CONFIG = { 'min_level' => 1, @@ -14,7 +15,8 @@ class Configuration 'list_class' => 'section-nav', 'sublist_class' => '', 'item_class' => 'toc-entry', - 'item_prefix' => 'toc-' + 'item_prefix' => 'toc-', + 'use_ordered_list' => false }.freeze def initialize(options) @@ -27,6 +29,7 @@ def initialize(options) @sublist_class = options['sublist_class'] @item_class = options['item_class'] @item_prefix = options['item_prefix'] + @use_ordered_list = options['use_ordered_list'] end private diff --git a/lib/table_of_contents/parser.rb b/lib/table_of_contents/parser.rb index 9b6ba3a..a33e0ba 100644 --- a/lib/table_of_contents/parser.rb +++ b/lib/table_of_contents/parser.rb @@ -8,6 +8,9 @@ module TableOfContents class Parser include ::Jekyll::TableOfContents::Helper + ORDERED_LIST_HTML_TAG = 'ol' + UNORDERED_LIST_HTML_TAG = 'ul' + def initialize(html, options = {}) @doc = Nokogiri::HTML::DocumentFragment.parse(html) @configuration = Configuration.new(options) @@ -19,7 +22,7 @@ def toc end def build_toc - %() + %(<#{list_tag} class="#{@configuration.list_class}">\n#{build_toc_list(@entries)}) end def inject_anchors_into_html @@ -74,7 +77,7 @@ def build_toc_list(entries) next_i = i + 1 if next_i < entries.count && entries[next_i][:h_num] > min_h_num nest_entries = get_nest_entries(entries[next_i, entries.count], min_h_num) - toc_list << %(\n\n#{build_toc_list(nest_entries)}\n) + toc_list << %(\n<#{list_tag}#{ul_attributes}>\n#{build_toc_list(nest_entries)}\n) i += nest_entries.count end # Add the closing tag for the current entry in the list @@ -121,6 +124,14 @@ def toc_headings_within(class_name) def ul_attributes @ul_attributes ||= @configuration.sublist_class.empty? ? '' : %( class="#{@configuration.sublist_class}") end + + def use_ordered_list? + @configuration.use_ordered_list + end + + def list_tag + use_ordered_list? ? ORDERED_LIST_HTML_TAG : UNORDERED_LIST_HTML_TAG + end end end end diff --git a/test/parser/test_ordered_list.rb b/test/parser/test_ordered_list.rb new file mode 100644 index 0000000..331b366 --- /dev/null +++ b/test/parser/test_ordered_list.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +require 'test_helper' + +class TestOrderedList < Minitest::Test + include TestHelpers + + def test_default_configuration + configuration = Jekyll::TableOfContents::Configuration.new({}) + + assert_equal configuration.use_ordered_list, false + end + + def test_disabled_ordered_list + configuration = Jekyll::TableOfContents::Configuration.new('use_ordered_list' => false) + + assert_equal configuration.use_ordered_list, false + end + + def test_enabled_ordered_list + configuration = Jekyll::TableOfContents::Configuration.new('use_ordered_list' => true) + + assert_equal configuration.use_ordered_list, true + end + + def test_basic_ordered_list_top_heading + parse_with_ordered_list + html = @parser.toc + + assert_match(/^
      /, html) + end + + def test_ordered_list_sub_headings + parse_with_ordered_list + html = @parser.toc + + assert_match(/
        \n
      1. /, html) + end + + def test_ordered_list_sub_headings_with_classes + parse_with_ordered_list_and_classes + html = @parser.toc + + assert_match(/
          /, html) + end + + def test_ordered_list_subheadings_with_classes_nested_structure + parse_with_ordered_list_and_classes + html = @parser.toc + + occurrences = html.scan(/
            /).count + + assert_equal occurrences, 5 + end + + private + + def parse_with_ordered_list + read_html_and_create_parser('use_ordered_list' => true) + end + + def parse_with_ordered_list_and_classes + read_html_and_create_parser( + 'use_ordered_list' => true, + 'list_class' => 'top-list-class', + 'sublist_class' => 'sublist-class' + ) + end +end \ No newline at end of file diff --git a/test/test_configuration.rb b/test/test_configuration.rb index caf16f0..032198a 100644 --- a/test/test_configuration.rb +++ b/test/test_configuration.rb @@ -12,6 +12,7 @@ def test_default_conf1guration assert_equal configuration.sublist_class, '' assert_equal configuration.item_class, 'toc-entry' assert_equal configuration.item_prefix, 'toc-' + assert_equal configuration.use_ordered_list, false end def test_type_error @@ -23,5 +24,6 @@ def test_type_error assert_equal configuration.sublist_class, '' assert_equal configuration.item_class, 'toc-entry' assert_equal configuration.item_prefix, 'toc-' + assert_equal configuration.use_ordered_list, false end end diff --git a/test/test_helper.rb b/test/test_helper.rb index d15e386..3faa4eb 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -20,7 +20,7 @@ HTML module TestHelpers - def read_html_and_create_parser - @parser = Jekyll::TableOfContents::Parser.new(SIMPLE_HTML) + def read_html_and_create_parser(options = {}) + @parser = Jekyll::TableOfContents::Parser.new(SIMPLE_HTML, options) end end