jekyll-aeo 1.0.0 → 1.1.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: 2f7c4d9f203c1e2bc36c2f3c1547d4f6056ed77cd07d250a25ee186a46bd7891
4
- data.tar.gz: 88f985556de2aae0ce6a2d0c57fb0be9be36c7a2b8f275910f7ff06e9f04bd3a
3
+ metadata.gz: a67da5680eb6edabb8dc5d19eac59183bfaa8d9e96d55f3bc61bae32f1ab5a23
4
+ data.tar.gz: 34e6338c176a2162370077a743dc22ab22a208de99667be9edc9002cd6296103
5
5
  SHA512:
6
- metadata.gz: 0110becea058f84e0c28790655d695f95d3f4394003795a7c1dafef7ca0c56fcecef12b3e1dfdbcc7a1bd4f194cc5bf5db3b60b0623e98642123265b2e9436b1
7
- data.tar.gz: ffaa6971e9bd344a1bb30775e00653dfe0fff53cf8ff4ec8adfcf32899c88df87003fa0b8e3bbd5e9e77507b8cae9b6a932f81adc880a3e6fcb2a6b4685094be
6
+ metadata.gz: aff3c6403325f75908ba1457350013a8995785c0e0ab851ec51b2ffc55c9a805aefebd8e86532e74043b4245cf7d6fc3c5df8324fcd1b6d722204c07855275d4
7
+ data.tar.gz: 381bdd47d7a8c4095afd5c40de07152ee756d2031441c15e0be5d51288c55b6234e71055d9d3511fcd4b2c8737039d5e5a73b8e92deeeca545cb45f2756021e4
@@ -72,6 +72,7 @@ module JekyllAeo
72
72
  content = File.read(llms_path, encoding: "utf-8")
73
73
  md_urls = content.scan(/\[.*?\]\(([^)]*\.md)\)/).flatten
74
74
 
75
+ dest_expanded = File.expand_path(dest)
75
76
  md_urls.each do |url|
76
77
  relative_url = if !baseurl.empty? && url.start_with?(baseurl)
77
78
  url.delete_prefix(baseurl)
@@ -79,6 +80,8 @@ module JekyllAeo
79
80
  url
80
81
  end
81
82
  file_path = File.join(dest, relative_url)
83
+ next unless File.expand_path(file_path).start_with?(dest_expanded)
84
+
82
85
  errors << "Referenced file not found: #{url} (expected at #{file_path})" unless File.exist?(file_path)
83
86
  end
84
87
  end
