jekyll-markdown-output 0.1.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 +7 -0
- data/CHANGELOG.md +18 -0
- data/LICENSE +21 -0
- data/README.md +148 -0
- data/lib/jekyll-markdown-output/generator.rb +61 -0
- data/lib/jekyll-markdown-output/markdown_page.rb +136 -0
- data/lib/jekyll-markdown-output/version.rb +7 -0
- data/lib/jekyll-markdown-output.rb +8 -0
- metadata +121 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: eef5e7fe6ffaa6a867b61c55c4e7da552745caac57be7f45c79402ddfe562283
|
|
4
|
+
data.tar.gz: 1c12840c040cf8f0ead3234d542dd702e3496fba1bb2bbfaeb067b4c464508c8
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 64f3a07d2967ee838f3ce05dd3d58721a6028c7e905f29a00b97059b00982a3635fb9c0e36262f2bbe7d64f33b2ea3a0aafedb9a12714e6159e82438c8d02817
|
|
7
|
+
data.tar.gz: 4de984d5b6570bb87f89b018f7095521b2efc05bdb5fdd04809931e82489c88a206b105220f0d8c1c841d2d1cdf0d70efd3a39739f3ddada219ded183944193f
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.1 - 2026-05-05
|
|
4
|
+
|
|
5
|
+
- Fix: when a post had no `summary` set, the fallback to `doc.data["excerpt"]`
|
|
6
|
+
serialized the entire `Jekyll::Excerpt` Ruby object graph into the
|
|
7
|
+
frontmatter. The fallback now coerces the excerpt to plain text and strips
|
|
8
|
+
HTML tags.
|
|
9
|
+
- Add an RSpec test suite (unit + integration against a fixture Jekyll site).
|
|
10
|
+
|
|
11
|
+
## 0.1.0
|
|
12
|
+
|
|
13
|
+
- Initial release.
|
|
14
|
+
- Generates a `.md` sibling for every document in the configured collections.
|
|
15
|
+
- Mirrors Markdown-sourced `site.pages` (e.g. `index.md`, `about.md`) too.
|
|
16
|
+
Disable with `pages: false`.
|
|
17
|
+
- Minimal YAML frontmatter (title, date, url, summary, tags, category, author).
|
|
18
|
+
- Per-document opt-out via `markdown_output: false` in frontmatter.
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Abhinav Saxena
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# jekyll-markdown-output
|
|
2
|
+
|
|
3
|
+
A Jekyll plugin that emits a `.md` sibling for every post (or any document in a configured collection), so AI agents, LLM crawlers, and other machine consumers can fetch clean Markdown instead of parsing HTML.
|
|
4
|
+
|
|
5
|
+
For a post rendered at `/foo`, this plugin also writes `/foo.md` containing:
|
|
6
|
+
|
|
7
|
+
- a small YAML frontmatter block (title, date, url, summary, tags, category, author)
|
|
8
|
+
- the post's source Markdown with Liquid rendered
|
|
9
|
+
|
|
10
|
+
No HTML conversion. No layout chrome. No nav, footer, theme toggles, or analytics scripts.
|
|
11
|
+
|
|
12
|
+
### Before / after
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
_site/
|
|
16
|
+
foo.html <- as before
|
|
17
|
+
foo.md <- new: clean Markdown, same URL
|
|
18
|
+
posts/
|
|
19
|
+
hello.html
|
|
20
|
+
hello.md
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Agents fetching `/foo.md` get the source content with a small frontmatter block. Browsers fetching `/foo` get the rendered HTML, untouched.
|
|
24
|
+
|
|
25
|
+
## Why
|
|
26
|
+
|
|
27
|
+
Agents that read your site spend tokens parsing HTML and stripping boilerplate. Serving a `.md` twin is the smallest change that gives them the actual content. It is the same pattern used by Anthropic's docs, Stripe, and a growing set of agent-friendly sites.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
Add to your `Gemfile`:
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
group :jekyll_plugins do
|
|
35
|
+
gem "jekyll-markdown-output"
|
|
36
|
+
end
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then in `_config.yml`:
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
plugins:
|
|
43
|
+
- jekyll-markdown-output
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Configure
|
|
47
|
+
|
|
48
|
+
Defaults are sensible for a typical blog. Override via `_config.yml`:
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
markdown_output:
|
|
52
|
+
enabled: true # set false to disable globally
|
|
53
|
+
collections: [posts] # which collections to mirror
|
|
54
|
+
pages: true # also mirror site.pages
|
|
55
|
+
page_extensions: [.md, .markdown] # which page sources count as Markdown
|
|
56
|
+
extension: .md # output extension
|
|
57
|
+
include_title_heading: true # prepend "# Title" to body
|
|
58
|
+
frontmatter_keys: # which fields to include
|
|
59
|
+
- title
|
|
60
|
+
- date
|
|
61
|
+
- url
|
|
62
|
+
- summary
|
|
63
|
+
- tags
|
|
64
|
+
- category
|
|
65
|
+
- author
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`pages: true` (the default) emits `.md` for top-level Markdown files such
|
|
69
|
+
as `index.md`, `about.md`, `now.md`. HTML-sourced pages are skipped: if
|
|
70
|
+
you want a `.md` twin for a page, write it in Markdown.
|
|
71
|
+
|
|
72
|
+
### Per-document opt-out
|
|
73
|
+
|
|
74
|
+
Add to a single post's frontmatter to skip it:
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
---
|
|
78
|
+
title: Draft thinking
|
|
79
|
+
markdown_output: false
|
|
80
|
+
---
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## URL mapping
|
|
84
|
+
|
|
85
|
+
| Source URL | Generated file |
|
|
86
|
+
|---|---|
|
|
87
|
+
| `/foo` | `/foo.md` |
|
|
88
|
+
| `/a/foo` | `/a/foo.md` |
|
|
89
|
+
| `/foo/` | `/foo/index.md` |
|
|
90
|
+
| `/` | `/index.md` |
|
|
91
|
+
|
|
92
|
+
## Output shape
|
|
93
|
+
|
|
94
|
+
```markdown
|
|
95
|
+
---
|
|
96
|
+
title: Terminal is having a second life
|
|
97
|
+
date: '2025-09-12T00:00:00+05:30'
|
|
98
|
+
url: https://www.abhinav.co/terminal-second-life
|
|
99
|
+
summary: How agentic coding tools have pulled the terminal back to the centre of the developer workflow.
|
|
100
|
+
tags:
|
|
101
|
+
- Terminal
|
|
102
|
+
- Tools
|
|
103
|
+
category: technology
|
|
104
|
+
author: Abhinav Saxena
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
# Terminal is having a second life
|
|
108
|
+
|
|
109
|
+
For years the terminal was the place you only opened to run a build...
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## How it works
|
|
113
|
+
|
|
114
|
+
The plugin registers a `:site, :post_write` hook that runs after Jekyll has finished its main build. For each document in the configured collections (and each Markdown-sourced page if `pages: true`), it reads the original source from disk, strips the frontmatter, optionally renders Liquid against the document context, and writes a `.md` file directly into `_site/`.
|
|
115
|
+
|
|
116
|
+
Because output goes through `File.write` rather than Jekyll's renderer, the file never passes through layouts, the Markdown-to-HTML converter, or any other plugin's hooks. The body stays as Markdown; Liquid (`{{ site.url }}`, `{% include %}`) resolves against the live site context.
|
|
117
|
+
|
|
118
|
+
## Compatibility
|
|
119
|
+
|
|
120
|
+
- Jekyll 3.7+ and 4.x
|
|
121
|
+
- Ruby 2.7+
|
|
122
|
+
|
|
123
|
+
### GitHub Pages
|
|
124
|
+
|
|
125
|
+
GitHub Pages restricts Jekyll plugins to a [whitelist](https://pages.github.com/versions/), and `jekyll-markdown-output` is not on it. If you host on GH Pages, you have two options:
|
|
126
|
+
|
|
127
|
+
1. Build the site yourself in CI (GitHub Actions, Netlify, Cloudflare Pages, Vercel) and deploy the built `_site/` to GH Pages, instead of relying on GH Pages' own Jekyll build.
|
|
128
|
+
2. Skip this plugin and serve `.html` only.
|
|
129
|
+
|
|
130
|
+
Cloudflare Pages, Netlify, Vercel, and self-hosted builds run the plugin without restriction.
|
|
131
|
+
|
|
132
|
+
## FAQ
|
|
133
|
+
|
|
134
|
+
**How is this different from `llms.txt`?**
|
|
135
|
+
|
|
136
|
+
`llms.txt` is one root file listing your content. This plugin emits a per-page `.md` next to each `.html`, so an agent that lands on `/foo` can fetch `/foo.md` directly without consulting an index. The two compose: ship both if you want.
|
|
137
|
+
|
|
138
|
+
**Why not just convert the rendered HTML back to Markdown?**
|
|
139
|
+
|
|
140
|
+
The HTML has already gone through layouts, includes, theme chrome, syntax highlighting wrappers, and possibly a markdown converter that drops information (smart quotes, ID anchors). Round-tripping is lossy. Reading the source is faithful.
|
|
141
|
+
|
|
142
|
+
**Will it slow my build down?**
|
|
143
|
+
|
|
144
|
+
No measurable cost on a site with hundreds of posts. The hook runs once after `:site, :post_write` and writes files in a tight loop.
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
MIT. See `LICENSE`.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
|
|
5
|
+
module Jekyll
|
|
6
|
+
module MarkdownOutput
|
|
7
|
+
DEFAULTS = {
|
|
8
|
+
"enabled" => true,
|
|
9
|
+
"collections" => ["posts"],
|
|
10
|
+
"pages" => true,
|
|
11
|
+
"page_extensions" => [".md", ".markdown"],
|
|
12
|
+
"extension" => ".md",
|
|
13
|
+
"include_title_heading" => true,
|
|
14
|
+
"frontmatter_keys" => MarkdownPage::DEFAULT_FRONTMATTER_KEYS,
|
|
15
|
+
}.freeze
|
|
16
|
+
|
|
17
|
+
def self.config_for(site)
|
|
18
|
+
DEFAULTS.merge(site.config["markdown_output"] || {})
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.write_all(site)
|
|
22
|
+
config = config_for(site)
|
|
23
|
+
return unless config["enabled"]
|
|
24
|
+
|
|
25
|
+
written = 0
|
|
26
|
+
|
|
27
|
+
Array(config["collections"]).each do |coll_name|
|
|
28
|
+
collection = site.collections[coll_name.to_s]
|
|
29
|
+
unless collection
|
|
30
|
+
Jekyll.logger.warn("MarkdownOutput:", "collection '#{coll_name}' not found, skipping")
|
|
31
|
+
next
|
|
32
|
+
end
|
|
33
|
+
collection.docs.each { |doc| written += 1 if write_one(site, doc, config) }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
if config["pages"]
|
|
37
|
+
exts = Array(config["page_extensions"]).map(&:downcase)
|
|
38
|
+
site.pages.each do |page|
|
|
39
|
+
next unless exts.include?(File.extname(page.path).downcase)
|
|
40
|
+
written += 1 if write_one(site, page, config)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
Jekyll.logger.info("MarkdownOutput:", "wrote #{written} markdown file(s)")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.write_one(site, source, config)
|
|
48
|
+
return false if source.data["markdown_output"] == false
|
|
49
|
+
|
|
50
|
+
page = MarkdownPage.new(site, source, config)
|
|
51
|
+
path = page.destination
|
|
52
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
53
|
+
File.write(path, page.to_s)
|
|
54
|
+
true
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
Jekyll::Hooks.register :site, :post_write do |site|
|
|
60
|
+
Jekyll::MarkdownOutput.write_all(site)
|
|
61
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jekyll
|
|
4
|
+
module MarkdownOutput
|
|
5
|
+
# Builds the Markdown bytes for a single source document.
|
|
6
|
+
# Not a Jekyll::Page on purpose: we write directly to _site/
|
|
7
|
+
# in a post_write hook so the converter and layout pipeline
|
|
8
|
+
# cannot touch the output.
|
|
9
|
+
class MarkdownPage
|
|
10
|
+
DEFAULT_FRONTMATTER_KEYS = %w[title date url summary tags category author].freeze
|
|
11
|
+
|
|
12
|
+
attr_reader :doc, :site, :options
|
|
13
|
+
|
|
14
|
+
def initialize(site, doc, options = {})
|
|
15
|
+
@site = site
|
|
16
|
+
@doc = doc
|
|
17
|
+
@options = options
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Absolute path on disk where this file should be written.
|
|
21
|
+
def destination
|
|
22
|
+
File.join(@site.dest, relative_destination)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Path relative to the site root, e.g. "/foo.md".
|
|
26
|
+
def relative_destination
|
|
27
|
+
ext = @options.fetch("extension", ".md")
|
|
28
|
+
url = @doc.url
|
|
29
|
+
if url.end_with?("/")
|
|
30
|
+
File.join(url, "index#{ext}")
|
|
31
|
+
else
|
|
32
|
+
dir = File.dirname(url)
|
|
33
|
+
base = File.basename(url, ".*")
|
|
34
|
+
File.join(dir, "#{base}#{ext}")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def to_s
|
|
39
|
+
parts = []
|
|
40
|
+
fm = build_frontmatter
|
|
41
|
+
parts << "---\n#{fm}---" unless fm.empty?
|
|
42
|
+
if @options.fetch("include_title_heading", true) && @doc.data["title"]
|
|
43
|
+
parts << "# #{@doc.data["title"]}"
|
|
44
|
+
end
|
|
45
|
+
parts << rendered_source.to_s.strip
|
|
46
|
+
"#{parts.join("\n\n")}\n"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def build_frontmatter
|
|
52
|
+
keys = @options["frontmatter_keys"] || DEFAULT_FRONTMATTER_KEYS
|
|
53
|
+
url = @doc.url
|
|
54
|
+
site_url = @site.config["url"]
|
|
55
|
+
url = "#{site_url}#{url}" if site_url && !url.start_with?("http")
|
|
56
|
+
|
|
57
|
+
candidates = {
|
|
58
|
+
"title" => @doc.data["title"],
|
|
59
|
+
"date" => format_date(@doc.data["date"]),
|
|
60
|
+
"url" => url,
|
|
61
|
+
"summary" => extract_summary,
|
|
62
|
+
"tags" => Array(@doc.data["tags"]).reject { |t| t.to_s.empty? },
|
|
63
|
+
"category" => @doc.data["category"],
|
|
64
|
+
"author" => @doc.data["author"] || @site.config["author"],
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
picked = keys.each_with_object({}) do |key, h|
|
|
68
|
+
v = candidates[key]
|
|
69
|
+
next if v.nil?
|
|
70
|
+
next if v.respond_to?(:empty?) && v.empty?
|
|
71
|
+
h[key] = v
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
return "" if picked.empty?
|
|
75
|
+
|
|
76
|
+
YAML.dump(picked).sub(/\A---\s*\n/, "")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def format_date(date)
|
|
80
|
+
return nil if date.nil?
|
|
81
|
+
date.respond_to?(:iso8601) ? date.iso8601 : date.to_s
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# `summary` falls back to the document's excerpt when not set in
|
|
85
|
+
# frontmatter. Excerpt may be a Jekyll::Excerpt object (whose YAML dump
|
|
86
|
+
# is a huge object graph) or already a string. Coerce to plain text and
|
|
87
|
+
# strip tags so it's safe to embed in YAML frontmatter.
|
|
88
|
+
def extract_summary
|
|
89
|
+
s = @doc.data["summary"]
|
|
90
|
+
return s.strip if s.is_a?(String) && !s.strip.empty?
|
|
91
|
+
|
|
92
|
+
excerpt = @doc.data["excerpt"]
|
|
93
|
+
return nil if excerpt.nil?
|
|
94
|
+
text = excerpt.respond_to?(:content) ? excerpt.content : excerpt
|
|
95
|
+
text = text.to_s.gsub(/<[^>]+>/, "").strip
|
|
96
|
+
text.empty? ? nil : text
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Resolve to an absolute path on disk. Document#path is already
|
|
100
|
+
# absolute; Page#path is relative to the site source.
|
|
101
|
+
def source_path
|
|
102
|
+
File.expand_path(@doc.path.to_s, @site.source)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Re-read the source body from disk. By the time post_write fires,
|
|
106
|
+
# Jekyll has overwritten doc.content with the converted HTML.
|
|
107
|
+
# Force UTF-8 because some build environments (e.g. Cloudflare Pages)
|
|
108
|
+
# default to US-ASCII, which breaks regex splits on non-ASCII bytes.
|
|
109
|
+
def source_body
|
|
110
|
+
raw = File.read(source_path, encoding: "UTF-8")
|
|
111
|
+
parts = raw.split(/^---\s*$\n/, 3)
|
|
112
|
+
parts.length >= 3 ? parts[2] : raw
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def rendered_source
|
|
116
|
+
body = source_body
|
|
117
|
+
# Skip Liquid only when the document explicitly opted out. We do not
|
|
118
|
+
# rely on Document#render_with_liquid? here because Jekyll mutates
|
|
119
|
+
# that flag to false after the main render pass, and our post_write
|
|
120
|
+
# hook runs strictly after that.
|
|
121
|
+
return body if @doc.data["render_with_liquid"] == false
|
|
122
|
+
|
|
123
|
+
info = {
|
|
124
|
+
filters: [Jekyll::Filters],
|
|
125
|
+
registers: { site: @site, page: @doc.to_liquid },
|
|
126
|
+
}
|
|
127
|
+
template = @site.liquid_renderer.file(source_path).parse(body)
|
|
128
|
+
template.render!(@site.site_payload.merge("page" => @doc.to_liquid), info)
|
|
129
|
+
rescue StandardError => e
|
|
130
|
+
rel = @doc.respond_to?(:relative_path) ? @doc.relative_path : @doc.path
|
|
131
|
+
Jekyll.logger.warn("MarkdownOutput:", "render failed for #{rel}: #{e.message}")
|
|
132
|
+
source_body
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: jekyll-markdown-output
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Abhinav Saxena
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-05-05 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: jekyll
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '3.7'
|
|
20
|
+
- - "<"
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: '5.0'
|
|
23
|
+
type: :runtime
|
|
24
|
+
prerelease: false
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
requirements:
|
|
27
|
+
- - ">="
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '3.7'
|
|
30
|
+
- - "<"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '5.0'
|
|
33
|
+
- !ruby/object:Gem::Dependency
|
|
34
|
+
name: kramdown-parser-gfm
|
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.1'
|
|
40
|
+
type: :development
|
|
41
|
+
prerelease: false
|
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '1.1'
|
|
47
|
+
- !ruby/object:Gem::Dependency
|
|
48
|
+
name: rake
|
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '13.0'
|
|
54
|
+
type: :development
|
|
55
|
+
prerelease: false
|
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '13.0'
|
|
61
|
+
- !ruby/object:Gem::Dependency
|
|
62
|
+
name: rspec
|
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '3.12'
|
|
68
|
+
type: :development
|
|
69
|
+
prerelease: false
|
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '3.12'
|
|
75
|
+
description: |
|
|
76
|
+
A Jekyll generator that writes a .md file alongside each rendered HTML page,
|
|
77
|
+
so AI agents and crawlers can fetch clean Markdown (with a small machine-
|
|
78
|
+
friendly frontmatter block) instead of parsing HTML. Configurable per
|
|
79
|
+
collection.
|
|
80
|
+
email:
|
|
81
|
+
- abhinav061@gmail.com
|
|
82
|
+
executables: []
|
|
83
|
+
extensions: []
|
|
84
|
+
extra_rdoc_files: []
|
|
85
|
+
files:
|
|
86
|
+
- CHANGELOG.md
|
|
87
|
+
- LICENSE
|
|
88
|
+
- README.md
|
|
89
|
+
- lib/jekyll-markdown-output.rb
|
|
90
|
+
- lib/jekyll-markdown-output/generator.rb
|
|
91
|
+
- lib/jekyll-markdown-output/markdown_page.rb
|
|
92
|
+
- lib/jekyll-markdown-output/version.rb
|
|
93
|
+
homepage: https://github.com/abhinavs/jekyll-markdown-output
|
|
94
|
+
licenses:
|
|
95
|
+
- MIT
|
|
96
|
+
metadata:
|
|
97
|
+
homepage_uri: https://github.com/abhinavs/jekyll-markdown-output
|
|
98
|
+
source_code_uri: https://github.com/abhinavs/jekyll-markdown-output/tree/main
|
|
99
|
+
bug_tracker_uri: https://github.com/abhinavs/jekyll-markdown-output/issues
|
|
100
|
+
changelog_uri: https://github.com/abhinavs/jekyll-markdown-output/blob/main/CHANGELOG.md
|
|
101
|
+
rubygems_mfa_required: 'true'
|
|
102
|
+
post_install_message:
|
|
103
|
+
rdoc_options: []
|
|
104
|
+
require_paths:
|
|
105
|
+
- lib
|
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: 2.7.0
|
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
|
+
requirements:
|
|
113
|
+
- - ">="
|
|
114
|
+
- !ruby/object:Gem::Version
|
|
115
|
+
version: '0'
|
|
116
|
+
requirements: []
|
|
117
|
+
rubygems_version: 3.5.22
|
|
118
|
+
signing_key:
|
|
119
|
+
specification_version: 4
|
|
120
|
+
summary: Emit a Markdown sibling for every Jekyll post or note, for agents and LLMs.
|
|
121
|
+
test_files: []
|