jekyll-agent-markdown 0.2.0 → 0.3.1

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: 747268dbb22f5d319ed8f760fa97ff9503eb12b632a44c8ef74bcef8694d821d
4
- data.tar.gz: 57e5b25acc73b618d1d74f3e11f8e20f44393af1f976bfd17669e2f6d52b226a
3
+ metadata.gz: 81a9e3ec622a528158f77eab0ea51648c8229b3a4faceb84deb7c648a6a7ae65
4
+ data.tar.gz: 95a3a69bf269b5399c50209d89bfd0ff24e137e9aba82955b5f82be3c5fbc4ab
5
5
  SHA512:
6
- metadata.gz: 02e6fa6d6a722bee4b94052f2a2d42ea0d5de18599f4380da778c1e42390a7b54e346d68e3830b7cb0bbb35c0634031ae4fac1c2d8374c074947191f38248cb6
7
- data.tar.gz: 715edcbd124b53fca22dedfbf96e115fc4ed1373797ef27ded43868c551f5ec61aecabc1f8057612a842f237d9a544c20e228ecd9ec33a3899d0c308854fb11c
6
+ metadata.gz: 4eeba03b01f2ffec891e0ab206f659135f5bb892591cd1dbff6ec141ef4db1f6f315baba491b617127614ba5ed167384661303fd2e85d90d50fb63c18de81545
7
+ data.tar.gz: 48d40c90d4677d033e803469b95521459192386db5fa83fb653446d2ad8190fa1d926ce9d1b77ae81004e01a41c113807b5f64a0350bca0c598ab04f74066bba
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.1] - 2026-08-20
4
+
5
+ - Include the site author in each exported article's metadata footer on the same line as published and updated dates.
6
+
7
+ ## [0.3.0] - 2026-08-20
8
+
9
+ - Include the site author's name in `llms.txt` by default, with an `include_author` opt-out.
10
+
3
11
  ## [0.2.0] - 2026-08-20
4
12
 
5
13
  - Add configurable `llms.txt` ordering by normalized published date, defaulting to newest first and placing missing or invalid dates last.
data/README.md CHANGED
@@ -28,10 +28,13 @@ agent_markdown:
28
28
  posts: true
29
29
  llms_txt: true
30
30
  sort: desc
31
+ include_author: true
31
32
  include_dates: true
32
33
  ```
33
34
 
34
- `posts`, `llms_txt`, and `include_dates` accept `true`, `false`, or one of the false-style strings `"false"`, `"no"`, and `"off"` (case-insensitively). `sort` accepts `asc` or `desc` and defaults to `desc`, ordering the `llms.txt` article list by normalized published date. Posts with a missing, incomplete, or invalid published date are listed last in their existing order. Unknown keys and other values stop the build with a configuration error instead of being silently ignored. An explicit per-post `agent_markdown` value follows the boolean-setting rules, so a mistyped opt-out cannot publish raw source by accident.
35
+ `posts`, `llms_txt`, `include_author`, and `include_dates` accept `true`, `false`, or one of the false-style strings `"false"`, `"no"`, and `"off"` (case-insensitively). `sort` accepts `asc` or `desc` and defaults to `desc`, ordering the `llms.txt` article list by normalized published date. Posts with a missing, incomplete, or invalid published date are listed last in their existing order. Unknown keys and other values stop the build with a configuration error instead of being silently ignored. An explicit per-post `agent_markdown` value follows the boolean-setting rules, so a mistyped opt-out cannot publish raw source by accident.
36
+
37
+ By default, `llms.txt` and each exported article footer include the blog author's name from either a scalar Jekyll setting (`author: Jane Doe`) or a mapping (`author: { name: Jane Doe }`). If no author name is configured, the entry is omitted. Set `include_author: false` under `agent_markdown` to omit author metadata from both outputs.
35
38
 
36
39
  Set `url` to your site's absolute HTTP(S) URL; the `llms.txt` index uses it to generate absolute article links:
37
40
 
@@ -56,14 +59,14 @@ Markdown sibling paths are deterministic:
56
59
 
57
60
  Extensions are matched case-insensitively, and percent-encoded aliases are compared by their final decoded destination. Destination ownership also treats case-only and Unicode-normalization aliases as equivalent on every platform, keeping builds portable across filesystems. File-versus-directory conflicts are reserved as well. Before adding an export, the plugin checks every page, static file, and writable collection document already known to Jekyll. The existing destination owner wins; later post exports are skipped with a warning and omitted from `llms.txt`. A committed `llms.txt` wins in the same way.
58
61
 
59
- The generated file preserves the post's original Markdown body as its initial content, with no front matter, HTML conversion, or Liquid rendering. Liquid tags and directives such as `{{ site.title }}` are published literally. By default, the plugin appends the post's published `date` and optional `last_modified_at` value as a small footer:
62
+ The generated file preserves the post's original Markdown body as its initial content, with no front matter, HTML conversion, or Liquid rendering. Liquid tags and directives such as `{{ site.title }}` are published literally. By default, the plugin appends the post's published `date`, optional `last_modified_at` value, and site author as a small footer:
60
63
 
61
64
  ```text
