jekyll_outline 1.2.5 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a31ba9e3b1f1b0962f5ac28695f41b2594acde555195fdcbbf0460fa220be66e
4
- data.tar.gz: bdd1e6536607a24271019aa3cc24e5de35e71b1ac4c61b925f286bb41dd5521c
3
+ metadata.gz: 88b2d41ecbd19787d53682b396bd2bbf9eabccf2ffa366026f4792079c3f827e
4
+ data.tar.gz: 44b1fbda200ea5c9a836538fc2f8e3565bef880b1dec9a77bedec513ef15f028
5
5
  SHA512:
6
- metadata.gz: e815455631865429afb66cfffce54187e4696e0ecb7e3571050ab98fa6991bd679791a212cdc9915b4e9a9d0c199bf6af0ca9d77a09babe89d7d5fa83a88fa4d
7
- data.tar.gz: bcc3910b01ca8d3c99ed101764350f17c95826f3b375733215f35659a6027605452881b528197709d1143b576c7c52cf2b51aad3971c1781b03b97c414f8d1dc
6
+ metadata.gz: 5d432be906fbe832e4db55e2333c969b7b9beda06b7c391a5f43b6cd13771646cd285847d13510678adc548db642fa3f3eb3d7521737d9e0b1f48f28eaffd991
7
+ data.tar.gz: 056b5a89bdbb45d9f56016f1fd17be96c7d7a6e000c5cefbfecad28c496e540c60bcf712a024107aa34e789f59dbefdcd09d9a096077e7955ea852ae3176c41d
data/.rubocop.yml CHANGED
@@ -1,4 +1,4 @@
1
- require:
1
+ plugins:
2
2
  # - rubocop-jekyll
3
3
  - rubocop-md
4
4
  - rubocop-performance
@@ -37,12 +37,18 @@ Metrics/BlockLength:
37
37
  - jekyll_plugin_support.gemspec
38
38
  Max: 30
39
39
 
40
+ Metrics/ClassLength:
41
+ Max: 150
42
+
40
43
  Metrics/CyclomaticComplexity:
41
44
  Max: 25
42
45
 
43
46
  Metrics/MethodLength:
44
47
  Max: 50
45
48
 
49
+ Metrics/ParameterLists:
50
+ Enabled: false
51
+
46
52
  Metrics/PerceivedComplexity:
47
53
  Max: 25
48
54
 
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Change Log
2
2
 
3
+ ## 1.3.0 / 2025-06-04
4
+
5
+ * Now relies on `jekyll_plugin_support` v3.1.0.
6
+ * Fixed missing </div>s.
7
+ * Reimplemented using nested classes, concluding with a call `to_s`
8
+ instead of implementing crazy nesting tracking.
9
+ * The `fields` parameter was renamed to `pattern`, however for compatibility, both parameter names are accepted.
10
+ If both are provided, `pattern` has priority.
11
+
12
+
13
+ ## 1.2.6 / 2025-01-03
14
+
15
+ * Added `exclude_from_outline` optional front matter YAML element.
16
+ * Ignores all files named `index`, regardless of file type.
17
+
18
+
3
19
  ## 1.2.5 / 2024-08-20
4
20
 
5
21
  * Added configurable error handling
data/README.md CHANGED
@@ -3,14 +3,194 @@
3
3
  `jekyll_outline` Jekyll tag plugin that creates a clickable table of contents.
4
4
 
5
5
 
