jekyll-secret-posts 0.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +151 -0
- data/lib/jekyll/secret_posts/config.rb +66 -0
- data/lib/jekyll/secret_posts/generator.rb +96 -0
- data/lib/jekyll/secret_posts/hooks.rb +67 -0
- data/lib/jekyll/secret_posts/url_tokenizer.rb +19 -0
- data/lib/jekyll/secret_posts.rb +14 -0
- data/lib/jekyll-secret-posts.rb +3 -0
- metadata +95 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: '032359338c8f0f94913d90be4ba0c17e1f86cff32c37636d7e493b77250ccc92'
|
|
4
|
+
data.tar.gz: a56e6bc96d5e924ed8897afe4f75b2dfb56f44a329bce40338f1a7844d1faa00
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 7fc592e410680cd2e0604245bcbcd7395c87486073e1c195fcd42f377c742aec3fae393e4f73d33c77a97e8e940496c7262e03e59bd0359fbb311a331ab72ee4
|
|
7
|
+
data.tar.gz: b0f75614598f7cca7ee4517f72288016e05c4b2d7e8fc4060cbd48432593a687af1c00a4fa1be842b05112e985d48ffe41dc1489b00b39117a8fc04c0ef93a54
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025
|
|
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,151 @@
|
|
|
1
|
+
# Jekyll Secret Posts
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/rb/jekyll-secret-posts)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
**Jekyll Secret Posts** is a lightweight, open-source [Jekyll](https://jekyllrb.com) plugin designed to publish "share-only" posts. It easily integrates with any Jekyll project and is compatible with other Jekyll plugins.
|
|
7
|
+
|
|
8
|
+
At build time, the plugin hashes the Markdown file path with SHA-256 to generate unique URLs. Since these hashed URLs are excluded from sitemaps and search engine indexing, your posts remain accessible only to those with the direct link.
|
|
9
|
+
|
|
10
|
+
By enabling link-only access, the plugin allows for exclusive content sharing and gives more privacy to your website.
|
|
11
|
+
|
|
12
|
+
<br>
|
|
13
|
+
|
|
14
|
+
* [Installation](#installation)
|
|
15
|
+
* [Getting Started](#getting-started)
|
|
16
|
+
* [Configuration](#configuration)
|
|
17
|
+
* [Compatibility](#compatibility)
|
|
18
|
+
* [Contributions](#contributions)
|
|
19
|
+
|
|
20
|
+
<br>
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
### With Bundler
|
|
25
|
+
|
|
26
|
+
Add `jekyll-secret-posts` gem to your `Gemfile`:
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
gem "jekyll-secret-posts"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
or use GitHub repository link:
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
gem "jekyll-secret-posts", git: "https://github.com/developerlee79/jekyll-secret-posts.git"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Manual
|
|
39
|
+
|
|
40
|
+
Or install the gem manually and specify the plugin in your `_config.yml`:
|
|
41
|
+
|
|
42
|
+
```shell
|
|
43
|
+
gem install jekyll-secret-posts
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
plugins:
|
|
48
|
+
- jekyll-secret-posts
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
<br>
|
|
52
|
+
|
|
53
|
+
## Getting Started
|
|
54
|
+
|
|
55
|
+
Create a `_secret` directory in your Jekyll project root and add markdown file(same as regular posts).
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
my-jekyll-site/
|
|
59
|
+
├── _config.yml
|
|
60
|
+
├── _layouts/
|
|
61
|
+
└── _secret/
|
|
62
|
+
└── article.md # Any .md files in this directory or its subfolders are supported
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Since the URL is hashed, you cannot know it without inspecting the built output. The easiest way to see it is in the build log when you build; this plugin only exposes those URLs in the log via the `list_urls` option.
|
|
66
|
+
|
|
67
|
+
However, enabling this in production or CI can expose hashed URLs on external servers or in pipeline logs. For that reason, `list_urls` defaults to `false` so you can turn it on manually only in safe environments.
|
|
68
|
+
|
|
69
|
+
For this guide, we enable it so you can verify that secret URLs are generated. Add the `list_urls` option to `_config.yml`:
|
|
70
|
+
|
|
71
|
+
```yaml
|
|
72
|
+
secret_posts:
|
|
73
|
+
list_urls: true
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
URLs are hashed using the `JEKYLL_SECRET_SALT` environment variable as salt. the plugin is able to hash without it, but in that case the URL can be guessed, so setting a salt is highly recommended for security.
|
|
77
|
+
|
|
78
|
+
Set it before build and build:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
export JEKYLL_SECRET_SALT="my-secret"
|
|
82
|
+
bundle exec jekyll build
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
or run build with the environment variable:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
JEKYLL_SECRET_SALT="my-secret" bundle exec jekyll build
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Then you will be able to find the hashed URL in the build log like this:
|
|
92
|
+
|
|
93
|
+
```log
|
|
94
|
+
Secret post URL: /s/eac1bc3d5e2cb1881215f42c7926d462/
|
|
95
|
+
AutoPages: Disabled/Not configured in site.config.
|
|
96
|
+
Pagination: Complete, processed 1 pagination page(s)
|
|
97
|
+
done in 1.825 seconds.
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
All done! Share the URL only with people who should see the post.
|
|
101
|
+
|
|
102
|
+
<br>
|
|
103
|
+
|
|
104
|
+
## Configuration
|
|
105
|
+
|
|
106
|
+
You can add custom settings to your `_config.yml` as follows:
|
|
107
|
+
|
|
108
|
+
```yaml
|
|
109
|
+
secret_posts:
|
|
110
|
+
source_dir: "_secret"
|
|
111
|
+
collection_name: "secret"
|
|
112
|
+
url_prefix: "/s/"
|
|
113
|
+
index_layout: "default"
|
|
114
|
+
redirect_url: "/"
|
|
115
|
+
list_urls: false
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
| Key | Default | Description |
|
|
119
|
+
|----------------------------|---------|-------------|
|
|
120
|
+
| `source_dir` | `"_secret"` | Directory containing target Markdown files |
|
|
121
|
+
| `collection_name` | `"secret"` | Internal Jekyll collection name |
|
|
122
|
+
| `url_prefix` | `"/s/"` | URL prefix for hashed URLs |
|
|
123
|
+
| `index_layout` | `"default"` | Layout used for the redirect page at the `url_prefix` |
|
|
124
|
+
| `redirect_url` | `baseurl` | URL to which the `url_prefix` index page redirects (If unset, the site `baseurl` is used; if that is also unset, `/` is used) |
|
|
125
|
+
| `list_urls` | `false` | When `true`, prints hashed URLs in Jekyll build log (Use only in safe environment) |
|
|
126
|
+
|
|
127
|
+
<br>
|
|
128
|
+
|
|
129
|
+
## Compatibility
|
|
130
|
+
|
|
131
|
+
### Jekyll Pagination
|
|
132
|
+
|
|
133
|
+
Secret posts live in a collection, not in `site.posts`, so they are not included in pagination.
|
|
134
|
+
|
|
135
|
+
### Jekyll Sitemap
|
|
136
|
+
|
|
137
|
+
Secret documents are set to `sitemap: false`, so they do not appear in the sitemap.
|
|
138
|
+
|
|
139
|
+
### Jekyll Polyglot
|
|
140
|
+
|
|
141
|
+
If you use Polyglot for localization and do not plan to support multiple languages for secret posts, add the secret source directory to `exclude_from_localization` in your `_config.yml` so that secret posts are not processed for multiple languages:
|
|
142
|
+
|
|
143
|
+
```yaml
|
|
144
|
+
exclude_from_localization: ["images", "css", "scss", "js", "_secret"]
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
<br>
|
|
148
|
+
|
|
149
|
+
## Contributions
|
|
150
|
+
|
|
151
|
+
Contributions are welcome. If you have an improvement or idea, feel free to open a pull request.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jekyll
|
|
4
|
+
module SecretPosts
|
|
5
|
+
class Config
|
|
6
|
+
DEFAULT_SOURCE_DIR = "_secret"
|
|
7
|
+
DEFAULT_COLLECTION_NAME = "secret"
|
|
8
|
+
DEFAULT_URL_PREFIX = "/s/"
|
|
9
|
+
DEFAULT_INDEX_LAYOUT = "default"
|
|
10
|
+
TOKEN_LENGTH = 32
|
|
11
|
+
|
|
12
|
+
def initialize(site_config)
|
|
13
|
+
@site_config = site_config
|
|
14
|
+
@secret_posts = site_config["secret_posts"] || {}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def source_dir
|
|
18
|
+
@secret_posts["source_dir"] || DEFAULT_SOURCE_DIR
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def collection_name
|
|
22
|
+
@secret_posts["collection_name"] || DEFAULT_COLLECTION_NAME
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def url_prefix
|
|
26
|
+
prefix = @secret_posts["url_prefix"] || DEFAULT_URL_PREFIX
|
|
27
|
+
prefix = DEFAULT_URL_PREFIX if prefix.to_s.strip.empty?
|
|
28
|
+
prefix.end_with?("/") ? prefix : "#{prefix}/"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def salt
|
|
32
|
+
ENV["JEKYLL_SECRET_SALT"].to_s
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def secret_index_layout
|
|
36
|
+
return DEFAULT_INDEX_LAYOUT unless @secret_posts.key?("index_layout")
|
|
37
|
+
|
|
38
|
+
layout = @secret_posts["index_layout"]
|
|
39
|
+
return nil if layout.nil? || layout == false
|
|
40
|
+
|
|
41
|
+
layout.to_s.empty? ? DEFAULT_INDEX_LAYOUT : layout.to_s
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def redirect_url
|
|
45
|
+
custom = @secret_posts["redirect_url"].to_s.strip
|
|
46
|
+
return custom.end_with?("/") ? custom : "#{custom}/" unless custom.empty?
|
|
47
|
+
|
|
48
|
+
base = @site_config["baseurl"].to_s.strip
|
|
49
|
+
if base.empty?
|
|
50
|
+
"/"
|
|
51
|
+
else
|
|
52
|
+
base.end_with?("/") ? base : "#{base}/"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def token_length
|
|
57
|
+
TOKEN_LENGTH
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def list_urls?
|
|
61
|
+
value = @secret_posts["list_urls"]
|
|
62
|
+
!value.nil? && value != false && value.to_s.strip != ""
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jekyll
|
|
4
|
+
module SecretPosts
|
|
5
|
+
class Generator < Jekyll::Generator
|
|
6
|
+
safe true
|
|
7
|
+
priority :high
|
|
8
|
+
|
|
9
|
+
def generate(site)
|
|
10
|
+
config = Config.new(site.config)
|
|
11
|
+
add_secret_index_page(site, config)
|
|
12
|
+
log_secret_urls(site, config) if config.list_urls?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def add_secret_index_page(site, config)
|
|
18
|
+
prefix_dir = config.url_prefix.gsub(%r{\A/|/\z}, "")
|
|
19
|
+
page = Jekyll::PageWithoutAFile.new(site, site.source, prefix_dir, "index.html")
|
|
20
|
+
page.data["permalink"] = config.url_prefix
|
|
21
|
+
page.data["sitemap"] = false
|
|
22
|
+
assign_redirect_content(page, config)
|
|
23
|
+
site.pages << page
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def assign_redirect_content(page, config)
|
|
27
|
+
url = config.redirect_url
|
|
28
|
+
if config.secret_index_layout
|
|
29
|
+
page.data["layout"] = config.secret_index_layout
|
|
30
|
+
page.content = redirect_fragment(url)
|
|
31
|
+
else
|
|
32
|
+
page.data["layout"] = nil
|
|
33
|
+
page.content = redirect_standalone_html(url)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def redirect_fragment(url)
|
|
38
|
+
<<~FRAGMENT.strip
|
|
39
|
+
<meta http-equiv="refresh" content="0;url=#{url}">
|
|
40
|
+
<p>Redirecting...</p>
|
|
41
|
+
<p><a href="#{url}">Go to homepage</a></p>
|
|
42
|
+
FRAGMENT
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def redirect_standalone_html(url)
|
|
46
|
+
<<~HTML.strip
|
|
47
|
+
<!DOCTYPE html>
|
|
48
|
+
<html>
|
|
49
|
+
<head><meta charset="utf-8"><meta http-equiv="refresh" content="0;url=#{url}"></head>
|
|
50
|
+
<body><p>Redirecting...</p><p><a href="#{url}">Go to homepage</a></p></body>
|
|
51
|
+
</html>
|
|
52
|
+
HTML
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def log_secret_urls(site, config)
|
|
56
|
+
collection = site.collections[config.collection_name]
|
|
57
|
+
unless collection
|
|
58
|
+
Jekyll.logger.info "Secret posts: no collection '#{config.collection_name}'"
|
|
59
|
+
return
|
|
60
|
+
end
|
|
61
|
+
ensure_collection_read(collection)
|
|
62
|
+
docs = collection.docs
|
|
63
|
+
if docs.empty?
|
|
64
|
+
Jekyll.logger.info "Secret posts: no documents"
|
|
65
|
+
return
|
|
66
|
+
end
|
|
67
|
+
log_secret_doc_urls(docs, config, site)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def log_secret_doc_urls(docs, config, site)
|
|
71
|
+
tokenizer = UrlTokenizer.new(config)
|
|
72
|
+
baseurl = normalized_baseurl(site.config["baseurl"])
|
|
73
|
+
docs.each { |doc| log_one_secret_url(doc, config, tokenizer, baseurl) }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def normalized_baseurl(baseurl_value)
|
|
77
|
+
baseurl = baseurl_value.to_s.strip
|
|
78
|
+
baseurl.empty? ? nil : baseurl
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def log_one_secret_url(doc, config, tokenizer, baseurl)
|
|
82
|
+
token = tokenizer.token_for(doc.collection.label, doc.relative_path)
|
|
83
|
+
path = "#{config.url_prefix}#{token}/"
|
|
84
|
+
full_url = baseurl ? "#{baseurl.sub(%r{/\z}, '')}#{path}" : path
|
|
85
|
+
Jekyll.logger.info "Secret post URL: #{full_url}"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def ensure_collection_read(collection)
|
|
89
|
+
return unless collection.docs.empty? && collection.respond_to?(:read)
|
|
90
|
+
|
|
91
|
+
coll_dir = collection.respond_to?(:directory) ? collection.directory.to_s : ""
|
|
92
|
+
collection.read if !coll_dir.empty? && File.directory?(coll_dir)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "jekyll/secret_posts/config"
|
|
4
|
+
require "jekyll/secret_posts/url_tokenizer"
|
|
5
|
+
|
|
6
|
+
module Jekyll
|
|
7
|
+
module SecretPosts
|
|
8
|
+
module Hooks
|
|
9
|
+
NOINDEX_META = '<meta name="robots" content="noindex, nofollow">'
|
|
10
|
+
|
|
11
|
+
def self.register
|
|
12
|
+
Jekyll::Hooks.register(:site, :after_init) do |site|
|
|
13
|
+
register_secret_collection(site)
|
|
14
|
+
end
|
|
15
|
+
Jekyll::Hooks.register(:documents, :post_init) do |doc|
|
|
16
|
+
apply_secret_permalink(doc)
|
|
17
|
+
end
|
|
18
|
+
Jekyll::Hooks.register(:documents, :post_render) do |doc|
|
|
19
|
+
inject_noindex(doc)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.register_secret_collection(site)
|
|
24
|
+
config = Config.new(site.config)
|
|
25
|
+
collections = site.config["collections"] ||= {}
|
|
26
|
+
return if collections.key?(config.collection_name)
|
|
27
|
+
|
|
28
|
+
collections[config.collection_name] = {
|
|
29
|
+
"output" => true,
|
|
30
|
+
"source" => config.source_dir
|
|
31
|
+
}
|
|
32
|
+
exclude = site.config["exclude"]
|
|
33
|
+
exclude.reject! { |e| e.to_s == config.source_dir } if exclude.is_a?(Array)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.apply_secret_permalink(doc)
|
|
37
|
+
return unless secret_document?(doc)
|
|
38
|
+
|
|
39
|
+
config = Config.new(doc.site.config)
|
|
40
|
+
tokenizer = UrlTokenizer.new(config)
|
|
41
|
+
token = tokenizer.token_for(doc.collection.label, doc.relative_path)
|
|
42
|
+
doc.data["permalink"] = "#{config.url_prefix}#{token}/"
|
|
43
|
+
doc.data["sitemap"] = false
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.secret_document?(doc)
|
|
47
|
+
doc.collection && doc.site &&
|
|
48
|
+
doc.collection.label == Config.new(doc.site.config).collection_name
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.inject_noindex(doc)
|
|
52
|
+
return unless doc.collection && doc.site
|
|
53
|
+
|
|
54
|
+
config = Config.new(doc.site.config)
|
|
55
|
+
return unless doc.collection.label == config.collection_name
|
|
56
|
+
return unless doc.output
|
|
57
|
+
|
|
58
|
+
new_output = if doc.output.include?("<head>")
|
|
59
|
+
doc.output.sub("<head>", "<head>\n #{NOINDEX_META}")
|
|
60
|
+
else
|
|
61
|
+
"#{NOINDEX_META}\n#{doc.output}"
|
|
62
|
+
end
|
|
63
|
+
doc.output = new_output
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "digest"
|
|
4
|
+
|
|
5
|
+
module Jekyll
|
|
6
|
+
module SecretPosts
|
|
7
|
+
class UrlTokenizer
|
|
8
|
+
def initialize(config)
|
|
9
|
+
@config = config
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def token_for(collection_label, relative_path)
|
|
13
|
+
identifier = "#{collection_label}#{relative_path}"
|
|
14
|
+
raw = Digest::SHA256.hexdigest(@config.salt + identifier)
|
|
15
|
+
raw[0, @config.token_length]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "jekyll"
|
|
4
|
+
require "jekyll/secret_posts/config"
|
|
5
|
+
require "jekyll/secret_posts/url_tokenizer"
|
|
6
|
+
require "jekyll/secret_posts/generator"
|
|
7
|
+
require "jekyll/secret_posts/hooks"
|
|
8
|
+
|
|
9
|
+
module Jekyll
|
|
10
|
+
module SecretPosts
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
Jekyll::SecretPosts::Hooks.register
|
metadata
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: jekyll-secret-posts
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- devl79
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-02-24 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: '4.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '4.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rspec
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '3.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '3.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rubocop
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '1.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '1.0'
|
|
55
|
+
description:
|
|
56
|
+
email:
|
|
57
|
+
- dltjgus0709@gmail.com
|
|
58
|
+
executables: []
|
|
59
|
+
extensions: []
|
|
60
|
+
extra_rdoc_files: []
|
|
61
|
+
files:
|
|
62
|
+
- LICENSE
|
|
63
|
+
- README.md
|
|
64
|
+
- lib/jekyll-secret-posts.rb
|
|
65
|
+
- lib/jekyll/secret_posts.rb
|
|
66
|
+
- lib/jekyll/secret_posts/config.rb
|
|
67
|
+
- lib/jekyll/secret_posts/generator.rb
|
|
68
|
+
- lib/jekyll/secret_posts/hooks.rb
|
|
69
|
+
- lib/jekyll/secret_posts/url_tokenizer.rb
|
|
70
|
+
homepage: https://github.com/developerlee79/jekyll-secret-posts
|
|
71
|
+
licenses:
|
|
72
|
+
- MIT
|
|
73
|
+
metadata:
|
|
74
|
+
homepage_uri: https://github.com/developerlee79/jekyll-secret-posts
|
|
75
|
+
source_code_uri: https://github.com/developerlee79/jekyll-secret-posts
|
|
76
|
+
post_install_message:
|
|
77
|
+
rdoc_options: []
|
|
78
|
+
require_paths:
|
|
79
|
+
- lib
|
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
81
|
+
requirements:
|
|
82
|
+
- - ">="
|
|
83
|
+
- !ruby/object:Gem::Version
|
|
84
|
+
version: 2.7.0
|
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
requirements: []
|
|
91
|
+
rubygems_version: 3.1.6
|
|
92
|
+
signing_key:
|
|
93
|
+
specification_version: 4
|
|
94
|
+
summary: Jekyll plugin for unlisted posts served at hashed, share-only URLs.
|
|
95
|
+
test_files: []
|