62
65
  ---
63
- Published at: 2026-01-01 | Updated at: 2026-02-03
66
+ Published at: 2026-01-01 | Updated at: 2026-02-03 | Author: Jane Doe
64
67
  ```
65
68
 
66
- Each available date is formatted as `YYYY-MM-DD`. String values must contain an explicit year, month, and day; missing, incomplete, and invalid values and their labels are omitted. An empty post contains only the metadata line, without a leading `---` that could be mistaken for front matter. Set `include_dates: false` to omit date metadata from both Markdown exports and `llms.txt`, leaving the body-only export shape used before date metadata was introduced.
69
+ Each available date is formatted as `YYYY-MM-DD`. String values must contain an explicit year, month, and day; missing, incomplete, and invalid values and their labels are omitted. An empty post contains only the metadata line, without a leading `---` that could be mistaken for front matter. `include_dates: false` omits dates from Markdown exports and `llms.txt` article links while leaving an author-only footer when an author is configured. `include_author: false` leaves a date-only footer. Set both options to `false` for a body-only export.
67
70
 
68
71
  Exclude one post with front matter:
69
72
 
@@ -88,6 +91,8 @@ The generated `/llms.txt` is a compact index, for example:
88
91
 
89
92
  > A short description
90
93
 
94
+ Author: Example Author
95
+
91
96
  ## Articles
92
97
 
93
98
  > Posts only. Pages and collections are not included.
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module AgentMarkdown
5
+ class AuthorMetadata
6
+ def initialize(config)
7
+ @config = config
8
+ end
9
+
10
+ def to_s
11
+ author_name = name
12
+ author_name.empty? ? "" : "Author: #{author_name}"
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :config
18
+
19
+ def name
20
+ author = config["author"]
21
+ author = author["name"] || author[:name] if author.is_a?(Hash)
22
+ author ? author.to_s.gsub(/\s+/, " ").strip : ""
23
+ end
24
+ end
25
+ end
26
+ end
@@ -6,7 +6,7 @@ require "uri"
6
6
  module Jekyll
7
7
  module AgentMarkdown
8
8
  class Configuration
9
- ALLOWED_SETTINGS = %w[include_dates llms_txt posts sort].freeze
9
+ ALLOWED_SETTINGS = %w[include_author include_dates llms_txt posts sort].freeze
10
10
  FALSE_STRINGS = %w[false no off].freeze
11
11
  SORT_ORDERS = %w[asc desc].freeze
12
12
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "date"
4
+ require_relative "metadata_footer"
4
5
 
5
6
  module Jekyll
6
7
  module AgentMarkdown
@@ -21,10 +22,7 @@ module Jekyll
21
22
  end
22
23
 
23
24
  def append_to(content)
24
- return content if to_s.empty?
25
- return "#{self}\n" if content.empty?
26
-
27
- "#{content}#{separator_for(content)}---\n#{self}\n"
25
+ MetadataFooter.new([to_s]).append_to(content)
28
26
  end
29
27
 
30
28
  def published_date = parsed_date(@data["date"])
@@ -36,10 +34,6 @@ module Jekyll
36
34
  "#{label}: #{date}" if date
37
35
  end
38
36
 
39
- def separator_for(content)
40
- content.end_with?("\n") ? "\n" : "\n\n"
41
- end
42
-
43
37
  def formatted_date(value)
44
38
  parsed_date(value)&.strftime(DATE_FORMAT)
45
39
  end
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "jekyll"
4
+ require_relative "author_metadata"
4
5
  require_relative "configuration"
5
6
  require_relative "date_metadata"
6
7
  require_relative "destination_claims"
8
+ require_relative "llms_headings"
7
9
  require_relative "markdown_sibling_path"
10
+ require_relative "metadata_footer"
8
11
  require_relative "raw_markdown_file"
9
12
 
10
13
  module Jekyll
@@ -46,7 +49,7 @@ module Jekyll
46
49
  setting_name = "agent_markdown in #{post.relative_path}"
47
50
  return unless Configuration.enabled_value?(setting, name: setting_name)
48
51
 
49
- file = RawMarkdownFile.new(site, MarkdownSiblingPath.for(post.url), post_content(post, settings))
52
+ file = RawMarkdownFile.new(site, MarkdownSiblingPath.for(post.url), post_content(site, post, settings))
50
53
  url = file.url
51
54
  return collision_warning(post, url) unless claim_destination?(destination_claims, site, file)
52
55
 
@@ -91,22 +94,10 @@ module Jekyll
91
94
  end
92
95
 
93
96
  def llms_txt(site, posts, settings)
94
- sections = [llms_headings(site), article_links(site, posts, settings)]
97
+ sections = [LlmsHeadings.new(site, settings).to_s, article_links(site, posts, settings)]
95
98
  "#{sections.reject(&:empty?).join("\n\n")}\n"
96
99
  end
97
100
 
98
- def llms_headings(site)
99
- title = one_line(site.config.fetch("title", ""))
100
- headings = ["# #{title}".rstrip]
101
- description = one_line(site.config["description"])
102
- headings << "> #{description}" unless description.empty?
103
- headings << "## Articles"
104
- headings << "> Posts only. Pages and collections are not included."
105
- headings.join("\n\n")
106
- end
107
-
108
- def one_line(value) = value ? value.to_s.gsub(/\s+/, " ").strip : ""
109
-
110
101
  def article_links(site, posts, settings)
111
102
  site_url = site.config["url"].sub(%r{/+\z}, "")
112
103
  sorted_posts(posts, settings).map { |post| article_link(site_url, post, settings) }.join("\n")
@@ -127,10 +118,11 @@ module Jekyll
127
118
  [link, date_metadata(post).to_s].reject(&:empty?).join(" | ")
128
119
  end
129
120
 
130
- def post_content(post, settings)
131
- return post.content unless Configuration.enabled?(settings, "include_dates")
132
-
133
- date_metadata(post).append_to(post.content)
121
+ def post_content(site, post, settings)
122
+ entries = []
123
+ entries << date_metadata(post).to_s if Configuration.enabled?(settings, "include_dates")
124
+ entries << AuthorMetadata.new(site.config).to_s if Configuration.enabled?(settings, "include_author")
125
+ MetadataFooter.new(entries).append_to(post.content)
134
126
  end
135
127
 
136
128
  def date_metadata(post) = DateMetadata.new(post.data)
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "author_metadata"
4
+ require_relative "configuration"
5
+
6
+ module Jekyll
7
+ module AgentMarkdown
8
+ class LlmsHeadings
9
+ def initialize(site, settings)
10
+ @site = site
11
+ @settings = settings
12
+ end
13
+
14
+ def to_s
15
+ [title_heading, description_heading, author_heading, "## Articles", articles_description]
16
+ .compact.join("\n\n")
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :site, :settings
22
+
23
+ def title_heading = "# #{one_line(site.config.fetch("title", ""))}".rstrip
24
+
25
+ def description_heading
26
+ description = one_line(site.config["description"])
27
+ "> #{description}" unless description.empty?
28
+ end
29
+
30
+ def author_heading
31
+ return unless Configuration.enabled?(settings, "include_author")
32
+
33
+ metadata = AuthorMetadata.new(site.config).to_s
34
+ metadata unless metadata.empty?
35
+ end
36
+
37
+ def articles_description = "> Posts only. Pages and collections are not included."
38
+
39
+ def one_line(value) = value ? value.to_s.gsub(/\s+/, " ").strip : ""
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module AgentMarkdown
5
+ class MetadataFooter
6
+ def initialize(entries)
7
+ @text = entries.compact.reject(&:empty?).join(" | ")
8
+ end
9
+
10
+ def append_to(content)
11
+ return content if text.empty?
12
+ return "#{text}\n" if content.empty?
13
+
14
+ "#{content}#{separator_for(content)}---\n#{text}\n"
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :text
20
+
21
+ def separator_for(content)
22
+ content.end_with?("\n") ? "\n" : "\n\n"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jekyll
4
4
  module AgentMarkdown
5
- VERSION = "0.2.0"
5
+ VERSION = "0.3.1"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-agent-markdown
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucian Ghinda
@@ -41,11 +41,14 @@ files:
41
41
  - LICENSE.txt
42
42
  - README.md
43
43
  - lib/jekyll-agent-markdown.rb
44
+ - lib/jekyll/agent_markdown/author_metadata.rb
44
45
  - lib/jekyll/agent_markdown/configuration.rb
45
46
  - lib/jekyll/agent_markdown/date_metadata.rb
46
47
  - lib/jekyll/agent_markdown/destination_claims.rb
47
48
  - lib/jekyll/agent_markdown/generator.rb
49
+ - lib/jekyll/agent_markdown/llms_headings.rb
48
50
  - lib/jekyll/agent_markdown/markdown_sibling_path.rb
51
+ - lib/jekyll/agent_markdown/metadata_footer.rb
49
52
  - lib/jekyll/agent_markdown/raw_markdown_file.rb
50
53
  - lib/jekyll/agent_markdown/version.rb
51
54
  homepage: https://github.com/lucianghinda/jekyll-agent-markdown