6
+ ## Order
7
+
8
+ This plugin requires every page in a collection to have an entry for
9
+ <code>order</code> in its front matter.
10
+ The value of <code>order</code> must be an integer.
11
+ This entry is normally used for sorting the pages.
12
+
13
+ The front matter for [this page](https://mslinn.com/jekyll_plugins/jekyll_outline.html) is:
14
+
15
+ ```yaml
16
+ ---
17
+ categories: [Jekyll]
18
+ date: 2020-10-03
19
+ description: "Organizes the index of a collection into chapters."
20
+ last_modified_at: 2025-01-09
21
+ layout: jekyll
22
+ order: 100
23
+ title: <span class="code">jekyll_outline</span>
24
+ ---
25
+ ```
26
+
27
+
28
+ ## Examples
29
+
30
+ You can see this plugin in action in most of the index pages of [`mslinn.com`](https://mslinn.com).
31
+ Following is the source for two of them:
32
+
33
+ ### [Django / Oscar](https://mslinn.com/django/index.html)
34
+
35
+ This is the simplest possible outline, without images.
36
+
37
+ ```text
38
+ {% outline attribution django %}
39
+ 0: Django / Oscar Evaluation
40
+ 400: Notes
41
+ 800: Digging Deeper
42
+ 1900: Debugging
43
+ 2700: Production
44
+ {% endoutline %}
45
+ ```
46
+
47
+ ### [A/V Studio Technology](https://mslinn.com/av_studio/index.html)
48
+
49
+ This outline features images associated with specific entries.
50
+
51
+ ```html
52
+ {% outline attribution av_studio %}
53
+ 0: Production Infrastructure
54
+ 150: Audio
55
+ 200: Video
56
+ 300: RME TotalMix
57
+ 400: OBS Studio
58
+ 500: Pro Tools
59
+ 550: Ableton Live &amp; Push
60
+ 600: Other Music Software
61
+ 700: MIDI Hardware &amp; Software
62
+ 800: Davinci Resolve
63
+ 1000: Computer Analysis
64
+ 2000: Music Theory
65
+ 3000: Business
66
+ 4000: General
67
+ {% endoutline %}
68
+
69
+ <div style="display: none">
70
+ {% img
71
+ align="right"
72
+ class=""
73
+ id="outline_150"
74
+ src="/av_studio/images/everse8/everse8d.webp"
75
+ size="eighthsize"
76
+ style="margin-top: 0"
77
+ wrapper_class="clear"
78
+ %}
79
+ {% img
80
+ align="right"
81
+ class=""
82
+ id="outline_200"
83
+ src="./images/equipment/sony_a7iii/sony_a7iii.webp"
84
+ size="eighthsize"
85
+ style="margin-top: 0"
86
+ wrapper_class="clear"
87
+ %}
88
+ {% img
89
+ align="right"
90
+ class=""
91
+ id="outline_300"
92
+ src="./images/rme/rme_logo.webp"
93
+ size="eighthsize"
94
+ style="margin-top: 0"
95
+ wrapper_class="clear"
96
+ %}
97
+ {% img
98
+ align="right"
99
+ class=""
100
+ id="outline_400"
101
+ src="./images/obsStudio/obs_logo.webp"
102
+ size="eighthsize"
103
+ style="margin-top: 0"
104
+ wrapper_class="clear"
105
+ %}
106
+ {% img
107
+ align="right"
108
+ class=""
109
+ id="outline_500"
110
+ src="./images/proTools/proToolsLogo.webp"
111
+ size="eighthsize"
112
+ style="margin-top: 0"
113
+ wrapper_class="clear"
114
+ %}
115
+ {% img
116
+ align="right"
117
+ class=""
118
+ id="outline_550"
119
+ src="./images/ableton/ableton_live_logo.webp"
120
+ size="eighthsize"
121
+ style="margin-top: 0"
122
+ wrapper_class="clear"
123
+ %}
124
+ {% img
125
+ align="right"
126
+ class="rounded"
127
+ id="outline_600"
128
+ src="./images/music21.webp"
129
+ size="eighthsize"
130
+ style="margin-top: 0"
131
+ wrapper_class="clear"
132
+ %}
133
+ {% img
134
+ align="right"
135
+ class=""
136
+ id="outline_700"
137
+ src="./images/midi/MIDI_logo.webp"
138
+ size="eighthsize"
139
+ style="margin-top: 0"
140
+ wrapper_class="clear"
141
+ %}
142
+ {% img
143
+ align="right"
144
+ class=""
145
+ id="outline_800"
146
+ src="./images/davinci_resolve/daVinci_resolve_logo.webp"
147
+ size="eighthsize"
148
+ style="margin-top: 0"
149
+ wrapper_class="clear"
150
+ %}
151
+ {% img
152
+ align="right"
153
+ class="rounded"
154
+ id="outline_2000"
155
+ src="./images/music_theory.webp"
156
+ size="eighthsize"
157
+ style="margin-top: 0"
158
+ wrapper_class="clear"
159
+ %}
160
+ {% img
161
+ align="right"
162
+ class=""
163
+ id="outline_4000"
164
+ src="./images/handsfree/pageflip_firefly.webp"
165
+ size="eighthsize"
166
+ style="margin-top: 0"
167
+ wrapper_class="clear"
168
+ %}
169
+ </div>
170
+
171
+ {% outline_js wrap_in_script_tag %}
172
+ ```
173
+
174
+
6
175
  ## Usage
7
176
 
8
- These examples are taken from [`demo/index.html`](demo/index.html).
177
+ All files in a collection are included in the outline,
178
+ except for those whose name starts with `index`,
179
+ and those with the following in their front matter:
180
+
181
+ ```yaml
182
+ exclude_from_outline: true
183
+ ```
184
+
185
+ Note that Jekyll requires all documents in a collection to have a value for `order` in their front matter.
186
+ This value is ignored by `outline_tag` if `exclude_from_outline` has a truthy value.
9
187
 
10
- Sort by `order` field:
188
+ The following examples are taken from [`demo/index.html`](demo/index.html).
189
+
190
+ Sort by the `order` field:
11
191
 
12
192
  ```html
13
- {% outline attribution fields="<b> title </b> &ndash; <i> description </i>" stuff %}
193
+ {% outline attribution pattern="<b> title </b> &ndash; <i> description </i>" stuff %}
14
194
  000: A Topic 0..19
15
195
  020: A Topic 20..39
16
196
  040: A Topic 40..
@@ -20,7 +200,7 @@ Sort by `order` field:
20
200
  Sort by `title` field:
21
201
 
22
202
  ```html
23
- {% outline attribution sort_by_title fields="<b> title </b> &ndash; <i> description </i>" stuff %}
203
+ {% outline attribution sort_by_title pattern="<b> title </b> &ndash; <i> description </i>" stuff %}
24
204
  000: B Topic 0..19
25
205
  020: B Topic 20..39
26
206
  040: B Topic 40..
@@ -51,21 +231,21 @@ By default, each displayed entry consists of a document title,
51
231
  wrapped within an &lt;a href&gt; HTML tag that links to the page for that entry,
52
232
  followed by an indication of whether the document is visible (a draft) or not.
53
233
 
54
- Entry can also include following fields:
234
+ Entry can also include following pattern:
55
235
  `draft`, `categories`, `description`, `date`, `last_modified` or `last_modified_at`, `layout`, `order`, `title`, `slug`,
56
- `ext`, `tags`, and `excerpt`.
236
+ `ext`, and `tags`.
57
237
 
58
- Specify the fields like this:
238
+ Specify the pattern like this:
59
239
 
60
240
  ```html
61
- {% outline fields="title &ndash; <i> description </i>" %}
241
+ {% outline pattern="title &ndash; <i> description </i>" %}
62
242
  000: Topic 0..19
63
243
  020: Topic 20..39
64
244
  040: Topic 40..
65
245
  {% endoutline %}
66
246
  ```
67
247
 
68
- Words that are not a known field are transcribed into the output.
248
+ Words in the `pattern` argument that are not recognized as a field are transcribed into the output.
69
249
 
70
250
  In the above example, notice that the HTML is space delimited from the field names.
71
251
  The parser is simple and stupid: each token is matched against the known keywords.
@@ -75,21 +255,14 @@ Tokens are separated by white space.
75
255
  ### CSS
76
256
 
77
257
  The CSS used for the demo website should be copied to your project.
78
- See the sections of
79
- [`demo/assets/css/styles.css`](/mslinn/jekyll_outline/blob/master/demo/assets/css/style.css#L252-L315) as shown:
258
+ See [`demo/assets/css/jekyll_outline.css`](https://github.com/mslinn/jekyll_outline/blob/master/demo/assets/css/jekyll_outline.css).
80
259
 
81
- ```css
82
- /* Start of jekyll_plugin_support css */
83
- ... copy this portion ...
84
- /* End of jekyll_plugin_support css */
85
-
86
- /* Start of jekyll_outline css */
87
- ... copy this portion ...
88
- /* End of jekyll_outline css */
89
- ```
90
260
 
91
261
  ### JavaScript
92
262
 
263
+ Copy [`jekyll_outline.js`](https://github.com/mslinn/jekyll_outline/blob/master/demo/assets/js/jekyll_outline.js)
264
+ to your Jekyll website's JavaScript directory.
265
+
93
266
  This project's `outline_js` tag returns the Javascript necessary to position images relating to the outline.
94
267
  If used without parameters it just returns the JavaScript.
95
268
  Use the tag this way:
@@ -153,6 +326,8 @@ and have `id`s that correspond to outline sections.
153
326
  Each of following image's `id`s have an `outline_` prefix, followed by a number, which corresponds to one of the sections.
154
327
  Note that leading zeros in the first column above are not present in the `id`s below.
155
328
 
329
+ Headings that do not have corresponding pages are not displayed.
330
+
156
331
  If you want to provide images to embed at appropriate locations within the outline,
157
332
  wrap them within an invisible `div` so the web page does not jump around as the images are loaded.
158
333
 
@@ -3,8 +3,8 @@ require_relative 'lib/jekyll_outline/version'
3
3
  Gem::Specification.new do |spec|
4
4
  github = 'https://github.com/mslinn/jekyll_outline'
5
5
 
6
- spec.authors = ['Mike Slinn']
7
- spec.bindir = 'exe'
6
+ spec.authors = ['Mike Slinn']
7
+ spec.bindir = 'exe'
8
8
  spec.description = <<~END_OF_DESC
9
9
  Jekyll tag plugin that creates a clickable table of contents.
10
10
  END_OF_DESC
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
14
14
  'demo/assets/js/jekyll_outline.js'
15
15
  ]
16
16
  spec.homepage = 'https://www.mslinn.com/jekyll_plugins/jekyll_outline.html'
17
- spec.license = 'MIT'
17
+ spec.license = 'MIT'
18
18
  spec.metadata = {
19
19
  'allowed_push_host' => 'https://rubygems.org',
20
20
  'bug_tracker_uri' => "#{github}/issues",
@@ -22,19 +22,20 @@ Gem::Specification.new do |spec|
22
22
  'homepage_uri' => spec.homepage,
23
23
  'source_code_uri' => github,
24
24
  }
25
- spec.name = 'jekyll_outline'
25
+ spec.name = 'jekyll_outline'
26
+ spec.platform = Gem::Platform::RUBY
26
27
  spec.post_install_message = <<~END_MESSAGE
27
28
 
28
29
  Thanks for installing #{spec.name}!
29
30
 
30
31
  END_MESSAGE
31
- spec.require_paths = ['lib']
32
+ spec.require_paths = ['lib']
32
33
  spec.required_ruby_version = '>= 2.6.0'
33
- spec.summary = 'Jekyll tag plugin that creates a clickable table of contents.'
34
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
35
- spec.version = JekyllOutlineVersion::VERSION
34
+ spec.summary = 'Jekyll tag plugin that creates a clickable table of contents.'
35
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
36
+ spec.version = JekyllOutlineVersion::VERSION
36
37
 
37
- spec.add_dependency 'jekyll', '>= 3.5.0'
38
- spec.add_dependency 'jekyll_draft', '>= 2.0.2'
39
- spec.add_dependency 'jekyll_plugin_support', '>= 1.0.2'
38
+ spec.add_dependency 'jekyll', '>= 4.4.0'
39
+ spec.add_dependency 'jekyll_draft', '>= 3.0.0'
40
+ spec.add_dependency 'jekyll_plugin_support', '>= 3.1.0'
40
41
  end
@@ -1,3 +1,3 @@
1
1
  module JekyllOutlineVersion
2
- VERSION = '1.2.5'.freeze
2
+ VERSION = '1.3.0'.freeze
3
3
  end
data/lib/outline_tag.rb CHANGED
@@ -1,79 +1,51 @@
1
- # @author Copyright 2022 {https://www.mslinn.com Michael Slinn}
2
-
3
1
  require 'jekyll_draft'
4
2
  require 'jekyll_plugin_logger'
5
3
  require 'jekyll_plugin_support'
6
- require 'yaml'
7
4
  require_relative 'jekyll_outline/version'
5
+ require_relative 'structure/outline'
6
+ require_relative 'structure/yaml_parser'
8
7
 
9
- # This class generates output of the form, where NNN is an order value:
10
- # <div class="outer_posts">
11
- # <h3 class="post_title clear" id="title_0">Django / Oscar Evaluation</h3>
12
- # <div id="posts_wrapper_0" class="clearfix">
13
- # <div id="posts_0" class="posts">
14
- # <span>2021-02-11</span> <span><a href="/collection/page1.html">Title 1</a></span>
15
- # <span>2023-12-09</span> <span><a href="/collection/page2.html">Title 2</a></span>
16
- # </div>
17
- # <h3 class="post_title clear" id="title_NNN">Notes</h3>
18
- # <div id="posts_wrapper_NNN" class="clearfix">
19
- # <div id="posts_400" class="posts">
20
- # <span>2021-04-14</span> <span><a href="/collection/page3.html">Title 3</a></span>
21
- # <span>2021-03-29</span> <span><a href="/collection/page4.html">Title 4</a></span>
22
- # </div>
23
- # </div>
24
- # <div id="jps_attribute_570007" class="jps_attribute">
25
- # <div>
26
- # <a href="https://www.mslinn.com/jekyll_plugins/jekyll_outline.html" target="_blank" rel="nofollow">
27
- # Generated by the jekyll_outline v1.2.1 Jekyll plugin, written by Mike Slinn 2024-01-09.
28
- # </a>
29
- # </div>
30
- # </div>
31
- # </div>
32
- # </div>
33
- #
34
- # Subclasses, such as jekyll_toc.rb, might generate other output.
35
-
8
+ # See spec/outline_spec for an example of HTML output.
36
9
  module JekyllSupport
37
10
  PLUGIN_NAME = 'outline'.freeze
38
- OutlineError = JekyllSupport.define_error
39
-
40
- # Interleaves with docs
41
- # Duck type compatible with Jekyll doc
42
- class Header
43
- attr_accessor :order, :title
44
-
45
- def initialize(yaml)
46
- @order = yaml[0]
47
- @published = true
48
- @title = yaml[1]
49
- end
50
11
 
51
- def to_s
52
- " <h3 class='post_title clear' id=\"title_#{@order}\">#{@title}</h3>"
53
- end
54
- end
12
+ OutlineError = JekyllSupport.define_error
55
13
 
56
- class OutlineTag < JekyllBlock # rubocop:disable Metrics/ClassLength
14
+ class OutlineTag < JekyllBlock
57
15
  include JekyllOutlineVersion
58
16
 
59
- FIXNUM_MAX = (2**((0.size * 8) - 2)) - 1
60
-
61
17
  def render_impl(text)
62
- headers = make_headers(super) # Process the block content.
18
+ block_content = super # Process the block content.
63
19
 
64
- @helper.gem_file __FILE__
20
+ @helper.gem_file __FILE__ # For attribution
65
21
 
66
22
  @die_on_outline_error = @tag_config['die_on_outline_error'] == true if @tag_config
67
23
  @pry_on_outline_error = @tag_config['pry_on_outline_error'] == true if @tag_config
68
24
 
69
- @fields = @helper.parameter_specified?('fields')&.split || ['title']
70
- @sort_by = @helper.parameter_specified?('sort_by_title') ? 'title' : 'order'
71
- @collection_name = @helper.remaining_markup
72
- raise OutlineError, 'collection_name was not specified' unless @collection_name
73
-
74
- @docs = obtain_docs(@collection_name)
75
- collection = headers + @docs
76
- render_outline collection
25
+ pattern = @helper.parameter_specified?('pattern')&.split ||
26
+ @helper.parameter_specified?('fields')&.split ||
27
+ ['title']
28
+ sort_by = @helper.parameter_specified?('sort_by_title') ? :title : :order
29
+ collection_name = @helper.remaining_markup
30
+ raise OutlineError, 'collection_name was not specified' unless collection_name
31
+
32
+ outline_options = OutlineOptions.new(
33
+ attribution: @attribution,
34
+ collection_name: collection_name,
35
+ enable_attribution: @attribution,
36
+ pattern: pattern,
37
+ sort_by: sort_by
38
+ )
39
+ yaml_parser = YamlParser.new outline_options, block_content
40
+ outline = Outline.new(outline_options: outline_options)
41
+ outline.add_sections yaml_parser.sections
42
+
43
+ abort "#{collection_name} is not a valid collection." unless @site.collections&.key?(collection_name)
44
+ docs = @site
45
+ .collections[collection_name]
46
+ .docs
47
+ outline.add_entries(collection_apages(docs))
48
+ outline.to_s
77
49
  rescue OutlineError => e # jekyll_plugin_support handles StandardError
78
50
  @logger.error { JekyllPluginHelper.remove_html_tags e.logger_message }
79
51
  binding.pry if @pry_on_outline_error # rubocop:disable Lint/Debugger
@@ -82,173 +54,16 @@ module JekyllSupport
82
54
  e.html_message
83
55
  end
84
56
 
85
- # Overload this for a subclass
86
- def render_outline(collection)
87
- <<~HEREDOC
88
- <div class="outer_posts">
89
- #{make_entries collection}
90
- </div>
91
- #{@helper.attribute if @helper.attribution}
92
- HEREDOC
93
- end
94
-
95
- def open_head; end
96
-
97
57
  private
98
58
 
99
- def header?(variable)
100
- variable.instance_of?(Header)
101
- end
102
-
103
- def make_headers(content)
104
- content = remove_leading_zeros remove_leading_spaces content
105
- yaml = YAML.safe_load content
106
- yaml.map { |entry| Header.new entry }
107
- rescue NoMethodError => e
108
- raise OutlineError, <<~END_MSG
109
- Invalid YAML within {% outline %} tag. The offending content was:
110
-
111
- <pre>#{content}</pre>
112
- END_MSG
113
- rescue Psych::SyntaxError => e
114
- msg = <<~END_MSG
115
- Invalid YAML found within {% outline %} tag:<br>
116
- <pre>#{e.message}</pre>
117
- END_MSG
118
- @logger.error { e.message }
119
- raise OutlineError, msg
120
- end
121
-
122
- # @section_state can have values: :head, :in_body
123
- # @param collection Array of Jekyll::Document and JekyllSupport::Header
124
- # @return Array of String
125
- def make_entries(collection)
126
- sorted = if @sort_by == 'order'
127
- collection.sort_by(&obtain_order)
128
- else
129
- collection.sort_by(&obtain_field)
130
- end
131
- pruned = remove_empty_headers sorted
132
- @section_state = :head
133
- @section_id = 0
134
- result = pruned.map do |entry|
135
- handle entry
136
- end
137
- result << " </div>\n </div>" if @section_state == :in_body # Modify this for TOC
138
- result&.join("\n")
139
- end
140
-
141
- KNOWN_FIELDS = %w[draft categories description date last_modified_at layout order title slug ext tags excerpt].freeze
142
-
143
- def handle(entry)
144
- if entry.instance_of? Header
145
- @header_order = entry.order
146
- section_end = " </div>\n" if @section_state == :in_body
147
- @section_state = :head
148
- entry = section_end + entry.to_s if section_end
149
- entry
150
- else
151
- if @section_state == :head
152
- section_start = <<~ENDTEXT # Modify this for TOC
153
- <div id="posts_wrapper_#{@header_order}" class='clearfix'>
154
- <div id="posts_#{@header_order}" class='posts'>
155
- ENDTEXT
156
- end
157
- @section_state = :in_body
158
- date = entry.data['last_modified_at'] # "%Y-%m-%d"
159
- draft = Jekyll::Draft.draft_html(entry)
160
- visible_line = handle_entry entry
161
- result = " <span>#{date}</span> <span><a href='#{entry.url}'>#{visible_line.strip}</a>#{draft}</span>" # Modify this for TOC
162
- result = section_start + result if section_start
163
- result
164
- end
165
- end
166
-
167
- def handle_entry(entry)
168
- result = ''
169
- @fields.each do |field|
170
- if KNOWN_FIELDS.include? field
171
- if entry.data.key? field
172
- result += "#{entry.data[field]} "
173
- else
174
- @logger.warn { "#{field} is a known field, but it was not present in entry #{entry}" }
175
- end
176
- else
177
- result += "#{field} "
178
- end
179
- end
180
- result
181
- end
182
-
183
- # Find the given document
184
- def obtain_doc(doc_name)
185
- abort "#{@collection_name} is not a valid collection." unless @site.collections.key? @collection_name
186
- @site
187
- .collections[@collection_name]
188
- .docs
189
- .find { |doc| doc.path.end_with? "#{doc_name}.html" }
190
- end
191
-
192
- # Ignores files called index.html
193
- def obtain_docs(collection_name)
194
- abort "#{@collection_name} is not a valid collection." unless @site.collections.key? @collection_name
195
- @site
196
- .collections[collection_name]
197
- .docs
198
- .reject { |doc| doc.path.end_with? 'index.html' }
199
- end
200
-
201
- # Sort entries within the outline tag which do not have the property specified by @sort_by at the end
202
- def obtain_field
203
- sort_by = @sort_by.to_s
204
- proc do |entry|
205
- if entry.respond_to? :data # page
206
- entry.data.key?(sort_by) ? entry.data[sort_by] || 'zzz' : 'zzz'
207
- else # heading
208
- entry.respond_to?(sort_by) ? entry.send(sort_by) || 'zzz' : 'zzz'
209
- end
210
- end
211
- end
212
-
213
- # Sort entries within the outline tag which do not have an order property at the end
214
- def obtain_order
215
- proc do |entry|
216
- if entry.respond_to? :data # page
217
- entry.data.key?('order') ? entry.data['order'] || FIXNUM_MAX : FIXNUM_MAX
218
- else # heading
219
- entry.order || FIXNUM_MAX
220
- end
221
- end
222
- end
223
-
224
- def remove_empty_headers(array)
225
- i = 0
226
- while i < array.length - 1
227
- if header?(array[i]) && header?(array[i + 1])
228
- array.delete_at(i)
229
- else
230
- i += 1
231
- end
232
- end
233
-
234
- array.delete_at(array.length - 1) if header?(array.last)
235
- array
236
- end
237
-
238
- def remove_leading_spaces(multiline)
239
- multiline
240
- .strip
241
- .split("\n")
242
- .map { |x| x.gsub(/\A\s+/, '') }
243
- .join("\n")
244
- end
245
-
246
- def remove_leading_zeros(multiline)
247
- multiline
248
- .strip
249
- .split("\n")
250
- .map { |x| x.gsub(/(?<= |\A)0+(?=\d)/, '') }
251
- .join("\n")
59
+ # Returns an APage for each document in the collection with the given named.
60
+ # Ignores files whose name starts with `index`,
61
+ # and those with the following in their front matter:
62
+ # exclude_from_outline: true
63
+ def collection_apages(pages)
64
+ pages
65
+ .reject { |doc| doc.url.match(/index(.\w*)?$/) || doc.data['exclude_from_outline'] }
66
+ .map { |x| ::JekyllSupport::APage.new(x, 'collection') if x }
252
67
  end
253
68
 
254
69
  JekyllPluginHelper.register(self, PLUGIN_NAME)
@@ -0,0 +1,46 @@
1
+ # Enriches JekyllSupport.APage
2
+ module JekyllSupport
3
+ KNOWN_FIELDS = %w[draft categories description date last_modified_at layout order title slug ext tags excerpt].freeze
4
+
5
+ # Overrides definition from `jekyll_plugin_support`
6
+ class APage
7
+ def render_outline_apage(pattern)
8
+ <<~END_ENTRY
9
+ <span>#{@last_modified.strftime('%Y-%m-%d')}</span>
10
+ <span><a href='#{@url}'>#{render_entry_details pattern}</a>#{@draft}</span>
11
+ END_ENTRY
12
+ end
13
+
14
+ # @param pattern can either be a String or [String]
15
+ # Renders a section entry as a string
16
+ # Recognized tokens are looked up, otherwise they are incorporated into the output
17
+ # Currently spaces are the only valid delimiters; HTML tags should be tokenized even when not delimited by spaces
18
+ def render_entry_details(pattern)
19
+ result = ''
20
+ fields = case pattern
21
+ when String
22
+ pattern.split
23
+ when Array
24
+ pattern
25
+ else
26
+ @logger.error { "Pattern is neither a String nor an Array (#{pattern})" }
27
+ end
28
+ fields.each do |field|
29
+ if KNOWN_FIELDS.include? field
30
+ if respond_to? field
31
+ value = send field
32
+ result += "#{value} "
33
+ elsif data.key?(field.to_sym) || data.key?(field.to_s)
34
+ value = data[field.to_sym] || data[field.to_s]
35
+ result += "#{value} "
36
+ else
37
+ @logger.warn { "'#{field}' is a known field, but it was not present in apage with url '#{@url}'." }
38
+ end
39
+ else
40
+ result += "#{field} "
41
+ end
42
+ end
43
+ result
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,156 @@
1
+ require 'jekyll_plugin_support'
2
+ require_relative 'section'
3
+
4
+ module JekyllSupport
5
+ # @param attribution sets the attribution message
6
+ # @param enable_attribution causes the attribution message to be displayed if truthy
7
+ # @param collection_name Name of the Jekyll collection the outline is organizing
8
+ # @param pattern String containing keyswords and literals; interpreted and displayed when an APage is rendered as a topic entry
9
+ # @param sort_by Either has value :order or :title
10
+ class OutlineOptions
11
+ attr_accessor :attribution, :enable_attribution, :collection_name, :logger, :pattern, :sort_by
12
+
13
+ def initialize(
14
+ collection_name: '_posts',
15
+ attribution: '',
16
+ enable_attribution: false,
17
+ logger: PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config),
18
+ pattern: '<b> title </b> &ndash; <i> description </i>',
19
+ sort_by: :order
20
+ )
21
+ @attribution = attribution
22
+ @enable_attribution = enable_attribution
23
+ @collection_name = collection_name
24
+ @logger = logger
25
+ @pattern = pattern
26
+ @sort_by = sort_by
27
+ end
28
+ end
29
+
30
+ class Outline
31
+ attr_reader :logger, :options, :sections
32
+
33
+ # Sort all entries first so they are iteratable according to the desired order.
34
+ # This presorts the entries for each section.
35
+ #
36
+ # If options[:sort_by] == :order then place each APage into it's appropriate section.
37
+ # Otherwise place all entries into one section.
38
+ #
39
+ # options[:pattern] defaults to ['title'], but might be something like
40
+ # ["<b>", "title", "</b>", "&ndash;", "<i>", "description", "</i>"]
41
+ def initialize(outline_options: OutlineOptions.new)
42
+ @add_sections_called = false
43
+ @options = outline_options
44
+
45
+ @logger = @options.logger
46
+ @sections = @options.sort_by == :order ? [] : [Section.new(@options, [0, ''])]
47
+ rescue StandardError => e
48
+ error_short_trace @logger, e
49
+ end
50
+
51
+ def add_entries(apages)
52
+ sorted_apages = make_entries sort apages
53
+ sorted_apages.each { |apage| add_apage apage }
54
+ self
55
+ end
56
+
57
+ def add_section(section)
58
+ return unless @options.sort_by == :order
59
+
60
+ @sections << section
61
+ self
62
+ end
63
+
64
+ def add_sections(sections)
65
+ sections.each { |x| add_section x }
66
+ @add_sections_called = true
67
+ self
68
+ end
69
+
70
+ def make_entries(docs)
71
+ docs.map do |doc|
72
+ draft = Jekyll::Draft.draft_html doc
73
+ JekyllSupport.apage_from(
74
+ date: doc.date,
75
+ description: doc.description,
76
+ draft: draft,
77
+ last_modified: doc.last_modified,
78
+ order: doc.order,
79
+ title: doc.title,
80
+ url: doc.url
81
+ )
82
+ end
83
+ end
84
+
85
+ # @param apages [APage]
86
+ # @return muliline String
87
+ def sort(apages)
88
+ if @options.sort_by == :order
89
+ apages.sort_by(&:order)
90
+ else
91
+ apages.sort_by { |apage| sort_property_value apage }
92
+ end
93
+ end
94
+
95
+ def to_s
96
+ return '' unless @sections&.count&.positive?
97
+
98
+ result = []
99
+ result << "<div class='outer_posts'>"
100
+ result << (@sections.map { |section| " #{section}" })
101
+ result << '</div>'
102
+ result << @options.attribution if @options.enable_attribution
103
+ result.join "\n"
104
+ end
105
+
106
+ private
107
+
108
+ def add_apage(apage)
109
+ unless apage
110
+ raise ::OutlineError, 'add_apage called with nil apage'
111
+ puts
112
+ end
113
+ raise ::OutlineError, 'add_apage called without first calling add_sections' unless @add_sections_called
114
+
115
+ section = section_for apage
116
+ section.add_child apage
117
+ end
118
+
119
+ def default_sort_value(sort_by)
120
+ case sort_by
121
+ when :date, :last_modified, :last_modified_at
122
+ Date.today
123
+ else
124
+ ''
125
+ end
126
+ end
127
+
128
+ # Obtain sort property value from APage instance, or return a default value
129
+ def sort_property_value(apage)
130
+ sort_by = @options.sort_by.to_s
131
+ if apage.data.key?(sort_by)
132
+ apage.data[sort_by] || default_sort_value(sort_by)
133
+ else
134
+ default_sort_value(sort_by)
135
+ end
136
+ end
137
+
138
+ # Only called when entries are organized into multiple sections
139
+ # @param apage must have a property called `order`
140
+ def section_for(apage)
141
+ return @sections.first if @sections.count == 1
142
+
143
+ last = @sections.length - 1
144
+ (0..last).each do |i|
145
+ return @sections.last if i == last
146
+
147
+ page_order = apage.order
148
+ this_section = @sections[i]
149
+ next_section = @sections[i + 1]
150
+ return this_section if (page_order >= this_section.order) && (page_order < next_section.order)
151
+ end
152
+ @sections.last
153
+ # raise OutlineError, "No Section found for APage #{apage}"
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,38 @@
1
+ require_relative 'a_page_enrichment'
2
+
3
+ module JekyllSupport
4
+ class Section
5
+ attr_accessor :children, :title, :order
6
+
7
+ def initialize(outline_options, parameter_array)
8
+ @outline_options = outline_options
9
+ @order = parameter_array[0].to_i
10
+ @title = parameter_array[1]
11
+ @children = []
12
+ end
13
+
14
+ def add_child(child)
15
+ @children << child
16
+ end
17
+
18
+ def to_s
19
+ return '' if @children.count.zero?
20
+
21
+ unless @children.first.instance_of?(JekyllSupport::APage)
22
+ raise "First child of Section was a #{@children.first.class}, not an APage"
23
+ end
24
+ apages = @children
25
+ .map { |x| x.render_outline_apage @outline_options.pattern }
26
+ .join("\n ")
27
+
28
+ <<~END_SECTION
29
+ <h3 class='post_title clear' id="title_#{@order}">#{@title}</h3>
30
+ <div id='posts_wrapper_#{@order}' class='clearfix'>
31
+ <div id="posts_#{@order}" class='posts'>
32
+ #{apages}
33
+ </div>
34
+ </div>
35
+ END_SECTION
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,58 @@
1
+ require 'yaml'
2
+ require_relative 'section'
3
+
4
+ class OutlineError < StandardError; end
5
+
6
+ module JekyllSupport
7
+ class YamlParser
8
+ attr_reader :sections
9
+
10
+ # @return array of empty Sections
11
+ def initialize(outline_options, content = '')
12
+ @logger = outline_options.logger
13
+ @sections = if content && !content.strip.empty?
14
+ parse_sections outline_options, content
15
+ else
16
+ []
17
+ end
18
+ end
19
+
20
+ # @return Array of Sections that do not contain children
21
+ def parse_sections(outline_options, content)
22
+ content = remove_leading_zeros remove_leading_spaces content
23
+ yaml = YAML.safe_load content
24
+ yaml.map { |entry| Section.new outline_options, entry }
25
+ rescue NoMethodError => e
26
+ raise OutlineError, <<~END_MSG
27
+ Invalid YAML within {% outline %} tag. The offending content was:
28
+
29
+ <pre>#{content}</pre>
30
+ END_MSG
31
+ rescue Psych::SyntaxError => e
32
+ msg = <<~END_MSG
33
+ Invalid YAML found within {% outline %} tag:<br>
34
+ <pre>#{e.message}</pre>
35
+ END_MSG
36
+ @logger.error { e.message }
37
+ raise OutlineError, msg
38
+ end
39
+
40
+ private
41
+
42
+ def remove_leading_spaces(multiline)
43
+ multiline
44
+ .strip
45
+ .split("\n")
46
+ .map { |x| x.gsub(/\A\s+/, '') }
47
+ .join("\n")
48
+ end
49
+
50
+ def remove_leading_zeros(multiline)
51
+ multiline
52
+ .strip
53
+ .split("\n")
54
+ .map { |x| x.gsub(/(?<= |\A)0+(?=\d)/, '') }
55
+ .join("\n")
56
+ end
57
+ end
58
+ end
data/spec/outline_spec.rb CHANGED
@@ -1,10 +1,152 @@
1
- require 'jekyll'
2
- require_relative '../lib/jekyll_outline'
1
+ require 'jekyll_plugin_support'
2
+ require 'rspec/match_ignoring_whitespace'
3
+ require_relative 'spec_helper'
4
+ require_relative '../lib/structure/outline'
3
5
 
4
- RSpec.describe(OutlineTag) do
5
- include Jekyll
6
+ RSpec.describe(JekyllSupport) do
7
+ outline_options = JekyllSupport::OutlineOptions.new(pattern: '<b> title </b> &ndash; <i> description </i>')
8
+ section1 = described_class::Section.new(outline_options, [0, 'Section 1'])
9
+ section2 = described_class::Section.new(outline_options, [3, 'Section 2'])
6
10
 
7
- it 'never works first time', skip: 'Just a placeholder' do
8
- expect(true).to be_truthy
11
+ apages = [
12
+ described_class.apage_from(
13
+ collection_name: '_posts',
14
+ date: '2023-01-01',
15
+ description: 'This is the entry1 description.',
16
+ draft: true,
17
+ last_modified: '2023-01-01',
18
+ order: 1,
19
+ title: 'Entry 1',
20
+ url: 'https://example.com/entry1'
21
+ ),
22
+ described_class.apage_from(
23
+ collection_name: '_posts',
24
+ date: '2023-01-02',
25
+ description: 'This is the entry2 description.',
26
+ last_modified: '2023-01-02',
27
+ order: 2,
28
+ title: 'Entry 2',
29
+ url: 'https://example.com/entry2'
30
+ ),
31
+ described_class.apage_from(
32
+ collection_name: '_posts',
33
+ date: '2023-10-03',
34
+ description: 'This is the entry3 description.',
35
+ last_modified: '2024-10-03',
36
+ order: 3,
37
+ title: 'Entry 3',
38
+ url: 'https://example.com/entry3'
39
+ ),
40
+ described_class.apage_from(
41
+ collection_name: '_posts',
42
+ date: '2023-10-04',
43
+ description: 'This is the entry4 description.',
44
+ draft: true,
45
+ last_modified: '2024-10-04',
46
+ order: 4,
47
+ title: 'Entry 4',
48
+ url: 'https://example.com/entry4'
49
+ ),
50
+ described_class.apage_from(
51
+ collection_name: '_posts',
52
+ date: '2023-10-05',
53
+ description: 'This is the entry5 description.',
54
+ last_modified: '2024-10-05',
55
+ order: 5,
56
+ title: 'Entry 5',
57
+ url: 'https://example.com/entry5'
58
+ ),
59
+ described_class.apage_from(
60
+ collection_name: '_posts',
61
+ date: '2023-10-06',
62
+ description: 'This is the entry6 description.',
63
+ last_modified: '2024-10-06',
64
+ order: 6,
65
+ title: 'Entry 6',
66
+ url: 'https://example.com/entry6'
67
+ )
68
+ ]
69
+
70
+ outline = described_class::Outline.new
71
+ outline.add_sections [section1, section2]
72
+ outline.add_entries apages
73
+
74
+ _attribution = <<~END_ATT
75
+ <div id="jps_attribute_570007" class="jps_attribute">
76
+ <div>
77
+ <a href="https://www.mslinn.com/jekyll_plugins/jekyll_outline.html" target="_blank" rel="nofollow">
78
+ Generated by the jekyll_outline v1.2.1 Jekyll plugin, written by Mike Slinn 2024-01-09.
79
+ </a>
80
+ </div>
81
+ </div>
82
+ END_ATT
83
+
84
+ expected_section1 = <<~END_EXPECTED
85
+ <h3 class='post_title clear' id="title_0">Section 1</h3>
86
+ <div id='posts_wrapper_0' class='clearfix'>
87
+ <div id="posts_0" class='posts'>
88
+ <span>2023-01-01</span>
89
+ <span><a href='https://example.com/entry1'><b> Entry 1 </b> &ndash; <i> This is the entry1 description. </i> </a> <i class='jekyll_draft'>Draft</i></span>
90
+
91
+ <span>2023-01-02</span>
92
+ <span><a href='https://example.com/entry2'><b> Entry 2 </b> &ndash; <i> This is the entry2 description. </i> </a></span>
93
+ </div>
94
+ </div>
95
+ END_EXPECTED
96
+
97
+ expected_section2 = <<~END_EXPECTED
98
+ <h3 class='post_title clear' id="title_3">Section 2</h3>
99
+ <div id='posts_wrapper_3' class='clearfix'>
100
+ <div id="posts_3" class='posts'>
101
+ <span>2024-10-03</span>
102
+ <span><a href='https://example.com/entry3'><b> Entry 3 </b> &ndash; <i> This is the entry3 description. </i> </a></span>
103
+
104
+ <span>2024-10-04</span>
105
+ <span><a href='https://example.com/entry4'><b> Entry 4 </b> &ndash; <i> This is the entry4 description. </i> </a> <i class='jekyll_draft'>Draft</i></span>
106
+
107
+ <span>2024-10-05</span>
108
+ <span><a href='https://example.com/entry5'><b> Entry 5 </b> &ndash; <i> This is the entry5 description. </i> </a></span>
109
+
110
+ <span>2024-10-06</span>
111
+ <span><a href='https://example.com/entry6'><b> Entry 6 </b> &ndash; <i> This is the entry6 description. </i> </a></span>
112
+ </div>
113
+ </div>
114
+ END_EXPECTED
115
+
116
+ it 'verifies initial values' do
117
+ expect(outline.options.sort_by).to eq(:order)
118
+ end
119
+
120
+ it 'sorts by :order' do
121
+ expect(outline.sort(apages)).to eq(apages)
122
+ end
123
+
124
+ it 'checks html shape' do
125
+ expect(outline.sections.count).to eq(2)
126
+ expect(outline.sections[0].children.count).to eq(2)
127
+ expect(outline.sections[1].children.count).to eq(4)
128
+ end
129
+
130
+ it 'verifies html for first section' do
131
+ actual = outline.sections[0].to_s
132
+ expect(expected_section1).to match_ignoring_whitespace(actual)
133
+ end
134
+
135
+ it 'verifies html for second section' do
136
+ actual = outline.sections[1].to_s
137
+ expect(expected_section2).to match_ignoring_whitespace(actual)
138
+ end
139
+
140
+ it 'verifies generated html' do
141
+ actual = outline.to_s
142
+
143
+ expected = <<~END_EXPECTED
144
+ <div class='outer_posts'>
145
+ #{expected_section1}
146
+ #{expected_section2}
147
+ </div>
148
+ END_EXPECTED
149
+
150
+ expect(expected).to match_ignoring_whitespace(actual)
9
151
  end
10
152
  end
data/spec/spec_helper.rb CHANGED
@@ -1,10 +1,23 @@
1
1
  require 'jekyll'
2
- require_relative '../lib/jekyll_outline'
3
2
 
4
- RSpec.configure do |config|
5
- config.filter_run_when_matching focus: true
6
- config.order = 'random'
3
+ # For testing Jekyll plugins based on jekyll_plugin_support:
4
+ require 'jekyll_plugin_logger'
5
+ require 'jekyll_plugin_support'
7
6
 
7
+ RSpec.configure do |config|
8
8
  # See https://relishapp.com/rspec/rspec-core/docs/command-line/only-failures
9
9
  config.example_status_persistence_file_path = 'spec/status_persistence.txt'
10
+
11
+ # See https://rspec.info/features/3-12/rspec-core/filtering/filter-run-when-matching/
12
+ # and https://github.com/rspec/rspec/issues/221
13
+ config.filter_run_when_matching :focus
14
+
15
+ # Other values: :progress, :html, :json, CustomFormatterClass
16
+ config.formatter = :documentation
17
+
18
+ # See https://rspec.info/features/3-12/rspec-core/command-line/order/
19
+ config.order = :defined
20
+
21
+ # See https://www.rubydoc.info/github/rspec/rspec-core/RSpec%2FCore%2FConfiguration:pending_failure_output
22
+ config.pending_failure_output = :skip
10
23
  end
@@ -1,3 +1,3 @@
1
- example_id | status | run_time |
2
- --------------------------- | ------- | --------------- |
3
- ./spec/outline_spec.rb[1:1] | pending | 0.00001 seconds |
1
+ example_id | status | run_time |
2
+ ---------------------------------- | ------ | --------------- |
3
+ ./spec/jekyll_outline_spec.rb[1:1] | passed | 0.00023 seconds |
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+ require 'rspec/match_ignoring_whitespace'
3
+ require_relative '../lib/structure/outline'
4
+ require_relative '../lib/structure/yaml_parser'
5
+
6
+ module JekyllSupport
7
+ logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
8
+ outline_options = OutlineOptions.new
9
+
10
+ # includes leading zeros and leading spaces, which are invalid in YAML
11
+ yaml_parser_big = YamlParser.new outline_options, <<~END_DATA
12
+ 0: Production Infrastructure
13
+ 0015000: Audio
14
+ 20000: Video
15
+ 30000: RME
16
+ 40000: OBS Studio
17
+ 50000: Pro Tools
18
+ 55000: Ableton Live &amp; Push
19
+ 60000: Other Music Software
20
+ 70000: MIDI Hardware &amp; Software
21
+ 80000: Davinci Resolve
22
+ 100000: Computer Analysis
23
+ 200000: Music Theory
24
+ 300000: Business
25
+ 400000: General
26
+ END_DATA
27
+
28
+ RSpec.describe(YamlParser) do
29
+ it 'handles no section headings' do
30
+ yaml_parser = described_class.new outline_options
31
+ sections = yaml_parser.sections
32
+ expect(sections.count).to equal(0)
33
+
34
+ yaml_parser = described_class.new outline_options, ''
35
+ sections = yaml_parser.sections
36
+ expect(sections.count).to equal(0)
37
+ end
38
+
39
+ it 'finds only 1 section heading' do
40
+ yaml_parser = described_class.new outline_options, '0: General'
41
+ sections = yaml_parser.sections
42
+ expect(sections.count).to equal(1)
43
+ # expect(sections.first)
44
+
45
+ yaml_parser = described_class.new outline_options, <<~END_DATA
46
+ 0: General
47
+ END_DATA
48
+ sections = yaml_parser.sections
49
+ expect(sections.count).to equal(1)
50
+
51
+ # Handle leading space (this is invalid YAML) and the lack of an end of line character
52
+ yaml_parser = described_class.new outline_options, ' 0: General'
53
+ sections = yaml_parser.sections
54
+ expect(sections.count).to equal(1)
55
+ end
56
+
57
+ it 'finds matching sections' do
58
+ sections = yaml_parser_big.sections
59
+ expect(sections.count).to equal(14)
60
+
61
+ section1 = sections.first
62
+ expect(section1.order).to eq(0)
63
+ expect(section1.title).to eq('Production Infrastructure')
64
+
65
+ outline = Outline.new.add_sections sections
66
+
67
+ apage0 = JekyllSupport.apage_from(date: Time.now, logger: logger, order: 0)
68
+ actual_section = outline.send :section_for, apage0
69
+ expect(actual_section.order).to eq(0)
70
+
71
+ apage1000 = JekyllSupport.apage_from(date: Time.now, logger: logger, order: 1000)
72
+ actual_section = outline.send :section_for, apage1000
73
+ expect(actual_section.order).to eq(0)
74
+
75
+ apage16000 = JekyllSupport.apage_from(date: Time.now, logger: logger, order: 16_000)
76
+ actual_section = outline.send :section_for, apage16000
77
+ expect(actual_section.order).to eq(15_000)
78
+
79
+ apage25000 = JekyllSupport.apage_from(date: Time.now, logger: logger, order: 25_000)
80
+ actual_section = outline.send :section_for, apage25000
81
+ expect(actual_section.order).to eq(20_000)
82
+ end
83
+ end
84
+ end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll_outline
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.5
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Slinn
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-08-20 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: jekyll
@@ -16,42 +15,42 @@ dependencies:
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: 3.5.0
18
+ version: 4.4.0
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
- version: 3.5.0
25
+ version: 4.4.0
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: jekyll_draft
29
28
  requirement: !ruby/object:Gem::Requirement
30
29
  requirements:
31
30
  - - ">="
32
31
  - !ruby/object:Gem::Version
33
- version: 2.0.2
32
+ version: 3.0.0
34
33
  type: :runtime
35
34
  prerelease: false
36
35
  version_requirements: !ruby/object:Gem::Requirement
37
36
  requirements:
38
37
  - - ">="
39
38
  - !ruby/object:Gem::Version
40
- version: 2.0.2
39
+ version: 3.0.0
41
40
  - !ruby/object:Gem::Dependency
42
41
  name: jekyll_plugin_support
43
42
  requirement: !ruby/object:Gem::Requirement
44
43
  requirements:
45
44
  - - ">="
46
45
  - !ruby/object:Gem::Version
47
- version: 1.0.2
46
+ version: 3.1.0
48
47
  type: :runtime
49
48
  prerelease: false
50
49
  version_requirements: !ruby/object:Gem::Requirement
51
50
  requirements:
52
51
  - - ">="
53
52
  - !ruby/object:Gem::Version
54
- version: 1.0.2
53
+ version: 3.1.0
55
54
  description: 'Jekyll tag plugin that creates a clickable table of contents.
56
55
 
57
56
  '
@@ -72,9 +71,14 @@ files:
72
71
  - lib/jekyll_outline/version.rb
73
72
  - lib/outline_js.rb
74
73
  - lib/outline_tag.rb
74
+ - lib/structure/a_page_enrichment.rb
75
+ - lib/structure/outline.rb
76
+ - lib/structure/section.rb
77
+ - lib/structure/yaml_parser.rb
75
78
  - spec/outline_spec.rb
76
79
  - spec/spec_helper.rb
77
80
  - spec/status_persistence.txt
81
+ - spec/yaml_parser_spec.rb
78
82
  homepage: https://www.mslinn.com/jekyll_plugins/jekyll_outline.html
79
83
  licenses:
80
84
  - MIT
@@ -102,12 +106,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
106
  - !ruby/object:Gem::Version
103
107
  version: '0'
104
108
  requirements: []
105
- rubygems_version: 3.5.17
106
- signing_key:
109
+ rubygems_version: 3.6.9
107
110
  specification_version: 4
108
111
  summary: Jekyll tag plugin that creates a clickable table of contents.
109
112
  test_files:
110
113
  - spec/outline_spec.rb
111
114
  - spec/spec_helper.rb
112
115
  - spec/status_persistence.txt
116
+ - spec/yaml_parser_spec.rb
113
117
  ...