@@ -5,6 +5,8 @@ module JekyllAeo
5
5
  DEFAULTS = {
6
6
  "enabled" => true,
7
7
  "exclude" => [],
8
+ "include_layouts" => nil,
9
+ "include_collections" => nil,
8
10
  "dotmd" => {
9
11
  "link_tag" => "auto",
10
12
  "include_last_modified" => true,
@@ -34,7 +36,7 @@ module JekyllAeo
34
36
  "url_map" => {
35
37
  "enabled" => false,
36
38
  "output_filepath" => "docs/Url-Map.md",
37
- "columns" => %w[page_id url lang layout path redirects markdown_copy skipped],
39
+ "columns" => %w[layout url url_dotmd dotmd_mode excluded path page_id lang redirects],
38
40
  "show_created_at" => true
39
41
  },
40
42
  "robots_txt" => {
@@ -4,17 +4,20 @@ require "fileutils"
4
4
 
5
5
  module JekyllAeo
6
6
  module Generators
7
- module MarkdownPage
7
+ module DotMdWriter
8
8
  YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m
9
+ LIQUID_PATTERN = /\{[{%]/
9
10
 
10
11
  def self.process(obj, site)
11
12
  config = JekyllAeo::Config.from_site(site)
12
13
  dotmd_config = config["dotmd"]
13
- source_path = JekyllAeo::Utils::SkipLogic.resolve_source_path(obj, site)
14
- return if JekyllAeo::Utils::SkipLogic.skip?(obj, site, config)
14
+ source_path = JekyllAeo::Utils::IncludeLogic.resolve_source_path(obj, site)
15
+ return unless JekyllAeo::Utils::IncludeLogic.include?(obj, site, config)
15
16
 
16
17
  dest_path = md_dest_path(obj, site)
17
- body = extract_body(source_path, obj, dotmd_config)
18
+ body, dotmd_mode = extract_body(source_path, obj, dotmd_config)
19
+ obj.data["aeo_dotmd_mode"] = dotmd_mode
20
+ return if body.nil? || body.strip.empty?
18
21
 
19
22
  if dotmd_config["include_last_modified"] && File.exist?(source_path)
20
23
  last_modified = resolve_last_modified(obj, source_path)
@@ -40,15 +43,52 @@ module JekyllAeo
40
43
  end
41
44
 
42
45
  def self.extract_body(source_path, obj, dotmd_config)
46
+ preferred = obj.data["dotmd_mode"]
47
+
48
+ return extract_html2dotmd(obj, dotmd_config) if preferred == "html2dotmd"
49
+ return extract_explicit_md2dotmd(source_path, obj) if preferred == "md2dotmd" && !File.exist?(source_path)
50
+
43
51
  if File.exist?(source_path)
44
- raw = File.read(source_path, encoding: "utf-8")
45
- body = raw.sub(YAML_FRONT_MATTER_REGEXP, "")
46
- JekyllAeo::Utils::ContentStripper.strip(body, dotmd_config["md2dotmd"])
52
+ extract_from_source(source_path, obj, dotmd_config, preferred)
47
53
  else
48
- JekyllAeo::Utils::HtmlConverter.convert(obj.output, dotmd_config["html2dotmd"])
54
+ html_output = obj.respond_to?(:output) ? obj.output : nil
55
+ return html2dotmd_result(html_output, dotmd_config) if html_output && !html_output.strip.empty?
56
+
57
+ [nil, "html2dotmd"]
49
58
  end
50
59
  end
51
60
 
61
+ def self.extract_html2dotmd(obj, dotmd_config)
62
+ html_output = obj.respond_to?(:output) ? obj.output : nil
63
+ return html2dotmd_result(html_output, dotmd_config) if html_output && !html_output.strip.empty?
64
+
65
+ Jekyll.logger.warn "Jekyll-AEO:",
66
+ "dotmd_mode: html2dotmd set but no rendered output for #{obj.url}"
67
+ [nil, "html2dotmd"]
68
+ end
69
+
70
+ def self.extract_explicit_md2dotmd(_source_path, obj)
71
+ Jekyll.logger.warn "Jekyll-AEO:",
72
+ "dotmd_mode: md2dotmd set but no source file for #{obj.url}"
73
+ [nil, "md2dotmd"]
74
+ end
75
+
76
+ def self.extract_from_source(source_path, obj, dotmd_config, preferred)
77
+ raw = File.read(source_path, encoding: "utf-8")
78
+ body = raw.sub(YAML_FRONT_MATTER_REGEXP, "")
79
+
80
+ if preferred != "md2dotmd" && body.match?(LIQUID_PATTERN)
81
+ html_output = obj.respond_to?(:output) ? obj.output : nil
82
+ return html2dotmd_result(html_output, dotmd_config) if html_output && !html_output.strip.empty?
83
+ end
84
+
85
+ [JekyllAeo::Utils::ContentStripper.strip(body, dotmd_config["md2dotmd"]), "md2dotmd"]
86
+ end
87
+
88
+ def self.html2dotmd_result(html, dotmd_config)
89
+ [JekyllAeo::Utils::HtmlConverter.convert(html, dotmd_config["html2dotmd"] || {}), "html2dotmd"]
90
+ end
91
+
52
92
  def self.build_header(obj, body, _config = nil, last_modified: nil)
53
93
  header = ""
54
94
  title = obj.data["title"]
@@ -142,7 +182,9 @@ module JekyllAeo
142
182
 
143
183
  private_class_method :build_header, :md_dest_path, :resolve_last_modified,
144
184
  :format_date, :build_metadata_block,
145
- :yaml_safe_scalar, :extract_body, :metadata_fields
185
+ :yaml_safe_scalar, :extract_body, :metadata_fields,
186
+ :extract_html2dotmd, :extract_explicit_md2dotmd,
187
+ :extract_from_source, :html2dotmd_result
146
188
  end
147
189
  end
148
190
  end
@@ -23,11 +23,11 @@ module JekyllAeo
23
23
  items = []
24
24
 
25
25
  site.documents.each do |doc|
26
- next if JekyllAeo::Utils::SkipLogic.skip?(doc, site, config)
26
+ next unless JekyllAeo::Utils::IncludeLogic.include?(doc, site, config)
27
27
 
28
28
  items << {
29
29
  obj: doc,
30
- title: doc.data["title"] || "",
30
+ title: title_for(doc),
31
31
  description: doc.data["description"] || "",
32
32
  url: doc.url,
33
33
  collection: doc.collection&.label,
@@ -36,11 +36,11 @@ module JekyllAeo
36
36
  end
37
37
 
38
38
  site.pages.each do |page|
39
- next if JekyllAeo::Utils::SkipLogic.skip?(page, site, config)
39
+ next unless JekyllAeo::Utils::IncludeLogic.include?(page, site, config)
40
40
 
41
41
  items << {
42
42
  obj: page,
43
- title: page.data["title"] || "",
43
+ title: title_for(page),
44
44
  description: page.data["description"] || "",
45
45
  url: page.url,
46
46
  collection: nil,
@@ -114,6 +114,16 @@ module JekyllAeo
114
114
  end
115
115
  end
116
116
 
117
+ def self.title_for(obj)
118
+ title = obj.data["title"]
119
+ return title if title.is_a?(String) && !title.strip.empty?
120
+
121
+ segment = obj.url.chomp("/").split("/").last
122
+ return "Untitled" if segment.nil? || segment.empty?
123
+
124
+ segment.split(/[_-]/).map(&:capitalize).join(" ")
125
+ end
126
+
117
127
  def self.build_llms_txt(site, sections, llms_config, config)
118
128
  lines = []
119
129
  lines << "# #{site.config['title']}"
@@ -158,8 +168,8 @@ module JekyllAeo
158
168
  end
159
169
 
160
170
  private_class_method :build_custom_sections, :build_auto_sections,
161
- :titleize, :build_llms_txt, :append_full_txt_link,
162
- :append_sections
171
+ :titleize, :title_for, :build_llms_txt,
172
+ :append_full_txt_link, :append_sections
163
173
  end
164
174
  end
165
175
  end
@@ -7,15 +7,18 @@ module JekyllAeo
7
7
  module UrlMap
8
8
  COLUMN_HEADERS = {
9
9
  "page_id" => "Page ID",
10
- "url" => "URL",
10
+ "url" => "Url",
11
11
  "lang" => "Lang",
12
12
  "layout" => "Layout",
13
13
  "path" => "Path",
14
14
  "redirects" => "Redirects",
15
- "markdown_copy" => "Markdown Copy",
16
- "skipped" => "Skipped"
15
+ "url_dotmd" => "Url DotMd",
16
+ "excluded" => "Excluded",
17
+ "dotmd_mode" => "DotMd Mode"
17
18
  }.freeze
18
19
 
20
+ DEFAULT_COLUMNS = %w[layout url url_dotmd dotmd_mode excluded path page_id lang redirects].freeze
21
+
19
22
  def self.generate(site)
20
23
  config = JekyllAeo::Config.from_site(site)
21
24
  return if config["enabled"] == false
@@ -23,39 +26,46 @@ module JekyllAeo
23
26
  url_map_config = config["url_map"] || {}
24
27
  return if url_map_config["enabled"] == false
25
28
 
26
- columns = url_map_config["columns"] || COLUMN_HEADERS.keys
29
+ columns = url_map_config["columns"] || DEFAULT_COLUMNS
27
30
  items = collect_all_items(site, config, columns)
28
31
  sections = build_sections(items)
29
32
  markdown = build_markdown(sections, columns, url_map_config)
30
33
 
31
- output_file = File.join(project_root(site), url_map_config["output_filepath"] || "docs/Url-Map.md")
34
+ root = project_root(site)
35
+ output_file = File.join(root, url_map_config["output_filepath"] || "docs/Url-Map.md")
36
+ unless File.expand_path(output_file).start_with?(File.expand_path(root))
37
+ Jekyll.logger.error "AEO Url Map:", "output_filepath escapes project root — skipped"
38
+ return
39
+ end
32
40
  FileUtils.mkdir_p(File.dirname(output_file))
33
41
  File.write(output_file, markdown)
34
42
  end
35
43
 
36
44
  def self.collect_all_items(site, config, columns)
37
45
  items = []
38
- needs_skip = columns.include?("skipped")
39
- needs_md = columns.include?("markdown_copy")
46
+ needs_excluded = columns.include?("excluded")
47
+ needs_md = columns.include?("url_dotmd")
48
+ needs_mode = columns.include?("dotmd_mode")
40
49
  baseurl = site.config["baseurl"].to_s.chomp("/")
41
50
 
42
51
  site.documents.each do |doc|
52
+ next if doc.is_a?(Jekyll::StaticFile)
43
53
  next unless doc.output_ext == ".html"
44
- next if doc.respond_to?(:collection) && doc.collection&.label == "assets"
45
54
 
46
- items << build_item(doc, doc.collection&.label, site, config, needs_skip, needs_md, baseurl)
55
+ items << build_item(doc, doc.collection&.label, site, config, needs_excluded, needs_md, needs_mode, baseurl)
47
56
  end
48
57
 
49
58
  site.pages.each do |page|
59
+ next if page.is_a?(Jekyll::StaticFile)
50
60
  next unless page.output_ext == ".html"
51
61
 
52
- items << build_item(page, nil, site, config, needs_skip, needs_md, baseurl)
62
+ items << build_item(page, nil, site, config, needs_excluded, needs_md, needs_mode, baseurl)
53
63
  end
54
64
 
55
65
  items
56
66
  end
57
67
 
58
- def self.build_item(obj, collection_label, site, config, needs_skip, needs_md, baseurl = "")
68
+ def self.build_item(obj, collection_label, site, config, needs_excluded, needs_md, needs_mode, baseurl = "")
59
69
  redirect_from = obj.data["redirect_from"]
60
70
  redirects_str = case redirect_from
61
71
  when Array then redirect_from.join(", ")
@@ -73,9 +83,10 @@ module JekyllAeo
73
83
  collection: collection_label
74
84
  }
75
85
 
76
- item[:skipped] = JekyllAeo::Utils::SkipLogic.skip_reason(obj, site, config) || "" if needs_skip
77
- item[:markdown_copy] = md_url(obj.url, baseurl) if needs_md && (!needs_skip || item[:skipped].empty?)
78
- item[:markdown_copy] ||= "" if needs_md
86
+ item[:excluded] = JekyllAeo::Utils::IncludeLogic.exclude_reason(obj, site, config) || "" if needs_excluded
87
+ item[:url_dotmd] = md_url(obj.url, baseurl) if needs_md && (!needs_excluded || item[:excluded].empty?)
88
+ item[:url_dotmd] ||= "" if needs_md
89
+ item[:dotmd_mode] = obj.data["aeo_dotmd_mode"] || "" if needs_mode
79
90
 
80
91
  item
81
92
  end
@@ -17,11 +17,11 @@ Jekyll::Hooks.register :pages, :post_render do |page|
17
17
  end
18
18
 
19
19
  Jekyll::Hooks.register :documents, :post_write do |doc|
20
- JekyllAeo::Generators::MarkdownPage.process(doc, doc.site)
20
+ JekyllAeo::Generators::DotMdWriter.process(doc, doc.site)
21
21
  end
22
22
 
23
23
  Jekyll::Hooks.register :pages, :post_write do |page|
24
- JekyllAeo::Generators::MarkdownPage.process(page, page.site)
24
+ JekyllAeo::Generators::DotMdWriter.process(page, page.site)
25
25
  end
26
26
 
27
27
  Jekyll::Hooks.register :site, :post_write do |site|
@@ -6,7 +6,7 @@ module JekyllAeo
6
6
  config = JekyllAeo::Config.from_site(site)
7
7
  dotmd_config = config["dotmd"]
8
8
  return unless dotmd_config["link_tag"] == "auto"
9
- return if JekyllAeo::Utils::SkipLogic.skip?(obj, site, config)
9
+ return unless JekyllAeo::Utils::IncludeLogic.include?(obj, site, config)
10
10
 
11
11
  md_url = JekyllAeo::Utils::MdUrl.for(obj.url, site.config["baseurl"])
12
12
  tag = %(<link rel="alternate" type="text/markdown" href="#{md_url}">)
@@ -17,7 +17,7 @@ module JekyllAeo
17
17
  config = JekyllAeo::Config.from_site(site)
18
18
  dotmd_config = config["dotmd"]
19
19
  return unless dotmd_config["link_tag"] == "data"
20
- return if JekyllAeo::Utils::SkipLogic.skip?(obj, site, config)
20
+ return unless JekyllAeo::Utils::IncludeLogic.include?(obj, site, config)
21
21
 
22
22
  md_url = JekyllAeo::Utils::MdUrl.for(obj.url, site.config["baseurl"])
23
23
  obj.data["md_url"] = md_url
@@ -16,8 +16,9 @@ module JekyllAeo
16
16
  return "" unless content_node
17
17
 
18
18
  STRIP_ELEMENTS.each { |tag| content_node.css(tag).each(&:remove) }
19
+ promote_code_languages(content_node)
19
20
 
20
- ReverseMarkdown.convert(content_node.inner_html, unknown_tags: :bypass).strip
21
+ ReverseMarkdown.convert(content_node.inner_html, unknown_tags: :bypass, github_flavored: true).strip
21
22
  end
22
23
 
23
24
  def self.extract_content(doc, config)
@@ -29,7 +30,18 @@ module JekyllAeo
29
30
  end
30
31
  end
31
32
 
32
- private_class_method :extract_content
33
+ # Jekyll/Rouge: <div class="language-python"><div class="highlight"><pre>…
34
+ # ReverseMarkdown: reads `highlight-{lang}` from <pre>'s parent
35
+ def self.promote_code_languages(node)
36
+ node.css('div[class*="language-"]').each do |div|
37
+ next unless div["class"] =~ /language-(\S+)/
38
+
39
+ pre = div.at_css("pre")
40
+ pre.parent["class"] = "highlight-#{Regexp.last_match(1)}" if pre&.parent
41
+ end
42
+ end
43
+
44
+ private_class_method :extract_content, :promote_code_languages
33
45
  end
34
46
  end
35
47
  end
@@ -2,13 +2,15 @@
2
2
 
3
3
  module JekyllAeo
4
4
  module Utils
5
- module SkipLogic
6
- def self.skip_reason(obj, site, config)
5
+ module IncludeLogic
6
+ def self.exclude_reason(obj, site, config)
7
7
  return "plugin disabled" if config["enabled"] == false
8
+ return "static file" if static_file?(obj)
8
9
  return "non-HTML output" unless html_output?(obj)
9
- return "markdown_copy: false" if obj.data["markdown_copy"] == false
10
- return "redirect" if obj.data["redirect_to"]
11
- return "assets collection" if assets_collection?(obj)
10
+
11
+ reason = filter_reason(obj, config)
12
+ return reason if reason
13
+
12
14
  return "llms file" if llms_file?(obj, site)
13
15
  return "excluded" if excluded?(obj, config)
14
16
  return "no source file" unless source_available?(obj, site, config)
@@ -16,8 +18,17 @@ module JekyllAeo
16
18
  nil
17
19
  end
18
20
 
19
- def self.skip?(obj, site, config)
20
- !skip_reason(obj, site, config).nil?
21
+ def self.filter_reason(obj, config)
22
+ return "dotmd_mode: disabled" if obj.data["dotmd_mode"] == "disabled"
23
+ return "redirect" if obj.data["redirect_to"]
24
+ return "layout: #{obj.data['layout']}" unless included_layout?(obj, config)
25
+ return "collection: #{obj.collection.label}" unless included_collection?(obj, config)
26
+
27
+ nil
28
+ end
29
+
30
+ def self.include?(obj, site, config)
31
+ exclude_reason(obj, site, config).nil?
21
32
  end
22
33
 
23
34
  def self.resolve_source_path(obj, site)
@@ -32,8 +43,24 @@ module JekyllAeo
32
43
  obj.output_ext == ".html"
33
44
  end
34
45
 
35
- def self.assets_collection?(obj)
36
- obj.respond_to?(:collection) && obj.collection&.label == "assets"
46
+ def self.static_file?(obj)
47
+ obj.is_a?(Jekyll::StaticFile)
48
+ end
49
+
50
+ def self.included_layout?(obj, config)
51
+ include_layouts = config["include_layouts"]
52
+ return true if include_layouts.nil?
53
+
54
+ include_layouts.include?(obj.data["layout"])
55
+ end
56
+
57
+ def self.included_collection?(obj, config)
58
+ return true unless obj.respond_to?(:collection)
59
+
60
+ include_collections = config["include_collections"]
61
+ return true if include_collections.nil?
62
+
63
+ include_collections.include?(obj.collection&.label)
37
64
  end
38
65
 
39
66
  def self.llms_file?(obj, site)
@@ -59,7 +86,8 @@ module JekyllAeo
59
86
  source_file_exists?(obj, site) || html2dotmd["enabled"]
60
87
  end
61
88
 
62
- private_class_method :html_output?, :assets_collection?, :llms_file?,
89
+ private_class_method :html_output?, :static_file?, :included_layout?,
90
+ :included_collection?, :llms_file?, :filter_reason,
63
91
  :excluded?, :source_file_exists?, :source_available?
64
92
  end
65
93
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JekyllAeo
4
- VERSION = "1.0.0"
4
+ VERSION = "1.1.0"
5
5
  end
data/lib/jekyll-aeo.rb CHANGED
@@ -4,11 +4,11 @@ require "jekyll"
4
4
  require_relative "jekyll-aeo/version"
5
5
  require_relative "jekyll-aeo/config"
6
6
  require_relative "jekyll-aeo/utils/content_stripper"
7
- require_relative "jekyll-aeo/utils/skip_logic"
7
+ require_relative "jekyll-aeo/utils/include_logic"
8
8
  require_relative "jekyll-aeo/utils/html_converter"
9
9
  require_relative "jekyll-aeo/utils/md_url"
10
10
  require_relative "jekyll-aeo/link_tag"
11
- require_relative "jekyll-aeo/generators/markdown_page"
11
+ require_relative "jekyll-aeo/generators/dot_md_writer"
12
12
  require_relative "jekyll-aeo/generators/llms_txt"
13
13
  require_relative "jekyll-aeo/generators/llms_full_txt"
14
14
  require_relative "jekyll-aeo/generators/url_map"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-aeo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manuel Gruber
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-14 00:00:00.000000000 Z
11
+ date: 2026-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -105,9 +105,9 @@ files:
105
105
  - lib/jekyll-aeo/commands/validate.rb
106
106
  - lib/jekyll-aeo/config.rb
107
107
  - lib/jekyll-aeo/generators/domain_profile.rb
108
+ - lib/jekyll-aeo/generators/dot_md_writer.rb
108
109
  - lib/jekyll-aeo/generators/llms_full_txt.rb
109
110
  - lib/jekyll-aeo/generators/llms_txt.rb
110
- - lib/jekyll-aeo/generators/markdown_page.rb
111
111
  - lib/jekyll-aeo/generators/robots_txt.rb
112
112
  - lib/jekyll-aeo/generators/url_map.rb
113
113
  - lib/jekyll-aeo/hooks.rb
@@ -121,8 +121,8 @@ files:
121
121
  - lib/jekyll-aeo/tags/aeo_json_ld.rb
122
122
  - lib/jekyll-aeo/utils/content_stripper.rb
123
123
  - lib/jekyll-aeo/utils/html_converter.rb
124
+ - lib/jekyll-aeo/utils/include_logic.rb
124
125
  - lib/jekyll-aeo/utils/md_url.rb
125
- - lib/jekyll-aeo/utils/skip_logic.rb
126
126
  - lib/jekyll-aeo/version.rb
127
127
  homepage: https://zaai.com/jekyll-aeo
128
128
  licenses: